用c语言编写2048小游戏_2048小游戏c语言课程设计
大家好,又见面了,我是你们的朋友全栈君。
一直很喜欢玩这个小游戏,简单的游戏中包含运气与思考与策略,喜欢这种简约又不失内涵的游戏风格。于是萌生了用C语言实现一下的想法。
具体代码是模仿这个:https://www.cnblogs.com/judgeyoung/p/3760515.html
博主分析的都很到位,很多算法技巧都值得借鉴,C语言实现2048的主要思想已经在那个博客中详细的分析了,但是我觉得在博主的代码中还是有很多很好的思想是值得我借鉴学习的。
比如这个生成随机数,顺便规定随机数的概率:
/* 生成随机数 函数定义 */
void add_rand_num()
{
srand(time(0));
int n = rand() % get_null_count();/* 确定在何处空位置生成随机数 */
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (board[i][j] == 0 && n-- == 0) /* 定位待生成的位置 */
{
board[i][j] = (rand() % 3 ? 2 : 4);/* 确定生成何值,设定生成2的概率是4的概率的两倍 */
return;
}
}
}
}
首先是 srand() 函数,他是一个随机数发生器的初始化函数。
原型为:void srand(unsigned seed)
用法是:程序员需要为这个函数提供一个随机数的种子:srand(随机数),如果使用相同的种子,那么后面的rand()函数就会每次运行都是生成一样的随机数,即伪随机数。
如:srand(1),直接用1来初始化种子,后面都是一样的随机数 。
为了生成真正的随机数,我们一般采用系统时间来作为随机数初始化函数的种子。使用time()函数来获取系统时间:
它的返回值为从 00:00:00 GMT, January 1, 1970 到现在所持续的秒数,然后将time_t型数据转化为(unsigned)型再传给srand函数,即: srand((unsigned) time(&t));
还有一个经常用法,不需要定义 time_t 型 t 变量,即: srand((unsigned) time(NULL)); 直接传入一个空指针,因为你的程序中往往并不需要经过参数获得的 t 数据。
第二句是:
int n = rand() % get_null_count();//在空余格中生成一个随机位置
利用随机数对剩余空格数目进行取余运算,得到小于剩余格数的随机数。
最后一句是:
if (board[i][j] == 0 && n-- == 0)//随机位置处为0时填入一个随机数,但是如果随机位置处不为0呢?
{
board[i][j] = (rand() % 3 ? 2 : 4);//在随机生成的空白格处填上一个2或者4,利用三项表达式对3取余,得到1/3,2/3的概率。
return;//结束函数
}
就是在格子中没有数字时并且在刚刚生成的随机数的位置处,填入一个数字2或者4,并且为了降低难度,固定生成2是生成4的概率的2倍。
利用三目运算符和对3取余的特点,产生概率分布。
rand()随机数对3取余只有可能是0/1/2,而在三目运算符中,当第一个数不为0时,运算符的值就取中间那个数的值,否则取最后一个数。所以取2的可能性为2/3,取4的可能性为1/3,这样就产生了不同的概率。但是这种方法只能产生 n:1 的概率分布,如果要产生 4:5, 8:17 的概率时,这种方法就不在适用了。
上面这些代码还是有一些漏洞的,因为游戏刚开始是需要有两个数的,一个数必为2,另一个数就是上面生成的那个数,但是如果第二个数恰好生成的随机位置处是第一个数,那么根据这儿代码,就什么也没有执行,最终导致出现刚开始界面就一个数字的情况。
解决办法就是在刚开始生成的两个数的程序中不使用 get_null_count(),而是获取第一个数字2的准确位置,然后生成第二个数字时,在排除第一个数字的地方生成数字即可。
程序的主体就是数字的上下左右移动,go_left()和其他三个函数,他们的思想都是相似的,就拿go_left()函数来分析一下:
按照原作者的思想,移动的时候一共有三种情况。
如果相邻的两个数一样,就合并,数字相加。
如果相邻的数字不一样,简单的说,又分两种情况:数字需要移动和不需要移动。
具体代码为:
/*左移函数*/ void go_left(void) { /*i遍历行下标*/ for (int i = 0; i < 4; i++) { /*j为列下标,k为待比较项列下标,循环进入时k < j*/ for (int j = 1,k = 0; j < 4; j++) { /*找出k后面第一个不为0的项*/ if (board[i][j] > 0) { /*情况1*/ if (board[i][j] == board[i][k]) //两个数相同就合并 { scoer += board[i][k++] <<= 1; board[i][j] = 0; if_need_add_num = 1; //合并之后需要生成随机数和刷新界面 } /*情况2*/ else if (board[i][k] == 0) //k项为空,则把j格移到k格 { board[i][k] = board[i][j]; board[i][j] = 0; if_need_add_num = 1; } /*情况3*/ else //k项不为空,也不等于j项,此时两个都不需要动,只是下标需要变换 board[i][++k] = board[i][j]; //把j项移到k项的紧挨着的右边 if (j != k) //移动过之后不相等说明之前他们不是紧挨着的 { board[i][j] = 0; if_need_add_num = 1; //此时移动虽然没有消去一个数,但是也要添加一个随机数出来 } } } } }
项目完整代码在原博客中已经给出。
运行效果:
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/166717.html原文链接:https://javaforall.cn
相关文章
- 用c语言编写一个学生成绩管理系统_c语言成绩查询系统编程
- python语言变量命名规则有什么_Python变量命名规则(超级详细)
- java源程序文件的扩展名_使用Java语言编写的源程序保存时的文件扩展名是什么…
- 只知道PHP是单继承语言,你了解Trait吗?
- c语言编写图书管理系统程序_C语言图书管理系统
- 用html语言编写一个简单的网页_html做网页
- R语言文本挖掘NASA数据网络分析,tf-idf和主题建模|附代码数据
- 使用R语言创建好看的表格
- c语言之字符型数据类型关键字_字符型系统数据类型主要包括
- [Nature Biotechnology | 论文简读] 使用语言模型和深度学习进行单序列蛋白质结构预测
- R语言中贝叶斯网络(BN)、动态贝叶斯网络、线性模型分析错颌畸形数据|附代码数据
- Go语言中的组合字面量语法(Composite Literal)
- 2023-03-15:屏幕录制并且显示视频,不要用命令。代码用go语言编写。
- 开心档之Go 语言常量
- 2023-03-24:音视频mp3和h264混合(muxer)编码为mp4,用go语言编写。
- Docker 之父:Go、Rust 为什么会成为云原生的主导语言?
- Go语言与C/C++进行交互
- Linux下编写C语言的简易指南(怎么用linux编c语言)
- 教你如何在Linux中编写C语言(linux怎么编写c语言)
- 在 Linux 中编写 C 语言程序(linux下编写c程序)
- Linux编程:走上开发之路(linux编写语言)
- “最好的语言” PHP 如何造就 Facebook?
- 如何在 Ubuntu 安装 Go 语言编写的 Git 服务器 Gogs
- 第一个 C 语言编译器是怎样编写的?
- 在Linux系统下学习C语言编程之旅(linux下编写c语言)
- Linux之下编写C语言程序的试验记(linux c语言试题)
- Linux C语言面试:挑战你的编程技能!(linuxc语言面试题)
- 使用MySQL语言编程,快速高效完成数据管理(mysql yang)
- Go语言helloworld实例