Создание программы крестики-нолики с использованием двумерного массива и функций на C - PullRequest
0 голосов
/ 30 октября 2018

В моем коде у меня всего десять функций, и я смог полностью закодировать только две из них, и моя основная функция полностью настроена. Другие функции, на которых я полностью потерян. Было бы очень полезно, если бы вы могли добавить пример кодирования и пояснения, чтобы я мог лучше понять.

Вот мой код:

#include <stdio.h>
#define SIZE 3

/* main function */
int main ()
{
    char board[SIZE][SIZE];
    int row, col;

    clear_table (board);
    display_table (board);

    do 
   {
        get_player1_mover (board, row, col);
        generate_player2_move (board, row, col);
    } while (check_end_of_game (board) == false);
    print_winner (board);

    return 0;
}

/* display table function */
void display_table (int board[][SIZE], int SIZE)
{
    int row, col;
    printf ("The current state of the game is:\n");
    for (row = 0; row < SIZE; row++) 
    {
        for (col = 0; col < SIZE; col++) 
        {
            char board[row][col];
            board[row][col] = '_';
            printf ("%c ", board[row][col]);
        }
        printf ("\n");
    }

}

/* clear table function */
void clear_table (int board[][SIZE], int SIZE)
{
    int row, col;
    char board[row][col];
    for (row = 0; row < SIZE; row++) {
        for (col = 0; col < SIZE; col++) {
            if (board[row][col] == 'x' || array[row][col] == 'o') {
                board[row][col] = '_';
            }
        }
    }

}

/* check table full function */
/* return True if board is full */
/* return False if board is not full */
check_table_full (int board[][SIZE], int SIZE)
{

/* update table function */
/* updates board with player moves */
/* return nothing */
void update_table (int board[][SIZE], int SIZE) 
{

/* check legal option function */
/* True if legal, False if not */
/* if move is within bounds of board or on empty cell */
check_legal_option (int board[][SIZE], int SIZE) 
{

/* generate player2(computer) move function */
/* generate a random move */
/* update board */
/* print out current state of board */
void generate_player2_move (int board[][SIZE], int SIZE) 
{

/* check three in a row function */
/* return zero if draw */
/* return one if player1 has three in a row */
/* return two if player2 has three in a row */
check_three_in_a_row (int board[][SIZE], int SIZE) 
{

/* check end of game function */
/* return True if game ended */
/* return false if game continues */
check_end_of_game (int board[][SIZE], int SIZE) 
{


/* get player 1 move function */
/* if given move is not valid get another move */
/* update board */
/* print out board */
void get_player1_move (int board[][SIZE], int SIZE) 
{
    int row, col;
    printf
        ("Player 1 enter your selection [row, col]: ");
    scanf ("%d,%d", &row, &col);
    char board[row][col];
    board[row][col] = 'o';
    printf ("The current state of the game is:\n");


/* print winner function */
void print_winner (int board[][SIZE], int SIZE) 
{

Я выполнил следующие функции: display_table, clear_table и я почти выполнил get_player1_move, но я застрял в том, как убедиться, что он печатает таблицу.

1 Ответ

0 голосов
/ 30 октября 2018

Очевидно, что вы застряли в понимании объявлений функций, где вы использовали int и где вы использовали char. (типы имеют значение).

Прежде чем обратиться к чему-либо еще, первое, что вы можете сделать, чтобы ваш компилятор помог вам с кодом, - включите предупреждения компилятора . Это означает, что как минимум для gcc / clang, добавьте -Wall -Wextra в качестве параметров компилятора (рекомендуем: -Wall -Wextra -pedantic -Wshadow), для VS (cl.exe) используйте /W3 и - не принимайте код, пока он не скомпилируется без предупреждение ! Ваш компилятор скажет вам точную строку (и много раз столбец), где он видит проблемный код. Пусть компилятор поможет вам написать лучший код.

Далее вы используете константу SIZE, чтобы указать размеры для board. Хорошо! Если вам нужна постоянная - #define одна или несколько - как у вас есть. Поймите, когда вы определяете константу, она имеет область видимости файла, ее можно увидеть и использовать в любой функции в этом файле (или в любом файле, который содержит заголовок, в котором определена константа). Таким образом, нет необходимости передавать SIZE в качестве параметра вашим функциям. Они знают, что такое SIZE, например ::1010 *

void display_table (char board[][SIZE]);
void clear_table (char board[][SIZE]);

Далее вы не можете повторно объявить char board[row][col];, как в clear_table(). Это объявление «затеняет» объявление board от main(), что вы передаете параметр, например void clear_table (char board[][SIZE]);. (таким образом, совет по включению опции компилятора -Wshadow, чтобы предупредить вас, когда вы попробуете что-то творческое ....) То же самое применимо к display_table.

Когда вы повторно декларируете board в clear_table (например, char board[row][col];) и затем используете board в clear_table, вы обновляете повторно объявленный board, то есть local к функции (и, следовательно, уничтожается при возврате функции), поэтому изменения никогда не будут видны в main().

Далее вы объявляете плату как char в main(), например,

    char board[SIZE][SIZE] = {{0}}; /* initialize all variables */

, но затем попытайтесь передать board как тип int, например,

void display_table (int board[][SIZE], int SIZE) {

Ваш параметр должен соответствовать вашему типу объявления.

С этими простыми настройками и очисткой clear_table и display_table просто немного, вы можете сделать что-то вроде:

/* display table function */
void display_table (char board[][SIZE])
{
    int row, col;
    printf ("\nThe current state of the game is:\n");
    for (row = 0; row < SIZE; row++) {
        for (col = 0; col < SIZE; col++) {
            putchar (' ');
            if (board[row][col])
                putchar (board[row][col]); /* use putchar for a single char */
            else
                putchar ('_');
        }
        putchar ('\n');
    }

}
/* clear table function */
void clear_table (char board[][SIZE])
{
    int row, col;
    // char board[row][col]; /* don't redeclare board */
                             /* your compiler should be screaming warnings */

    for (row = 0; row < SIZE; row++)
        for (col = 0; col < SIZE; col++)
            board[row][col] = '_';      /* just clear, no need to check */

}

Теперь просто убедитесь, что вы предоставили прототип функций выше main() в вашем файле, чтобы main() знал о существовании обеих функций, прежде чем они будут вызваны в main() (в качестве альтернативы вы можете просто переместить определение обеих функций выше main()). (функция должна быть объявлена ​​до того, как ее можно будет использовать - это означает, что над функцией, где она вызывается при «чтении сверху» файла)

Ваш код для обеих функций был не так уж и далек, вы просто упустили несколько деталей реализации (правил). Чтобы обеспечить рабочие clear_table и display_table (наряду с функцией cheezy diagonal_x для инициализации диагонали для всех 'x', а оставшуюся часть для 'o', вы можете сделать:

#include <stdio.h>

#define SIZE 3     /* if you need a constant, #define one (Good!) */

void display_table (char board[][SIZE]);
void clear_table (char board[][SIZE]);

/* cheezy init funciton */
void diagonal_x (char (*board)[SIZE])
{
    for (int row = 0; row < SIZE; row++)
    for (int col = 0; col < SIZE; col++)
        if (row == col)
            board[row][col] = 'x';
        else
            board[row][col] = 'o';
}

int main (void)     /* no comment needed, main() is main() */
{
    char board[SIZE][SIZE] = {{0}}; /* initialize all variables */

    clear_table (board);        /* set board to all '_' */
    display_table (board);      /* output board */

    diagonal_x (board);         /* init board to diagonal_x */
    display_table (board);      /* output board */

    /* 
    do {
        get_player1_mover (board, row, col);
        generate_player2_move (board, row, col);
    } while (check_end_of_game (board) == false);
    print_winner (board);
    */

    return 0;
}

/* display table function */
void display_table (char board[][SIZE])
{
    int row, col;
    printf ("\nThe current state of the game is:\n");
    for (row = 0; row < SIZE; row++) {
        for (col = 0; col < SIZE; col++) {
            putchar (' ');
            if (board[row][col])
                putchar (board[row][col]); /* use putchar for a single char */
            else
                putchar ('_');
        }
        putchar ('\n');
    }

}
/* clear table function */
void clear_table (char board[][SIZE])
{
    int row, col;
    // char board[row][col]; /* don't redeclare board */
                             /* your compiler should be screaming warnings */

    for (row = 0; row < SIZE; row++)
        for (col = 0; col < SIZE; col++)
            board[row][col] = '_';      /* just clear, no need to check */

}

( примечание: независимо от того, включаете ли вы '{' и '}' в циклы или условные выражения, содержащие только одно выражение, зависит только от вас. Это может помочь сделать все для вас - вплоть до вас. )

Также обратите внимание, что вы можете передать board как указатель на массив из char [SIZE], например. char (*board)[SIZE], а также char board[][SIZE], они эквивалентны.

Пример использования / Вывод

Примечание: я добавил пробел перед каждым символом на доске, чтобы сделать отображение немного более читабельным - вы можете удалить его, если хотите.

$ ./bin/checkerinit

The current state of the game is:
 _ _ _
 _ _ _
 _ _ _

The current state of the game is:
 x o o
 o x o
 o o x

Это должно помочь вам. Дайте мне знать, если у вас есть дополнительные вопросы.

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