您需要添加边界检查。例如,当用户输入移动坐标时,您需要确保它们在 0 到 2 的范围内。下面的示例验证输入以确保只输入数字,X 和 Y 坐标都输入在一行上,并且坐标在范围内。它用于std::stringstream
解析坐标,而不必处理检查和清除故障位std::cin
#include <string> // at top of your .cpp file
#include <sstream>
// in main()
// Get en entire input line so we can skip extra characters
// after the cell coordinates
string inputLine;
std::getline(cin, inputLine);
stringstream inputStream(inputLine);
if(!(inputStream >> X) || !(inputStream >> Y))
{
cout << "Please enter the cell coordinates in the form of # #" << endl;
continue;
}
bool invalidCoordinates = false;
if(X < 0 || X > 2)
{
cout << "invalid X location" << endl;
invalidCoordinates = true;
}
if(Y < 0 || Y > 2)
{
cout << "invalid Y location" << endl;
invalidCoordinates = true;
}
// check for invalid input
if(invalidCoordinates) continue;
在检查是否可以进行有效移动时,您还需要在Vertical
and函数中执行相同的操作。Horizontal
例如 if x
is 2 and y
is 2 以下Vertical
行将访问数组边界之外的数据。
if(tictac[x+1][y]==0)
{
tictac[x+1][y]=2;
return 1;
}
这是因为您实际上是使用 访问第四个元素x+1
。这个元素在技术上是不存在的,但是你最终会访问一个多维数组tictac[0][y+1]
。
您可以绕过边界检查Vertical
并Horizontal
通过在边缘周围添加一些填充并用表明它们不可用的值填充它们。在您的情况下,将每个方向的大小增加 3。
int tictac[9][9] = {
{3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3},
{3,3,3,0,0,0,3,3,3},
{3,3,3,0,0,0,3,3,3},
{3,3,3,0,0,0,3,3,3},
{3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3},
};
您需要对它们进行适当的调整,X
以便Y
它们指向正确的位置。
X += 3; // Adjust for padding
Y += 3; // Adjust for padding
if(tictac[X][Y]==0)
{
tictac[X][Y] = 1;
displayBoard(tictac);
AI(X,Y,tictac);
displayBoard(tictac);
}
您可能需要对代码的其他部分进行调整,但上面的示例应该可以帮助您入门。
displayBoard
你的功能也有问题。当它打印出数组的元素i
并被j
反转时,板看起来旋转了 90 度。更改以下行
cout << tictac[i][j] << " ";
至
cout << tictac[j][i] << " ";
另一个问题是,您\n
在输出的每一行的末尾都使用了,而没有使用std::flush
来确保将行发送到控制台。您可以放在<< flush;
这些行之后,也可以删除\n
and 放在<< endl;
行尾。
cout << "\n-------------------------\nComputer plays: \n" << flush;
或者
cout << "\n-------------------------\nComputer plays: " << endl;
下面的代码是您问题中包含的原始代码的完整更新。它结合了上述建议并进行了一些其他更改。我还添加了一个残局检查以确定是否还有任何动作。
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
static const int BoardSize = 3;
static const int BoardPadding = BoardSize;
static const int ArraySize = BoardSize + (BoardPadding * 2);
void displayBoard(int tictac[ArraySize][ArraySize])
{
for(int y = 0; y < BoardSize; y++)
{
for(int x = 0; x < BoardSize; x++)
{
cout << tictac[BoardPadding + x][BoardPadding + y] << " ";
}
cout << endl ;
}
cout << endl;
}
int Horizontal(int x, int y, int tictac[ArraySize][ArraySize])
{
if(tictac[x][y+1]==0)
{
tictac[x][y+1]=2;
return 1;
}
if(tictac[x][y-1]==0)
{
tictac[x][y-1]=2;
return 1;
}
if(tictac[x][y-2]==0)
{
tictac[x][y-2]=2;
return 1;
}
if(tictac[x][y+2]==0)
{
tictac[x][y+2]=2;
return 1;
}
return 0;
}
int Vertical(int x, int y, int tictac[ArraySize][ArraySize])
{
if(tictac[x+1][y]==0)
{
tictac[x+1][y]=2;
return 1;
}
if(tictac[x-1][y]==0)
{
tictac[x-1][y]=2;
return 1;
}
if(tictac[x-2][y]==0)
{
tictac[x-2][y]=2;
return 1;
}
if(tictac[x+2][y]==0)
{
tictac[x+2][y]=2;
return 1;
}
return 0;
}
void AI(int X,int Y,int tictac[ArraySize][ArraySize])
{
int done = 0;
cout << "\n-------------------------\nComputer plays: " << endl;
done = Horizontal(X,Y,tictac);
if(done == 0)
{
done = Vertical(X,Y,tictac);
}
}
// Check if all moves have been made
bool isEndGame(int tictac[ArraySize][ArraySize])
{
int count = 0;
for(int y = 0; y < BoardSize; y++)
{
for(int x = 0; x < BoardSize; x++)
{
count += tictac[BoardPadding + x][BoardPadding + y] ? 1 : 0;
}
}
return count == (BoardSize * BoardSize);
}
int main()
{
int tictac[ArraySize][ArraySize] = {
{3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3},
{3,3,3,0,0,0,3,3,3},
{3,3,3,0,0,0,3,3,3},
{3,3,3,0,0,0,3,3,3},
{3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3},
};
int X, Y;
while(isEndGame(tictac) == false)
{
cout << "\n-------------------------\nPlayer play a move: " << flush;
// Get en entire input line so we can skip extra characters
// after the cell coordinates
string inputLine;
std::getline(cin, inputLine);
stringstream inputStream(inputLine);
if(!(inputStream >> X) || !(inputStream >> Y))
{
cout << "Please enter the cell coordinates in the form of # #" << endl;
continue;
}
bool invalidCoordinates = false;
if(X < 0 || X >= BoardSize)
{
cout << "invalid X location" << endl;
invalidCoordinates = true;
}
if(Y < 0 || Y >= BoardSize)
{
cout << "invalid Y location" << endl;
invalidCoordinates = true;
}
// check for invalid input
if(invalidCoordinates) continue;
// adjust the coordinates and do our thing
X += BoardPadding;
Y += BoardPadding;
if(tictac[X][Y]==0)
{
tictac[X][Y] = 1;
displayBoard(tictac);
AI(X,Y,tictac);
displayBoard(tictac);
}
else
{
cout << "Space occupied. Try different cell." << endl;
}
}
cout << "game finished...check for winner" << endl;
}
注意:使用using namespace std;
. 它将命名空间中的所有内容拉std
入当前范围(在本例中为全局命名空间),并可能导致冲突。最好使用完全限定的名称std::cout
来避免这种情况。