#实现思路

首先我们要明确目的,开发一个游戏当然是为了给人玩的,所以让玩家读懂游戏是很重要的。所以在操作之前不要一昧的就开始写游戏的具体实现细节,而应该先实现游戏的菜单界面,先写出大概框架后在将具体实现细节填入对应菜单上的功能。

#关于菜单

一个游戏的菜单需要有什么功能,想必玩过一些游戏的老铁都应该有所了解。首先,我们需要暴露给玩家我们这个游戏的入口与出口,即玩家可以选择进入游戏与退出游戏。由于我们这个游戏比较简单,所以关于菜单也不必太过复杂,一个进入与一个退出即可。代码如下:

void menu() // 菜单
{printf("******************************\n");printf("***** 0.exit  1.play *********\n");printf("******************************\n");
}

#玩家选择

说完了菜单,我们就需要想想,玩家选择这个菜单上的选项后我们的程序对应要进行怎样的操作。玩家的选择有3种,除去0.exit 与1.play外,玩家还可能输入其他菜单中不存在的数字。此时我们就应该提醒玩家要重新输入选项。当玩家顺利进入游戏并且结束游戏后玩家是可以选择重复玩游戏还是选择0.exit退出游戏。上述就是我们这个程序的答题框架了,说到这了,不知道你有没有什么好的想法来实现这个框架呢?如果没有的话请在想想这几句话,开始时让玩家选择,选择错误后重新选择,并且可以重复选择。怎么样是不是一下就想到了do  while循环来实现,开始时的选择与重复选择(因为do while循环是必定会执行一次的),之后的选项可以有if语句或者用switch语句解决,此处我们采用switch语句。具体代码如下:

do {printf("请选择,你接下来的操作:\n");menu();scanf("%d", &input);switch (input){case 0:printf("退出游戏。");break;case 1:printf("开始游戏:");printf("\n");game();break;default:printf("没有此选项请重新选择!!!");break;}} while (input);

此时请注意观察while的执行条件与我们菜单的功能选项,不知你是否感觉到了我们之前为什么要把0作为退出游戏的选项而1作为进入游戏的选项呢?这是因为当玩家想结束游戏是如果选择0,此时将同时跳出while循环,不再进行选择,这让代码变得简洁。

#游戏相关功能的实现

1.游戏框架

当游戏开始时,首先展示给玩家便是一张空白的棋盘,之后玩家下棋,电脑下棋(这里采用电脑代替第二名玩家),玩家在下完后同时显示棋盘。同时在一名玩家下棋后我们也应该判断其输赢情况,而不是在两名玩家都下棋后在判断输赢,这样有可能会造成不必要的平局。具体我们要实现的函数如下:

        char board[ROW][COL] = { 0 };Init_Board(board, ROW, COL); //初始化棋盘为“ ”Display_Board( board, ROW, COL); //展示棋盘Player_Move(board, ROW, COL); //玩家下棋Display_Board(board, ROW, COL); //展示棋盘Judge_Winner(board, ROW, COL); // 判断输赢Computer_Move(board, ROW, COL); //电脑下棋Display_Board(board, ROW, COL); //展示棋盘Judge_Winner(board, ROW, COL);// 判断输赢

2.棋盘的初始化

由于我们实现的时三子棋,在这里我们便将ROW与COL初始化为3,在这里我比较推荐大家在头文件中用宏的方式定义,这样如果将来需要实现例如五子棋这类游戏时只需要修改宏与输赢的判断规则即可,就不必修改函数中的行与列了。由于棋盘本质上为一个二维数组,所以用嵌套的循环结构就能轻松解决。代码如下:

void Init_Board(char board[][COL], int row, int col)
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++)board[i][j] = ' ';}
}

3.展示棋盘

在对棋盘进行初始化后我们就需要对棋盘的结构进行规划了,大家玩过三子棋应该对三子棋的棋盘都有所了解,其本质上就是一个井字型,我们实现后的效果如下:

之后系统便会提示玩家开始下棋,这步我们稍后在谈。首先,我们可以从图中看到整个棋盘是由      |-- 构成的。对于竖杠来说如果我们选择单独打印它,那么这会对我们接下来的下棋操作起到阻碍(因为我们对于下棋的位置与竖杠的位置距离需要把控),所以我们选择将竖杠与玩家下棋的位置一同打印,那么要如何实现呢?非常简单,代码如下:

for ( j = 0; j < col; j++){printf(" %c |", board[i][j]); //打印每列的|}
printf("\n");

此时数组已用空格初始化,当然打印后记得换行方便之后打印横杠。那么对于横杆来说,因为最后一行是不需要打印横杆的,所以说打印横杠是要记得在循环条件中减去一。同时为了我们之后如果改变之前定义宏中的ROW与COL所以最好自行控制看看一个格子中大概需要多少横杆,具体实现代码如下:

if (i < row - 1){z = 0; //每次进入if判断时重置while的判断条件while (z < col) //控制每行插入多少---{printf("----");z++;}printf("\n");}

这样我们就完成了一次的横杆与竖杠的打印,那么我们要打印多少次呢?答案很显然,有多少行打印多少次,所以我们此时只需要在外面嵌套一个循环次数为ROW的循环就完成了。那么这个板块的所有代码如下:

void Display_Board(char board[][COL], int row, int col)
{int i = 0;int j = 0;int z = 0;for ( i = 0; i < row; i++){for ( j = 0; j < col; j++){printf(" %c |", board[i][j]); //打印每列的|}printf("\n");if (i < row - 1){z = 0; //每次进入if判断时重置while的判断条件while (z < col) //控制每行插入多少---{printf("----");z++;}printf("\n");}}
}

话接上文,如果我们此时将定义宏中的行与列改为10,棋盘也会随之改变,如下:

4.玩家下棋

棋盘打印完成后,我们玩家就可以开始下棋的操作了,因为考虑到玩游戏的玩家也许并不是程序员所以我们下棋的的第一行就为第一行而不是第零行了。那么玩家下棋需要考虑那些因素呢?首先,当然是玩家输入的坐标应该合法,其次玩家输入的坐标不应该占用电脑或者自身已经输入过的坐标。此时我们依然需要让玩家优先输入一个坐标然后我们才去判断其坐标的合理性,怎么样这是不是和上文中提到的菜单中的玩家选择的思路相同?所以我们依然需要依赖于do while循环去完成这个功能。代码如下:

void Player_Move(char board[][COL], int row, int col)
{int x = 0;int y = 0;printf("玩家下棋:");do {scanf("%d %d", &x, &y);if (board[x - 1][y - 1] == ' ') //因为玩家可能不是程序员,不了解数组第一行为0所以我们减去1,使其输入1是为第0行{board[x - 1][y - 1] = '*';break;}elseprintf("该坐标被占用,请重新输入!!\n");}while(x <= 1 || x >= row || y >= col || y <= 1 || board[x - 1][y - 1] == '#');//判断坐标的合理性}

5.电脑下棋

玩家下棋之后便轮到了电脑下棋,那么对于电脑下棋我们应该如何去实现呢?其实很简单,我们只需要使用随机数就能很好的解决这个问题,因为我们的棋盘为3*3,所以随机值的大小不应超过3.虽然此时电脑下棋经过我们的控制后并不会发生越界,但它依然存在着一个问题,那就是因为由于电脑下棋是随机的,它并不知道那个坐标已经被下过了,所以我们此时就需要利用循环来让它不断的选择位置,直到选到正确的位置后跳出。具体代码如下:

void Computer_Move(char board[][COL], int row, int col)
{int x;int y;printf("电脑下棋:\n");while (1){x = rand_x;y = rand_y;if (board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = '#';break;}}
}

同样的,随机数的值也在头文件的宏中定义,方便以后更改。

6.判断输赢

玩家下棋与电脑下棋我们都已经搞定了,最后只需完成判断输赢的功能这个游戏就完成了。

根据我们玩游戏的经验不难得出判断输赢中存在3个可能,分别为电脑赢,玩家赢,平局。

其中电脑赢与玩家赢是有胜者的情况,为了简化代码我们只需在有胜者的情况下返回一个符号作为判断即可。例如,此时我们以返回‘*’ 为 玩家赢,返回‘#’为电脑赢。那么判断胜利的条件有哪些呢?分别为行满,列满与对角线满这三种情况,只要这三种情况中有一种实现并且满格的符号相等且不为我们初始化的空格那么即可认为此时有胜者。具体代码如下:

int i = 0;//行for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')return board[i][0];}//列for (i = 0; i < col; i++){if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')return board[0][i];}//对角线if ((board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][i] != ' ') )return board[0][0];if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')return board[0][2];

注意返回的元素其实是随意的,因为它们都相等。说完了有胜者的情况,我们来谈谈平局的情况。平局的情况当然是棋盘中已经没有空格元素并且不存在上述的胜利情况,所以我们只需要用两个循环去遍历这个二维数组判断其是否有空格即可,具体代码如下:

int is_full(char board[][COL], int row, int col)
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){if (board[i][j] == ' ')return 0;}}return 1;
}
if (is_full(board, row, col) == 1){return 'Q';}elsereturn 'C';

当有空格时返回0,此时if语句将会返回‘C’(continue)表示游戏还没有胜者游戏继续,当返回1时即代表返回‘Q’(quit)游戏结束。同时注意is_full函数可以与Judge_Winner这个函数写在同一个.c文件下并不用在头文件中声明,因为此函数只是在该.c文件下作为一个判断函数使用并不需要暴露。虽然我们说返回某些符号时游戏会有不同的情况,那么这些情况时如何实现的呢?很简单,我们只需要在游戏框架中稍加一些判断即可,代码如下:

void game()
{char board[ROW][COL] = { 0 };Init_Board(board, ROW, COL); //初始化棋盘为“ ”Display_Board( board, ROW, COL); //展示棋盘while (1){Player_Move(board, ROW, COL); //玩家下棋Display_Board(board, ROW, COL); //展示棋盘ret = Judge_Winner(board, ROW, COL); // 判断输赢if (ret != 'C')break;Computer_Move(board, ROW, COL); //电脑下棋Display_Board(board, ROW, COL); //展示棋盘ret = Judge_Winner(board, ROW, COL);// 判断输赢if (ret != 'C')break; }if (ret == '*')printf("玩家win!\n");else if (ret == '#')printf("电脑win!\n");elseprintf("平局。\n");}

其中ret为声明的字符型全局变量,并且当返回值等于‘’C(continue)时则循环继续,继续游戏,当为‘Q’或者‘*’或者‘#’即判断胜者还是平局。

#写在最后

好了,到这整个游戏的实现就已经完成了,以下这个来链接中即可找到整个游戏的源码,日期为21.11.7

https://gitee.com/ye-yukun/test.git

三子棋的实现(C语言)相关推荐

  1. 呆头呆脑的电脑----三子棋小游戏(C语言版)

    目录 1.需求分析 2.程序架构 3.代码实现(分函数呈现) (1)主函数代码实现 分析: 异常处理: (2)菜单函数的实现 分析: (3)游戏函数的实现 分析: (4)棋盘的初始化 分析: (5)棋 ...

  2. java三子棋人机游戏_C语言编程入门游戏《三子棋》

    经过C语言初级阶段的系统学习,对基本C语言的知识有了一定的了解和认识,能够通过C语言编程解决一些简单的问题.本次完成一个简单的游戏<三子棋>. 游戏简介:常见的3x3棋盘,有两名游戏玩家, ...

  3. 三子棋游戏实现(c语言)

    我们想要完成一个真正的项目,我们需要先创建一个(test.c)文件存放主函数部分:再创建一个(game.c)文件去完成游戏的基本逻辑:最后,用(game.h)文件来包含我们使用的头文件. 一.三子棋游 ...

  4. 三子棋 java_用C语言实现三子棋游戏(上)

    先上代码: #include "game.h" //测试三子棋游戏 void menu() { printf("***********************\n&quo ...

  5. 三子棋游戏【C语言实现】保姆级教程,小白也能看懂,冲就对了❗❗❗

    前言 ❤️ 铁汁们大家好,欢迎大家来到出小月的博客里,

  6. C语言实战项目1——三子棋(可转变为N子棋)

    文章目录 前言 一.三子棋实现步骤 1.什么是三子棋? 2.C语言实现逻辑 3.函数实现 二.源代码 1.头文件 2.函数实现 3.主函数 总结 前言 学习就是一个总结以及融汇贯通的的过程,适当的对知 ...

  7. 利用C语言巧妙实现棋类游戏——三子棋

    小游戏:三子棋用C语言实现 你是否学完了C语言的函数.数组.选择结构.循环结构苦于没有实战小项目巩固自己所学的知识呢,今天小程序猿就给大家带来了一个游戏的小游戏--三子棋,利用C语言实现的,希望对大家 ...

  8. 【C_Game001_三子棋】

    C语言_游戏目录 C_Game001_三子棋 文章目录 C语言_游戏目录 前言 一.测试模块test.c 二.游戏模块game.h 三.游戏模块game.c 总代码 总结 前言 思路:多文件组织完成三 ...

  9. 用C语言实现三子棋游戏(附上思路+项目展示+源代码)

    文章目录 前言 一.三子棋游戏整体实现思路 二.实现步骤 分模板实现 (以及具体应用实列) 1.test.c 源文件讲解: 2. game.c 源文件讲解: 3.game.h 源文件讲解 三 game ...

  10. C语言小游戏——三子棋

    C语言 -- 三子棋 本篇主要是用二维数组和多个函数来实现三子棋游戏. 让我们先来看看这个编写这个游戏的思路:首先要打印三子棋的棋盘,然后是玩家下棋,电脑下棋,最后判断谁赢了,或者看看是否平局. 我们 ...

最新文章

  1. Red Hat linux 9 初装配置
  2. vant图标怎么显示不出来_U盘插进电脑但不显示怎么解决
  3. 集合去重 (集合元素为引用类型)--- java 8 新特性 --- 根据元素单属性、多属性实现去重
  4. Linux下9个有用的touch命令示例
  5. 《阿凡达》3月12日内地重映:部分影院已开启预售
  6. Html5中的徽章,CSS 常见样式 特殊用法 贯穿线徽章箭头
  7. Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyExce
  8. django项目基础
  9. [Intellij] Project Structure 配置说明
  10. 丁可以组什么词_“一”可以组什么词?落语读书会学期总结
  11. DPDK-VPP 学习笔记-03 Load Balancer plugin
  12. Extjs之EditorGridPanel的beforeedit事件参数
  13. 使用max函数计算EXCEL个税公式
  14. 10月24日程序员HTML5,【通知】10月24日程序员节放假1天
  15. AAU,BBU,RRU区分与功能
  16. 终于搞清楚了:happen-before原则是干什么的
  17. EasyX 图片透明设置
  18. SQL 保留2位小数的方法/四舍五入
  19. 一加8T 原装65W WARP闪充 充电功率记录
  20. 刀片之家礼品兑换帮助

热门文章

  1. 工业互联网数据监测预警解决方案
  2. IEEE 1588/802.1AS标准、硬件,Linux软件学习建议
  3. RK3588平台开发系列讲解(AUDIO篇)基于alsa api的音频播放/录制流程
  4. idea不支持Lambda表达式
  5. UVA 1494 - Qin Shi Huang's National Road System(次小生成树)
  6. 云计算之java项目上线
  7. 数据库基础语法(上)
  8. php ajax多图上传预览,Ajax上传图片及先预览功能的实现方法
  9. 噪声振动频谱分析与实例
  10. 指派问题与匈牙利解法