c ++ ti c ta c toe Не int-символы, вызывающие бесконечный цикл - PullRequest
0 голосов
/ 01 апреля 2020

Попытка выполнить задание для простой игры ti c ta c toe без использования функций или чего-либо, что не было рассмотрено в нашем классе. В настоящее время все в коде приемлемо, но я продолжаю сталкиваться с бесконечной проблемой l oop, когда выбираю квадрат и использую символ, который не является числом. Любая помощь будет оценена!

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

1 голос
/ 01 апреля 2020

Если при чтении из потока возникает ошибка, устанавливается флаг ошибки, и чтение невозможно, пока вы не очистите флаги ошибок. Вот почему вы получаете бесконечное число l oop.

Скопировал ответ от здесь , так что мне не в чести: P

И как сказал @ PaulMcKenz ie лучше сначала прочитать его в строку, а затем выполнить необходимые проверки.

0 голосов
/ 01 апреля 2020

Как правильно указал melk, проблема в том, что флаг ошибки устанавливается, когда вы вводите неверный ввод, не позволяющий вам использовать поток до того, как вы сбросите флаг.

Другие предложили использовать строки и затем проверить вход, который будет работать довольно хорошо. Но, если вы не хотите вносить много изменений в свой код, вы можете просто объявить переменную choice типа char.

Теперь, после того как вы взяли ввод, потому что Как работает тип данных char, ваша переменная выбора будет хранить значение ASCII символа, введенного пользователем. Чтобы вместо этого хранить само значение числового значения c, вы можете выполнить этот изящный трюк:

choice -= '0';

Это использует тот факт, что в ASCII числовые символы c приходят один за другим, начиная с '0'. Так что '1' - '0' даст 1, а '5' - '0' даст 5.

Теперь остальная часть вашего кода теперь работает хорошо, так как у вас не возникнет проблем с проверкой, был ли введенный символ число между 1-9.

Хотя вам нужно сделать еще одну вещь, чтобы очистить буфер ввода sh, когда пользователь вводит неправильный выбор. Это сделано для того, чтобы сообщение об ошибке не появлялось несколько раз (по одному разу для каждого введенного символа), если пользователь вводит несколько символов.

Таким образом, ваш код должен выглядеть примерно так (я только что добавил еще две строки):

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

Отличная работа над игрой, в остальном, кстати. Отлично смотрится для консольного проекта.

0 голосов
/ 01 апреля 2020

Вы можете использовать что-то вроде

string mystr;
getline (cin,mystr);

, чтобы прочитать строку из cin в строку. После этого вы можете проверить, является ли это число, а затем получить его или, если это не так, показать ошибку.

PS: вам не следует использовать глобальные переменные, и вы должны разбить свой код на функции. Кроме того, ваш массив на один больше, чем нужно (вы выделяете пространство для 10 элементов, но вам просто нужно 9). Будьте осторожны, так как вы ошибочно начинаете индексы с 1, когда массивы начинаются с 0, что означает, что сейчас вы полностью игнорируете первый элемент. Если вы измените его, чтобы выделить 9 элементов, убедитесь, что вычитаете 1 для всех ваших индексов, чтобы они были правильными (в противном случае доступ к 9 приведет к ошибкам при доступе к элементу за пределами массива).

...