目录

一、五子棋的准备工作

二、五子棋的具体实现

1.棋盘

2.人机对战

2.1 玩家下棋

2.2 电脑下棋

2.3 判断输赢

三、总结


一、五子棋的准备工作

我们在写一个项目的时候,首先第一步就是应该规划一个项目应该有哪些文件,然而五子棋的代码逻辑比较简单,这里我就分了三个文件来写:

  • game.h(这个文件用来存储头文件和函数的声明),
  • game.c(这个文件用来存储具体的实现代码),
  • test.c(这个文件用来测试我们的代码)

第二步就是规划一个项目应该有哪些功能或者说有哪些机制,比如说五子棋,他可能就有人机对战,玩家下一步,电脑下一步,判断棋盘有没有一片区域是连成一块的,这些都是我们要考虑到的,并且把他们一个个封装成函数,整个逻辑就可以运行起来,下面是具体要实现的一些功能的函数并且还有相应的头文件,我都放到game.h里面了

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>//棋盘的长度和宽度
#define ROW 5
#define COL 5//初始化
void board_init(char arr[ROW][COL], int row, int col);//打印
void board_display(char arr[ROW][COL], int row, int col);//玩家下棋
void player_move(char arr[ROW][COL], int row, int col);//电脑下棋
computer_move(char arr[ROW][COL], int row, int col);//判断是否赢了
char is_win(char arr[ROW][COL], int row, int col);

二、五子棋的具体实现

1.棋盘

下五子棋,第一步就是要有一个棋盘,我们常见可能有3*3的棋盘或5*5的棋盘,用来下井字棋最合适,我本来以为我写的棋盘可能会和下面这些图一样。

但是没想到自己写的棋盘长这样,其实也还能看。

下面就是具体实现过程:

我们会发现棋盘的每一个格子是由上下两部分组成的,首先是上面部分是由两个空格加上中间的数据区域加上右边的竖杠(|),然后是下面部分是由三个减号(-)加上右边的竖杠(|),但是我们会发现我们数据区域好像一开始也是空格,那是因为在实现打印棋盘的函数之前,我先给所有区域都初始化为空格,为什么要初始化空格呢?首先初始化空格可以帮助我们占一个位置,如果你不初始化,很可能就是随机值,到时候打印出来就会很奇怪,那为什么一定要初始化空格呢?首先空格可以帮助我们占一个位置,就是把右边空格顶过去,如果你初始化为0,就不会帮你占位置,右边的空格就和左边的空格挨在一起,就会很难看,下面是初始化的代码:

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

这样我们很快就分析出,棋盘第一行是数据区域,第二行是分隔线,然后以此类推,每一行都是这样的,那我们就想先用for循环遍历第一行把数据的那一部分先打印出来,然后用第二个for循环把分割线也打印出来,但是这样就会有一个问题,我们会发现图中右边和下边多出了一行分割线。

所以我们还要加一个限制条件,当j<col-1时,我就不再打印竖杠(|),当i<row-1时,我就不再打印减号(-),具体打印棋盘实现代码如下:

//打印
void board_display(char arr[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 ", arr[i][j]);if (j < col - 1)printf("|");}printf("\n");for (j = 0; j < col; j++) {if (i < row - 1) {printf("---");if (j < col - 1)printf("|");}}if (i < row - 1)printf("\n");}
}

2.人机对战

棋盘已经有了,下一步就是人机对战,大致逻辑就是玩家走一步,电脑走一步,然后每次判断棋盘有没有已经连成一片的区域,如果有,则返回连成那一片区域里的棋子,返回*(星号)玩家胜利,返回#(井号)电脑胜利,返回q代表游戏平局,就是所有棋盘都下满了,结果还没有连成一块,就平局,如果上面三条都不符合,则返回c(continue)表示游戏继续,这就是五子棋里面的所有逻辑。

2.1 玩家下棋

玩家要怎么下棋呢?我们这个棋盘有可能是3*3或5*5,最好的方式就是利用坐标来下棋,每次让玩家输入坐标,输入一个合理的坐标,我们就在棋盘相应的位置放置一颗*(星号),当然我们必须去检查玩家输入的坐标,玩家可能好奇心上来,比如输入一个(10 10),很明显超出了棋盘范围,这时就要友好的提示一下,说玩家“输入坐标不合法,请重新输入”,很明显这里应该设置一个循环,直到玩家输入了正确的坐标,我才跳出这个循环,那我们分析完之后,这里代码就好写了,首先定义两个变量x,y,然后让玩家输入,但是玩家不知道我们这个棋盘是从0开始的,可能一开始以为是从1开始的,其实问题也不大,我们只需要一开始设置条件x>=1且x<=row且y>=1且y<=col,玩家输入的范围就只能在1到棋盘最大界限之间,然后后面给玩家输入的数字-1就行,比如玩家输入了两个数(1 1),我们程序自动为这两个数-1,并且在相应位置上放上*(星号),这样玩家就能看到具体效果了。

下面是具体实现代码:

//玩家下棋
void player_move(char arr[ROW][COL], int row, int col) {int x = 0;int y = 0;printf("玩家下棋\n");printf("请输入坐标:>");scanf("%d%d", &x, &y);while (1) {if (x >= 1 && x <= row && y >= 1 && y <= col) {if (arr[x - 1][y - 1] == ' ') {arr[x - 1][y - 1] = '*';break;}else {printf("已有旗子,请重新输入\n");}}else {printf("输入坐标不合法,请重新输入\n");}printf("玩家下棋\n");printf("请输入坐标:>");scanf("%d%d", &x, &y);}
}

2.2 电脑下棋

电脑怎么下棋呢?其实就更简单了,比玩家下的逻辑还简单一点,电脑下棋就随机下,哪里有位置,就往哪里下,首先定义x,y两个变量,并给这两个变量赋值成随机值,这个随机值范围是0到棋盘最大界限之间,这里就可以调用rand()函数,但是rand()函数的随机值的范围是0-32767,我们肯定要控制一下,看了文档之后,才知道这个函数是可以控制的,其实只需要用这个函数随机出来的值去%(取模)棋盘的最大界限值,假设棋盘的最大界限值是3,然后随机值对3取模,那得出来的结果一定是0-3之间的数,但是不包括3,这样就拿到我们想要的结果了,但是好像还是有问题,每次随机的结果竟让都是一样的。

这不是同一张图,而是我运行了两次程序,却发现每次结果都是一样的,然后我又去看了文档,之后才明白,在用这个函数之前,还要再调用一个srand()函数,才能使rand()函数,每次出来的值都是不一样的,但是srand()函数,也要传一个随机值,那这不就完了,我现在想要的就是随机值,结果你告诉我,还得传个随机值给你,其实文档解释的很清楚,只要是一直动的数字就行了,什么东西会一直动呢?那就是时间,具体来说是时间戳,时间戳就是指(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。那问题现在就简单多了,得到时间戳传给你不就完了,时间戳也有个函数叫做time(),这个函数就可以返回一个时间戳,没有参数就在括号里面写NULL,但是这个函数返回值类型是time_t,好家伙我都没见过这个类型,转到定义才发现是typedef重新定义的一个名字,但是typedef写的又是另一个类型__time64_t,好家伙更没见过了,再次转到定义,才发现就是一个int64位类型,但是srand函数的参数要一个unsigned int的类型,这就更简单了,老师讲过强制类型转换,我们只需要转换一下,这样我们的问题就都解决了。

这样每次结果都不一样,这才是我想要的,剩下就简单了,判断棋盘的格子里面是不是空格,如果是空格,则就可以落子了,不是空格,就说明这个格子被占用了,那我们就重新获取随机数,直到可以落子,然而我们发现这又是一个循环,内容都分析差不多了,代码就很容易实现了,代码如下:

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

2.3 判断输赢

玩家下棋,电脑下棋,我们都说完了,只剩下判断输赢了,如果返回*(星号),则玩家赢,如果返回#(井号),则电脑赢,如果返回q,则平局,以上情况都不满足,则返回c(continue),游戏继续。判断输赢其实很简单,五子棋,棋盘为5*5,看的就是谁能连成5个棋子,那他的情况也就那么几种,先看每一行有没有连成的棋子,再看每一列有没有连成的棋子,最后再看两条对角线,如果都没有连成5个棋子,判断棋盘是否已满,如果满了,则平局,没满则继续下棋,棋盘5*5就这么些情况,如果棋盘再大一点的话,判断东西可能就复杂了,我们先实现简单的,后面有能力再去实现复杂的。然后具体操作逻辑就是对每一行或每一列遍历,首先我会先把第一行或第一列的第一个字符先保存下来,这个字符可能是#(井号)也可能是*(星号),还可能是空格,然后我再一个一个的跟后面的字符比较,如果全部相同,则返回当前的字符,当然在比较之前一定要加条件,首先这个字符一定不能是空格,不是空格我才接着和后面的字符比较,全部相同则返回当前字符,比较之中如果有一个不相同,赶紧break,没有必要进行下一次比较了。然后后面的逻辑都是这样处理的,包括两条对角线也是这样处理的。还有个平局的逻辑没讲到,其实也很简单,创建一个函数is_full(),这个函数专门用来看棋盘满没满,如果上面四种情况都不满足,就来看棋盘有没有满,其实棋盘有没有满也很好判断,就是遍历一遍棋盘看还有没有多余的空格,如果一个空格都没有了,说明平局了,这时候我们就会返回q,游戏就平局了。如果以上五种情况都没有发生,说明游戏还没有结束,则返回c(continue),游戏继续,一直到两方有一方赢了,或者平局,游戏才会结束。整体逻辑就是这样,分析完了,就开始写代码了,代码如下:

//判断是否满了
static int is_full(char arr[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 (arr[i][j] == ' ') {return 1;}}}return 0;
}//判断是否赢了
char is_win(char arr[ROW][COL], int row, int col) {char tmp = 0;int i = 0;int j = 0;//判断是否有一行连成一片for (i = 0; i < row; i++) {tmp = arr[i][0];for (j = 1; j < col; j++) {if (tmp == arr[i][j] && tmp != ' ') {if (j == col - 1) {return tmp;}}else {break;}}}//判断是否有一列连成一片for (j = 0; j < col; j++) {tmp = arr[0][j];for (i = 1; i < row; i++) {if (tmp == arr[i][j] && tmp != ' ') {if (i == row - 1) {return tmp;}}else {break;}}}//判断左对角线是否有连成一片tmp = arr[0][0];for (i = 1; i < row; i++) {if (tmp == arr[i][i] && tmp != ' ') {if (i == row - 1) {return tmp;}}else {break;}}//判断右对角线是否有连成一片tmp = arr[0][col - 1];for (i = 0, j = col - 1; i < row; i++, j--) {if (tmp == arr[i][j] && tmp != ' ') {if (i == row - 1) {return tmp;}}else {break;}}//判断是否满了int ret = is_full(arr, row, col);if (ret == 1)return 'c';else {return 'q';}
}

全部逻辑已经写完了,剩下就是测试代码了

游戏测试完成之后,逻辑和自己想到的差不多,基本功能也实现了,基本没有什么太大的问题,可能以后有时间会再优化一下代码,或者写一些更好玩的游戏。


三、总结

其实感觉写代码挺爽的,特别是用自己学会的东西,来实现一个比较简单的小程序,这个游戏可能有200多行代码吧!我觉得挺开心的,因为可以把老师在课堂上教的东西,学以致用,这更能证明你平时有没有努力的练习,就和我讲的一样,想成功一定要多努力,努力不一定能成功,但不努力一定不会成功。上面所有代码我都会放在我的码云上,如果有兴趣可以去玩一下哟!希望大家能多多支持哟!
链接:https://gitee.com/smnhaaa/c-project.git

用C语言来实现五子棋小游戏相关推荐

  1. C语言制作一个五子棋小游戏【附代码】

    目录 五子棋游戏设计与实现 1.1 系统开发思路(需求分析) 1.2 系统功能设计 1.3 系统详细设计 1.3.1数据结构设计 1.4 系统实现 1.5 系统测试 五子棋游戏设计与实现 1.1 系统 ...

  2. c语言编写五子棋小游戏ppt,C语言实现简单五子棋小游戏

    五子棋简单功能实现,供大家参考,具体内容如下 游戏功能演示 代码如下: #include #include #include #include // 棋盘 char board[15][15]; // ...

  3. C语言——简单的五子棋小游戏开发设计

    下面展示一些 功能实现 一.菜单功能模块设计 int Menu() {system("color 3F");printf("-----------------亲,欢迎来到 ...

  4. c语言五子棋学年论文,基于c语言五子棋小游戏生本科论文.doc

    基于c语言五子棋小游戏生本科论文 五子棋小游戏 需求分析 现在有越来越多的人使用电脑,而且五子棋的受众广泛但实体棋操作较为繁琐且平时较难实现,所以电脑版的五子棋游戏应运而生.大家对于这个小游戏的需求如 ...

  5. c语言五子棋小游戏vc,C语言实现五子棋小游戏

    C语言实现五子棋小游戏 # include # include # include # include//插入输入输出头文件 # include//字符数组的函数定义的头文件 # include//s ...

  6. c语言实现五子棋游戏,C语言实现五子棋小游戏

    C语言实现五子棋小游戏 # include # include # include # include//插入输入输出头文件 # include//字符数组的函数定义的头文件 # include//s ...

  7. c语言课程设计作业五子棋,C语言课程设计之五子棋小游戏.doc

    C语言课程设计之五子棋小游戏.doc C语言课程设计 题目名称:五子棋小游戏 氺氺木木木 专 业计算机类 班 级 *班 指导教师J22 编写日期2016.05.26 目录 TOC \o "1 ...

  8. C语言---简单五子棋小游戏

    效果图如下: 设计思路: 棋盘设计为15×15格,初始状态光标在棋盘的中央,白棋先走,轮流落子,当一方连成五子或下满棋盘时,游戏结束(连成五子的一方获胜,下满棋盘为和棋).当游戏一方胜利后显示胜利信息 ...

  9. c语言五子棋对局结果存储,基于C语言五子棋小游戏总结.doc

    五子棋小游戏 需求分析 现在有越来越多的人使用电脑,而且五子棋的受众广泛但实体棋操作较为繁琐且平时较难实现,所以电脑版的五子棋游戏应运而生.大家对于这个小游戏的需求如下:首先,设计这个游戏最基本的就是 ...

最新文章

  1. Shell test 命令
  2. 服务器更改IP(公网)地址后,Program Neighborhood客户端无法连接服务器
  3. python3:语法变动 及新特性
  4. 前端学习总结——CSS布局方式之传统布局
  5. python账号密码一一对应_python模拟用户登录系统,如何两个用户输入各自的密码才能登入?...
  6. [Kaggle] Spam/Ham Email Classification 垃圾邮件分类(spacy)
  7. 安卓逆向_19( 一 ) --- APK保护策略【APP打开就崩溃 之 霸哥apk过签名校验】
  8. poj 1724ROADS(bfs和dfs做法)
  9. Docker快速搭建Oracle12c
  10. pytorch卷积模型定义
  11. c++ 之 关键字--explicit
  12. Java语言中的----条件循环
  13. 区块链 试题_区块链期末复习四
  14. 在线播放,将文件转成流媒体
  15. Visio中字体与Word中字体的对应
  16. 机器学习之PCA算法的人脸图像识别-平均脸的计算(详细操作步骤)
  17. mac brew安装/卸载
  18. 产品营销策划方案:6个创意来源
  19. react-子传父案例(汇率转换)
  20. Win11麦克风测试在哪里?Win11测试麦克风的方法

热门文章

  1. 基于Transformer实现英语-->西班牙语的翻译任务
  2. ArcGIS Engine基础(23)之布局视图工具类(地图打印设置)
  3. 疯狂动物城中英文字幕文本
  4. 【HCIA 06】 华为OSPF配置 (链路状态路由协议)
  5. 网站的架构与优化[价值十万块的课程]
  6. IT外企面试回答技巧
  7. 【校招VIP】[前端][二本][7分]简历样式符合一线校招要求
  8. 软件经验|玩转无人机全景照片——获取、制作及展示
  9. 今日份安利:提词器app用什么好?
  10. linux下安装万能播放器mplayer