【C语言入门简单程序】三子棋——新手轻松学
目录
设计思路
功能实现
展示棋盘 Show_board
棋盘的初始化 Initial_Board
玩家下棋 Player_Move
电脑下棋 Computer_Move
判断棋局
优化与改进
判定胜出的优化
提升效率的小设计
设计思路
在设计整个程序前,我们要先思考出整个程序设计的框架,三子棋游戏的流程是什么,具体需要什么函数来实现每一步的功能。
根据经验来看,首先需要一个菜单功能来确定玩家想要进入游戏,而非误触等操作。
在进入游戏后,我们可以选择单人模式或双人模式,单机和电脑玩,设计出来和朋友一起玩。
(带一点凡尔赛性质,是不是瞬间在朋友面前就高大起来了!那就接着看下去吧!
在单机模式下,在我们出子之后,需要电脑出子,
出子完毕后需要通过当前的棋盘判断下一次落子的位置
当有三个棋子连成一条线时,判定胜利。
至此我们可以分析出来,这个游戏需要实现的功能有:玩家下棋、电脑下棋、展示棋盘、判断棋局。
功能实现
首先建立三个文件,包含相应的函数
test.c——测试
game.h——函数的声明
game.c——函数的实现
之后我们实现相应的功能。
展示棋盘 Show_board
首先我们需要对棋盘进行设计,通过打印,分割出九个格子,实现简单的可视化。
void Show_board(char board[ROW][COL], int r, int c)
{int i = 0;for (int i = 0; i < ROW; i++){for (int j = 0; j < COL; j++){printf(" %c ", board[i][j]);if(j<COL-1) printf("|");else printf("\n");}for (int k = 0; k < ROW; k++){if (i < ROW - 1){printf("---");if (k < COL - 1)printf("|");else printf("\n");}}}
}
打印后就是这个样子啦。
棋盘的初始化 Initial_Board
我们通过一个3*3的二维数组存储用户输入来实现三子棋的落子,在此之前,先对没有下过子的棋盘进行初始化。为简明起见,我们这里将数组中的每一个元素设置为空。
void Initinal_Board(char board[ROW][COL], int r, int c)
{for (int i = 0; i < r; i++){for (int j = 0; j < c; j++){board[i][j] = ' ';}}
}
玩家下棋 Player_Move
用一个字符表示玩家下棋。对于玩家来说,玩家并没有“这是用数组模拟实现的一个小游戏,而数组的下标是从零开始”的意识,为了服务用户,我们这里将用户输入的数-1后的值记为真实的坐标值。当用户输入有误时,提醒用户。
void Player_Move(char board[ROW][COL], int r, int c)
{int x = 0;int y = 0;printf("\n--------玩家的回合-------\n");printf("请输入落子的位置->x:__ y:__\n");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] = 'p';}else{printf("该位置已被占用");}}else{printf("不能下在这里!输入的坐标有误\n");}Show_board(board, ROW, COL);
}
电脑下棋 Computer_Move
这里我们仅仅实现一个傻瓜操作,电脑:哪里有空下哪里!
void Computer_Move(char board[ROW][COL], int r, int c)
{printf("\n-------电脑的回合:-------\n");Sleep(500);while (1){int x = rand() % 3;int y = rand() % 3;if (board[x][y] == ' '){board[x][y] = 'c';break;}}Show_board(board, ROW, COL);
}
判断棋局
这里比较复杂,我们需要判断棋盘是否有三子连成一条线,而三子连线可能有三种情况:行相连、列相连,对角线相连。
如果没有,查看棋盘是否为“满”的状态。
如果有三子连成一条线,判断是电脑胜出还是玩家胜出。
char is_win(char board[ROW][COL], int r, int c)
{int i = 0;//行相同for (i = 0; i < ROW; i++){if (board[i][0] == board[i][1] == board[i][2] &&board[i][0] !=' ')return board[i][0];}//列相同for (i = 0; i < ROW; i++){if (board[0][i] == board[1][i] == board[2][i]&&board[0][i]!=' ')return board[i][0];}//对角线1for (i = 0; i < ROW; i++){if (board[0][0] == board[1][1] == board[2][2]&&board[0][0]!=' ')return board[i][0];}//对角线2for (i = 0; i < ROW; i++){if (board[0][2] == board[1][1] == board[2][0] && board[0][0] != ' ')return board[i][0];}//判断平局if (is_full(board, ROW, COL) == 1){return 'Q';}return 'c';
}
优化与改进
判定胜出的优化
之前的代码仅适用于三子棋,复用性差,因此我们做一个很挫但有用的提升版本,欢迎各位佬多多指教。(这个版本的优化真的很挫,但是我尽力了)
void Judge(char board[ROW][COL], int r, int c)
{//判断行或列 是否连成x子for (int i = 0; i < r; i++){int countp1 = 0;int countc1 = 0;int countp2 = 0;int countc2 = 0;for (int j = 0; j < c; j++){if (board[i][j] == board[i][j + 1] && j + 1 < c ){if (board[i][j] == 'c') countc1++;if (board[i][j] == 'p') countp1++;}if (board[j][i] == board[j+1][i] && j+1 < r && board[i][j] != ' '){if (board[i][j] == 'c') countc2++;if (board[i][j] == 'p') countp2++;}}if (countc1 == c - 1 || countc2 == c - 1) return Player;if (countp1 == r - 1 || countp2 == r - 1) return Computer;}
//判断两条对角线for (int i = 0; i < c; i++){int countc1 = 0;int countc2 = 0;int countp1 = 0;int countp2 = 0;for (int j = 0; j < r; j++){if (i == j && board[i][j] == 'c') countc1++;if (i == j && board[i][j] == 'p') countp1++;if (i + j == r && board[i][j] == 'c') countc2++;if (i + j == r && board[i][j] == 'p') countp2++;}if (countc1 == r || countc2 == c) return Player;if (countp1 == r || countp2 == c) return Computer;}
//判断是否为“满”int count = 0;for (int i = 0; i < ROW; i++){int j = 0;for (j = 0; j < COL; j++){if (board[i][j] == ' '){return Continue;}else count++;}}if (count++ != 0) return Equal;
//接着玩return Continue;}
提升效率的小设计
使用enum定义棋局判断常量
当你不知道枚举类型到底有什么用的时候,它来了,它来了,它带着代码的易读性走来了。
使用define定义宏
#define CASE break;case
//避免因忘记break而出错
int main()
{int input = 0;srand((unsigned int)time(NULL));do {menu();printf("请选择->");scanf("%d", &input);switch (input){CASE 0:printf("退出游戏\n");CASE 1 :game();default:printf("输入错误");break;}} while (input);
}
双人模式
增设一个Player1_Move()和Player2_Move(),并修改游戏细节。
void menu()
{printf("\n");printf("*********************\n");printf("********0.EXIT*******\n");printf("****1.ONE PLAYER*****\n");printf("****2.TWO PLAYER*****\n");printf("*********************\n");printf("\n");
}
debug
在测试时发现了如下问题:在单击模式下,如果玩家输入错误,将自动延顺至电脑的回合。
解决这个问题我们只需要在玩家下棋的函数中嵌套Player_Move()
怎么样是不是很简单呢,快码起代码叫你的朋友和你一起来玩吧!
【C语言入门简单程序】三子棋——新手轻松学相关推荐
- 【C语言】通过C语言实现简单的三子棋
[C语言]通过C语言实现简单的三子棋 文章目录 [C语言]通过C语言实现简单的三子棋 前言 一.本次小小小小项目前提 二.游戏简易菜单 1.菜单打印 2.游戏菜单的逻辑执行 三.三子棋游戏 1.初始化 ...
- C语言的简单运用——三子棋
前言 学习新知识固然重要,但如何运用所学的知识解决生活中的问题更为重要.只会学而不会用,何异于纸上谈兵.那么就让我们来看看如何用C语言来实现一个简单的三子棋吧! 目录 前言 一点建议 一.游戏菜单 1 ...
- 【C语言】简单实现三子棋(井字棋)小游戏
背景 C语言学习过程中会有很多有趣的实践小程序需要大家编写,这里带给大家一个常见的三子棋小游戏的代码.如果有不足之处,还望指出,感谢浏览. 框架 这里给刚开始学习或接触C语言的小伙伴分享一点我个人的经 ...
- c语言小游戏 三子棋,C语言实现简单的三子棋小游戏
学习完数组就能用C语言写出的简单小游戏: 编译器使用的为VS2013 代码分为三个部分 1.头文件 game.h 2.源文件 game.c 用来存放游戏中所有的函数 3.源文件 test.c 用来存放 ...
- C语言实现简单游戏 三子棋
对基本C语言的知识有了一定的了解和认识,能够通过C语言编程解决一些简单的问题.使用C语言编程完成一个简单的游戏<三子棋>. 游戏简介:常见的3x3棋盘,有两名游戏玩家,在本版本中实现的效果 ...
- C语言 小游戏 电脑大概率获胜,用C语言实现简单的三子棋小游戏
三子棋问题即在3 * 3的二维数组上下棋,只要有棋子在行.列或对角线连成一线即取得胜利. 可实现玩家与电脑对弈. 说明 : (1)本游戏玩家输入的是棋盘的坐标. (2)"X"代表玩 ...
- 【C语言入门游戏】三子棋的实现———【保姆级教学】
目录 1.何为三子棋,三子棋的规则如何? 2. 游戏的整体框架 2.1 创建游戏菜单 test.c game.h 编辑 2.2 初始化棋盘 game.c 2.3 打印棋盘 2.4 玩家下棋 2.5 ...
- C语言实现简单的三子棋小游戏(童年游戏)
⭐️前面的话⭐️
- C语言实战项目1——三子棋(可转变为N子棋)
文章目录 前言 一.三子棋实现步骤 1.什么是三子棋? 2.C语言实现逻辑 3.函数实现 二.源代码 1.头文件 2.函数实现 3.主函数 总结 前言 学习就是一个总结以及融汇贯通的的过程,适当的对知 ...
最新文章
- shell输出没有换行符
- java对多态的理解_对于Java中多态的理解
- 蓝桥杯入门训练Fibonacci数列
- Java新职篇:一维数组
- 事业单位计算机岗位考公基吗,江苏事业单位统考考公基吗
- 分裂 BZOJ2064 状压DP
- [20150228]Delayed Block Cleanout 2.txt
- 资源下载的终极利器-资源轻松简单下载-资源万能下载法
- 数据:FIT2CLOUD飞致云连续进入云管理软件市场权威研究报告
- MVC3.0+knockout.js+Ajax 实现简单的增删改查
- 【python实战】制作微信动态名片
- 非网络打印机/扫描仪无线解决方案
- 自建私有云与公有云托管对比_云托管:利与弊
- Android软件开发面试题,安卓面试题库
- 回收站清空了怎么恢复?快来get实用方法!
- 上手Fragment
- php网页制作代码_如何制作一个简单的HTML登录页面(附代码)
- linux实验二文件与文件夹操作
- 孕妇不能吃哪些食物?(协和妇产权威版)
- 咕泡P6:ElasticStack高级开发与架构(实战班)二期