日记只是记录,不一定天天写日记,但代码天天写两个作业(悲)
今天写的是扫雷游戏
代码整体思路不难,就是长了点写的头会昏掉。
总体分为3部分。1是游戏进入界面,2是游戏设计,3是游戏执行过程。1,3倒是不麻烦,重要的是游戏设计。在介绍代码之前,我们先介绍一点必备的小知识,二维数组,自定义函数,以及跨文件传输。
二维数组只是相对于一维数组来说多几行而已,一维数组写法arr[],二维数组则是arr[][],顺序为几行几列,行可以不写,编译器会自行判断,但列必须写,例如arr[][3],比如说我们二维数组行列都不写,编译器没法判断,会报错,只写行数,列数没法确定,也会报错,但是列数确定了,即一行有多少个,那么行数也可以确定下来,这是二维数组。
自定义函数写法为 类似 int arr(int x,int y)这种,前面为数据类型时,必须要写return返回一个值,但如果是 void则不需要加return。下方介绍代码我们会看到两种写法。同时说明一点,写下return后自定义函数就会直接返回了,函数内剩下的代码不会继续执行。
跨文件传输直接上图
game.h是我写头文件,在创建时也要选择头文件,头文件一般用于函数声明,函数声明只是说明有这个函数存在而已,不写函数声明的话自定义函数必须写在其他用到该函数的代码之前,不然会报错。而写了的话定义这个函数则可以放在后面。下面两个是源文件。game.c用于函数定义,而test.c则是代码执行的本体。所以关于文件传输就两点,头文件用于函数声明,源文件用于函数定义。代码本体要用到头文件时只需要#include "头文件名"即可,当然,我上面那串把头文件函数函数删了也能正常执行,但是定义这些数据的值不能删,本体要用到。
以上这些提供基础,理论存在,实践开始!
首先让我们设置一下界面,这些只要在本体上写下来就好,其他的又臭又长的自定义函数放另一个文件吧,不然本体太长了看的难受。
朴实无华的界面。
下方是游戏设计,很简单,定义放在界面用来看的展示数组show,和放在幕后的地雷数组mine。
Initboard函数是我定义的初始化函数,用于将输入的数组初始化为同一个字符。
ROWS和COLS是扫雷的整个范围大小,即外层边框,扫雷实际是在边框内部执行的。
ROW和COL是游戏范围,不含边框。这张图是我放在头文件的全部函数声明和数组的值定义,以及应用了随机数函数stdlib和时间函数time。由于随机数是伪随机所以我们要通过时间函数改变随机数的值(伪随机就是说随机数是算出来的而不是真正的随机,感兴趣的可以自己试试看每次输入的值是不是一样的,当然了,相同的是每次重启程序后的产生的随机数,而不是单次程序执行产生的)。ROW和COL可以自己更改大小来改变游戏范围。以上这些是头文件里的。
让我们回到函数本体。
上方有注释,这一个游戏函数是单次扫雷内部的执行程序。分别为打印初始化界面,给幕后地雷数组埋下地雷和游戏的玩法,排查雷。一步步分析,这个游戏就很简单了。
最后是代码本体的最后一块,选择是否继续玩游戏。
时间函数改变随机数的初始值(这里就不介绍了,太长了),总之就是随机函数rand其实有一个初始值,通过这个值来计算出伪随机数,而通过时间的改变来改变时间随机函数的初始值就可以达到随机的目的,每次游戏地雷位置都不会相同。srand函数用来输入rand函数的初始值,里面的数要不带符号的所以用unsigned int。通过do while语句实现游戏的可持续游玩,不想玩后输入0即可退出(怎么会有人闲得发慌一直玩,毕竟我是很忙的(悲),碰都不会碰一下这游戏)。
最后简简单单,一行即可。(背后的定义函数连本带利吃回来)
好的,让我们看看定义函数都定义了些什么东西,打开我的源文件game.c后发现。
映入眼帘的就是引用了头文件,其实主要目的就是把ROWS和COLS取出来定义数组的行和列
然后又来定义一个数EASY_COUNT,给它定义为10,就当雷的个数,在这里提前定义,目的是为了方便以后修改雷的个数,更改游戏难度(确实是方便,后面要用到EASY_COUNT,如果写确定的数的话找起来头皮发麻了就)。
然后就是Initboard函数,给它设定四个量,数组,行数,列数和要修改成的字符,通过一点简单语句即可实现该目的(不写上字符的话要定义两个函数来初始化幕后和展示面板,又占空间又麻烦)。
接下来是展示面板函数(此展示非彼展示,这个是动词)
这个函数每次输入用到一次,扫雷游戏用于好看和分隔,下方的%-3是一种方式,用来决定每个输出的所占位置,(对于数字有不同的意义,对于字符这个就是用来占位子的)。加‘-’意为左对齐,总共3个位置,字符不够的话剩下的位置就是空白,用于分隔,例如输入'a',加上'-3'就是'a ',而不加上'-'则是右对齐' a',我觉得不好看,所以加上了'-'。打印过程也非常的简单,就是把展示面板放出来,for语句轻松解决。
接下来这个函数
这是布置雷的函数,给幕后布置雷,使用随机函数和if语句也是轻轻松松,rand()%row+1他的范围是[1,row],包括左右两边的,扫雷游戏最后呈现的效果也是范围[1,row]。count用于计算剩余雷的个数,放置完就结束。
下一个
用于计算该点附近雷的个数,简单的循环语句不包括该点本身,幕后如果是地雷的话值是1,不是则为0,由于数组定义的是字符,所以减去的不是数字0而是字符'0'。
重头戏来了,查找雷。
查找雷分3块,输入错误,输入位置有雷,输入位置无雷。win用于计算走过的个数。
1.先是有雷,将输入位置与幕后数组进行比较,发现该位置是雷,pong!展示面板,恭喜玩家英勇就义,为了排雷光荣牺牲,请重开下一局!
2.无雷,计算该点周围雷的个数并在展示面板上将该点改为雷数量的字符,数字的ascll码不等于数字本身,所以要加上'0'。
3.输错了,这个就直接发输错了,没啥。
最后,当玩家走过的步数为row*col-10,10是雷的个数,步数为这个值代表玩家将所有非雷位置全部走过一遍,就直接输出"你,赢了!"。
当然,这个时候EASY_COUNT的作用就出来了,像这里直接写10到时候还要找然后改(我写的时候也忘了)。ok,程序设计结束,让我们运行一下,扫雷我玩不来,输两行就不玩了。
OK,今天的日记到此结束,下次有缘再见!!(下班下班)