码迷,mamicode.com
首页 > 其他好文 > 详细

也来山寨一个2048

时间:2014-06-15 14:04:07      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:winform   style   class   blog   code   http   

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

bubuko.com,布布扣bubuko.com,布布扣

 实现思路:

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

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

bubuko.com,布布扣
//初始化游戏数据
        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中产生随机位置。

bubuko.com,布布扣
//随机产生空格处的坐标位置
        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,不能合并

bubuko.com,布布扣
//先合并元素
            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)、合并完成后移动元素至最左端

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

bubuko.com,布布扣
//合并之后移动元素
            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或者有可合并的元素可继续,否则结束

bubuko.com,布布扣
//产生单个随机数
        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数据更新界面

bubuko.com,布布扣
//根据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版本中要注意键盘上下左右事件方法要重写:

bubuko.com,布布扣
//重写上下左右键响应方法
        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不熟悉,期待大神解答原因

bubuko.com,布布扣
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

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

也来山寨一个2048

标签:winform   style   class   blog   code   http   

原文地址:http://www.cnblogs.com/tobebetter/p/3789292.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!