逻辑错误,在Tic Tac Toe中检查获胜者

时间:2015-12-19 04:02:47

标签: c++ if-statement

好吧,所以我非常接近完成这个计划。我理解为什么我的程序没有采取行动,我能够解决它,但现在我正在努力检查获胜者。我意识到我的winGame()函数应该在某种程度上或者在while循环中结束游戏。但是,当我试图做一些调试来解决一些问题时,我意识到一些令人不安的事情。它总是说它是一个平局,即使它不应该是。这些是很小的事情,我很惭愧,不理解,我真的希望得到一些帮助,我可以解决它。另外,我知道如果有胜利的话,应该有一段时间或者做while循环来结束游戏。我只是不确定在哪里放,所以如果您有任何建议,请告诉我。

*请注意,在我的有效移动函数中有一个小数组,我打算将其作为一个静态const数组。我的get函数返回名称中的值(例如getIval()返回单元格对象的初始值),而我的set函数只是适当地赋值。

bool TicTacToe::validMove(char move){
    char options[9] = { '1','2', '3', '4','5','6','7', '8','9' };
    bool validate = false;
    for ( int i = 0; i < 9; i++ ){
        if ( move == options[i]){
            validate = true;
        }
    }

    return ( validate );
}

void TicTacToe::setMove( char move ){
    for ( int i = 0; i < ROW; i++ ){
        for ( int j = 0; j < COL; j++ ){
            if ( board[i][j].getiVal() == move ){
                board[i][j].setiVal( players[currentPlayer].getMarker() );
                switchPlayer();
                break;
            }
        }
    }
}

void TicTacToe::makeAMove(){
    char move;
    int turns = 1;
    bool validate = true;

    do{
        cout << "Player " << (getCurrentPlayer() + 1) << " make a move." << endl;
        cin >> move;

        if ( validMove( move ) ){
            if ( turns > 4 ){
                cout << "Nested if-else statement." << endl;
                winGame();
                setMove( move );
            }
            else
                setMove(move);
        }
        else{
            cout << "Invalid Move. Please reenter." << endl;
            cin >> move;
        }

        DrawBoard();
        turns++;

    } while ( turns <= 9 );   
}

bool TicTacToe::winGame(){
    cout << "Calling winGame() "  << endl;
    bool validate = false;
    int k = 0;
    for ( int i = 0; i < COL; i++ ){
        //check column wins
        if ( board[0][i].getMarker() == board[1][i].getMarker() && board[1][i].getMarker() == board[2][i].getMarker() && board[2][i].getMarker() != (' ')){
            cout << "Column win " << endl;
            validate = true;
            break;
        }
        //check row wins
        else if ( board[i][0].getMarker() == board[i][1].getMarker() && board[i][1].getMarker() == board[i][2].getMarker() && board[i][2].getMarker() !=  (' ')){
            cout << "Row win." << endl;
            validate = true;
            break;
        }
    }

    if( board[0][0].getMarker() == board[1][1].getMarker() && board[1][1].getMarker() == board[2][2].getMarker() && board[2][2].getMarker() != (' ')){
        cout << "Diagonal 1" << endl;
        validate = true;
    }
    else if ( board[0][2].getMarker() == board[1][1].getMarker() && board[1][1].getMarker() == board[2][0].getMarker() && board[2][0].getMarker() != (' ') ){
        cout << "Diagonal 2 " << endl;
        validate = true;
    }
    else{
        cout << "It's a draw!" << endl;
        validate = true;
    }

    return (validate);
}

以下是该程序的示例运行供您参考。

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

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

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

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

+--+--+--+
|X |O |X |
+--+--+--+
|4 |O |6 |
+--+--+--+
|7 |8 |9 |
+--+--+--+
Player 1 make a move.
+--+--+--+
|X |O |X |
+--+--+--+
|4 |O |6 |
+--+--+--+
|7 |8 |9 |
+--+--+--+
Player 1 make a move.
7
Nested if-else statement.
Calling winGame()
It's a draw!

+--+--+--+
|X |O |X |
+--+--+--+
|4 |O |6 |
+--+--+--+
|X |8 |9 |
+--+--+--+
Player 2 make a move.
8
Nested if-else statement.
Calling winGame()
It's a draw!

+--+--+--+
|X |O |X |
+--+--+--+
|4 |O |6 |
+--+--+--+
|X |O |9 |
+--+--+--+

2 个答案:

答案 0 :(得分:2)

此代码存在3个问题。

  1. 游戏循环不会在胜利时结束。
  2. 胜利确认后,胜利功能不会立即返回。
  3. 绘制条件的逻辑不正确。
  4. 这些很容易修复。

    • 在你的do-while循环中,如果WinGame == true
    • 则会中断
    • 使用return validate
    • 更改行和列胜利中的中断
    • Pass转入WinGameme函数并创建一个额外的if语句 检查是否转弯== 9

      void TicTacToe :: makeAMove(){         char move;         int turns = 1;         bool validate = true;

          do{
                  cout << "Player " << (getCurrentPlayer() + 1) << " make a move." << endl;
                  cin >> move;
      
                  if ( validMove( move ) ){
                          if ( turns > 4 ){
                                  cout << "Nested if-else statement." << endl;
      
                                  setMove( move );
                                  if (winGame(turns)==true)
                                  {
                                      break;
                                  }
                          }
                          else
                                  setMove(move);
                  }
                  else{
                          cout << "Invalid Move. Please reenter." << endl;
                          cin >> move;
                  }
      
                  DrawBoard();
                  turns++;
      
          } while ( turns <= 9 );
          cout << "Game Over" <<endl;
      

      }

    然后

    bool TicTacToe::winGame(int turns)
    {
            cout << "Calling winGame() "  << endl;
            bool validate = false;
            int k = 0;
            for ( int i = 0; i < COL; i++ )
            {
                    //check column wins
                if ( board[0][i].getMarker() == board[1][i].getMarker() &&
                     board[1][i].getMarker() == board[2][i].getMarker() &&
                     board[2][i].getMarker() != (' ')){
                            cout << "Column win " << endl;
                            validate = true;
                            break;
                    }
                    //check row wins
                     else if ( board[i][0].getMarker() == board[i][1].getMarker() &&
                               board[i][1].getMarker() == board[i][2].getMarker() && 
                               board[i][2].getMarker() !=  (' ')){
                            cout << "Row win." << endl;
                            validate = true;
                            break;
                    }
            }
    
            if( board[0][0].getMarker() == board[1][1].getMarker() && 
                board[1][1].getMarker() == board[2][2].getMarker() && 
                board[2][2].getMarker() != (' ')){
                    cout << "Diagonal 1" << endl;
                    validate = true;
            }
            else if ( board[0][2].getMarker() == board[1][1].getMarker() &&
                      board[1][1].getMarker() == board[2][0].getMarker() &&
                      board[2][0].getMarker() != (' ') ){
                    cout << "Diagonal 2 " << endl;
                    validate = true;
            }
            else
            {
                if (turns==9)
                    {
                        cout << "It's a draw!" << endl;
                        validate = true;
                    }
            }
    
            return (validate);
    } 
    

答案 1 :(得分:2)

  

它总是说它是平局,即使它不应该是平局。

原因是您的winGame函数在检测到行或列获胜者时不会立即返回。相反,如果行或列获胜,则会进行额外检查以无缘无故地检查对角线获胜者。

代码应在检测到列或行获胜者时立即返回,而不是进入对角线检查。如果代码以这种方式完成,也不需要validate变量。

如果采用更系统化的方法,只需编写3种不同的获胜方式的代码:按行,按行和按对角线,这样会更好。如果其中任何一个是获胜者,那么立即返回。

此外,在检查行,列或对角线之前检查是否首先检查标记会更快。您的代码最后会对标记进行空白检查,因此在不需要调用它时会不必要地调用getMarker

该代码说明了所提出的观点:

bool TicTacToe::winGame()
{
    char marker;

    // row check
    for ( int i = 0; i < COL; i++ )
    {
       marker = board[i][0].getMarker();  // get the initial marker
       // test if something is there
       if ( marker != ' ')
       {
          // now test the other two markers to see if they match
          if (  board[i][1].getMarker() == marker && 
                board[i][2].getMarker() == marker )
            return true;
       }
    }

    // column check
    for ( int i = 0; i < COL; i++ )
    {
       marker = board[0][i].getMarker();
       if ( marker != ' ')
       {
          if (  board[1][i].getMarker() == marker && 
                board[2][i].getMarker() == marker )
            return true;
       }
    }

    // check diagonals next
    //... (code not shown)
    return false; // if the diagonals fail
}

我没有编写代码来测试对角线,但你应该明白这个想法。行和列检查是在单独的循环中完成的(没什么特别的)。如果在这些循环的任何迭代中都有赢家,则返回值为true,表示获胜者。