零基础井字棋设计——仅需函数和数组的部分

井字棋小游戏 · 7a03a57 · 夜夜亮晶晶/studying - Gitee.com

一、介绍游戏基本功能

零基础井字棋设计——仅需函数和数组的部分_第1张图片

本游戏只能完成玩家和电脑通过井字棋互动,而不能进行有效的竞技。电脑只负责随机下棋并根据结果判断局势,不能根据游戏规则去创造平局或者想方设法赢得游戏。

二、游戏设计整体思路

2.1打印菜单menu()
不输入1就一直打印 输入其他的要提示错误
while循环
switch语句

2.2输入1就打印棋盘
用3*3的空格表示数组
还需打印分割线
for循环

2.3玩家输入
提示玩家输入并让玩家指定数组元素输入#️⃣

确认玩家指定数组元素为空格
填充#️⃣并打印

若玩家指定数组不为空格
提示输入错误

if语句

2.4电脑输入
电脑随机填充某个数组元素且该数组元素为空格
且随机数应在表格大小内
rand%
strand((unsighed int)time(NULL))

打印电脑输入

2.5判断结果
2.5.1玩家赢
2.5.2电脑赢
2.5.3平局
2.5.4继续游戏 

2.6重复
重复3.4.5

三、设计程序前准备

在设计程序前,我们可以分别创建一个存放主程序的test.c文件;一个存放游戏函数的game.c文件;一个声明函数的game.h文件。

这样我们就可以让我们的程序看起来更加简洁。

同时,在.h文件中,我们可以存放我们需要用到的所有头文件,除此之外,我们可以定义两个值ROW和COL,这样能更方便我们以后修改游戏数据。

零基础井字棋设计——仅需函数和数组的部分_第2张图片

我们在test.c中,只需要用#include"game.h",就可以使用game.h中的所有文件,包括stdio.h,其中和stdio.h不同的是,我们自己创建的文件名需要用双引号" ",而不是< >。零基础井字棋设计——仅需函数和数组的部分_第3张图片

在game.c中,为了实现各个函数的调用,我们同样在前加上#include"game.h"。

四、游戏设计

4.1设计游戏整体框架

首先我们先来写一个menu函数,打印我们的菜单

零基础井字棋设计——仅需函数和数组的部分_第4张图片

通过游戏菜单,我们可以知道我们需要输入选项,当我们输入1时可以进入程序,输入0时可以退出程序,输入其他值时需要提示我们输入有误,而且如果我们玩一局不够还想玩第二局时,可以接着进行选择而不退出游戏。

这样,我们就可以设计一个循环来执行,在这个循环中,我们先执行一次程序,然后根据输入的值来判断是否存在下一次。而游戏的选项可以用switch语句,来根据我们输入的选项判断选择的内容

零基础井字棋设计——仅需函数和数组的部分_第5张图片

来看代码:零基础井字棋设计——仅需函数和数组的部分_第6张图片

 根据C语言中,0表示假,非0表示真的特点,我们正好可以将menu的选项设置为0和1。零基础井字棋设计——仅需函数和数组的部分_第7张图片

 4.2 game函数各部分实现

虽然我们看似是在棋盘中输入我们的数据,但实际上,棋盘只是我们打印出来的数据,我们操纵的其实是一个二维数组。

在game函数中,我们先创建一个字符数组char board[ROW][COL];

4.2.1初始化数组

我们需要创建一个初始化数组的函数。

 这里我们需要插入一些函数与数组的知识: 

定义函数时,如果需要传入数组,可以用 (数组类型  数组名[ ][ ]) 或者 (数组类型* 数组名) 定义,但不可以(数组类型 数组名)

原因:

数组名是数组首元素的地址。有两个例外:
1. sizeof( 数组名 ) ,计算整个数组的大小, sizeof 内部单独放一个数组名,数组名表示整个数
组。
2. & 数组名,取出的是数组的地址。 & 数组名,数组名表示整个数组。
除此 1,2 两种情况之外,所有的数组名都表示数组首元素的地址。

零基础井字棋设计——仅需函数和数组的部分_第8张图片

在game函数中调用初始化数组的函数时,需要传入(数组名称,行数,列数)

4.2.2打印棋盘格 

我们先来看看打印出的棋盘样式

零基础井字棋设计——仅需函数和数组的部分_第9张图片

 我们先把空格换成 * ,这样方便我们阅读

零基础井字棋设计——仅需函数和数组的部分_第10张图片

我们把表格拆解一下,可以看到其实打印了五行,行与行用了'\n'分隔。零基础井字棋设计——仅需函数和数组的部分_第11张图片

思路如图: 

 零基础井字棋设计——仅需函数和数组的部分_第12张图片

 请看代码:零基础井字棋设计——仅需函数和数组的部分_第13张图片

 4.2.3玩家下棋

接下来我们就可以让玩家开始下棋了零基础井字棋设计——仅需函数和数组的部分_第14张图片

但需要注意的是,我们填充的是数组元素,所以 当玩家输入x和y的值后,我们对应的数组元素应该是board[x-1][y-1]。下面请看代码:零基础井字棋设计——仅需函数和数组的部分_第15张图片

 4.2.4电脑下棋

请看思路:

零基础井字棋设计——仅需函数和数组的部分_第16张图片

 下面我们来介绍一个随机数函数:

rand()是随机数函数,我们可以用int值来接收,如果我们需要生成100以内的随机数,就可以用rand()%100,意思就是rand()对100取余,这样就算rand()是再大的数生成的数也会小于100。

当我们用rand函数前,我们需要用srand函数,这是要求,当我们想要rand生成的随机数随时间改变的话,就要用到time函数,写为srand((unsigned int)time(NULL)),其中unsigned int 为强制类型转换。

因为这样生成的随机数就可以根据时间变化,所以我们只需要一个srand函数就够了,所以我们把他写在主函数里就可以了。

同时我们需要用到随机数函数和时间函数的头文件#include和#include

下面我们来看代码:零基础井字棋设计——仅需函数和数组的部分_第17张图片

4.2.5局势判断

我们发现,一共会出现四种局势,玩家赢,电脑赢,平局,继续游戏。

为了判断方便,我们就可以定义一个char类型的函数is_Win,并在game函数中接收它的值,根据值去选择我们的判断结果。

某一方赢根据井字棋的游戏规则,当某一行、某一列、主对角线、副对角线中满足任一条件三子相同且不为空格时,就会有一方获胜。当判断某一行或某一列的结果时,我们就可以用for循环来简化我们的代码;主对角线和副对角线因为元素固定,我们可以直接敲出。判断的条件也很简单,用if语句即可实现。 

我们可以让is_Win直接返回具有相同元素的三个数组元素的某个,来判断哪一方获胜。零基础井字棋设计——仅需函数和数组的部分_第18张图片

平局当出现平局时,场上棋子都被填满,且未出现某一方赢的局面,这样我们可以定义一个tmp变量来统计场上不为空格的数组元素的个数,当tmp的值和整个棋盘的大小(ROW * COL)相同时,就出现了平局。零基础井字棋设计——仅需函数和数组的部分_第19张图片

 继续游戏:当以上场景都未出现时,继续游戏。零基础井字棋设计——仅需函数和数组的部分_第20张图片

 下面我们来看代码:零基础井字棋设计——仅需函数和数组的部分_第21张图片

 4.3game函数各部分联系及组合

我们知道当我们使用game时,需要反复使用的是:

玩家下棋,打印棋盘,局势判断;

电脑下棋,打印棋盘,局势判断。

所以我们就可以写一个包含上述信息的死循环,当局势判断不为继续游戏时,就退出循环。零基础井字棋设计——仅需函数和数组的部分_第22张图片

需要注意的是,每次玩家下棋和电脑下棋后,都需要给ret重新赋值,让is_Win时刻判断场上局势 

下面是game函数的代码:零基础井字棋设计——仅需函数和数组的部分_第23张图片

 五、代码展示

5.1 game.h文件

零基础井字棋设计——仅需函数和数组的部分_第24张图片

 5.2 test.c文件

零基础井字棋设计——仅需函数和数组的部分_第25张图片

5.3 game.c文件

零基础井字棋设计——仅需函数和数组的部分_第26张图片

感谢您的阅读,评论区欢迎您的指正! 

  

你可能感兴趣的:(C语言,c语言,游戏)