c ++ tic tac toe非int字符导致无限循环

时间:2020-04-01 02:10:46

标签: c++ loops while-loop nested-loops

尝试完成一个简单的井字游戏的作业,而不使用函数或我们班上未涉及的任何内容。目前代码中的所有内容都是可以接受的,但是在选择一个正方形并使用非数字字符时,我一直遇到无限循环问题。任何帮助将不胜感激!

#include <iostream>
using namespace std;

int i;
char board[10];
bool gameover;
bool check_choice;
char player;
int choice = 0;
char restart;

int main()
{

do
{


    for (int i = 0; i < 10; i++) board[i] = ' ';

    bool gameover = false;
    bool check_choice = true;
    char player = 'X';

    do
    {
        // Draw game board

        cout << "+---+---+---+ \n";
        cout << "| " << board[1] << " | " << board[2] << " | " << board[3] << " |  \n";
        cout << "+---+---+---+ \n";
        cout << "| " << board[4] << " | " << board[5] << " | " << board[6] << " |  \n";
        cout << "+---+---+---+ \n";
        cout << "| " << board[7] << " | " << board[8] << " | " << board[9] << " |  \n";
        cout << "+---+---+---+ \n";

        // Win Check

        if ((board[1] == 'X' && board[2] == 'X' && board[3] == 'X') ||
            (board[4] == 'X' && board[5] == 'X' && board[6] == 'X') ||
            (board[7] == 'X' && board[8] == 'X' && board[9] == 'X') ||
            (board[1] == 'X' && board[4] == 'X' && board[7] == 'X') ||
            (board[2] == 'X' && board[5] == 'X' && board[8] == 'X') ||
            (board[3] == 'X' && board[6] == 'X' && board[9] == 'X') ||
            (board[1] == 'X' && board[5] == 'X' && board[9] == 'X') ||
            (board[3] == 'X' && board[5] == 'X' && board[7] == 'X'))
        {
            cout << "Game Over - X wins! \n";
            gameover = true;
        }

        else if ((board[1] == 'O' && board[2] == 'O' && board[3] == 'O') ||
            (board[4] == 'O' && board[5] == 'O' && board[6] == 'O') ||
            (board[7] == 'O' && board[8] == 'O' && board[9] == 'O') ||
            (board[1] == 'O' && board[4] == 'O' && board[7] == 'O') ||
            (board[2] == 'O' && board[5] == 'O' && board[8] == 'O') ||
            (board[3] == 'O' && board[6] == 'O' && board[9] == 'O') ||
            (board[1] == 'O' && board[5] == 'O' && board[9] == 'O') ||
            (board[3] == 'O' && board[5] == 'O' && board[7] == 'O'))
        {
            cout << "Game Over - O wins! \n \n";
            gameover = true;
        }
        // Draw Check

        else if ((board[1] != ' ' && board[2] != ' ' && board[3] != ' ') &&
                 (board[4] != ' ' && board[5] != ' ' && board[6] != ' ') &&
                 (board[7] != ' ' && board[8] != ' ' && board[9] != ' '))
        {
            cout << "Game Over - Draw \n \n";
            gameover = true;
        }
        else

            check_choice = true;

        while (check_choice == true)
        {
            cout << "Place " << player << " at: ";
            cin >> choice;

            if (choice > sizeof(board) || choice == 0 || choice == 10)
            {
                cout << "Invalid input! 1-9 only. \n";
                check_choice = true;
            }

            else if (board[choice] == ' ')
            {
                board[choice] = (player == 'X') ? 'X' : 'O';
                player = (player == 'X') ? 'O' : 'X';
                check_choice = false;
            }
            else
            {
                cout << "Invalid input! Position already filled. \n";
                check_choice = true;
            }
        }

    } while (gameover == false);



    cout << "Would you like to play again? (Y / N): ";
    cin >> restart;
    cin.ignore();

} while (restart == 'y' || restart == 'Y');



cout << "Thanks for playing!! \n \n";

system("pause");
return 0;
} 

3 个答案:

答案 0 :(得分:1)

当从流中读取时发生错误时,将设置一个错误标志,除非清除错误标志,否则无法再进行读取。这就是为什么您会遇到无限循环的原因。

here复制了答案,所以对我不屑一顾:P

正如@PaulMcKenzie所说,最好先将其读取为字符串,然后再进行必要的检查。

答案 1 :(得分:0)

正如麦尔克正确指出的那样,问题在于错误标志,当您输入错误时会设置该错误标志,从而阻止您在清除标志之前使用流。

其他人建议使用字符串,然后验证输入效果,效果很好。但是,如果您不想在代码中进行很多更改,则只需声明choice变量为char类型即可。

现在,在接受输入之后,由于char数据类型的工作方式,您的选择变量将存储用户输入的字符的ASCII值。要使其存储数值本身,您可以执行以下巧妙的操作:

choice -= '0';

这利用了以下事实:在ASCII中,数字字符从'0'开始一个接一个地出现。因此'1' - '0'将给出1,而'5' - '0'将给出5

现在,剩下的代码现在可以正常工作了,因为检查输入的字符是否为1到9之间的数字不会遇到任何问题。

您还需要做的一件事是,当用户输入错误的选择时刷新输入缓冲区。如果用户输入多个字符,这是为了防止错误消息多次出现(对于输入的每个字符一次)。

因此您的代码总体上应如下所示(我刚刚添加了两行):

#include <iostream>
using namespace std;

int i;
char board[10];
bool gameover;
bool check_choice;
char player;
char choice = 0; // the choice variable is now a character
char restart;

int main()
{

do
{


    for (int i = 0; i < 10; i++) board[i] = ' ';

    bool gameover = false;
    bool check_choice = true;
    char player = 'X';

    do
    {
        // Draw game board

        cout << "+---+---+---+ \n";
        cout << "| " << board[1] << " | " << board[2] << " | " << board[3] << " |  \n";
        cout << "+---+---+---+ \n";
        cout << "| " << board[4] << " | " << board[5] << " | " << board[6] << " |  \n";
        cout << "+---+---+---+ \n";
        cout << "| " << board[7] << " | " << board[8] << " | " << board[9] << " |  \n";
        cout << "+---+---+---+ \n";

        // Win Check

        if ((board[1] == 'X' && board[2] == 'X' && board[3] == 'X') ||
            (board[4] == 'X' && board[5] == 'X' && board[6] == 'X') ||
            (board[7] == 'X' && board[8] == 'X' && board[9] == 'X') ||
            (board[1] == 'X' && board[4] == 'X' && board[7] == 'X') ||
            (board[2] == 'X' && board[5] == 'X' && board[8] == 'X') ||
            (board[3] == 'X' && board[6] == 'X' && board[9] == 'X') ||
            (board[1] == 'X' && board[5] == 'X' && board[9] == 'X') ||
            (board[3] == 'X' && board[5] == 'X' && board[7] == 'X'))
        {
            cout << "Game Over - X wins! \n";
            gameover = true;
        }

        else if ((board[1] == 'O' && board[2] == 'O' && board[3] == 'O') ||
            (board[4] == 'O' && board[5] == 'O' && board[6] == 'O') ||
            (board[7] == 'O' && board[8] == 'O' && board[9] == 'O') ||
            (board[1] == 'O' && board[4] == 'O' && board[7] == 'O') ||
            (board[2] == 'O' && board[5] == 'O' && board[8] == 'O') ||
            (board[3] == 'O' && board[6] == 'O' && board[9] == 'O') ||
            (board[1] == 'O' && board[5] == 'O' && board[9] == 'O') ||
            (board[3] == 'O' && board[5] == 'O' && board[7] == 'O'))
        {
            cout << "Game Over - O wins! \n \n";
            gameover = true;
        }
        // Draw Check

        else if ((board[1] != ' ' && board[2] != ' ' && board[3] != ' ') &&
                 (board[4] != ' ' && board[5] != ' ' && board[6] != ' ') &&
                 (board[7] != ' ' && board[8] != ' ' && board[9] != ' '))
        {
            cout << "Game Over - Draw \n \n";
            gameover = true;
        }
        else

            check_choice = true;

        while (check_choice == true)
        {
            cout << "Place " << player << " at: ";
            cin >> choice;
            choice -= '0'; // added this line to convert character to number

            if (choice > sizeof(board) || choice == 0 || choice == 10)
            {
                cout << "Invalid input! 1-9 only." << std::endl;
                check_choice = true;
                fflush(stdin); // added this line to clear input buffer
            }

            else if (board[choice] == ' ')
            {
                board[choice] = (player == 'X') ? 'X' : 'O';
                player = (player == 'X') ? 'O' : 'X';
                check_choice = false;
            }
            else
            {
                cout << "Invalid input! Position already filled. \n";
                check_choice = true;
            }
        }

    } while (gameover == false);



    cout << "Would you like to play again? (Y / N): ";
    cin >> restart;
    cin.ignore();

} while (restart == 'y' || restart == 'Y');



cout << "Thanks for playing!! \n \n";

system("pause");
return 0;
}

顺便说一句,在游戏上做得很好。对于控制台项目看起来很棒。

答案 2 :(得分:-1)

您可以使用类似的

string mystr;
getline (cin,mystr);

将cin的一行读为字符串。此后,您可以检查它是否为数字,然后获取它,或者如果不是,则显示错误。

PS:您不应使用全局变量,而应将代码拆分为函数。另外,您的数组比需要的数组大一个(您正在为10个元素分配空间,但只需要9个)。请小心,因为您错误地将索引从1开始,而数组从0开始,这意味着您现在完全忽略了第一个元素。如果将其更改为分配9个元素,请确保对所有索引正确地减去1(否则,当您将9个元素移出数组边界时,将9赋值将导致错误)。

相关问题