查看: 26653|回复: 52510
打印 上一主题 下一主题

C语言实现简易2048小游戏

[复制链接]
诚博welcome备用
跳转到指定楼层
楼主
发表于 2019-04-23 00:58:14 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

C语言实现简易2048小游戏


一直很喜欢玩这个小游戏,简单的游戏中包含运气与思考与策略,喜欢这种简约又不失内涵的游戏风格。于是萌生了用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;            //此时移动虽然没有消去一个数,但是也要添加一个随机数出来
                }
            }
        }
    }
}

项目完整代码在原博客中已经给出。

运行效果:

 

当前文章://unoarray/05tqb.html

发布时间:2019-04-23 00:21:21

qy8千亿国际pt老虎机 - 2018专业游戏平台 澳门皇冠—澳门皇冠赌场 澳门银河娱乐场网址 鸿运国际-鸿运国际会员手机登录-会员鸿运国际手机登陆 新濠天地娱乐_新濠天地娱乐官网_澳门新濠天地娱乐场官网 亿万先生_亿万先生娱乐_mr007亿万先生_mr007亿万先生网页版 银河娱乐官方网站 银河娱乐网站网址-老品牌欢迎您的光临 优德娱乐_优德娱乐场|优德娱乐场w88 

点击获取礼包
优发娱乐手机版
沙发
发表于 2019-04-23 00:45:00 | 只看该作者
更别说是精确控制自己全部力量的刘皓了,来到这个陌生的地方,天知道征服空间给自己安排什么任务,小心一点总无大错的,毕竟这个世界可都在众神的监察之下,自己这个外来客一出现很可能会引人注意,所以还是收敛自身气息隐藏起来比较好。
回复 支持 反对

使用道具 举报

无极2娱乐下载地址
板凳
发表于 2019-04-23 00:18:22 | 只看该作者
大师带着来找唐三的七宝琉璃宗弟子来到木屋前,“小三。你出来一下。”/uno2019/fzat0/
回复 支持 反对

使用道具 举报

宝马会国际娱乐官网骗子
地板
发表于 2019-04-23 00:15:21 | 只看该作者
领头的幸亏是变成了玄鸟真身,若是以人身显现的话,不知道这张老脸已经羞红成了什么样子了。
回复 支持 反对

使用道具 举报

通发娱乐
5#
发表于 2019-04-23 00:14:21 | 只看该作者
蚩尤将手一指,吊着她的绳索自行断去,他道:“我看你这小丫头还是蛮漂亮蛮有趣的,死了可惜。九幽不是一个让人玩耍的好地方,你还是快点离开吧。”
回复 支持 反对

使用道具 举报

百万发登陆
6#
发表于 2019-04-23 00:00:55 | 只看该作者
他的身体突然动了,随着他的身体开始有了动作,只要是他到过的地方,那里的人定会一拨拨的倒下。
回复 支持 反对

使用道具 举报

云顶集团4008om
7#
发表于 2019-04-23 00:26:23 | 只看该作者
“啾”的一声尖啸,一颗大口径炮弹呼啸着从运河南岸飞来,划过碉楼上空,呼啸着朝前面鬼子炮兵阵地里砸了过去!
回复 支持 反对

使用道具 举报

菲律宾申博官网
8#
发表于 2019-04-23 00:37:26 | 只看该作者
天斗帝国皇室不可能知道这样的秘密,否则,就算他们再看重自己也没有将瀚海乾坤罩赠予的道理,如自己在海神岛上所受到的待遇都是因为这小小的瀚海乾坤罩所引来,那么,一切的解释就都变得合理了。
回复 支持 反对

使用道具 举报

顶级国际娱 乐城59666a com
9#
发表于 2019-04-23 00:09:15 | 只看该作者
“恐惧?哼”叶扬冷哼一声,精神力量直接涌出,将他心头的恐惧给驱走了。这个天伦王若是遇到别的对手,凭借他这手*控别人情绪的力量,一定可以占到上风。但是在面对叶扬这种精神力高手的时候,他那种*控别人情绪的力量就完全失效了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

乐虎国际lehu9888 - 官网直营!是互联网最大的搜索引擎优化研究中心,是致力于培养学员用户体验意识和提供专业技术解答的专业培训机构, 成立于2007年,2008年第一家入驻歪歪的培训机构,2014年成为腾讯课堂战略合作机构。
© 2007-2016 乐虎国际lehu9888 - 官网直营! 湘ICP备13004652号-1 Powered by Discuz!X  Template by 乐虎国际lehu9888 - 官网直营! 
快速回复 返回顶部 返回列表