«

C语言三子棋的实现代码怎么写

时间:2024-3-3 11:42     作者:韩俊     分类: Java


这篇文章主要介绍“C语言三子棋的实现代码怎么写”,在日常操作中,相信很多人在C语言三子棋的实现代码怎么写问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言三子棋的实现代码怎么写”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!


    一、三子棋小游戏的简单介绍

    要说大家都很熟悉的一个小游戏,三子棋算是其中一个了。相信大家都玩过三子棋小游戏,在这里我还是给大家介绍简单的游戏规则:

    • 一次只能下一个棋子;

    • 玩家下完棋子后,电脑下棋子;

    • 不能再重复的位置上下棋子;

    • 不管是玩家还是电脑,谁先达到三个棋子连接在一起的时候获胜;

    • 三个棋子的连接包括:横三个、竖三个、斜三个。

    二、三子棋的思路及代码实现

    1、打印游戏菜单

    我们实现游戏之前,应该想到先给玩家提供一个菜单。这个菜单的功能就是帮助用户选择是否要开始游戏。菜单的实现我们可以单独自定义一个函数,我们用到菜单的时候调用此函数即可。

    void meau()
    {
        printf("*********************
    ");
        printf("*****  1.play   *****
    ");
        printf("*****  0.exit   *****
    ");
        printf("*********************
    ");
    }

    通过上面的代码我们可以很容易看出,选择‘1’是开始游戏,选择‘0’是退出游戏。

    2、选择是否开始游戏

    提到选择,我们这里可以联想到switch-case语句。由上面的菜单可知:选择‘1’是开始游戏,选择‘0’是退出游戏。当然我们不能排除不小心输入错误,所以这里我们还要考虑到选择错误的情况下要给出相应的提示。当选择错误时,给出提示且重新选择,同时再把菜单打印出,提供玩家选择。那怎么实现重新选择呢?我们这里其实可以使用do-while()语句。我们先来看一下代码的实现。

    void test()
    {
        int input = 0;
        do
        {
            meau();
            printf("请选择是否要开始游戏:");
            scanf("%d", &input);
            switch (input)
            {
            case 1:
                game();  //开始三子棋游戏
                break;
            case 0:
                printf("退出游戏
    ");
                break;
            default:
                printf("选择错误
    ");
            }
        } while (input);
    }

    我们看上面的代码是放在的一个自定义的test()函数中,我们只要再主函数中调用一下即可。上面的代码很巧妙,当我们输入‘1’的时候,开始游戏。当游戏结束时,循环继续。其实是实现了一个玩完一局可以反复玩的效果。当我们输入‘0’的时候,循环结束,就是相当于结束游戏了。当我们输入错误时,循环仍然继续,再次打印菜单提供我们选择。这也是 do-while()语句的巧妙之处。

    3、创建并且初始化棋盘

    3.1、创建棋盘

    创建棋盘很简单,我们这里需要的是一个二维数组。那么棋盘的大小呢?我们首先想到的是3x3的棋盘——char board[3][3]。那要是想改成5x5的棋盘呢?我们是把整个工程中的board[3][3]改成board[5][5]吗?这样太麻烦了,当然也不现实。这里我们可以引用#define 定义的标识符常量。这时候我们可以写成char board[ROW][COL]。改变大小的时候只需要改变#define 定义的标识符常量的值就行。

    #define ROW 3
    #define COL 3
    char board[ROW][COL];

    3.2、初始化棋盘

    我们这里将初始化棋盘放在一个init_board(board, ROW, COL)函数中。为什么要初始化棋盘呢?当我们不初始化的时候,期盼中的每个位置放的是‘’。而我们想要得到的棋盘是一个空棋盘,这样的话更加有利于玩家操作下棋。空棋盘看起开也比较整洁。我们看一下初始化代码的实现。

    void init_board(char board[ROW][COL], int row, int col)
    {
        int i = 0;
        for (i = 0; i < row; i++)
        {
            int j = 0;
            for (j = 0; j < col; j++)
            {
                board[i][j] = ' ';
            }
        }
    }

    4、打印格式化棋盘

    当我们初始化完棋盘后,我们就应该把棋盘打印出来让玩家看到并且选择要下棋的位置。这里我们先来看打印棋盘。打印出来的棋盘应该格式鲜明,每个位置独立分开,而不是一片空白。我们先看一下棋盘的格式:

    3x3

    5x5

    通过上面的两个图,我们就可以建立一个大概的打印棋盘的思路了。其实我们可以把”_ _ _|_ _ _|_ _ _“看作我们要打印的第一行内容,但是要注意最后一行是” | | “。打印的思路有了,把打印棋盘内容放在print_board(board, ROW, COL)函数中。我们来看一下代码的实现。

    void print_board(char board[ROW][COL], int row, int col)
    {
        int i = 0;
        for (i = 0; i < row; i++)
        {
            int j = 0;
            for (j = 0; j < col; j++)
            {
                printf(" %c ", board[i][j]);
                if (j < col - 1)
                    printf("|");
            }
            printf("
    ");
            if (i < row - 1)
            {
                for (j = 0; j < row; j++)
                {
                    printf("---");
                    if (j < col - 1)
                        printf("|");
                }
            }
            printf("
    ");
        }
    }

    5、玩家下棋

    当我们把棋盘打印出来后,这时候就要提示玩家选择下棋了。我们采用的是坐标的形式让玩家进行选择下棋位置。这里要有几点要注意的事项

    • 玩家选择的位置就是所看到的位置,跟代码中的数组下标访问还是有所差距的;

    • 玩家输入的坐标后,要判断该坐标是否已经被占用,也就是不能重复在同一个位置上下棋;

    • 玩家输入坐标后,要判断坐标是否合法,不合法的话要给出提示,并且重新输入。

    • 当玩家输入的坐标合法后,电脑玩家进行下棋;

    • 玩家下完棋后要再次调用打印棋盘函数print_board(board, ROW, COL),使玩家更方便的观看已经下棋的位置;

    • 我们把玩家下的坐标用 &lsquo; * &rsquo; 来代表。

    我们将玩家下棋内容放在player_move(board, ROW, COL)函数中,我们来看一下玩家下棋的代码实现。

    void player_move(char board[ROW][COL], int row, int col)
    {
        int x = 0;
        int y = 0;
        printf("请选择你要下棋的坐标:");
        while (1)
        {
            scanf("%d %d", &x, &y);
            if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
            {
                if (board[x - 1][y - 1] == ' ')
                {
                    board[x - 1][y - 1] = '*';
                    break;
                }
                else
                {
                    printf("该坐标已经被占有,请重新选择:");
                }
            }
            else
            {
                printf("该坐标非法,请输入合法坐标:");
            }
        }
    }

    6、电脑下棋

    玩家下棋后,就该电脑下棋了。电脑下棋其实就是随机下棋。当然电脑下棋也是不能重复在同一个位置上下棋,且是合法的。提到随机,我们就因该联想到rand()函数和srand()函数,在这里我就不详细介绍这两个函数的使用方法了,在之前的猜数字小游戏中有详细的解释,可以去了解一下。电脑下完棋后也要调用打印棋盘函数print_board(board, ROW, COL),使玩家更方便的观看已经下棋的位置。我们把玩家下的坐标用 &lsquo; #&rsquo; 来代表。把电脑下棋代码放在computer_move(board, ROW, COL)函数中。那我们来看一下电脑下棋的代码实现。

    void computer_move(char board[ROW][COL], int row, int col)
    {
        printf("电脑下棋:
    ");
        while (1)
        {
            int x = rand() % 3;
            int y = rand() % 3;
            if (board[x][y] == ' ')
            {
                board[x][y] = '#';
                break;
            }
        }
    }

    7、判断是否玩家或者电脑赢

    其实,每当玩家或者电脑下完一次棋后,我们都需要判断一下是否有赢的。如果没有赢的,我们就进行反复下棋。如果有赢的,我们就停止下棋,并输出”玩家赢“或者”电脑赢“。我们同时还要想到是否为平局,如果为平局的话,就输出”平局“。判断输赢的函数我们定义成char is_win(board[ROW][COL], ROW, COL)。

    判断输赢函数返回值注意:

    • 我们这个判断输赢的函数是有返回值的,返回类型为char;

    • 当返回 &lsquo;*&rsquo; 时,玩家胜利;

    • 当返回 &lsquo;#&rsquo; 时,电脑胜利;

    • 当返回 &lsquo;Q&rsquo; 时,平局;

    • 当返回 &lsquo;C&rsquo; 时,游戏继续。

    当我们在编写输赢函数时,我们要注意不能数组越界访问。我们先来看一下判断输赢函数的实现。

    char is_win(char board[ROW][COL], int row, int col)
    {
        int i = 0;
        //判断行
        for (i = 0; i < row; i++)
        {
            int j = 0;
            for (j = 0; j < col; j++)
            {
                if (j == 0)
                {
                    if ((board[i][0] == board[i][1]) && (board[i][1] == board[i][2]) && (board[i][1] != ' '))
                        return board[i][0];
                }
                else if (j == 1)
                {
                    if ((board[i][0] == board[i][1]) && (board[i][1] == board[i][2]) && (board[i][1] != ' ')
                        || (board[i][1] == board[i][2]) && (board[i][2] == board[i][23]) && (board[i][1] != ' '))
                        return board[i][1];
                }
                else if (j == col - 1)
                {
                    if ((board[i][j] == board[i][j - 1]) && (board[i][j - 1] == board[i][j - 2]) && (board[i][j] != ' '))
                        return board[i][j];
                }
                else if (j == col - 2)
                {
                    if ((board[i][j] == board[i][j - 1]) && (board[i][j - 1] == board[i][j - 2]) && (board[i][j] != ' ')
                        || (board[i][j] == board[i][j - 1]) && (board[i][j] == board[i][j + 1]) && (board[i][j] != ' '))
                    return board[i][j];
                }
                else
                {
                    if ((board[i][j] == board[i][j - 1]) && (board[i][j - 1] == board[i][j - 2]) && (board[i][j] != ' ')
                        || (board[i][j] == board[i][j - 1]) && (board[i][j] == board[i][j + 1]) && (board[i][j] != ' ')
                        || (board[i][j] == board[i][j + 1]) && (board[i][j + 1] == board[i][j + 2]) && (board[i][j] != ' '))
                        return board[i][j];
                }
            }
        }
        //判断列
        int j = 0;
        for (j = 0; j < col; j++)
        {
            for (i = 0; i < row; i++)
            {
                if (i == 0)
                {
                    if ((board[0][j] == board[1][j]) && (board[1][j] == board[2][j]) && (board[1][j] != ' '))
                        return board[0][j];
                }
                else if (i == 1)
                {
                    if ((board[0][j] == board[1][j]) && (board[1][j] == board[2][j]) && (board[1][j] != ' ')
                        || (board[1][j] == board[2][j]) && (board[2][j] == board[3][j]) && (board[1][j] != ' '))
                        return board[1][j];
                }
                else if (i == row - 1)
                {
                    if ((board[i][j] == board[i - 1][j]) && (board[i - 1][j] == board[i - 2][j]) && (board[i][j] != ' '))
                        return board[i][j];
                }
                else if (i == row - 2)
                {
                    if ((board[i][j] == board[i - 1][j]) && (board[i - 1][j] == board[i - 2][j]) && (board[i][j] != ' ')
                        || (board[i][j] == board[i - 1][j]) && (board[i - 1][j] == board[i + 1][j]) && (board[i][j] != ' '))
                        return board[i][j];
                }
                else
                {
                    if ((board[i][j] == board[i + 1][j]) && (board[i + 1][j] == board[i + 2][j]) && (board[i][j] != ' ')
                        || (board[i][j] == board[i - 1][j]) && (board[i - 1][j] == board[i + 1][j]) && (board[i][j] != ' ')
                        || (board[i][j] == board[i - 1][j]) && (board[i - 1][j] == board[i - 2][j]) && (board[i][j] != ' '))
                        return board[i][j];
                }
            }
        }
        //判断主对角线
        for (i = 0; i < row; i++)
        {
            for (j = 0; j < col; j++)
            {
                if (i<row-2&&j<col-2)
                {
                    if((board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' '))
                        return board[i][j];
                }
                if (i>0&&i<row-1&&j>0&&j<col-1)
                {
                    if ((board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i - 1][j - 1] && board[i][j] != ' '))
                        return board[i][j];
                }
                if (i >1&&j>1)
                {
                    if ((board[i][j] == board[i - 1][j - 1] && board[i][j] == board[i - 2][j - 2] && board[i][j] != ' '))
                        return board[i][j];
                }
            }
        }
        //判断次对角线
        for (i = 0; i < row; i++)
        {
            for (j = 0; j < col; j++)
            {
                if (i<row-2&&j>1)
                {
                    if ((board[i][j] == board[i + 1][j - 1] && board[i][j] == board[i + 2][j - 2] && board[i][j] != ' '))
                        return board[i][j];
                }
                if (j>0&&j<col-1&&i>0&&i<row-1)
                {
                    if ((board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i + 1][j - 1] && board[i][j] != ' '))
                        return board[i][j];
                }
                if (i>1&&j<col-2)
                {
                    if ((board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i - 2][j + 2] && board[i][j] != ' '))
                        return board[i][j];
                }
            }
        }
        //判断平局
        int flag = 0;
        for (i = 0; i < row; i++)
        {
            for (j = 0; j < col; j++)
            {
                if (board[i][j] == ' ')
                    flag = 1;
            }
        }
        if (flag == 0)
            return 'Q';
        return 'C';
    }

    我们这里再看一下反复调用玩家下棋player_move(board, ROW, COL)函数和电脑下棋computer_move(board, ROW, COL)函数和打印棋盘函数print_board(board, ROW, COL)函数到终止循环的代码。反复调用这几个函数也就是实现了反复下棋的效果。如果没有赢的,我们就进行反复下棋。如果有赢的或者平局,我们就停止下棋。我们来看代码实现。

     while (1)
        {
            //玩家下棋
            player_move(board, ROW, COL);
            print_board(board, ROW, COL);
            //判断是否结束 
            // * 玩家胜利
            // # 电脑胜利
            // Q 平局
            // C 继续游戏
            ret=is_win(board, ROW, COL);
            if (ret != 'C')
                break;
            //电脑下棋
            computer_move(board, ROW, COL);
            print_board(board, ROW, COL);
            ret = is_win(board, ROW, COL);
            if (ret != 'C')
                break;
        }

    综上就是我整个三子棋游戏实现的思路了。总体来说还是比较简单的。我们把上面的代码整合一下来看。

    三、整合三子棋游戏代码

    由于代码量相对来说有一点多,所以我们就将函数的声明的定义分开,这样有利于提高代码的可读性,同时会保持一个良好的思路,且方便编写代码。

    我们将函数的声明放在单独的一个game.h的头文件,函数的实现放在一个单独的game.c源文件,函数的主方法及调用放在另一个单独的test.c源文件。

    game.h

    #include<stdio.h>
    //数组行和列的大小
    #define ROW 3
    #define COL 3
    //初始化数组 
    void init_board(char board[ROW][COL],int row,int col);
    //打印格式化数组
    void print_board(char board[ROW][COL], int row, int col);
    //玩家下棋 *
    void player_move(char board[ROW][COL], int row, int col);
    //电脑下棋 #
    void computer_move(char board[ROW][COL], int row, int col);
    //判断输赢或者平局
    char is_win(char board[ROW][COL], int row, int col);

    game.c

    #include "game.h"
    void init_board(char board[ROW][COL], int row, int col)
    {
        int i = 0;
        for (i = 0; i < row; i++)
        {
            int j = 0;
            for (j = 0; j < col; j++)
            {
                board[i][j] = ' ';
            }
        }
    }
    void print_board(char board[ROW][COL], int row, int col)
    {
        int i = 0;
        for (i = 0; i < row; i++)
        {
            int j = 0;
            for (j = 0; j < col; j++)
            {
                printf(" %c ", board[i][j]);
                if (j < col - 1)
                    printf("|");
            }
            printf("
    ");
            if (i < row - 1)
            {
                for (j = 0; j < row; j++)
                {
                    printf("---");
                    if (j < col - 1)
                        printf("|");
                }
            }
            printf("
    ");
        }
    }
    void player_move(char board[ROW][COL], int row, int col)
    {
        int x = 0;
        int y = 0;
        printf("请选择你要下棋的坐标:");
        while (1)
        {
            scanf("%d %d", &x, &y);
            if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
            {
                if (board[x - 1][y - 1] == ' ')
                {
                    board[x - 1][y - 1] = '*';
                    break;
                }
                else
                {
                    printf("该坐标已经被占有,请重新选择:");
                }
            }
            else
            {
                printf("该坐标非法,请输入合法坐标:");
            }
        }
    }
    void computer_move(char board[ROW][COL], int row, int col)
    {
        printf("电脑下棋:
    ");
        while (1)
        {
            int x = rand() % 3;
            int y = rand() % 3;
            if (board[x][y] == ' ')
            {
                board[x][y] = '#';
                break;
            }
        }
    }
    char is_win(char board[ROW][COL], int row, int col)
    {
        int i = 0;
        //判断行
        for (i = 0; i < row; i++)
        {
            int j = 0;
            for (j = 0; j < col; j++)
            {
                if (j == 0)
                {
                    if ((board[i][0] == board[i][1]) && (board[i][1] == board[i][2]) && (board[i][1] != ' '))
                        return board[i][0];
                }
                else if (j == 1)
                {
                    if ((board[i][0] == board[i][1]) && (board[i][1] == board[i][2]) && (board[i][1] != ' ')
                        || (board[i][1] == board[i][2]) && (board[i][2] == board[i][23]) && (board[i][1] != ' '))
                        return board[i][1];
                }
                else if (j == col - 1)
                {
                    if ((board[i][j] == board[i][j - 1]) && (board[i][j - 1] == board[i][j - 2]) && (board[i][j] != ' '))
                        return board[i][j];
                }
                else if (j == col - 2)
                {
                    if ((board[i][j] == board[i][j - 1]) && (board[i][j - 1] == board[i][j - 2]) && (board[i][j] != ' ')
                        || (board[i][j] == board[i][j - 1]) && (board[i][j] == board[i][j + 1]) && (board[i][j] != ' '))
                    return board[i][j];
                }
                else
                {
                    if ((board[i][j] == board[i][j - 1]) && (board[i][j - 1] == board[i][j - 2]) && (board[i][j] != ' ')
                        || (board[i][j] == board[i][j - 1]) && (board[i][j] == board[i][j + 1]) && (board[i][j] != ' ')
                        || (board[i][j] == board[i][j + 1]) && (board[i][j + 1] == board[i][j + 2]) && (board[i][j] != ' '))
                        return board[i][j];
                }
            }
        }
        //判断列
        int j = 0;
        for (j = 0; j < col; j++)
        {
            for (i = 0; i < row; i++)
            {
                if (i == 0)
                {
                    if ((board[0][j] == board[1][j]) && (board[1][j] == board[2][j]) && (board[1][j] != ' '))
                        return board[0][j];
                }
                else if (i == 1)
                {
                    if ((board[0][j] == board[1][j]) && (board[1][j] == board[2][j]) && (board[1][j] != ' ')
                        || (board[1][j] == board[2][j]) && (board[2][j] == board[3][j]) && (board[1][j] != ' '))
                        return board[1][j];
                }
                else if (i == row - 1)
                {
                    if ((board[i][j] == board[i - 1][j]) && (board[i - 1][j] == board[i - 2][j]) && (board[i][j] != ' '))
                        return board[i][j];
                }
                else if (i == row - 2)
                {
                    if ((board[i][j] == board[i - 1][j]) && (board[i - 1][j] == board[i - 2][j]) && (board[i][j] != ' ')
                        || (board[i][j] == board[i - 1][j]) && (board[i - 1][j] == board[i + 1][j]) && (board[i][j] != ' '))
                        return board[i][j];
                }
                else
                {
                    if ((board[i][j] == board[i + 1][j]) && (board[i + 1][j] == board[i + 2][j]) && (board[i][j] != ' ')
                        || (board[i][j] == board[i - 1][j]) && (board[i - 1][j] == board[i + 1][j]) && (board[i][j] != ' ')
                        || (board[i][j] == board[i - 1][j]) && (board[i - 1][j] == board[i - 2][j]) && (board[i][j] != ' '))
                        return board[i][j];
                }
            }
        }
        //判断主对角线
        for (i = 0; i < row; i++)
        {
            for (j = 0; j < col; j++)
            {
                if (i<row-2&&j<col-2)
                {
                    if((board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' '))
                        return board[i][j];
                }
                if (i>0&&i<row-1&&j>0&&j<col-1)
                {
                    if ((board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i - 1][j - 1] && board[i][j] != ' '))
                        return board[i][j];
                }
                if (i >1&&j>1)
                {
                    if ((board[i][j] == board[i - 1][j - 1] && board[i][j] == board[i - 2][j - 2] && board[i][j] != ' '))
                        return board[i][j];
                }
            }
        }
        //判断次对角线
        for (i = 0; i < row; i++)
        {
            for (j = 0; j < col; j++)
            {
                if (i<row-2&&j>1)
                {
                    if ((board[i][j] == board[i + 1][j - 1] && board[i][j] == board[i + 2][j - 2] && board[i][j] != ' '))
                        return board[i][j];
                }
                if (j>0&&j<col-1&&i>0&&i<row-1)
                {
                    if ((board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i + 1][j - 1] && board[i][j] != ' '))
                        return board[i][j];
                }
                if (i>1&&j<col-2)
                {
                    if ((board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i - 2][j + 2] && board[i][j] != ' '))
                        return board[i][j];
                }
            }
        }
        //判断平局
        int flag = 0;
        for (i = 0; i < row; i++)
        {
            for (j = 0; j < col; j++)
            {
                if (board[i][j] == ' ')
                    flag = 1;
            }
        }
        if (flag == 0)
            return 'Q';
        return 'C';
    }

    test.c

    #include "game.h"
    void game()
    {
        char ret = 0;
        srand(time(NULL));
        char board[ROW][COL];
        //初始化数组 全为空格
        init_board(board, ROW, COL);
        //打印格式化数组
        print_board(board, ROW, COL);
        while (1)
        {
            //玩家下棋
            player_move(board, ROW, COL);
            print_board(board, ROW, COL);
            //判断是否结束 
            // * 玩家胜利
            // # 电脑胜利
            // Q 平局
            // C 继续游戏
            ret=is_win(board, ROW, COL);
            if (ret != 'C')
                break;
            //电脑下棋
            computer_move(board, ROW, COL);
            print_board(board, ROW, COL);
            ret = is_win(board, ROW, COL);
            if (ret != 'C')
                break;
        }
        if (ret == '*')
            printf("恭喜玩家取得胜利!
    ");
        else if (ret == '#')
            printf("电脑取得胜利。
    ");
        else if (ret == 'Q')
            printf("平局了哦。
    ");
    }
    void meau()
    {
        printf("*********************
    ");
        printf("*****  1.play   *****
    ");
        printf("*****  0.exit   *****
    ");
        printf("*********************
    ");
    }
    void test()
    {
        int input = 0;
        do
        {
            meau();
            printf("请选择是否要开始游戏:");
            scanf("%d", &input);
            switch (input)
            {
            case 1:
                game();
                break;
            case 0:
                printf("退出游戏
    ");
                break;
            default:
                printf("选择错误
    ");
            }
        } while (input);
    }
    int main()
    {
        test();
        return 0;
    }

    标签: java

    热门推荐