也来山寨一个2048

2048最近似乎热度已过,但是并不影响我山寨一个它。周末闲来无事,终于付诸实现,包含winform和js版本。有图有真相

 实现思路:

1、通过二维数组data=int[4][4]来存储游戏数据,初始全部为0

2、游戏初始在4X4布局中随机位置产生2个随机数(只随机2,4)

//初始化游戏数据
        void InitGame()
        {
            ClearGame();
            Random rand = new Random();
            int pos1 = Convert.ToInt32(rand.Next(16));
            SetData(pos1, rand.NextDouble() < 0.8 ? 2 : 4);
            int pos2 = GetRandPos();
            SetData(pos2, rand.NextDouble() < 0.8 ? 2 : 4);
        }

分解:

  a、随意位置产生一个随机数

  b、在剩下的随机空白位置产生一个随机数,此方法在游戏移动后产生一个随机数时也要用到。随机空白位置的产生:遍历数据数组data,取得所有位置为空的集合pos,data中数据为0的即对应位置为空,可产生随机数;在pos中产生随机位置。

//随机产生空格处的坐标位置
        int GetRandPos()
        {
            List<int> pos = new List<int>();
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    if (data[i,j] == 0)
                        pos.Add(4 * i + j);//数组坐标刚好可以通过pos/4,pos%4得到
                }
            }
            Random r = new Random();
            int rand = r.Next(pos.Count);
            return pos[rand];
        }

  这里要注意data[i][j]和布局位置的对应关系:data[i][j]=>pos[4*i+j],pos[i]=>data[i/4][i%4];

3、移动操作:先合并再移动,以左移为例

  a)、查找可合并的元素合并,以一次合并为例:

0 1 2 3

  1) data1=从左到右第一个不为0的元素,假设是第j位置pos[j]

  2) data2=pos[j+1]

  3) a.  data1==data2则进行合并操作

    b.  data2==0,data2下移一个

    c. data2!=0&&data1!=data2,不能合并

//先合并元素
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    int tb = data[i,j];//取一个元素值
                    if (tb != 0)
                    {
                        for (int k = j + 1; k < 4; k++)
                        {
                            int nexttb = data[i,k];//下一元素值
                            if (nexttb != 0)
                            {
                                if (tb == nexttb)
                                {//相等合并,计算分数,设置移动状态
                                    data[i,j] = tb * 2;
                                    data[i,k] = 0;
                                    totalscore += tb * 2;
                                    moveflag = true;
                                }
                                break;
                            }
                        }
                    }
                }
            }

  b)、合并完成后移动元素至最左端

  前面的元素为空就依次把后面不为空的元素往前移,移动后后面元素置为空

//合并之后移动元素
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    int tb = data[i,j];//取一个元素值
                    if (tb == 0)
                    {//取得元素值为0表示当前位置为空
                        for (int k = j + 1; k < 4; k++)
                        {
                            int nexttb = data[i,k];//下一个元素值
                            if (nexttb != 0)
                            {//下一元素值不为0移动,设置移动标志
                                data[i,j] = nexttb;
                                data[i,k] = 0;
                                moveflag = true;
                                break;
                            }
                        }
                    }
                }
            }

4、判断游戏是否结束,未结束则产生一个随机数

  判断游戏是否结束:有元素为0或者有可合并的元素可继续,否则结束

//产生单个随机数
        void GetRandNum()
        {
            if (IsGameOver()) {
                if (MessageBox.Show("失败,是否重新开始?", "GameOver", MessageBoxButtons.YesNo)== DialogResult.Yes)
                {
                    InitGame();
                }
                else return;
            }
            Random rand=new Random ();
            if(moveflag)
                SetData(GetRandPos(), rand.NextDouble() < 0.8 ? 2 : 4);
            moveflag = false;//重置是否移动标识
        }

5、通过data数据更新界面

//根据data更新td内容,并设置样式
        void InitData()
        {
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    var td = btns.Find(m => m.Name == "btn" + (4 * i + j).ToString()); //btns[4 * i + j];
                    string tdval = td.Text.Length == 0 ? "0" : td.Text;
                    if (data[i, j].ToString() != tdval)
                        td.Text = data[i, j] == 0 ? "" : data[i, j].ToString();
                    //此处可设置数字样式
                }
            }
            lblscore.Text = totalscore.ToString();
        }

其他方向移动操作依葫芦画瓢,至此,一个简略山寨版2048完成。

需要注意的是Winform版本中要注意键盘上下左右事件方法要重写:

//重写上下左右键响应方法
        protected override bool ProcessDialogKey(Keys keyData)
        {
            switch (keyData)
            {
                case Keys.Up:
                    MoveUp();
                    break;
                case Keys.Down:
                    MoveDown();
                    break;
                case Keys.Left:
                    MoveLeft();
                    break;
                case Keys.Right:
                    MoveRight();
                    break;
                default:
                    break;
            }
            return base.ProcessDialogKey(keyData);
        }

通过下面的KeyDown事件监控没有效果,本人对winform不熟悉,期待大神解答原因

private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Left)
                MoveLeft();
        }

废话不多说了,代码见附件,另附js版本

参考文章:http://blog.csdn.net/touchsnow/article/details/22985527


也来山寨一个2048,布布扣,bubuko.com

时间: 2024-12-10 18:18:48

也来山寨一个2048的相关文章

用javascript实现一个2048游戏

早就想自己写一个2048游戏了,昨晚闲着没事,终于写了一个如下图,按方向键开始玩吧.如果觉得操作不方便,请直接打开链接玩吧:http://gujianbo.1kapp.com/2048/2048.html 附上源代码链接:https://github.com/gujianbo/js2048 个人博客地址:http://gujianbo.1kapp.com/ 新浪微博:http://weibo.com/gujianbobo 欢迎读者交流讨论并提出宝贵意见. 用javascript实现一个2048游

如何在CentOS上安装一个2048小游戏

如何在centos上安装一个2048小游戏 最近在学习CentOS系统,就琢磨着玩点什么,然后我看到有人在玩2048小游戏,所有我就在想,为啥不装一个2048小游戏搞一下嘞,于是乎,我就开始工作啦 由于我个人的编程能力不强,所以我就在网上找到了一个C语言版的2048游戏小程序,我把它放到我的百度网盘上,可以供大家下载(链接:http://pan.baidu.com/s/1jIutb3g 密码:mu9z),然后我们把这个程序给复制到CentOS系统下,在进行下一步的工作.我们可以在CentOS上安

利用CEF山寨一个翻译器

起因 在某些情况下,有将从某种类型的语言翻译成另一种类型语言的需求.比如在生成实体时,可能需要将中文名称转换成英文.于是利用CEFSharp山寨了一个翻译器.效果图如下: CEF简介 CEF全称为Chromium Emmbed Framework,是一个开源项目.用于嵌入基于 Google Chromium 项目的 Web 浏览器控件. CEF在.NET中的应用 CEF是由C++所写,无法直接应用到.NET中.需要通过某种形式进行包装.常见的有Xilium.CefGlue和CEFSharp.我个

原生js写一个2048游戏

本例逻辑1,一个二维数组,记录数字方块的数值与对应dom对象 2, 一个一维数组,记录空白方块的坐标(行与列)3,左移,最左边一列不做移动测试,从左边倒数第二列开始依次向左边做移动测试,若可合并,则向左移,数字不变或乘2.其他方向同逻辑 4, 判断输赢,若某个方块的值达到2048,即赢,游戏可以继续.当空白坐标数组的长度为0是,依次检测每个方块在四个方向可否移动,若都不能,即游戏结束. → → → → 预览 ← ← ← ← js代码: /*game 2048*/ //事件处理对象 var Eve

Egret的第一个2048游戏

http://bbs.egret-labs.org/thread-242-1-1.html 对于AS3的开发者来说,可以直接过渡到的HTML5框架就是Egret了,基本上是了解了TypeSprite的基本语法(http://www.nshen.net/article/2013-05-18/as3-to-typescript/)就可以直接上手开发了. 这个是我花了1周的闲暇时间做的2048,大家有兴趣可以参考一下源码.

最少javascript代码完成一个2048游戏

原生javascript代码写的2048游戏.建议在谷歌浏览器下跑.'WASD'控制方向.演示地址请移步:http://runjs.cn/detail/bp8baf8b 直接贴代码~ html: <!DOCTYPE> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/htm

【python学习】使用python写一个2048小游戏

个人博客:jerwang.cn 没有参考其他代码,效果图: 话不多少,源代码: https://github.com/jerustc/Python/blob/master/2048.py

[Practice]山寨2048之Terminal版

吹水: 今日得闲没野做,就捻着搵点野料下. 我玩过2048,觉得规则挺简单的,应该挺好入手的. 毕竟,也是开源的.网上也存在很多教材或自定义,神马的. 于是,我本着尝试的态度,不看教程,能否山寨一个出来. 分析:去官网http://gabrielecirulli.github.io/2048/玩上几盘,一步一步地摸索其规则. 最后,经过一个下午和傍晚的时间,我实现了大致的功能,也不清楚是否和原版100%相同. 而且程序效率也不高,在此就不详解我自己的做法了.有兴趣的人,可自行参照网上的教程. 此

爱加密宣战山寨App!安卓应用安全加密!!!

   中国IT研究中心(CNIT-Research)本月发布的<2014年Q1中国手机安全产品市场调研报告>显示,超9成的用户担心手机安全问题,占比达到93.7%.同时,移动应用数据分析公司 App Annie 最新发布的2014年第一季度移动应用市场指数报告显示在 Google Play 工具类榜单上,排名前五的应用当中有四个都是反病毒和安全类应用. 从以上数据不难看出手机安全越来越受到用户的普遍重视,其中很重要的一个原因就是国内不安全的山寨App盛行.打包党将正版手机App破解之后内嵌广告