c++中井字游戏的AI问题
Issues with AI for a tic tac toe game in C++
所以我对我的井字游戏的AI有一些问题。AI是纯粹防御性的,所以它总是会阻碍你。它通常在我的第一种情况下起作用,例如,如果我播放左上角,然后播放中上角,它总是会播放右上方。在其他情况下,比如我玩两条对角线,可能会冻结游戏,或者允许我进行第二次回合。这些问题是在我执行了错误的智能AI之后才出现的。最初,这个程序有一个"愚蠢的人工智能",可以随机选择一些点,就像你在代码底部看到的那样。此外,我认为问题在于一些阻塞条件可能相互冲突并导致问题。我该如何解决这个问题?有关守则如下:坐标基于tic tac toe网格,其中左上角为(0,0),右下角为(2,2)
void Game::AIGetNextMoveRand()
{
//top row
if(GetSquareState(0,0) == O && GetSquareState(1,0) == O)
{
do
{
AIMoveX = 2;
AIMoveY = 0;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
else if(GetSquareState(2,0) == O && GetSquareState(1,0) == O)
{
do
{
AIMoveX = 0;
AIMoveY = 0;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
//middle row
else if(GetSquareState(0,1) == O && GetSquareState(1,1) == O)
{
do
{
AIMoveX = 2;
AIMoveY = 1;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
else if(GetSquareState(2,1) == O && GetSquareState(1,1) == O)
{
do
{
AIMoveX = 0;
AIMoveY = 1;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
// bottom row
else if(GetSquareState(0,2) == O && GetSquareState(1,2) == O)
{
do
{
AIMoveX = 2;
AIMoveY = 2;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
else if(GetSquareState(2,2) == O && GetSquareState(1,2) == O)
{
do
{
AIMoveX = 0;
AIMoveY = 2;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
// vert 0
else if(GetSquareState(0,0) == O && GetSquareState(0,1) == O)
{
do
{
AIMoveX = 0;
AIMoveY = 2;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
else if(GetSquareState(0,2) == O && GetSquareState(0,1) == O)
{
do
{
AIMoveX = 0;
AIMoveY = 0;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
// vert 1
else if(GetSquareState(1,0) == O && GetSquareState(1,1) == O)
{
do
{
AIMoveX = 1;
AIMoveY = 2;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
else if(GetSquareState(1,2) == O && GetSquareState(1,1) == O)
{
do
{
AIMoveX = 1;
AIMoveY = 0;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
//vert 2
else if(GetSquareState(2,2) == O && GetSquareState(2,1) == O)
{
do
{
AIMoveX = 2;
AIMoveY = 0;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
else if(GetSquareState(2,0) == O && GetSquareState(2,1) == O)
{
do
{
AIMoveX = 2;
AIMoveY = 2;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
// diagonal 1
else if(GetSquareState(0,0) == O && GetSquareState(1,1) == O)
{
do
{
AIMoveX = 2;
AIMoveY = 2;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
else if(GetSquareState(2,2) == O && GetSquareState(1,1) == O)
{
do
{
AIMoveX = 0;
AIMoveY = 0;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
//diagonal 2
else if(GetSquareState(0,2) == O && GetSquareState(1,1) == O)
{
do
{
AIMoveX = 0;
AIMoveY = 2;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
else if(GetSquareState(0,2) == O && GetSquareState(1,1) == O)
{
do
{
AIMoveX = 2;
AIMoveY = 0;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
// mid 0
else if(GetSquareState(0,0) == O && GetSquareState(2,0) == O)
{
do
{
AIMoveX = 1;
AIMoveY = 0;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
//mid 1
else if(GetSquareState(1,0) == O && GetSquareState(2,1) == O)
{
do
{
AIMoveX = 1;
AIMoveY = 1;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
// mid 2
else if(GetSquareState(0,2) == O && GetSquareState(2,2) == O)
{
do
{
AIMoveX = 1;
AIMoveY = 2;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
//diag 1
else if(GetSquareState(0,0) == O && GetSquareState(2,2) == O)
{
do
{
AIMoveX = 1;
AIMoveY = 1;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
//diag 2
else if(GetSquareState(2,0) == O && GetSquareState(0,2) == O)
{
do
{
AIMoveX = 1;
AIMoveY = 1;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
else
{
do
{
AIMoveX = rand() % 3;
AIMoveY = rand() % 3;
}while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
}
void Game::DoAITurnRand()
{
AIGetNextMoveRand();
SetSquareState(AIMoveX,AIMoveY,activePlayer);
EndTurn();
}
do while循环是垃圾。想想看,如果你的规则做出了一个错误的选择(游戏邦注:比如试图在一个填满的方块上玩游戏),那么再次做出同样的错误选择并没有什么帮助。事实上,这就是为什么你会"冻结"。您需要重新组织代码的逻辑。我建议,如果你的AI选择了一个非法的方块,那么你应该回到你的随机选择代码,那么至少你会得到一个合法的移动。
像这样
// no move selected yet
AIMoveX = -1;
AIMoveY = -1;
// AI rules
if(GetSquareState(0,0) == O && GetSquareState(1,0) == O)
{
AIMoveX = 2;
AIMoveY = 0;
}
else if(GetSquareState(2,0) == O && GetSquareState(1,0) == O)
{
AIMoveX = 0;
AIMoveY = 0;
}
// lots more rules
...
// check for fallback to random move
if ((AIMoveX == -1 && AIMoveY == -1) // if no rules applied
|| GetSquareState(AIMoveX,AIMoveY) != EMPTY) // or if the square is not empty
{
// pick a random square
do
{
AIMoveX = rand() % 3;
AIMoveY = rand() % 3;
}
while(GetSquareState(AIMoveX,AIMoveY) != EMPTY);
}
我最初将AIMoveX和AIMoveY设置为-1,以表明尚未选择任何规则。如果在检查完所有规则后它们仍然是-1,那么我就知道没有规则被选中,我必须随机选择。如果一个规则被选中了,但它选中了一个非空的方块,那么我也会随机选择。我在代码末尾测试了这两种情况。
你必须仔细考虑你写的代码到底是做什么的。在一个地方放一个do while循环,因为它在另一个地方有效,这是不对的。
相关文章:
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 一个关于在C++中重载布尔运算符的问题
- 首要问题的答案让值班员搞错了
- setlocale的C++土耳其字符串问题
- 如何重构类层次结构以避免菱形问题
- 基于boost的程序的静态链接——zlib问题
- C++格式化输出问题
- c++中井字游戏的AI问题