C语言之三子棋小游戏的应用
文章目录
- 前言
- 一、前期准备
- 模块化设计
- 二、框架搭建
- 三、游戏实现
- 打印棋盘
- 代码优化
- 玩家下棋
- 电脑下棋
- 判断输赢
- 四、结束
前言
三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是三子棋在很多时候会出现和棋的局面。
本篇博客就来进行讲解这个三子棋小游戏,跟着我来一起看把!(本文使用的编译器是VS2022)
一、前期准备
模块化设计
在写三子棋的时候,我们先要了解一下什么事模块化设计:
模块化程序设计是指在进行程序设计时将一个大程序按照功能划分为若干小程序模块,每个小程序模块完成一个确定的功能,并在这些模块之间建立必要的联系,通过模块的互相协作完成整个功能的程序设计方法
- 上面是百度百科的介绍,可能有同学看不懂,简单来说就是份文件写
- 在我们写一些程序的时候就会遇到一个.c文件里写很多,会显得杂乱,可读性会变的非常差,那么我们就要使用份文件来写代码,这样就会变得条理清晰,可读性强,这样是一种良好的编程习惯,那么怎么做呢?接下来看~~
- 建立一个
game.h头文件:存储行列信息,包含函数库,对函数进行声明 - 建立一个
game.c文件:实现游戏中的函数 - 建立一个
test.c文件:实现函数主体逻辑,在书写时可用此函数进行测试 - 将
game.c和test.c文件中包含#include"game.h"

二、框架搭建
创建好文件后,将game.c和test.c引入game.h,头文件的包含和函数的声明就在这里面

游戏界面:

game.h
- 这里定义一个三行三列,并且初始化,当想要变成n行m列的只需要改一下这里define定义的就行
//行
#define ROW 3
//列
#define COL 3
//初始化棋盘
void InitBoard(char board[ROW][COL],int row,int col);
- 玩家输入选择,switch处理对应逻辑,输入值顺便还可以作为循环结束的条件。
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"void menu()
{printf("\n");printf("**************************\n");printf("***** 1.play ******\n");printf("***** 0.exit ******\n");printf("**************************\n");printf("\n");
}void game()
{printf("玩游戏\n");
}int main()
{int input = 0;do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏!\n");break;default:printf("选择错误,请重新选择!\n");break;}} while (input);return 0;
}
game.h
- 在这里把需要引入的头文件写入
#pragma once
#include<stdio.h>
- 可以看到,游戏已经正常运行了,但是里面的game函数还没有实现,接下来就让我们继续往下看(完成一部分功能就运行一下看看,及时发现BUG,越早发现越容易找到BUG)
三、游戏实现
创建棋盘&初始化棋盘
game.h
void InitBoard(char board[ROW][COL],int row,int col);
test.c
void game()
{//创建棋盘char board[ROW][COL];//初始化棋盘InitBoard(board, ROW, COL);
}
game.c
- 初始化棋盘,将数组所有元素初始化为
空格
void InitBoard(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){board[i][j] = ' ';//初始化为空格}}
}
打印棋盘
game.h
打印棋盘
void DisplayBoard(char board[ROW][COL], int row,int col);
test.c
DisplayBoard(board, ROW, COL);
game.c
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;for (i = 0; i < row; i++){printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);if (i < row - 1)printf("---|---|---\n");}
}

如果我们要修改棋盘大小,行是循环出来的,但是列就写死了
代码优化
- 首先打印
空格 空格和|,要打印row行col列,这里要注意的是当col列为col-1时才打印,也就是说打印了2列| - 打印
---也是一样的,同理
game.c
void DisplayBoard(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){printf(" %c ", board[i][j]);if (j < col - 1)printf("|");}printf("\n");if (i < row - 1){for (j = 0; j < col; j++){printf("---");if (j < col - 1)printf("|");}printf("\n");}}
}
我们将ROW和COL修改成10也是可以打印的

玩家下棋
game.h
void PlayMove(char board[ROW][COL], int row, int col);
test.c
//玩家下棋
while (1)
{PlayMove(board, ROW, COL);DisplayBoard(board, ROW, COL);
}
- 玩家下棋是不是要输入坐标,那么我们就先定义x和y,首先判断玩家输入的xy坐标合法,在棋盘范围内,如果合法,就继续,否则提示
- 在玩家下棋时,需要判断是否要下的位置为
空格,是空格说明当前位置没有棋子,不是空格说明当前位置已被下棋,就提示重新下棋
game.c
void PlayMove(char board[ROW][COL], int row, int col)
{int x = 0;int y = 0;printf("玩家下棋\n");while (1){printf("请输入坐标:>");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("该坐标被占用,请输入其他坐标\n");}}else {printf("坐标非法,请重新输入\n");}}
}
电脑下棋
- 电脑下棋要进行
game.h
#include<time.h>
#include<stdlib.h>
void ComputerMove(char board[ROW][COL], int row, int col);
test.c
在main函数里,调用srand
srand((unsigned int)time(NULL));
game函数
while (1)
{//玩家下棋PlayMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//电脑随机下棋ComputerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);
}
game.c
- 电脑下棋也是同理,调用rand函数随机生成一个数
- 检测要下棋的位置是否为空格,是空格才可以下,不是空格重新生成一个随机数,重新下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{printf("电脑下棋\n");int x = 0;int y = 0;x = rand() % row;y = rand() % col;while (1){if (board[x][y] == ' '){board[x][y] = '#';break;}}
}
这个时候就可以正常下棋了,但是:没有判断输赢,下完了也不会结束,而是死循环
判断输赢
判断输赢有四种状态
- 玩家赢
- 电脑赢
- 平局
- 游戏继续
玩家赢返回
*
电脑赢返回#
平局返回Q
游戏继续返回C
game.h
char IsWin(char board[ROW][COL], int row, int col);
- 这里判断输赢的时候首先玩家下棋,进行判断有没有输赢,然后电脑下棋,如果有一方输赢了,就进行返回
test.c
char ret = 0;
while (1)
{//玩家下棋PlayMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//判断输赢ret = IsWin(board,ROW,COL);if (ret != 'C'){break;}//电脑随机下棋ComputerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);ret = IsWin(board, ROW, COL);if (ret != 'C'){break;}
}
if (ret == '*')
{printf("玩家赢\n");
}
else if (ret == '#')
{printf("电脑赢\n");
}
else
{pprintf("平局\n");
}
- 这里是进行判断棋盘输赢的逻辑
game.c
int Is_Full(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){if (board[i][j] == ' '){return 0; // 棋盘没满}}}return 1; // 棋盘满了
}char IsWin(char board[ROW][COL], int row, int col)
{int i = 0;/* 判断三行 */for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' '){return board[i][1];}}/* 判断三列 */for (i = 0; i < col; i++){if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' '){return board[1][i];}}/* 判断对角线 */if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[1][1];}if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' '){return board[1][1];}/* 判断平局 *///如果棋盘满了返回1, 不满返回0if (Is_Full(board, row, col)){return 'Q';}/* 继续 */return 'C';
}
四、结束
最后代码还是可以优化的,比如判断输赢这里是写死了,只能判断三行三列斜线,如果是多行就不能了,还有让电脑下棋智能一点,能判断玩家下棋的位置再进行下棋,这样更有可玩性!
好了,本文就到这里结束了,下一篇是扫雷小游戏!
相关文章:
C语言之三子棋小游戏的应用
文章目录 前言一、前期准备模块化设计 二、框架搭建三、游戏实现打印棋盘代码优化玩家下棋电脑下棋判断输赢 四、结束 前言 三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子&#…...
优雅处理并发:Java CompletableFuture最佳实践
第1章:引言 大家好,我是小黑,今天,小黑要和大家聊聊CompletableFuture,这个Java 8引入的强大工具。 在Java传统的Future模式里,咱们都知道,一旦开始了一个异步操作,就只能等它结束…...
熟悉HDFS常用操作
1. 利用Hadoop提供的Shell命令完成下列任务 (1)向HDFS中上传任意文本文件,如果指定的文件在HDFS中已经存在,由用户指定是追加到原有文件末尾还是覆盖原有的文件。 #检查文件是否存在./bin/hdfs dfs -test -e text.txt echo $? #结果是1 代表已存在 #根据结果判断出文件已存…...
Adobe XD是什么?探索这款创新的用户体验设计工具
Adobexd是一种基于矢量的设计工具,主要用于设计移动和Web应用程序的用户界面(UI)。与Photoshop或ilustrator等其他Adobe产品相比,它相当轻。对于对快速设计和原型迭代感兴趣的界面设计师来说,轻量级并不是一件坏事。 在早期,Adob…...
java常用应用程序编程接口(API)——ArrayList概述及使用案例
前言: 学习了ArrayList,整理下ArrayList的常用功能及基本案例。打好基础,daydayup! 如果需要了解API是什么并如何使用,可以看这篇文章。 java常用应用程序编程接口(API)——String概述及使用案…...
2024年了,Layui再战三年有问题不?
v2.9.3 2023-12-31 2023 收官。 form 优化 input 组件圆角时后缀存在方框的问题 #1467 bxjt123优化 select 搜索面板打开逻辑,以适配文字直接粘贴触发搜索的情况 #1498 Sight-wcgtable 修复非常规列设置 field 表头选项时,导出 excel 出现合计行错位的…...
消息队列-RocketMQ-概览与搭建
RocketMQ 领域模型 RockeMQ整体结构预览 RocketMQ 中的一些概念 Topic:主题,可以理解为类别、分类的概念 MessageQueue:消息队列,存储数据的一个容器(队列索引数据),默认每个 Topic 下有 4 个队…...
Vue3技术解析(小册子)
随着 Vue 3 正式版本的发布,未来 Vue 3 将会成为前端的主流框架,这个毋庸置疑。Vue 3 在使用方面会兼容部分 Vue 2.x 的特性,比如 options API。 所以,究竟是要先学习 Vue 2 打好基础,还是直接学习 Vue 3 呢ÿ…...
即将消失的五种编程语言?
1. Ruby Ruby 在 1999 年发布后立即受到程序员们的热捧,它能够快速构建应用程序的特性给程序员留下了非常深刻的印象。紧随其后,备受欢迎的 Ruby on Rails 框架于 2004 年发布,由于 Ruby 和 Rails 这两个名称在当时几乎成为了同义词…...
c++学习:STL库(框架)+字符串模板类string+vector容器+list链表
目录 stl库 常用组件包括 字符串库 字符串模板类string 头文件 最常用的字符串模板类 字符串类型 模板原型 模板的成员数据类型 模板成员函数 有些函数会有重载,可以去下面网址查看std::basic_string - cppreference.comhttps://zh.cppreference.com/w/cp…...
2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷④
2023年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷4 目录 需要竞赛软件包环境以及备赛资源可私信博主!!! 2023年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷4 模块一 …...
使用Scikit Learn 进行识别手写数字
使用Scikit Learn 进行识别手写数字 作者:i阿极 作者简介:数据分析领域优质创作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏…...
GB/T 15036-2018 实木地板检测
实木地板是指未经拼接、覆贴的单块木材直接加工而成的地板,实木地板具有脚感舒适,环保等优良的性能,在家庭装修中被广泛使用,尤其是在国内很受欢迎。 GB/T 15036-2018 实木地板测试介绍: 测试项目 测试方法 外观 G…...
基于ElementUI封装的下拉树选择可搜索单选多选清空功能
效果: 组件代码 /*** 树形下拉选择组件,下拉框展示树形结构,提供选择某节点功能,方便其他模块调用* author wy* date 2024-01-03 * 调用示例:* <tree-select * :height"400" // 下拉框中树形高度* …...
计算机网络-各层协议
大家在搞嵌入式开发的时候基本都了解过七层网络协议、五层网络协议、四层网络协议,那么今天让我们更加的深入了解一下: 历史发展介绍 OSI七层模型由ISO国际标准化组织提出的通信标准。TCP/IP四层模型是OSI七层模型的简化版,OSI在它被官方完…...
LeetCode 84:柱状图中的最大矩形
一、题目描述 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 求在该柱状图中,能够勾勒出来的矩形的最大面积。 示例 1: 输入:heights [2,1,5,6,2,3] 输出:10 解释:…...
老生重谈:大模型的「幻觉」问题
一、什么是大模型「幻觉」 大模型的幻觉问题通常指的是模型在处理输入时可能会产生一些看似合理但实际上是错误的输出,这可能是因为模型在训练时过度拟合了训练数据,导致对噪声或特定样本的过度敏感。 "大数据幻觉"指的是在处理大规模数据时…...
golang实现skiplist 跳表
跳表 package mainimport ("errors""math""math/rand" )func main() {// 双向链表///**先理解查找过程Level 3: 1 6Level 2: 1 3 6Level 1: 1 2 3 4 6比如 查找2 ; 从高层往下找;如果查找的值比当前值小 说明没有可查找的值2比1大 往当前…...
尝试OmniverseFarm的最基础操作
目标 尝试OmniverseFarm的最基础操作。本地机器作为Queue和Agent,同时在本地提交任务。 主要参考了官方文档: Farm Queue — Omniverse Farm latest documentation Farm Agent — Omniverse Farm latest documentation Farm Examples — Omniverse Far…...
第28关 k8s监控实战之Prometheus(二)
------> 课程视频同步分享在今日头条和B站 大家好,我是博哥爱运维。 这节课我们用prometheus-operator来安装整套prometheus服务 https://github.com/prometheus-operator/kube-prometheus/releases 开始安装 1. 解压下载的代码包 wget https://github.com/…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
