【发布时间】:2015-06-28 12:15:26
【问题描述】:
我正在尝试构建人工智能。井字游戏使用 minimax 算法,但它返回奇怪的动作 - 有时它只返回我认为第一个可用的动作(左上、中上、右上......),但其他时候它只是返回看起来像“随机”移动。但据我所知,这些动作并不是随机的,而且 A.I.在相同的条件下播放总是相同的。
当有 2 名人类玩家时,游戏才有效。整个游戏很大,所以我创建了AITest 类,它应该显示行为的重要部分。它让两个 A.I.玩家玩并打印棋盘。请注意,这是一个单独的类,不是根据最佳实践编写的,并且被大大简化(不检查是否获胜......)。但很明显,A.I.很傻。
感谢您的建议。
package tic_tac_toe;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AITest {
public enum Tile {
EMPTY, O, X;
}
// [row][column]
private static Tile[][] board;
private static int moveCount = 0;
private Tile mySeed;
private Tile opponentSeed;
public static void main(String[] args) {
board = new Tile[3][3];
for (int y = 0; y < board.length; y++) {
for (int x = 0; x < board.length; x++) {
board[y][x] = Tile.EMPTY;
}
}
AITest ai = new AITest(Tile.X);
AITest opponent = new AITest(Tile.O);
// simulate some moves
for (int i = 0; i < 15; i++) {
checkReset();
int[] move = ai.getNextMove(board);
board[move[0]][move[1]] = Tile.X;
printBoard();
checkReset();
int[] opponentMove = opponent.getNextMove(board);
board[opponentMove[0]][opponentMove[1]] = Tile.O;
printBoard();
}
}
private static void checkReset() {
moveCount++;
if (moveCount == 9) {
for (int y = 0; y < board.length; y++) {
for (int x = 0; x < board.length; x++) {
board[y][x] = Tile.EMPTY;
}
}
moveCount = 0;
}
}
private static void printBoard() {
StringBuilder sb = new StringBuilder();
sb.append("-----------------------\n");
Map<Tile, String> map = new HashMap<>();
map.put(Tile.EMPTY, "e");
map.put(Tile.O, "O");
map.put(Tile.X, "X");
for (Tile[] row : board) {
for (Tile t : row) {
sb.append(map.get(t) + "|");
}
sb.append("\n");
}
System.out.println(sb.toString());
}
public AITest(Tile seed) {
mySeed = seed;
opponentSeed = (mySeed == Tile.X) ? Tile.O : Tile.X;
}
public int[] getNextMove(Tile[][] board) {
int[] result = minimax(board, mySeed);
// row, column
return new int[] { result[1], result[2] };
}
private int[] minimax(Tile[][] board, Tile player) {
// mySeed is maximizing, opponentSeed is minimizing
int bestScore = (player == mySeed) ? Integer.MIN_VALUE
: Integer.MAX_VALUE;
int currentScore;
int bestRow = -1;
int bestCol = -1;
List<Point> possibleMoves = getPossibleMoves(Arrays.copyOf(board,
board.length));
if (possibleMoves.isEmpty()) {
bestScore = getScore(board, player);
} else {
for (Point move : possibleMoves) {
// try the move
board[move.y][move.x] = player;
if (player == mySeed) {
currentScore = minimax(board, opponentSeed)[0];
if (currentScore > bestScore) {
bestScore = currentScore;
bestRow = move.y;
bestCol = move.x;
}
} else {
currentScore = minimax(board, mySeed)[0];
if (currentScore < bestScore) {
bestScore = currentScore;
bestRow = move.y;
bestCol = move.x;
}
}
// undo the move
board[move.y][move.x] = Tile.EMPTY;
}
}
return new int[] { bestScore, bestRow, bestCol };
}
private List<Point> getPossibleMoves(Tile[][] board) {
List<Point> possibleMoves = new ArrayList<>();
for (int y = 0; y < board.length; y++) {
for (int x = 0; x < board.length; x++) {
if (board[y][x] == Tile.EMPTY) {
possibleMoves.add(new Point(x, y));
}
}
}
return possibleMoves;
}
private int getScore(Tile[][] board, Tile player) {
if (isWinner(board, mySeed)) {
return 1;
}
if (isWinner(board, opponentSeed)) {
return -1;
}
return 0;
}
private boolean isWinner(Tile[][] board, Tile player) {
// rows
for (int i = 0; i < board.length; i++) {
if (checkLine(player, board[i])) {
return true;
}
}
// columns
for (int i = 0; i < board.length; i++) {
if (checkLine(player, board[0][i], board[1][i], board[2][i])) {
return true;
}
}
// diagonals
return checkLine(player, board[0][0], board[1][1], board[2][2])
|| checkLine(player, board[0][2], board[1][1], board[2][0]);
}
private boolean checkLine(Tile player, Tile... line) {
for (Tile tile : line) {
if (tile != player) {
return false;
}
}
return true;
}
}
【问题讨论】:
-
请问你能比“返回奇怪的动作”更具体吗?
-
@AndyTurner 已编辑 - 见第一段。
-
你能举一些“随机”动作的例子吗?您期望什么,它会做什么?
-
@AndyTurner 我从(中、中)人工智能开始。进入(顶部,左侧) - 到目前为止可能还可以。然后我移动(中,左)和 A.I.移动(顶部,右侧),而它应该阻止 - i。 e.走(中,右)。
-
你曾经战胜过人工智能吗?你实施了吗?
标签: java tic-tac-toe minimax