所以我对我的tic tac toe游戏的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();
}
答案 0 :(得分:1)
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循环放在一个地方,因为它在另一个地方工作是不对的。