Как я могу завершить цикл, когда каждая строка и столбец на доске с крестиком 3х3 заполнены буквами X и O? - PullRequest
0 голосов
/ 11 июля 2019

Поэтому я прошу пользователя ввести X и O после того, как доска Tic Tac Toe полностью заполнена X и O. Я хочу, чтобы программа завершилась и не продолжала запрашивать ввод значений в доску после того, как они уже были заполнены.Итак, я сделал целочисленную переменную count и установил ее на 0. После того, как каждому игроку предлагается ввести либо X, либо O, я хочу, чтобы он увеличивал каждый раунд, и как только счет стал равным 10, я хочу, чтобы он вырвался целиком.из цикла do while и завершения функции.Но это, кажется, не работает и продолжает просить пользователя ввести X и O.Любые предложения будут полезны, спасибо.

void CreateBoard(int m, int n, char board[][n])
{
    int i, j, position;
    int count = 0;
    do {
        SCAN:
        printf("Enter the number of the cell you want to insert X or O or enter -1 to exit: \n");
        scanf("%d", &position);

        if(position < 0){
            break;
        }
        if(position > 9){
            goto SCAN;
        }

        printf("Type X or O: \n");

        switch(position)
        {
            case 1: scanf(" %c", &board[0][0]); break;
            case 2: scanf(" %c", &board[0][1]); break;
            case 3: scanf(" %c", &board[0][2]); break;
            case 4: scanf(" %c", &board[1][0]); break;
            case 5: scanf(" %c", &board[1][1]); break;
            case 6: scanf(" %c", &board[1][2]); break;
            case 7: scanf(" %c", &board[2][0]); break;
            case 8: scanf(" %c", &board[2][1]); break;
            case 9: scanf(" %c", &board[2][2]); break;
        }

        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
            printf("%c ", board[i][j]);
            if (j != 2)
                printf(" | ");
            }      
            if (i != 2)
                printf("\n------------");
            printf("\n");
        }

        count++;

        if(count == 10){
            break;
        }
    }while(position != -1);

}

Ответы [ 2 ]

0 голосов
/ 11 июля 2019

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

Использование goto

Сначала используется ключевое слово goto. Обычно считается плохой практикой использовать его в цикле, как у вас. Вам лучше не использовать его, а использовать другую условную структуру. Например ( см. Здесь ),

// See it in action here https://ideone.com/xM15y8
do
{
    printf("Enter the number of the cell y....");
    scanf("%d", &position);
    const bool input_is_valid = (position == -1) || ((position > 0) && (position < 10));
    if (input_is_valid)
        break;
    printf("\nInput invalid, try again\n"); 
} while(true);

Я добавил проверку ввода нуля, поскольку это также неверный ввод в вашу программу, насколько я вижу.

Использование scanf()

Вы можете сделать еще одно улучшение. Существует проблема с scanf() ... стандарт гласит:

... результат преобразования помещается в объект, на который указывает первый аргумент после аргумента формата, который еще не получил результат преобразования. Если этот объект не имеет подходящего типа или если результат преобразования не может быть представлен в объекте, поведение не определено ...

Таким образом, если бы пользователь набрал что-то вроде 8589934592, хотя это явно было бы довольно глупо, то невозможно сказать, что может содержать переменная position, поскольку введенное значение не может быть представлено int, потому что оно слишком велик Более безопасный способ - использовать fgets() для чтения стандартного ввода в маленький буфер, а затем использовать strtol() для анализа ввода.

Размер платы ограничен

Еще одно ограничение функции CreateBoard() заключается в том, что она принимает плату любого размера, но функция позволяет вводить только позиции 1 - 9. Оператор switch не может сделать ничего, кроме этого. С этим можно справиться двумя способами.

Индекс строки на вашей доске - это целочисленное деление zero_indexed_position/num_cols. Это переводится как (position - 1) / n.

Индекс столбца является остатком вышеупомянутого - (position - 1) % n.

Таким образом, мы могли бы написать, вместо switch ( проверено здесь ),

const int row = (position - 1) / n;
const int col = (position - 1) % n;
scanf(" %c", &board[row][col]);

Другим способом было бы индексировать плату с помощью *((int *)board + (position -1)), используя преимущества расположения массива в памяти.

0 голосов
/ 11 июля 2019

У вас возникла проблема «один за другим».

Давайте проверим это на компьютере:

Когда начинается блок do, count равен 0. В конце блока,это 1. 1 == 10?Нету.Далее.

count равно 1. В конце это 2. Является ли 2 == 10?Нету.Далее.

count равно 2. В конце концов, это 3. Является ли 3 == 10?Нету.Далее.

и т. Д.до:

count равно 9. В конце концов, равно 10. Является ли 10 == 10?Да.Out.

Давайте посчитаем, сколько раз вы находитесь внутри блока: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Это 10.

Итак10 слишком много.Вы знаете исправление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...