2D 阵列井字 - 我做错了什么



在让我的游戏工作时遇到问题...对我可能会做什么有什么想法吗?我已经浏览了大部分代码并对其进行了初始化,但由于某种原因,它说大多数函数我没有正确的点。此外,drawBoard没有空隙类型。请帮忙

谢谢

#include <iostream>
using namespace std;
// initialize a 2d board (3,3) with asterisk 
void drawBoard(char board[][]);
char check_Winner(char [][]);
int main(){
char board[3][3]={{'*','*','*'},{'*','*','*'},{'*','*','*'}};
bool win = false;
bool in_row = false;
bool in_col = false;
int row;
int column;


// run a loop:
while (!win) {
// Display the content of the board
drawBoard(char board[][]));
cout << "Player 1's turn:";
// Ask player one to chose a location (row, column)
cout << "What is the row:?n";
cin >> row;
cout << "What is the column?n";
cin >> column;
// check if move is valid
//check if location has astericks and its between 0 thru 2
bool valid = false;
while (!valid) 
{
//check if the move is within range.
if(!(row <= 3 && row >= 1 && column <= 3 && column >= 1)){
cout << "Error: Either the row or column is not within range of the board.n";
// ask again (error: row in column not within range)
cout << "What is the row:?n";
cin >> row;
cout << "What is the column?n";
cin >> column;
}
else if(board[row-1][column-1] != '*')
{
cout << "Error: The (row,column) is already occupied.n";
cout << "What is the row:?n";
cin >> row;
cout << "What is the column?n";
cin >> column;
}else {
valid = true;
}

}
board[row-1][column-1] = 'X';
drawBoard(char board[][]);
// Check if someone won or  if there is a tie
check_Winner(char board[][]);
// Ask player two to chose a location (row, column)
cout << "Player 2's turn:";
cout << "What is the row:?n";
cin >> row;
cout << "What is the column?n";
cin >> column;
// check if move is valid
//check if location has astericks and its between 0 thru 2
bool valid = false;
while (!valid) 
{
//check if the move is within range.
if(!(row <= 3 && row >= 1 && column <= 3 && column >= 1)){
cout << "Error: Either the row or column is not within range of the board.n";
// ask again (error: row in column not within range)
cout << "What is the row:?n";
cin >> row;
cout << "What is the column?n";
cin >> column;
}
else if(board[row-1][column-1] != '*')
{
cout << "Error: The (row,column) is already occupied.n";
cout << "What is the row:?n";
cin >> row;
cout << "What is the column?n";
cin >> column;
}else 
{
valid = true;
}
board[row-1][column-1] = 'O';
}
drawBoard(char board[][])
// Check if someone won or  if there is a tie
check_Winner(char board[][]);
}
system("pause");
return 0;
}
char check_Winner(char board[][]){
char winner = 'T';
// Checks for horizontal:
for (int i = 0; i < 3; i++)
if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
winner = board[i][0];
// Checks for vertical:
for (int i = 0; i < 3; i++)
if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
winner = board[0][1];
// Checks for diagnol:
if ((board[0][0] == board[1][1] && board[1][1] == board[2][2]) || 
(board[0][2] == board[1][1] && board[1][1] == board[2][0]))
winner = board[1][1];
// checking the result:
switch (winner) {
case 'T': cout << "IT'S A TIE";/* tie */ break;
case 'X': cout << "PLAYER 1 WON!";/* X won */ break;
case 'O': cout << "PLAYER 2 WON!";/* O won */ break;
default : cout << "NEXT PLAYER'S TURN...>"; continue;
}
}
void drawBoard(char board[][])
{
cout << "     1   2   3" << endl;
cout << "   +---+---+---+" << endl;
cout << " 1" << " | " << board[0][0] << " | " << board[0][1] << " | " << board[0][2] << " | " << endl;
cout << "   +---+---+---+" << endl;
cout << " 2" << " | " << board[1][0] << " | " << board[1][1] << " | " << board[1][2] << " | " << endl;
cout << "   +---+---+---+" << endl;
cout << " 3" << " | " << board[2][0] << " | " << board[2][1] << " | " << board[2][2] << " | " << endl;
cout << "   +---+---+---+" << endl;
}

我把你的代码粘贴到 codepad.org 中并编译了它。第一条错误消息是:

第 6 行:错误:将"board"声明为多维数组必须具有除第一个维度之外的所有维度的边界

换句话说 - 如果你不告诉编译器一些关于二维数组维度的信息,它就不知道如何找到一个元素。为什么?好吧,当你访问一个由m x n个元素组成的2D数组a[i][j]时,你实际上是在计算。

*(a + n * i + j)

因为每次递增行i时,都会跳过另一个n元素。

另一种思考方式 - "2D"元素实际上是一个大块。如果你有

0  1  2  3
4  5  6  7
8  9 10 11

它们实际上存储为

0 1 2 3 4 5 6 7 8 9 10 11

你可以找到元素 [1][1],比如说,通过计算偏移量(如果你愿意的话,一维索引)1 * 4 + 1 = 5.果然,线性数组中的元素 5 的值为5,这是你通过向下和一次穿越会发现的。

我们通过替换来修复第一个编译器错误

void drawBoard(char board[][]);
char check_Winner(char [][]);

void drawBoard(char board[][3]);
char check_Winner(char [][3]);

(顺便说一句,我不确定为什么check_Winner被定义为返回char(你的函数中没有return Winner;语句......),以及为什么你在函数名称中使用下划线和大写字母的奇怪组合。我们稍后会回到这个问题)

接下来,编译器会抱怨您调用这些函数的方式。 您需要调用它们(在第 23 行和其他地方)而不是

drawBoard(char board[][]);

但简单地作为

drawBoard(board);

由于您已经定义了要传递char,并且您不需要[][]来提醒编译器board的类型(您之前定义了它)。

编译器抛出的下一个错误(修复后)是

In function 'int main()':

Line 72: error: redeclaration of 'bool valid'

事实上,你定义了

bool valid = false;

在第 33 行。之后,当引用同一变量时,您不得在变量名称前面放置bool- 看起来您正在(重新)声明变量。只要把

valid = true

在第 72 行。(除此之外 - 你显然做了一大块代码的复制粘贴,这就是这个错误是如何潜入的。你想认真考虑找到一种方法,使"make a move"成为可以为玩家 1 或玩家 2 调用的单个函数 - 那么你不需要重复所有这些代码,事情会看起来更干净。而且不太容易出错。

修复后,编译器抱怨第 99 行:

In function 'int main()':

Line 99: error: expected ';' before 'check_Winner'

与此类错误的情况一样,问题出在前面的行中。第 97 行:

drawBoard(board)

末尾缺少分号,应该是

drawBoard(board);

修复后,编译器抱怨第 130 行:

default : cout << "NEXT PLAYER'S TURN...>"; continue;

In function 'char check_Winner(char (*)[3])':

Line 130: error: continue statement not within a loop

continue语句用于表示"直接进入您所在循环的下一个迭代"(whilefor...)。但是您在switch语句中使用它,并且没有代码可以跳转到的循环(在您所在的函数范围内)。 如果您只是关闭continue;,代码将继续正常。

事实上(虽然这不是你要问的),break'不会导致程序停止;它只会把你带到函数的末尾,代码会继续。 这就是为什么你真的需要在check_Winner函数中有一个返回值 - 你需要在调用它之后检查它,以便你可以采取适当的操作(打印消息,然后退出游戏)。

去掉 130 行的continue,我们现在在第 133 行遇到警告:

In function 'char check_Winner(char (*)[3])':

Line 133: warning: control reaches end of non-void function

这是在说"你声明了这个函数来返回一个char,但你忘了输入一个return语句! 加

return winner;

在功能结束之前,投诉就消失了。

所有这些编辑的结果是以下代码。我并不是说它是"好"的代码,但至少编译器错误已被删除。我希望我描述的过程对你的学习有所帮助。大多数编译器都有标志来启用警告和错误消息;我强烈建议您始终启用每个警告,并注意编译器抱怨的内容。您将学习编写更好的代码。

免责声明- 我在"在路上"写这篇文章,所以我只能使用 codepad.org 进行基本调试。它不允许交互式编程,所以我无法测试最终代码是否"有效"——我只能告诉你,它不再抱怨代码中的错误......我 99% 确定您的check_Winner代码中有一些逻辑错误 - 首先,您从

winner = 'T';

这意味着除非满足其他条件之一,否则您将拨打平局;我认为只有在没有星号的情况下才应该调用领带(如果你想变得非常聪明,你可以在没有可能的解决方案时调用领带,但这是一个更难编码的问题)。

无论如何 - 这是编译的代码。在你有一个工作游戏之前,还有更多的事情要做,我想......

#include <iostream>
using namespace std;
// initialize a 2d board (3,3) with asterisk 
void drawBoard(char board[][3]);
char check_Winner(char board[][3]);
int main(){
char board[3][3]={{'*','*','*'},{'*','*','*'},{'*','*','*'}};
bool win = false;
bool in_row = false;
bool in_col = false;
int row;
int column;


// run a loop:
while (!win) {
// Display the content of the board
drawBoard(board);
cout << "Player 1's turn:";
// Ask player one to chose a location (row, column)
cout << "What is the row:?n";
cin >> row;
cout << "What is the column?n";
cin >> column;
// check if move is valid
//check if location has astericks and its between 0 thru 2
bool valid = false;
while (!valid) 
{
//check if the move is within range.
if(!(row <= 3 && row >= 1 && column <= 3 && column >= 1)){
cout << "Error: Either the row or column is not within range of the board.n";
// ask again (error: row in column not within range)
cout << "What is the row:?n";
cin >> row;
cout << "What is the column?n";
cin >> column;
}
else if(board[row-1][column-1] != '*')
{
cout << "Error: The (row,column) is already occupied.n";
cout << "What is the row:?n";
cin >> row;
cout << "What is the column?n";
cin >> column;
}else {
valid = true;
}

}
board[row-1][column-1] = 'X';
drawBoard(board);
// Check if someone won or  if there is a tie
check_Winner(board);
// Ask player two to chose a location (row, column)
cout << "Player 2's turn:";
cout << "What is the row:?n";
cin >> row;
cout << "What is the column?n";
cin >> column;
// check if move is valid
//check if location has astericks and its between 0 thru 2
valid = false;
while (!valid) 
{
//check if the move is within range.
if(!(row <= 3 && row >= 1 && column <= 3 && column >= 1)){
cout << "Error: Either the row or column is not within range of the board.n";
// ask again (error: row in column not within range)
cout << "What is the row:?n";
cin >> row;
cout << "What is the column?n";
cin >> column;
}
else if(board[row-1][column-1] != '*')
{
cout << "Error: The (row,column) is already occupied.n";
cout << "What is the row:?n";
cin >> row;
cout << "What is the column?n";
cin >> column;
}else 
{
valid = true;
}
board[row-1][column-1] = 'O';
}
drawBoard(board);
// Check if someone won or  if there is a tie
check_Winner(board);
}
system("pause");
return 0;
}
char check_Winner(char board[][3]){
char winner = 'T';
// Checks for horizontal:
for (int i = 0; i < 3; i++)
if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
winner = board[i][0];
// Checks for vertical:
for (int i = 0; i < 3; i++)
if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
winner = board[0][1];
// Checks for diagnol:
if ((board[0][0] == board[1][1] && board[1][1] == board[2][2]) || 
(board[0][2] == board[1][1] && board[1][1] == board[2][0]))
winner = board[1][1];
// checking the result:
switch (winner) {
case 'T': cout << "IT'S A TIE";/* tie */ break;
case 'X': cout << "PLAYER 1 WON!";/* X won */ break;
case 'O': cout << "PLAYER 2 WON!";/* O won */ break;
default : cout << "NEXT PLAYER'S TURN...>";
}
return winner;
}
void drawBoard(char board[][3])
{
cout << "     1   2   3" << endl;
cout << "   +---+---+---+" << endl;
cout << " 1" << " | " << board[0][0] << " | " << board[0][1] << " | " << board[0][2] << " | " << endl;
cout << "   +---+---+---+" << endl;
cout << " 2" << " | " << board[1][0] << " | " << board[1][1] << " | " << board[1][2] << " | " << endl;
cout << "   +---+---+---+" << endl;
cout << " 3" << " | " << board[2][0] << " | " << board[2][1] << " | " << board[2][2] << " | " << endl;
cout << "   +---+---+---+" << endl;
}

附言。

无论如何,我都不是一个C++专家。但是那些倾向于坚持不使用using namespace std;的人,而是写

std::cout << "hello world" << std::endl;

等。随着代码变得越来越复杂,明确哪个函数/常量属于哪个类变得更加重要。所以我被告知... 请参阅为什么"使用命名空间 std"被视为不良做法?。问题和答案都得到了很多赞成票......建议这是人们思考的重要事情。请阅读超出接受的答案...在该页面的下方有一些宝石。

我可以建议你尝试在你的电路板上使用typedef吗?

typedef char tttboard[3][3];

您的董事会声明:

tttboard board={{'*','*','*'},{'*','*','*'},{'*','*','*'}};

您的函数将如下所示:(通过引用!

void drawBoard(tttboard& board);
char check_Winner(tttboard& board);

正如您在评论中被告知的那样,您在没有char的情况下称呼它,并像这样[][]

drawBoard(board);
check_Winner(board);

最新更新