[ C语言 ] 用C语言实现小游戏 ---- 三子棋 代码 + 解析
前言
本篇文章记录了用C语言实现三子棋小游戏,主要目的是对之前C语言知识学习的巩固,联系各个知识,以及怎么样实际使用各个知识。
一、三子棋的游戏规则
玩家将会看到一个3X3的网格棋盘,默认玩家先下棋,电脑后下棋。
规定:先连成一条直线(3个棋子)的玩家获胜,行,列,对角线均可。若在棋盘下满时仍未分出胜负,则为平局
二、使用到的头文件
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
定义3*3的棋盘
#define ROW 3
#define COL 3
初始化棋盘:
void InitBoard(char board[ROW][COL],int row,int col);
打印棋盘:
void DisplayBoard(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);
判断输赢:
//玩家赢 - '*'
//电脑赢 - '#'
//平局 - 'Q'
//继续 - 'C'
char is_win(char board[ROW][COL],int row,int col);
三、游戏的测试
主函数:
int main() {test();//调用test测试函数return 0;
}
test函数:
void test() {int input = 0;srand((unsigned int)time(NULL));do {menu();printf("请选择:>");scanf("%d",&input);switch (input) {case 1:game();break; case 0:printf("退出游戏\n");break; default:printf("选择错误\n");break;}} while (input);
}
解析test函数主要构成:
i>菜单menu()函数:
void menu() {printf("******************************\n");printf("***** 1. play ********\n");printf("***** 0. exit ********\n");printf("******************************\n");}
实现效果:
ii>switch case 语句:实现了玩家通过不同输入选择实现不同的功能。
效果显示:
iii>game()函数:当玩家输入1时,跳入到游戏的实现代码之中。
void game() {// 数据存储,玩家下棋'*',电脑下棋是'#'char board[ROW][COL] = {0};//数组的内容 应该是全部空格InitBoard(board,ROW,COL);// 初始化棋盘// 打印棋盘DisplayBoard(board,ROW,COL);//下棋char ret = 0;while (1) {player_move(board, ROW, COL);DisplayBoard(board, ROW, COL);ret = is_win(board, ROW, COL);if (ret != 'C') {break;}computer_move(board, ROW, COL);DisplayBoard(board, ROW, COL);ret = is_win(board, ROW, COL);if (ret != 'C') {break;}}if (ret == '*') {printf("玩家赢\n");}else if (ret == '#') {printf("电脑赢\n");}else{printf("平局\n");}}
game()函数里面包括了:打印棋盘函数,初始化棋盘函数,玩家下棋函数,电脑下棋函数,判断输赢函数的调用,已经规定输赢的条件,具体每个函数的实现代码和问题如下。
注:最后有game()函数的逻辑顺序。
四、游戏的实现
游戏的实现逻辑:
(一)打印棋盘
我们首先实现对棋盘的打印:
我们在头文件中规定了 3行3列
#define ROW 3
#define COL 3
自定义函数DisplayBoard实现对棋盘的打印:
预期实现的棋盘模样:
我们发现里面包含了数据和分割行,实现代码:
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");}
}
(二)初始化棋盘函数
定义InitBoard()函数,主要实现代码如下:
void InitBoard(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;for (i = 0; i < row; i++) { //3行for (j = 0; j < col; j++) { // 3列board[i][j] = ' ';}}
}
初始化棋盘全为空格
(三)玩家下棋
自定义函数 player_move 实现,代码如下:
void player_move(char board[ROW][COL], int row, int col) {printf("玩家下棋:>");int x = 0;int y = 0;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("该坐标被占用,请重新输入!\n");}}else {printf("坐标非法,请重新输入!\n");}}
}
这里面包含了很多小问题和解决方案:
1:输入的坐标不在棋盘的范围内怎么办?
答:使用if else 选择语句,如果输入的坐标合法,则输入成功,如果输入的坐标不合法则会提醒“坐标非法,请重新输入!”字样。
if (x >= 1 && x <= row && y >= 1 && y <= col)
2:输入的坐标在棋盘上已被占用怎么办?
这个问题我们需要转化成这个问题解决:
i>怎么判断输入坐标被占用?
答:我们通过对选择语句if else 对改坐标进行判断,由于我们在初始化棋盘时,初始化棋盘全部为空格,如果输入坐标所对应的格子是空格,则说明未被占用,如果输入坐标所对应的格子不是空格,则说明该格子已经被占用。
if (board[x - 1][y - 1] == ' ')
ii>如何正确输入棋子?
如果输入坐标所对应的格子是空格,则可以成功输入,如果不是空格,则会else提醒玩家“该坐标被占用,请重新输入!”字样。利用while循环语句可再次输入正确的未被占用的坐标。
(四)电脑下棋
自定义函数 computer_move 实现,代码如下:
void computer_move(char board[ROW][COL], int row, int col) {int x = 0;int y = 0;printf("电脑下棋:>\n");while (1) {x = rand() % ROW; // 0 ~ 2y = rand() % COL; // 0 ~ 2if (board[x][y] == ' ') {board[x][y] = '#';break;}}
}
这里也包含了几个小问题和解决方案:
1:这里电脑的输入是随机输入,如何实现?
答:这里我们并非是真的随机值,只是利用了时间戳,由于时间在每时每刻的改变,所以在不同的时间,经过处理后的时间我们也无法知道,可当做随机值使用。这里调用了time函数,实现代码如下:
#include <time.h>
srand((unsigned int)time(NULL));
由于在这里强制转化为正整数。
2:如何控制电脑随机输入的值合法?
答:这个问题的意思是,如果不对这个随机值进行处理,那么这个值很可能超出棋盘,所以要对这个值进行控制,由于棋盘规定3行3列,数组下标由0开始,所以随机值只要在0~2之内即可。所以我们对这个随机值进行取模(取余数)处理即可解决此问题:
x = rand() % ROW; // 0 ~ 2
y = rand() % COL; // 0 ~ 2
为了区分玩家和电脑的棋子不同,在此规定
玩家使用 ' * ' , 电脑使用 ' # '
因为这里电脑输入坐标均为随机值,所以不具有判断的能力,读者可以思考一种优化算法,写出一种最快赢下比赛的算法。而不至于出现可能都已经一行出现2个棋子了,随机值可能再下到别处的情况(哈哈 人工“智障”)。
(五)判断输赢
实现代码:
char is_win(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];}//判断平局if (1 == is_full(board, row, col)) {return 'Q';}//继续return 'C';
}
游戏规定,首先完成一行或者一列或者对角线的玩家获胜,在此我们只需要进行三行,三列,对角线的判断以及平局的判断,游戏继续判断。具体是玩家赢还是电脑赢,我们在测试函数test中有规定,不同的玩家对应不同的字符,在此规定:
三行的判断:
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];}
平局的判断:
游戏规定,当棋盘下满时,还未分出胜负时,则为平局。
因此首先我们思考如何判断棋盘是否下满?
答:在这里我们通过返回值的数字来判断是否下满
自定义函数 is_full函数,具体代码:
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;
}
代码逻辑:我们通过返回值来判断棋盘是否下满,
如果未被下满,则返回值是0(return 0 )
如果下满我们将返回1(return 1)
小问题:我们如何判断是否下满?
我们遍历数组的过程中,如果发现还有空格存在,说明棋盘还没有被下满,我们立刻返回0,否则说明棋盘没有空格存在,说明已经下满,返回1.
所以我们就可以通过返回值判断平局,代码如下:
if (1 == is_full(board, row, col)) {return 'Q';}
如果返回值 == 1 说明 棋盘被下满 我们返回字符 ' Q ' (我们刚刚已经规定Q为平局)
五、game()函数
我们再次将game()函数调出进行详解:
void game() {// 数据存储,玩家下棋'*',电脑下棋是'#'char board[ROW][COL] = {0};//数组的内容 应该是全部空格InitBoard(board,ROW,COL);// 初始化棋盘// 打印棋盘DisplayBoard(board,ROW,COL);//下棋char ret = 0;while (1) {player_move(board, ROW, COL);DisplayBoard(board, ROW, COL);ret = is_win(board, ROW, COL);if (ret != 'C') {break;}computer_move(board, ROW, COL);DisplayBoard(board, ROW, COL);ret = is_win(board, ROW, COL);if (ret != 'C') {break;}}if (ret == '*') {printf("玩家赢\n");}else if (ret == '#') {printf("电脑赢\n");}else{printf("平局\n");}}
根据代码发现主要逻辑顺序:
这是game()函数内部的主要逻辑顺序,每一步所对应的函数调用和判断也均在图中显示。
六、演示
完整代码: 完整代码我放在我的Gitee仓库内,链接如下:
https://gitee.com/Yaulixingyu/c-language/tree/master/三子棋/三子棋
游戏演示:
总结
以上就是我对三棋子小游戏的实现,有兴趣的小伙伴可以对代码进行优化,可实现五子棋等,也可以对电脑下棋记性优化,使电脑不再人工“智障”。
哈哈哈~由于文章较长,感谢各位小伙伴的观看,由于本人的技术水平有待提高,如果遇到错误也请及时指正。如果各位小伙伴觉得不错的话,可以点赞关注一波~多谢多谢
下期预告:扫雷 小游戏
链接:[ C语言 ] 扫雷 ------> 用C语言实现game2_小白又菜的博客-CSDN博客
[ C语言 ] 用C语言实现小游戏 ---- 三子棋 代码 + 解析相关推荐
- 童年小游戏三子棋(C语言数组实现)
目录 认识游戏 游戏框架 游戏实现 基本构思 棋子 棋盘 下棋 判断输赢 效果展示 全部代码 游戏效果 认识游戏 三子棋是黑白棋的一种.三子棋是一种民间传统游戏,又叫九宫棋.圈圈叉叉.一条龙.井字棋等 ...
- c语言小游戏 三子棋,C语言实现简单的三子棋小游戏
学习完数组就能用C语言写出的简单小游戏: 编译器使用的为VS2013 代码分为三个部分 1.头文件 game.h 2.源文件 game.c 用来存放游戏中所有的函数 3.源文件 test.c 用来存放 ...
- C语言小游戏——三子棋
C语言 -- 三子棋 本篇主要是用二维数组和多个函数来实现三子棋游戏. 让我们先来看看这个编写这个游戏的思路:首先要打印三子棋的棋盘,然后是玩家下棋,电脑下棋,最后判断谁赢了,或者看看是否平局. 我们 ...
- 简单小游戏------三子棋
目录 前言 一.整体的逻辑 创建菜单 创建棋盘 打印棋盘 玩家下棋 电脑下棋 判断输赢 整合代码 game.c test.c game.h 总结 前言 经典数组游戏三子棋 一.整体的逻辑 1.创建菜单 ...
- 用c语言实现小游戏三子棋
小游戏之三子棋 小游戏之三子棋 三子棋的基本玩法 游戏制作思路 制作步骤 1.菜单 2.初始化棋盘 3.打印棋盘 4.玩家下棋 5.电脑下棋 6.判断胜利 完整代码 小结 三子棋的基本玩 ...
- C语言小游戏——三子棋(井字棋)
文章目录 前言 一.前期准备 二.游戏整体结构及思路 1.程序主体结构: 2.代码解读 3.完整源代码 总结 前言 相信大家小时候都玩过井字棋小游戏,拿石子在地上画或是用笔在纸上画······今天我们 ...
- C语言趣味小游戏——三子棋
全篇无任何废话,本文的解释大多数都在代码段中,所以一定要看代码,边看边学边理解. 这只是初学者入门的一个小游戏,不难懂,没有什么复杂的内容 可以先学习一下比三子棋还简单的猜数字小游戏 C语言趣味小游戏 ...
- C语言简易小游戏--三子棋
小时候,在学校和小伙伴除了互相追逐着玩闹玩游戏以外,相信很多小伙伴们也有和朋友在课堂上拿一张纸玩井字棋的美好回忆.(如下图酱紫啦~) 那今天呢,我们就用C语言制作一款简易的井字棋来练习一下对代码的感觉 ...
- (超详解)C语言实现小游戏三子棋
目录 一,实现目标 二,整体思路 1.创立三个文件:text.c(实现测试的逻辑) ...
- 趣味益智小游戏 三子棋+五子棋 优化版(可任意选择棋盘大小)
前言 今天牛牛给大家分享的是c语言实现三子棋和五子棋游戏,初学者可能有些不理解的地方,记得私信提问哦,牛牛会一 一回答的. 目录 前言 一.游戏介绍 二.游戏设计思路 2.1 主函数测试区(test. ...
最新文章
- android按钮点击后闪退_CAD如何恢复自动崩溃、闪退的文件?
- Spring 容器(Spring 的上下文)
- Fescar TC-beigin流程
- [Java] 蓝桥杯ALGO-63 算法训练 乘法表
- Sci-Hub又又又被起诉了!这个论文免费下载网站也太难了...
- 如何查看linux 版本
- 阿里研究院安筱鹏:云计算推动企业迈向高频竞争时代
- 用C语言编程复数计算器,简单实现C++复数计算器
- 计算机图形学——游戏方向 第一章 计算机图形学概述
- 【分享】pushplus入驻集简云平台,实现无代码集成数百款应用
- linux weblogic 内存溢出,weblogic10内存溢出解决方法
- 在线视频转音频怎么弄?这几个软件建议你们收藏
- Fans没信心,回家继续修行
- 18个配色(色彩搭配)资源网站——设计师福利
- ccf-csp201912
- 瓶子破碎的最高安全楼层
- linux7 seinfo,SELinux+
- 号牌号码识别,支持新能源车牌,离线识别,喜欢就收下吧
- windows 同步其他windows时间 w32time
- axure中文语言包安装