当前位置:首页 > 技术 > 正文内容

使用C语言实现可扩展的多子棋游戏

访客 技术 2026年7月3日 1

项目概述

本项目基于C语言构建一个可配置的棋类游戏框架,支持三子棋、四子棋乃至任意尺寸的连珠式对弈。通过模块化设计,将核心逻辑与主控流程分离,便于后续功能拓展和维护。

代码结构设计

采用标准三文件架构,提升代码可读性与协作效率:

  • test.c:负责用户交互与游戏流程控制。
  • game.c:实现所有游戏规则与算法逻辑。
  • game.h:声明接口函数及全局常量。

核心功能实现

棋盘初始化

使用二维字符数组模拟棋盘,初始状态全部填充为空格(' '),并通过宏定义灵活控制棋盘大小。

void InitializeBoard(char board[ROW][COL], int rows, int cols) {
    for (int i = 0; i < rows; ++i)
        for (int j = 0; j < cols; ++j)
            board[i][j] = ' ';
}

棋盘可视化输出

动态生成带分隔线的网格布局,每行数据间用竖线连接,行之间添加横线分隔,增强视觉清晰度。

void RenderBoard(const char board[ROW][COL], int rows, int cols) {
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            printf(" %c ", board[i][j]);
            if (j < cols - 1) printf("|");
        }
        printf("\n");
        if (i < rows - 1) {
            for (int k = 0; k < cols; ++k) {
                printf("---");
                if (k < cols - 1) printf("|");
            }
        }
        printf("\n");
    }
}

玩家落子处理

接收用户输入的行列坐标(从1开始),转换为数组索引,并验证位置有效性与是否已被占据。

void MakePlayerMove(char board[ROW][COL], int rows, int cols) {
    int row, col;
    while (1) {
        printf("请输入落子位置(行 列): ");
        scanf("%d %d", &row, &col);
        if (row > 0 && row <= rows && col > 0 && col <= cols) {
            if (board[row-1][col-1] == ' ') {
                board[row-1][col-1] = '*';
                break;
            } else {
                printf("该位置已有棋子,请重新输入。\n");
            }
        } else {
            printf("坐标超出范围,请重新输入。\n");
        }
    }
}

AI自动走棋

利用随机数生成器在空位中选择一个有效位置,确保电脑不会重复下在同一格。

void MakeAIMove(char board[ROW][COL], int rows, int cols) {
    while (1) {
        int x = rand() % rows;
        int y = rand() % cols;
        if (board[x][y] == ' ') {
            board[x][y] = '#';
            break;
        }
    }
}

胜负判定机制

游戏状态返回值用于统一判断结果,提高代码复用性:

  • '*':玩家胜利
  • '#':AI胜利
  • 'Q':棋盘填满,平局
  • 'A':游戏继续

行与列检测

逐行/列扫描,统计连续相同非空格的数量,若达到目标长度则判定为胜。

for (int i = 0; i < rows; ++i) {
    int count = 0;
    for (int j = 0; j < cols - 1; ++j)
        if (board[i][j] == board[i][j+1] && board[i][j] != ' ')
            count++;
    if (count == cols - 1) return board[i][0];
}

对角线检测

分别检查主对角线(左上→右下)与副对角线(右上→左下)的连贯性。

// 主对角线
int diag1 = 0;
for (int i = 0; i < rows - 1; ++i)
    if (board[i][i] == board[i+1][i+1] && board[i][i] != ' ')
        diag1++;
if (diag1 == rows - 1) return board[0][0];

// 副对角线
int diag2 = 0;
for (int i = 0; i < rows - 1; ++i)
    if (board[i][cols-1-i] == board[i+1][cols-2-i] && board[i][cols-1-i] != ' ')
        diag2++;
if (diag2 == rows - 1) return board[0][cols-1];

平局判断

遍历整个棋盘,只要有空格即未结束。

int IsBoardFull(const char board[ROW][COL], int rows, int cols) {
    for (int i = 0; i < rows; ++i)
        for (int j = 0; j < cols; ++j)
            if (board[i][j] == ' ') return 0;
    return 1;
}

完整程序入口

主循环持续展示菜单,根据用户选择启动或退出游戏。

int main() {
    srand(time(NULL));
    int choice;
    do {
        printf("=== 棋类游戏 ===\n");
        printf("1. 开始游戏\n");
        printf("0. 退出\n");
        printf("请选择: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1: PlayGame(); break;
            case 0: printf("感谢游玩!\n"); break;
            default: printf("无效输入,请重试。\n"); break;
        }
    } while (choice == 1);
    return 0;
}

配置与扩展说明

只需修改头文件中的宏定义即可轻松适配不同玩法:

#define ROW 4
#define COL 4

当设置为4×4时,游戏变为"四子棋",满足连续四个同色棋子即获胜。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。