[英]Determine best move in tic tac toe
我想编写一个递归函数来确定给定井字游戏中的最佳动作
int nextMove(struct Game g, enum Symbol player) {
if (game_over(g) != 0) {
return -1;
}
int i, j;
int score, end;
for(i = 0; i < 3; i += 1) {
for (j = 0; j < 3; j += 1) {
if(g.board.fields[i][j] == 0) {
g.board.fields[i][j] = player;
score = nextMove(g, -player);
}
}
}
end = game_over(g)
}
我的game_over函数:
enum Symbol game_over(struct Game g)
{
int x, y = x = 0;
int full = 0;
for (y = 0; y < SIZE_Y_AXIS; y += 1)
{
for (x = 0; x < SIZE_X_AXIS; x += 1)
{
if (g.board.fields[x][y] == NONE)
full++;
else if (x < SIZE_X_AXIS - 2 &&
g.board.fields[x][y] == g.board.fields[x+1][y] &&
g.board.fields[x][y] == g.board.fields[x+2][y])
return g.board.fields[x][y];
else if (y < SIZE_Y_AXIS - 2 &&
g.board.fields[x][y] == g.board.fields[x][y+1] &&
g.board.fields[x][y] == g.board.fields[x][y+2])
return g.board.fields[x][y];
else if (x < SIZE_X_AXIS - 2 && y < SIZE_Y_AXIS - 2 &&
g.board.fields[x][y] == g.board.fields[x+1][y+1] &&
g.board.fields[x][y] == g.board.fields[x+2][y+2])
return g.board.fields[x][y];
else if (x >= 2 && y < SIZE_Y_AXIS - 2 &&
g.board.fields[x][y] == g.board.fields[x-1][y+1] &&
g.board.fields[x][y] == g.board.fields[x-2][y+2])
return g.board.fields[x][y];
}
}
if (full == 0)
return FULL;
return NONE;
}
我认为烟叶的生产效果很好,但是我不知道如何确定哪一叶(或哪一招)是最好的? 现在有什么建议吗?
谢谢
在井字游戏中,搜索树是如此之小,可以评估所有叶子节点(与象棋或围棋这样的搜索被缩短的游戏不同)。 由于检查了所有节点,因此可以通过检查叶子节点是赢,输还是平局来评估叶子节点。 您可以分别使用1,-1和0来表示这些值。 完成后,将节点的值返回给它的父节点。 对于非叶节点,它必须选择其子节点的最大值或最小值,这取决于它是最大节点(计算机)还是最小节点(其对手),这将一直备份树根,为其所有可能的移动赋予价值。 在树的根部具有最高值的移动是该位置的最佳移动。这是minimax算法。 此外,在您提供的代码示例中,您未能在所有字段都填满之前检查游戏是否结束。 相反,请检查玩家是否已经连续获得三局,因为游戏已经结束。 注意:您的nextMove函数声称返回一个int,但在大多数情况下不返回。 那必须解决。 这是我要添加到您的代码中的内容(伪代码中添加的部分)。 我不确定确切的game_over函数做什么,所以我不确定确切的代码应该是什么。 因此,我要删除它并添加psuedocode来代替它。
int nextMove(struct Game g, enum Symbol player) {
if (computerWon) {
return 1;
}
if (OpponnentWon) {
return -1;
}
if (allSquaresAreFull) {
return 0;
}
int i, j;
int bestScore;//use this to calculate which move to return
int score, end;
//now check whose turn it is
if(player == 1){//I'm assuming this is the computer player
bestScore = -100;//start with an arbitrary low value
for(i = 0; i < 3; i += 1) {
for (j = 0; j < 3; j += 1) {
if(g.board.fields[i][j] == 0) {
g.board.fields[i][j] = player;
score = nextMove(g, -player);
g.board.fields[i][j] = 0;//make sure to undo every move made in the search
if(score > bestScore){//a better move for this player
bestScore = score;//update bestScore
}
}
}
}
return bestScore;//return best move to parent;
}
if(player == -1){//I'm assuming this is the opponent
bestScore = 100;//start with an arbitrary high value
for(i = 0; i < 3; i += 1) {
for (j = 0; j < 3; j += 1) {
if(g.board.fields[i][j] == 0) {
g.board.fields[i][j] = player;
score = nextMove(g, -player);
g.board.fields[i][j] = 0;//make sure to undo every move made in the search
if(score < bestScore){//a better move for the opponent is a lower move
bestScore = score;//update bestScore
}
}
}
}
return bestScore;//return best move to parent;
}
end = game_over(g)//this variable is never used. Not sure what it does. I would remove it, it seems useless
}
这应该返回头寸的值(如果赢得,丢失或平仓)。 为了确定采取哪一步,必须对此做些微修改。 添加一个测试以查看是否在第一次调用nextMove(即根),而不是仅跟踪移动的值ony bestMove,同时跟踪实际的最佳移动是什么(也许在移动结构中)。 如果最好的话,将其返回。 现在nextMove将返回要采取的动作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.