【问题标题】:Creating a tic-tac-toe program using a 2-D array and functions in C使用 C 中的二维数组和函数创建井字游戏程序
【发布时间】:2018-10-30 05:21:29
【问题描述】:

在我的代码中,我总共有十个函数,我只能对其中两个进行完全编码,并且我已经设置了我的主要函数。我完全迷失了其他功能。如果您可以添加示例编码和解释,这将是一个巨大的帮助,以便我更好地理解。

这是我的代码:

#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_tableclear_table,我几乎完成了get_player1_move,但我不知道如何确保它打印出表格。

【问题讨论】:

  • 嗯,没有右括号的空函数比完整函数多。您目前正在打印表格吗? (提示:开始时,每级至少使用 4 个空格缩进,至少我发现这有助于保持逻辑清晰)。

标签: c function multidimensional-array


【解决方案1】:

很明显,您无法理解您的函数声明以及您在哪里使用过int 以及您在哪里使用过char。 (类型很重要)。

在解决任何其他问题之前,让编译器帮助您编写代码的第一件事就是启用编译器警告。这意味着至少对于 gcc/clang,添加 -Wall -Wextra 作为编译器选项(推荐:-Wall -Wextra -pedantic -Wshadow),对于 VS(cl.exe)使用 /W3 并且 -- 在编译干净之前不要接受代码警告!你的编译器会告诉你它看到有问题的代码的确切行(以及很多次列)。让编译器帮你写出更好的代码。

接下来,您使用常量SIZE 为您的board 提供维度。好的!如果你需要一个常量——#define 一个或多个——就像你一样。了解,当您定义一个常量时,它具有文件范围,可以在该文件内的任何函数中看到和使用它(或在包含定义常量的标头的任何文件中)。因此,无需将SIZE 作为参数传递给您的函数。他们知道SIZE 是什么,例如:

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

接下来,您不能像在 clear_table() 中那样重新声明 char board[row][col];。该声明从main() 中“遮蔽”了board 的声明,即您传递了一个参数,例如void clear_table (char board[][SIZE]);。 (因此建议包含-Wshadow 编译器选项以在您尝试有创意的东西时警告您......)同样适用于display_table

当您在clear_table(例如char board[row][col];)中重新声明board,然后在clear_table 中使用board,您正在更新重新声明的board,即本地 em> 到函数(因此在函数返回时被销毁),因此在 main() 中永远不会看到更改。

此外,您在 main() 中将 board 声明为类型 char,例如

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

但随后尝试将board 作为int 类型传递,例如

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

您的参数需要与您的声明类型相匹配。

通过这些简单的调整和清理您的clear_tabledisplay_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_tabledisplay_table(连同一个俗气的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

这应该可以让您继续前进。如果您还有其他问题,请告诉我。

【讨论】:

  • 你在clear table功能下说我不应该重新声明board,为什么我不需要为我的其他功能重新声明board?
  • 还有我的 get player1 move 功能怎么样?虽然不完整可以吗?我很确定这就是让玩家为“o”角色选择一个位置的方法,但是我如何将它与表格中的下划线一起打印出来?该函数是否也包含更新函数?
  • @PhilippPenalber 与 char board[row][col]; 重新声明相同的问题,但如果您验证 scanf 返回,它将设置 board[row][col]'o'
  • 如何检查是否存在连续三个“x”或“o”
  • for (int row = 0; row &lt; SIZE; row++) { int val = board[row][0]; for (int col = 1; col &lt; SIZE; col++) if (board[row][col] != val) return 0; } return 1; (如果列值不匹配,将返回 0,如果所有列值都与第一列值匹配,则返回 1)您可能会省略外部循环并直接传入要检查的 row 值。您还可以让函数在不匹配时返回-1,或者简单地返回匹配的行号(这就是我要做的)——有很多方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-03
  • 2022-01-15
  • 1970-01-01
相关资源
最近更新 更多