zoukankan      html  css  js  c++  java
  • 也来山寨一个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); 
            }
    View Code

    分解:

      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];
            }
    View Code

       这里要注意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;
                                }
                            }
                        }
                    }
                }
    View Code

      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;
                                }
                            }
                        }
                    }
                }
    View Code

    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;//重置是否移动标识
            }
    View Code

    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();
            }
    View Code

    其他方向移动操作依葫芦画瓢,至此,一个简略山寨版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);
            }
    View Code

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

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

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

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

    
    
  • 相关阅读:
    java往文本文件中写入信息并修改
    idea中写servlet时报错--关于405错误
    关于引入js文件乱码的问题
    关于HTML的引入CSS文件问题
    后缀算法
    vim中 E212:无法打开并写入文件的解决办法
    Restful风格API
    Restful概念
    Andriod实现推送的解决方案(转)
    IOS系统推送原理
  • 原文地址:https://www.cnblogs.com/tobebetter/p/3789292.html
Copyright © 2011-2022 走看看