2D阵列tic tac toe - 我做错了什么?

时间:2014-01-23 01:34:18

标签: c++ arrays 2d tic-tac-toe

让我的游戏开始工作时遇到问题...对我可能会做什么的任何想法?我已经完成了大部分代码并对其进行了初始化,但由于某种原因,我认为大多数函数都没有正确的点。此外,drawBoard没有void类型。请帮忙

由于

#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;

}

2 个答案:

答案 0 :(得分:1)

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

typedef char tttboard[3][3];

你的董事会声明:

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

您的功能将如下所示:(通过引用!)

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

正如您在评论中被告知的那样,您没有char[][]这样称呼它:

drawBoard(board);
check_Winner(board);

答案 1 :(得分:1)

我将您的代码粘贴到codepad.org并进行编译。第一条错误消息是:

  

第6行:错误:声明&#39; board&#39;因为多维数组必须具有除第一个

之外的所有维度的边界

换句话说 - 如果你不告诉编译器某事有关二维数组的维度,它就不会知道如何找到一个元素。这是为什么?好吧,当你访问一个m×n个元素的二维数组时,a [i] [j],你真的在​​计算

*(a + n * i + j)

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

另一种思考方式 - &#34; 2D&#34;元素真是一大块。如果你有

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],比如计算偏移量(1D索引,如果你愿意的话)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行。(除此之外 - 你清楚地做了一个大块代码的复制粘贴,这就是这个错误悄然进入的方式。你想要努力想办法制作一个方法来制作一个&#34;移动& #34;可以为玩家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语句用于表示&#34;直接进入您所在循环的下一次迭代&#34; (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

这就是说&#34;你声明这个函数返回char,但是你忘了输入return语句!&#34;。添加

return winner;

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

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

免责声明 - 我正在写这篇文章&#34;在路上&#34;所以我只能使用codepad.org进行基本调试。它不允许交互式编程,所以我无法测试最终的代码是否有效&#39; - 我只能告诉你它停止抱怨代码中的错误...我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;

等。随着代码变得越来越复杂,明确哪个函数/常量属于哪个类变得更加重要。所以我被告知......见Why is "using namespace std" considered bad practice?。问题和答案都得到了很多赞成......这表明这是人们想到的重要事情。阅读超出接受的答案......在该页面下面还有一些宝石。