【问题标题】:Tic Tac Toe Trouble ( some logical mistakes )井字游戏麻烦(一些逻辑错误)
【发布时间】:2015-12-16 04:00:21
【问题描述】:

我正在使用类编写这个井字游戏程序。我写了这个函数叫makeAMove()。这个函数应该验证玩家的移动,但它一直显示这是一个无效的移动,它要求玩家重新进入。可能有一些逻辑错误,但我只是没有看到它们。任何人都可以帮忙吗?这是一个使用名为Cell board[ROW][COL] 的对象和另一个名为Player players[2] 的对象的类。标记是XO,而iVal 是棋盘的初始值(棋盘上的每个单元格都有一个从 1 到 9 的数字)。这里包括winGame()switchPlayer() 供您参考。虽然我认为我的 winGame() 函数没问题,但我知道我可以使用 sum 来做到这一点。换句话说,每个单元格都有内部标记,如-1或1,如果行、列等的总和为-3或3,则与玩家对应的内部标记将输出获胜者。如果您对如何执行此操作有任何见解,请随时分享,否则,我的 winGame 很好。

int TicTacToe::switchPlayer(){
        if ( currentPlayer == 0)
                currentPlayer = 1;
        else if ( currentPlayer == 1 )
                currentPlayer = 0;

        return (currentPlayer);
}
//
//method to make a move
//
void TicTacToe::makeAMove(){
        char move;
        int turns = 1;
        do{
                cout << "Player " << (getCurrentPlayer() + 1) << " make a move." << endl;
                cin >> move;
                for ( int i = 0; i < ROW; i++ ){
                        for ( int j = 0; j < COL; j++ ){
                                //This is where my problem begins
                                if ( board[i][j].getiVal() == move ){
                                        board[i][j].setiVal( players[currentPlayer].getMarker());
                                        DrawBoard();
                                        switchPlayer();
                                        turns++;
                                }

                                else if ( board[i][j].getiVal() == 'X' || board[i][j].getiVal() == 'O'){
                                        cout << "Invalid move, please reenter. " << endl;
                                        cin >> move;
                                }//the else if statement always outputs:x
                        }
                }
        } while ( turns <= 9 || !winGame() );
        cout << "Congratulations " << ( getCurrentPlayer() + 1 ) << "you won the game!" << endl;
}
bool TicTacToe::winGame(){
        bool validate = false;
        int k = 0;
        for ( int i = 0; i < ROW; i++ ){
                //check column wins
                if ( board[0][i].getMarker() == board[1][i].getMarker() && board[1][i].getMarker() == board[2][i].getMarker()){
                        players[currentPlayer].setNumWin(k++);
                        validate = true;
                        break;
                }
                //check row wins
                else if ( board[i][0].getMarker() == board[i][1].getMarker() && board[i][1].getMarker() == board[i][2].getMarker()){
                        players[currentPlayer].setNumWin(k++);
                        validate = true;
                        break;
                }
        }

        if( board[0][0].getMarker() == board[1][1].getMarker() && board[1][1].getMarker() == board[2][2].getMarker()){
                players[currentPlayer].setNumWin(k++);
                validate = true;
        }
        else if ( board[0][2].getMarker() == board[1][1].getMarker() && board[1][1].getMarker() == board[2][0].getMarker()){
                players[currentPlayer].setNumWin(k++);
                validate = true;
        }

        return (validate);
}

这是程序的示例运行

    +--+--+--+
    |1 |2 |3 |
    +--+--+--+
    |4 |5 |6 |
    +--+--+--+
    |7 |8 |9 |
    +--+--+--+
    Player 1 make a move.
    1

    +--+--+--+
    |O |2 |3 |
    +--+--+--+
    |4 |5 |6 |
    +--+--+--+
    |7 |8 |9 |
    +--+--+--+
    Player 2 make a move.
    5
    Invalid move, please reenter.
    6

    +--+--+--+
    |O |2 |3 |
    +--+--+--+
    |4 |5 |X |
    +--+--+--+
    |7 |8 |9 |
    +--+--+--+
    Player 1 make a move.

【问题讨论】:

    标签: c++ if-statement logical-operators


    【解决方案1】:

    这里的逻辑错误可以归结为:

    for ( int i = 0; i < ROW; i++ ){
       for ( int j = 0; j < COL; j++ ){
             if ( board[i][j].getiVal() == move ){
    
                   // Not important what happens here
             }
       else if ( board[i][j].getiVal() == 'X' || board[i][j].getiVal() == 'O'){
                   cout << "Invalid move, please reenter. " << endl;
    
                   // Not important what happens here
       }
    

    这里可以使用“橡皮鸭”的方法来调试逻辑错误。

    “橡皮鸭”的调试方法包括将漂浮在浴缸中的橡皮鸭放在显示器屏幕旁边,然后尝试向橡皮鸭解释您的代码在做什么,然后您继续解释,直到你自己找出问题所在。

    在这里,您将首先向您的橡皮鸭解释您的代码将扫描井字游戏矩阵,一次一行,一次一列,从左上角开始,并在右下角结束。这就是嵌套的 for 循环在这里所做的。

    橡皮鸭会同意,你会继续解释这段代码。

    您现在将告诉您的橡皮鸭您的代码将继续扫描井字游戏板,直到它在当前扫描位置看到 moveXO。如果它看到XO,您的代码将抱怨移动无效。

    因此,如果第一个单元格,即左上角的单元格,包含“X”或“O”,则此代码将在内循环的第一次迭代中看到它,并报告错误消息,否不管井字棋矩阵的其余部分中还包含什么。

    至此,您已经成功识别出这里的逻辑错误,使用橡皮鸭的方法进行调试。

    【讨论】:

    • 非常感谢您的回复!我只是有点困惑如何设置我的 X 和 O
    • 如果您了解逻辑问题是什么,那么解决方案应该是显而易见的。提示:如果下一步是针对单元格 #n,其中 n 是 1 到 9,那么下一步是针对行 (n-1)/3,列 (n-1)%3。自己试试这个数学,来验证这个惊天动地的发现(例如,当 n=6 时,这涉及到行 (6-1)/3=1,列 (6-1)%3=2),然后尝试弄清楚为什么数学会这样。其余的应该是显而易见的。根本不需要嵌套的 for 循环。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多