Я работаю над простым tictactoe AI, используя минимаксный алгоритм в Kotlin. Кажется, что-то работает, но в этом сценарии ничего не получается:
Я двигаюсь первым и я 'X' ИИ равен 'O'
X | |
----------
| |
----------
| |
, тогда возвращаемое значение равно
X | O |
----------
| |
----------
| |
вместо оптимального хода, который должен быть средним.
Что я обнаружил: я попробовал отладку и понял, что после моего первого хода все возвращаемые значения из минимаксной функции равны 10 (10 - это константа, которую я установил для функции, возвращаемой в случае победы ИИ)
findPossibleMoves
fun findPossibleMoves(board: CharArray) : IntArray {
var possibleMoves: ArrayList<Int> = ArrayList(0)
for (cellIndex in board.indices) {
if (board[cellIndex] == ' ') {
possibleMoves.add(cellIndex)
}
}
return possibleMoves.toIntArray()
}
findBestMove
fun findBestMove(board: CharArray) : Int {
var boardClone = CharArray(9)
for (cellIndex in boardClone.indices) {
boardClone[cellIndex] = board[cellIndex]
}
val possibleMoves = findPossibleMoves(boardClone)
var bestMove = 0
var max = -1000
for (move in possibleMoves) {
boardClone[move] = currentPlayer
var value = minimax(boardClone, false, 1)
Log.wtf("T", "$move $value")
boardClone[move] = EMPTY
if (value > max) {
max = value
bestMove = move
}
}
Log.wtf("T", "-------------------------------")
return bestMove
}
минимакс
fun minimax(board: CharArray, isMaximising: Boolean, depth: Int) : Int {
if (isGameOver(board)) {
if (doesWinenrExist(board)) {
when (getWinner(board)) {
PLAYER -> {
return -10
}
CPU -> {
return 10
}
}
}
return 0
}
var possibleMoves = findPossibleMoves(board)
if (isMaximising) {
var bestValue = -1000
for (move in possibleMoves) {
board[move] = CPU
var temp = minimax(board, !isMaximising, depth + 1)
board[move] = EMPTY
if (temp > bestValue) {
bestValue = temp
}
}
return bestValue
} else {
var bestValue = 1000
for (move in possibleMoves) {
board[move] = PLAYER
var temp = minimax(board, !isMaximising, depth + 1)
board[move] = EMPTY
if (temp < bestValue) {
bestValue = temp
}
}
return bestValue
}
}
вспомогательные функции
fun isBoardFull(board: CharArray) : Boolean {
for (cell in board) {
if (cell == ' ') {
return false
}
}
return true
}
fun doesWinenrExist(board: CharArray) : Boolean {
var board2d: Array<CharArray> = arrayOf(board.sliceArray(0..2), board.sliceArray(3..5), board.sliceArray(6..8))
//check row
for (row in board2d) {
if (row.all { it == PLAYER } || row.all { it == CPU }) {
return true
}
}
//check col
for (i in 0..2) {
var col: ArrayList<Char> = ArrayList(0)
for (firstIndexInGroupsOf3 in i until board.size step 3) {
col.add(board[firstIndexInGroupsOf3])
}
if (col.all { it == PLAYER } || col.all { it == CPU }) {
return true
}
}
//check diag
for (x in 0..2 step 2) {
var diag: ArrayList<Char> = ArrayList(0)
for (y in 0..2) {
diag.add(board2d[y][if (x == 2) (x - y) else y])
}
if (diag.all { it == PLAYER } || diag.all { it == CPU }) {
return true
}
}
return false
}
fun isGameOver(board: CharArray) : Boolean {
return isBoardFull(board) || doesWinenrExist(board)
}
fun getWinner(board: CharArray) : Char {
var noOfX = board.count { it == PLAYER }
var noOfO = board.count { it == CPU }
return if (noOfO > noOfX) CPU else PLAYER
}
Очень благодарен за любую помощь от yall! Спасибо!
=============================================== ==========
решено! проблема заключается в getWinner ()
обновленная функция getWinner:
fun getWinner() : Char {
return currentPlayer
}