问题很简单。我用3X3阵列做了3X3 tictactoe游戏。但问题是:
array[0][3] = array[1][0]
这很奇怪,因为首先,我制作的阵列没有第四列。所以array[0][3]
甚至不存在!为了使事情变得复杂,它需要[1][0]
当我输入我的移动的坐标时,我遇到了问题:0 2
void displayBoard(int tictac[3][3])
{
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
cout << tictac[i][j] << " ";
} cout << "\n" ;
} cout << "\n";
}
int Horizontal(int x, int y, int tictac[3][3])
{
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[3][3])
{
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[3][3])
{
int done = 0;
cout << "\n-------------------------\nComputer plays: \n";
done = Horizontal(X,Y,tictac);
if(done == 0)
{
done = Vertical(X,Y,tictac);
}
}
int main()
{
int tictac[3][3] = {{0,0,0},{0,0,0}, {0,0,0} };
int X, Y;
for(int r=1; r<100; r++)
{
cout << "\n-------------------------\nPlayer play a move: \n";
cin >> X;
cin >> Y;
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;
}
}
}
答案 0 :(得分:3)
您需要添加边界检查。例如,当用户输入移动坐标时,您需要确保它们在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
和Horizontal
函数中执行相同的操作。例如,如果x
为2且y
为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
并将<< 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
来避免这种情况。
答案 1 :(得分:1)
如果是这个数组
int array[3][3];
以下声明有效
array[0][3] == array[1][0]
,因为:
[j][i]
变为[j * width + i]
。array[0][3]
指向内存中的0 * 3 + 3
(第三个)单元格,但array[1][0]
指向内存的1 * 3 + 0
(也是第三个!)单元格,从2D阵列的开始。