问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

三子棋游戏开发教程:从规则到C语言实现

创作时间:
作者:
@小白创作中心

三子棋游戏开发教程:从规则到C语言实现

引用
CSDN
1.
https://blog.csdn.net/m0_63703622/article/details/141034358

本文将详细介绍如何用C语言开发一个简单的三子棋游戏。从游戏规则、设计思路到完整的代码实现,本文将带领读者一步步完成这个有趣的小项目。

1. 三子棋概述

三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是三子棋在很多时候会出现和棋的局面。

2. 设计思路

既然是棋类游戏,那么它就具有棋类一般具有的规则和落子的棋盘。从图中可以看出,三子棋是一个9宫格类型的棋盘,因此可以用一个3x3的二维数组来模拟储存落子点。此外,游戏还需要实现菜单、AI下棋和输赢的判断等功能。

可以总结出三子棋小游戏设计所需要实现的功能:

  1. 游戏菜单
  2. 初始化一个空的3x3棋盘
  3. 玩家落子
  4. 电脑落子
  5. 打印更新后的棋盘
  6. 判断输赢

为了保持代码的逻辑性和复用性,可以将代码分为以下几个模块:

  • game.c
  • game.h
  • test.c

具体内容将在后续部分详细呈现。

3. 代码实现

3.1 游戏菜单

由于三子棋游戏本身比较简单单一,因此菜单设计也相对简单,主要包含开始和退出两个选项。

3.2 初始化棋盘

棋盘的形状可以自由设计,但必须是9宫格。例如:

形状并非固定,有兴趣可以自行去设计。以一个示例棋盘为例,其中每一个格子内并非空空如也,程序的初始化时就已经将存储落子的二位数组内的每一位,即每一个方格中都初始化为一个空格‘ ’,表示此处未落子。

3.3 玩家落子

玩家落子是通过坐标形式实现的。由于棋盘是3x3的,因此可以使用横纵坐标来确定落子位置。为了方便用户输入,数组下标从0开始,但输入时最好从1开始。在已有落子的位置不可重复落子,因此需要进行判空操作。

3.4 电脑落子

电脑落子可以使用随机数实现,让电脑在九宫格内随机找一个空位落子。这需要判断棋盘空余位置,即判断二维数组中该落子的地方是否为‘ ’。

3.5 更新棋盘

每次玩家落子后和电脑落子后,都需要重新打印棋盘,显示最新的棋局情况。

3.6 判断输赢

当玩家落子或者电脑落子后,游戏可能有以下运行情况:

  1. 玩家落子后,玩家三子连线,玩家胜利,游戏结束。
  2. 电脑落子后,玩家三子连线,电脑胜利,游戏结束。
  3. 玩家或者电脑落子后,棋盘已满,平局。
  4. 玩家或者电脑落子后,棋盘未满且无一方胜出,游戏继续。

在处理游戏输赢的情况时,可以分为以下几个小过程:

  1. 当某一行连成线,一方胜出。
  2. 当某一列连成线,一方胜出。
  3. 当左上到右下的斜线连成线,一方胜出。
  4. 当右上到左下的斜线连成线,一方胜出。
  5. 以上情况均不发生,但棋盘已满,则平局。
  6. 以上情况均不发生,游戏继续。

具体实现思路如下:

  • 当某一行连成线时(返回值为连成线的棋子样式):通过两两比较,如果相等则让一个变量自增,最后判断如果等于2则表示一行连成线。
  • 当某一列连成线时(返回值为连成线的棋子样式):思路和行一样。
  • 当左上到右下的斜线连成线,即“\”时(返回值为连成线的棋子样式):
  • 当右上到左下的斜线连成线,即“/”时(返回值为连成线的棋子样式):
  • 以上情况均不发生,但棋盘已满时:
  • 以上情况均不发生:

直接返回‘C’:表示游戏继续

4. 完整代码实现

4.1 game.h

#pragma once
#define ROW 3
#define COL 3
#include <stdio.h>
#include <Windows.h>

// 初始化
void Initgame(char board[ROW][COL], int row, int col);
// 更新棋盘
void Displaygame(char board[ROW][COL], int row, int col);
// 玩家下棋
void Ourplay(char board[ROW][COL], int row, int col);
// 电脑下棋
void pcplay(char board[ROW][COL], int row, int col);
// 判断输赢
char iswin(char board[ROW][COL], int row, int col);

4.2 game.c

#include "game.h"

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

// 打印棋盘
void Displaygame(char board[ROW][COL], int row, int col)
{
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            printf(" %c ", board[i][j]);
            if (j != col-1)
            {
                printf("|");
            }
        }
        printf("\n");
        if (i != row - 1)
        {
            for (int j = 0; j < col; j++)
            {
                printf("---");
                if (j != col - 1)
                {
                    printf("|");
                }
            }
            printf("\n");
        }
    }
}

// 玩家下棋
void Ourplay(char board[ROW][COL], int row, int col)
{
    int x, y;
    while (1)
    {
        scanf_s("%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("此处已有棋子,请重新落子\n");
            }
        }
        else
        {
            printf("落子非法,请重新落子\n");
        }
    }
}

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

// 判断输赢
char iswin(char board[ROW][COL], int row, int col)
{
    // 行
    int i,j;
    for (i = 0; i < row; i++)
    {
        int flag = 0;
        for (j = 0; j < col-1; j++)
        {
            if ((board[i][j] == board[i][j + 1] && board[i][j] != ' '))
            {
                flag++;
            }
        }
        if (flag==2) return board[i][j-1];
    }

    // 列
    for (i = 0; i < col-1 ; i++)
    {
        int flag = 0;
        for (j = 0; j < row ; j++)
        {
            if ((board[j][i] == board[j+1][i] && board[j][i] != ' '))
            {
                flag++;
            }
        }
        if (flag==2) return board[j-1][i];
    }

    // 右斜(\)
    int flag=0;
    for (int i = 0; i < row-1; i++)
    {
        if ((board[i][i] == board[i + 1][i + 1] && board[i][i] != ' '))
        {
            flag++;
        }
    }
    if (flag==2) return board[0][0];

    // 左斜(/)
    flag = 0;
    j = col - 1;
    for (int i = 0; i<row-1;i++)
    {
        for (; j >= 0;)
        {
            if ((board[i][j] == board[i + 1][j - 1] && board[i][j] != ' '))
            {
                flag++;
            }
            j--;
            break;
        }
    }
    if (flag==2) return board[0][2];

    flag = 1;
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            if (board[i][j] == ' ')
            {
                flag = 0;
                break;
            }
        }
    }
    if (flag) return'Q';
    return 'C';
}

4.3 test.c

#include "game.h"

// 游戏主菜单
void menu()
{
    printf("************************\n");
    printf("********1.开始游戏******\n");
    printf("********0.退出游戏******\n");
    printf("************************\n");
}

void game(char board[ROW][COL],int row,int col)
{
    // 棋盘初始化
    Initgame(board, row, col);
    // 打印棋盘
    Displaygame(board, row, col);
    while (1)
    {
        printf("玩家回合,请输入落棋坐标=>\n");
        // 玩家下棋
        Ourplay(board, row, col);
        // 判断输赢
        char ch = iswin(board, row, col);
        if (ch == '*')
        {
            system("cls");
            printf("玩家胜利\n");
            Displaygame(board, row, col);
            break;
        }
        else if (ch == 'Q')
        {
            system("cls");
            printf("平局\n");
            Displaygame(board, row, col);
            break;
        }
        else{  }
        printf("电脑回合=>\n");
        // 电脑下棋
        pcplay(board, row, col);
        ch = iswin(board, row, col);
        if (ch == '#')
        {
            system("cls");
            printf("电脑胜利\n");
            Displaygame(board, row, col);
            break;
        }
        else if (ch == 'Q')
        {
            system("cls");
            printf("平局\n");
            Displaygame(board, row, col);
            break;
        }
        else {
            system("cls");
            Displaygame(board, row, col); }
    }
}

int main()
{
    int input = 0;
    srand((unsigned)time(NULL));
    char board[ROW][COL]={0};
    do
    {
        menu();
        printf("请输入您的选择:\n");
        scanf_s("%d", &input);
        switch (input)
        {
        case 1:
            // 游戏入口
            system("cls");
            game(board, ROW, COL);
            break;
        case 0:
            printf("游戏退出\n");
            break;
        default:
            printf("非法输入,请重新选择。\n");
            break;
        }
    } while (input);
    return 0;
}

5. 总结

本次代码虽然功能实现没什么问题,但是代码比较冗余,更待优化。在撰写本文的过程中,可能未能传达我所有的初衷与见解,这主要归咎于我个人在表达上的局限性。为此,希望每一位读者能够理解和包容。若您在阅读过程中发现任何表述不清或词不达意之处,非常欢迎您在评论区留下宝贵的问题、意见或建议。同时,对于文中涉及的代码部分,我也持开放态度接受大家的审视。如果您发现任何潜在的错误、改进空间或优化建议,请不吝赐教。我们共同的学习与讨论,将推动知识的进步与共享。

感谢你们的关注与支持,期待与你们在评论区展开更加丰富的交流与互动。

代码已上传Gitee,如有需要可以下载哦。
https://gitee.com/wang-codeplay/c-language-learning

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号