2015-12-19 7 views
5

OK, quindi sono incredibilmente vicino alla conclusione di questo programma. Capisco perché il mio programma non ha fatto una mossa e sono stato in grado di risolverlo, ma ora sto cercando di verificare la presenza di un vincitore. Mi rendo conto che la mia funzione winGame() dovrebbe essere in una sorta di while while do do while loop per terminare il gioco. Ma, quando stavo cercando di fare un po 'di debug per risolvere alcune cose, mi rendo conto di qualcosa di inquietante. Dice sempre che è un pareggio, anche quando non dovrebbe essere. Queste sono cose di poco conto che mi vergogno di non capire e mi piacerebbe davvero un po 'di aiuto su come posso risolvere il problema. Inoltre, so che ci dovrebbe essere un po 'di tempo mentre fai un ciclo per terminare il gioco se c'è una vittoria. Non sono sicuro di dove metterlo, quindi se hai qualche suggerimento, per favore fammelo sapere.Errori logici, verifica di un vincitore in Tic Tac Toe

* Nota che nella mia funzione di spostamento valida c'è un piccolo array, ho intenzione di renderlo un array const statico. Le mie funzioni get restituiscono il valore nel nome (ad esempio, getIval() restituisce il valore iniziale dell'oggetto cell), mentre le mie funzioni set assegnano semplicemente i valori in modo appropriato.

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); 
} 

Ecco un esempio di esecuzione del programma per il vostro riferimento.

//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 | 
+--+--+--+ 
+1

Perché non si restituisce 'true' immediatamente una volta rilevato un vincitore? Invece, stai rilevando il vincitore e invece di tornare subito, il tuo codice esegue più controlli senza motivo. – PaulMcKenzie

+0

Sono stato informato dal mio istruttore che avere più ritorni in una funzione era una cattiva pratica di programmazione. Ma dato che più persone mi stanno dicendo la stessa cosa, sto iniziando a pensare che il mio istruttore mi abbia fornito informazioni errate. Ora che lo so, lo prenderò in considerazione. Grazie per la risposta! –

risposta

2

Ci sono 3 problemi con questo codice.

  1. Il ciclo di gioco non termina con la vittoria.
  2. La funzione di vincita non ritorna non appena viene confermata la vittoria.
  3. La logica per la condizione di estrazione non è corretta.

tuttavia sono facilmente risolvibili.

  • nel do-while posto ciclo una pausa, se wingame == true
  • cambiamento le interruzioni di riga e colonna vittorie con ritorno convalidano
  • Passo si trasforma in funzione WinGameme e fare un extra if che controlla se gira == 9

    void TicTacToe :: makeAMove() { spostamento di caratteri; 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; 
    

    }

e poi

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); 
} 
2

Si dice sempre che si tratta di un pareggio, anche quando non dovrebbe essere.

Il motivo è che la funzione winGame non ritorna immediatamente al rilevamento di un vincitore di riga o colonna. Invece, se una colonna o colonna vince, vengono effettuati ulteriori controlli per verificare il vincitore della diagonale senza motivo.

Il codice deve restituire immediatamente il rilevamento di una colonna o di un vincitore di riga anziché eseguire i controlli diagonali.Non ci sarebbe nemmeno bisogno di una variabile validate se il codice fosse fatto in questo modo.

Sarebbe meglio se si adottasse un approccio più sistematico e basta scrivere il codice per i 3 diversi modi di vincere: per riga, per colonna e per diagonale. Se qualcuno di questi è vincente, torna immediatamente.

Inoltre, è più veloce controllare se c'è un marcatore prima di controllare riga, colonna o diagonali. Il tuo codice controlla l'indicatore per vuoto per ultimo, quindi inutilmente chiamando getMarker quando non è necessario chiamarlo.

Il codice illustra i punti fatti:

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 
} 

non ho scritto il codice per verificare le diagonali, ma si dovrebbe ottenere l'idea. I controlli riga e colonna vengono eseguiti in loop separati (niente di speciale). Se c'è un vincitore in qualsiasi iterazione di questi loop, il valore di ritorno è true, che indica un vincitore.

+0

Ciao, grazie per la tua risposta riflessiva, lo apprezzo davvero. Il mio istruttore mi ha detto che era una cattiva pratica di programmazione avere più ritorni in una funzione. Tuttavia, questa non è la prima volta che qualcuno mi ha informato di aggiungere altre dichiarazioni di reso. È una cosa comune da fare? –

Problemi correlati