也來山寨一個2048

2048最近彷佛熱度已過,可是並不影響我山寨一個它。週末閒來無事,終於付諸實現,包含winform和js版本。有圖有真相數組

 實現思路:dom

一、經過二維數組data=int[4][4]來存儲遊戲數據,初始所有爲0ide

二、遊戲初始在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

分解:spa

  a、隨意位置產生一個隨機數.net

  b、在剩下的隨機空白位置產生一個隨機數,此方法在遊戲移動後產生一個隨機數時也要用到。隨機空白位置的產生:遍歷數據數組data,取得全部位置爲空的集合pos,data中數據爲0的即對應位置爲空,可產生隨機數;在pos中產生隨機位置。3d

//隨機產生空格處的座標位置
        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];code

三、移動操做:先合併再移動,以左移爲例orm

  a)、查找可合併的元素合併,以一次合併爲例:blog

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

四、判斷遊戲是否結束,未結束則產生一個隨機數

  判斷遊戲是否結束:有元素爲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

五、經過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

相關文章
相關標籤/搜索