实现井字游戏的极大极小算法
Implementing minimax algorithm for tic-tac-toe
我正在尝试为井字游戏实现最小最大算法,在该游戏中,两名玩家都是人类,每次计算机都使用最小最大算法建议最佳移动。但它并不是每次都给出正确的建议。例如:对于以下情况,它没有给出正确的建议:玩家X:1玩家O:2玩家X:5。这是我的代码:
#include <stdio.h>
#include <algorithm>
#include <string>
using namespace std;
#define inf 1<<20
int posmax, posmin;
char board[15];
void print_board()
{
int i;
for (i = 1; i <= 9; i++)
{
printf("%c ",board[i]);
if (i % 3 == 0)
printf("n");
}
printf("n");
}
int check_win(char board[])
{
if ((board[1] == 'X' && board[2] == 'X' && board[3] == 'X') ||
(board[4] == 'X' && board[5] == 'X' && board[6] == 'X') ||
(board[7] == 'X' && board[8] == 'X' && board[9] == 'X') ||
(board[1] == 'X' && board[4] == 'X' && board[7] == 'X') ||
(board[2] == 'X' && board[5] == 'X' && board[8] == 'X') ||
(board[3] == 'X' && board[6] == 'X' && board[9] == 'X') ||
(board[1] == 'X' && board[5] == 'X' && board[9] == 'X') ||
(board[3] == 'X' && board[5] == 'X' && board[7] == 'X'))
{
return 1;
}
else if((board[1] == 'O' && board[2] == 'O' && board[3] == 'O') ||
(board[4] == 'O' && board[5] == 'O' && board[6] == 'O') ||
(board[7] == 'O' && board[8] == 'O' && board[9] == 'O') ||
(board[1] == 'O' && board[4] == 'O' && board[7] == 'O') ||
(board[2] == 'O' && board[5] == 'O' && board[8] == 'O') ||
(board[3] == 'O' && board[6] == 'O' && board[9] == 'O') ||
(board[1] == 'O' && board[5] == 'O' && board[9] == 'O') ||
(board[3] == 'O' && board[5] == 'O' && board[7] == 'O'))
{
return -1;
}
else return 0;
}
int check_draw(char board[])
{
if ((check_win(board) == 0) && (board[1] != '_') && (board[2] != '_') &&
(board[3] != '_') && (board[4] != '_') && (board[5] != '_') &&
(board[6] != '_') && (board[7] != '_') && (board[8] != '_') &&
(board[9] != '_'))
{
return 1;
}
else return 0;
}
int minimax(int player, char board[], int n)
{
int i, res, j;
int max = -inf;
int min = inf;
int chk = check_win(board);
if (chk == 1)
return 1;
else if (chk == (-1))
return -1;
else if (chk = check_draw(board))
return 0;
for (i = 1; i <= 9; i++)
{
if(board[i] == '_')
{
if(player == 2)
{
board[i] = 'O';
res = minimax(1, board, n + 1);
board[i] = '_';
if(res < min)
{
min = res;
if (n == 0)
posmin = i;
}
}
else if (player == 1)
{
board[i] = 'X';
res = minimax(2, board, n + 1);
board[i] = '_';
if (res > max)
{
max = res;
if (n == 0)
posmax = i;
}
}
}
}
if (player == 1)
return max;
else return min;
}
// 1 is X, 2 is O
int main()
{
int i, j, input, opt;
for(i = 1; i <= 9; i++)
board[i] = '_';
printf("Board:n");
print_board();
for(i = 1; i <= 9; i++)
{
if (i % 2 == 0)
printf("Player O give input:n");
else
printf("Player X give input:n");
scanf("%d", &input);
if (i % 2 != 0)
board[input] = 'X';
else
board[input] = 'O';
printf("Board:n");
print_board();
int chk = check_win(board);
if (chk == 1)
{
printf("Player X wins!n");
break;
}
else if (chk == -1)
{
printf("Player O wins!n");
break;
}
else if ((chk == 0) && (i != 9))
{
posmax = -1;
posmin = -1;
if(i % 2 == 0)
{
opt = minimax(1, board, 0);
printf("Optimal move for player X is %dn", posmax);
}
else
{
opt = minimax(2, board, 0);
printf("Optimal move for player O is %dn", posmin);
}
}
else
printf("The game is tied!n");
}
return 0;
}
在我看来,您的程序没有给出错误的建议。如果两个玩家都处于最佳状态,Minimax会计算出一次移动的得分。在你的情况下,分数可以是+1、-1和0,因此,如果一场比赛不可避免地输掉了,那么输掉的深度也没有什么区别。给定以下游戏状态
X O _
X _ _
_ _ _
以及玩家X的最佳打法,玩家O在哪里移动并不重要(无论哪种情况他都会输):
- O打7,X打5,O打6,X打8-->X获胜
- O打3后,X打7-->X获胜
玩家X获胜。第7步的得分与第3步和所有其他可玩的动作相同。如果你想让你的算法给出这个例子的移动建议7,你必须将游戏深度包括在你的评估函数中。您可以将函数的返回值更改为以下值:
int chk = check_win(board);
if (chk == 1)
return (10 - n);
else if (chk == (-1))
return -(10 - n);
else if (chk = check_draw(board))
return 0;
除非我读错了main(),否则在宣布它为平局之前,只需要填充8个正方形。这可能不是你正在寻找的错误,但这只是一个开始。
我认为这(尽管编码效率低下)是正确的。如果没有,请给出你认为程序错误的移动顺序。
它并没有给出最短的移动顺序,这可能就是你想要的。然后,你应该重构它,以返回给出最短移动序列(如果获胜)或最长移动序列(当失败)的移动。
替换 printf("Optimal move for player X is %d %dn", posmax);
具有 printf("Optimal move for player X is %dn", posmax);
和
printf("Optimal move for player O is %d %dn", posmin);
具有 printf("Optimal move for player O is %dn", posmin);
其他一切似乎都是正确的,尽管它并不总是打印出最快的胜利(如果胜利存在的话)。
- 为什么这个选择排序算法仍然切换一个元素,当它已经是其他元素中最小的元素时?
- 井字游戏具有奇怪行为的最小最大值算法(C++)
- 如何在不导致堆栈溢出的情况下计算非常大的数字和很小的 HCF.我正在使用欧几里得算法
- 最小 kth 用于快速选择算法
- 如何使用 STL 算法找到最小值和最大值?
- 用于查找ABS的最小值的算法(A [I] A [J] -K)
- C 中的贪婪算法最小搜索
- 修改算法 STL 中的make_heap C++以用作最小堆
- 搜索一组点,其长度总和最小为矩形.算法是什么
- 在二叉搜索树中查找最小和的算法改进
- 算法,用于查找获取排序列表所需的最小移动元素到结束步骤
- 使用算法查找自定义数据向量中的最大值和最小值
- 2D函数最小化算法或C/C 库
- 算法的正确性和逻辑:最小步骤
- 用于井字游戏故障的最小最大算法
- 实现井字游戏的极大极小算法
- 极小极大递归究竟是如何工作的
- 找到最主要的局部极小值
- 神经网络陷入局部极小值
- 浮点数-在c++中处理极小的数字