Я учу C, и составил стол Tic Tac Toe.Теперь, как я могу ссылаться на отдельные ячейки? - PullRequest
2 голосов
/ 12 августа 2010

Я изучаю C, поэтому решил попробовать сделать игру Tic Tac Toe, используя в качестве таблицы ASCII-арт.

У меня еще немного ...

#include <stdio.h> 

#define WIDTH 2;

#define HEIGHT 2;

int main (int argc, char *argv[]) {

    printf("Welcome to Tic Tac Toe!\n\n");

    int width = WIDTH;
    int height = HEIGHT;

    // Make grid

    for (int y = 0; y <= height; y++) {

        for (int x = 0; x <= width; x++) {

            printf("%d%d", x, y);

            if (x != width) {
                printf("||");
            }

        }


        if (y != height) {
            printf("\n");

            for (int i = 0; i < (width + (width * 4)); i++) {
                printf("=");
            }

            printf("\n");
        } else {
            printf("\n");
        }


    }

    // Ask for user input

    printf("Please enter the cell where you would like to place an X, e.g. for example the first top left cell is '00'\n");

}

При запуске в командной строке я получаю этот вывод

Welcome to Tic Tac Toe!

00||10||20
==========
01||11||21
==========
02||12||22
Please enter the cell where you would like to place an X, e.g. for example the first top left cell is '00'

Теперь, когда я выясню, как получить ввод более чем одного символа (я знаю только, как использовать getchar() для получения отдельных символов, хотя это может работать нормально для этого примера), я бы хотел повторите цикл и поместите X для соответствующей ячейки.

Должен ли я написать функцию для печати таблицы, которая принимает аргументы, такие как 'int markerX, int markerY`, чтобы разместить X?

Как мне тогда сохранить положение маркера, чтобы я мог проверить, выиграна ли игра или нет?

Является ли мой Выбор ячейки для размещения маркера наилучшим способом запроса ввода данных пользователем для игры в командной строке?

Спасибо!

Ответы [ 4 ]

3 голосов
/ 12 августа 2010

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

Как правило, когда у вас есть двумерная сетка элементов для моделирования, простейшая модель для их представления - 2массив .Вы можете определить один из них следующим образом:

int board[WIDTH][HEIGHT]

Затем вы можете получить доступ к текущему состоянию любого элемента на доске, ссылаясь на него по его индексу (который всегда идет на 0-1 меньше, чем количество элементов вмассив, например, так:

int element = board[0][1]

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

Наконец, вам нужно реализовать цикл. while - наиболее подходящая для этого структура - она ​​циклична, пока условие не выполнится.

int shouldExit = 0;
while (shouldExit == 0) {
    printBoard();
    getPlayerInput();
    updateBoard();

    // you can set shouldExit to 1 if the game is over 
    // (someone won, or the player inputted something that indicates they want to quit.
}
1 голос
/ 12 августа 2010

Я бы создал функцию, единственной задачей которой было напечатать доску, как это (не проверено):

void board_print(const char b[3][3]) }
   int i = 1;
   printf(        "     A   B   C\n");     // NOTE: Letters on top, like a spreadsheet
   while (1) {
      printf(      "%i  %c | %c | %c\n", i, b[i][0], b[i][1], b[i][2]);
      if (++i <=3) {
          printf(  "  ---+---+---\n");
      } else {
         break;
      }
   }
}

А затем создайте доску, подобную этой:

int main(void) {
    char board[3][3] =
        {{ ' ', ' ', ' ' },
         { ' ', ' ', ' ' },
         { ' ', ' ', ' ' }};

    while (1) {
       board_print(board);
       printf("Place X at : ");

Тогда я бы создал другую функцию, вся задача которой - попытаться поместить X или O в позицию:

int board_place (char char [3] [3], маркер char, строка char, столбец char);

marker здесь будет либо «x», либо «o».

board_place может возвращать значение, которое вы можете использовать для определения общего состояния игры. Например, если board_place не может сделать перемещение, потому что в этой позиции уже есть маркер, он должен вернуть отдельный код ошибки, если строка находится вне диапазона. Это также может быть в том случае, если вы определяете, есть ли победитель (потому что текущий ход будет выигрышным (легко, поскольку вам нужно только проверить линии, в том числе текущий квадрат)), или если доска заполнена без победителя и возврата отдельные вещи для каждого из них.

Тогда ваш основной код просто решает, что делать, основываясь на возвращаемом значении board_place (выдайте сообщение об ошибке пользователю и запросите другую позицию, попробуйте сделать ход за O, поздравьте пользователя с победой, сообщите пользователю что этот кот выиграл, ...).

Что касается чтения в позиции, то здесь пользовательский интерфейс встречается с обработкой текста. Простого scanf вызова может быть достаточно, или, может быть, всего несколько вызовов getchar. Я предлагаю вам по-разному индексировать строки и столбцы (я использовал буквы и цифры), потому что это, вероятно, будет проще для большинства людей. Затем вы можете либо настроить до board_place, либо просто выполнить настройку индексов внутри board_place.

0 голосов
/ 12 августа 2010

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

Чтобы упростить задачу, вы можете написать функцию draw_table, которая рисует доску крестики-нолики, используя текущее значение ваших переменных.

Если вы используете только getch для ввода, то вы можете ссылаться на свои ячейки как 1-9 вместо использования двузначного числа. Это также может упростить отслеживание ваших переменных, вы можете назвать их cell1, cell2 и т. Д. Вы также можете использовать массив, но это может быть слишком сложно, если вы только начинаете.

0 голосов
/ 12 августа 2010

Вероятно, будет хорошей идеей сохранить ваш игровой статус в некоторой структуре данных - я бы порекомендовал двумерный массив символов, в котором хранится, поместил ли игрок 1 или 2 маркер там.

char board[WIDTH][HEIGHT];

Затем, после инициализации каждого элемента в массиве, вы можете получить доступ к маркеру с помощью

.
board[1][2]

например, если вы хотите получить маркер на 1, 2.

Теперь каждый раз, когда меняется плата, вы можете написать функцию, которая снова печатает плату, используя вложенный цикл for, как вы делали раньше, за исключением того, что теперь вы будете получать доступ к 2d массиву.

...