【Winform开发2048小游戏】

时间:2021-02-07 03:25:00

先来看一下界面:

【Winform开发2048小游戏】

 

 游戏帮助类

class GameCore
    {
        //游戏地图
        private int[,] map = new int[4, 4];
        //合并时用到的临时数组
        private int[] mergeArr = new int[4];
        //空位数量
        private int emptyCount = 16;
        //所有空位位置
        private Location[] emptyArr = new Location[16];
        private Random random = new Random();
        //画板
        private Graphics gp = null;
        //用位图做画板
        private Image image = null;
        // 游戏项大小
        private const int ITEMSIZE = 80;
        //游戏得分
        private int score = 0;

        public bool IsChange { get; set; }

        /// <summary>
        /// 当前得分
        /// </summary>
        public int Score
        {
            get { return score; }
        }

        /// <summary>
        /// 空位数量
        /// </summary>
        public int EmptyCount
        {
            get
            {
                return emptyCount;
            }
        }

        /// <summary>
        /// 游戏初始化
        /// </summary>
        public GameCore()
        {
            ComputeEmptyCount();
            // 初始化数组
            Location loc1;
            GenerateNum(out loc1);

            ComputeEmptyCount();
            GenerateNum(out loc1);
            //初始化画板
            image = new Bitmap(ITEMSIZE * 4 + 5 * 8,
                                              ITEMSIZE * 4 + 5 * 8);
            gp = Graphics.FromImage(image);


        }

        #region 移动并合并相邻的相同数字

        /// <summary>
        /// 移动单元格数据
        /// </summary>
        /// <param name="direction"></param>
        public void Move(string direction)
        {
            IsChange = false;
            switch (direction)
            {
                case "Up": MoveUp(); break;
                case "Down": MoveDown(); break;
                case "Left": MoveLeft(); break;
                case "Right": MoveRight(); break;
            }
        }
        /// <summary>
        /// 上移
        /// </summary>
        public void MoveUp()
        {
            //1
            for (int c = 0; c < 4; c++)//列
            {
                for (int r = 0, index = 0; r < 4; r++)//行
                {
                    if (map[r, c] != 0)//非零
                    {
                        mergeArr[index++] = map[r, c];//放入合并数组
                    }
                    //数字位置发生变化
                    if (mergeArr[r] != map[r, c])
                    {
                        IsChange = true;
                    }
                    map[r, c] = 0;//将矩阵中取走的清零

                }
                //2合并
                MergeCell();
                //3 将合并后的数据放入矩阵
                for (int i = 0, r = 0; i < 4; i++)
                {
                    if (mergeArr[i] != 0)
                    {
                        map[r++, c] = mergeArr[i];
                        mergeArr[i] = 0;
                    }
                }
            }
        }

        /// <summary>
        /// 下移
        /// </summary>
        public void MoveDown()
        {
            //1
            for (int c = 0; c < 4; c++)//列
            {
                for (int r = 3, index = 0; r >= 0; r--)//行
                {
                    if (map[r, c] != 0)//非零
                    {
                        mergeArr[index++] = map[r, c];//放入合并数组
                    }
                    if (mergeArr[3-r] != map[r, c])  
                    {
                        IsChange = true;
                    }
                    map[r, c] = 0;//将矩阵中取走的清零
                }
                //2合并
                MergeCell();
                //3 将合并后的数据放入矩阵
                for (int i = 0, r = 3; i < 4; i++)
                {
                    if (mergeArr[i] != 0)
                    {
                        map[r--, c] = mergeArr[i];
                        mergeArr[i] = 0;
                    }
                }
            }



        }

        /// <summary>
        /// 合并单元格
        /// </summary>
        private void MergeCell()
        {
            for (int i = 0; i < 3; i++)
            {
                if (mergeArr[i] != 0 && mergeArr[i] == mergeArr[i + 1] )
                {
                    mergeArr[i] += mergeArr[i + 1];
                    score += mergeArr[i];
                    IsChange = true;
                    mergeArr[i + 1] = 0;
                }
            }
        }

        /// <summary>
        /// 左移
        /// </summary>
        public void MoveLeft()
        {
            //1
            for (int r = 0; r < 4; r++)//行
            {
                for (int c = 0, index = 0; c < 4; c++)//列
                {
                    if (map[r, c] != 0)//非零
                    {
                        mergeArr[index++] = map[r, c];//放入合并数组
                    }
                    if (mergeArr[c] != map[r, c])
                    {
                        IsChange = true;
                    }
                    map[r, c] = 0;//将矩阵中取走的清零
                }
                //2合并
                MergeCell();
                //3 将合并后的数据放入矩阵
                for (int i = 0, c = 0; i < 4; i++)
                {
                    if (mergeArr[i] != 0)
                    {
                        map[r, c++] = mergeArr[i];
                        mergeArr[i] = 0;
                    }
                }
            }
        }

        /// <summary>
        /// 右移
        /// </summary>
        public void MoveRight()
        {
            //1
            for (int r = 0; r < 4; r++)//行
            {
                for (int c = 3, index = 0; c >= 0; c--)//列
                {
                    if (map[r, c] != 0)//非零
                        mergeArr[index++] = map[r, c];//放入合并数组

                    if (mergeArr[3-c] != map[r, c])
                        IsChange = true;
                
                    map[r, c] = 0;//将矩阵中取走的清零
                }
                //2合并
                MergeCell();
                //3 将合并后的数据放入矩阵
                for (int i = 0, c = 3; i < 4; i++)
                {
                    if (mergeArr[i] != 0)
                    {
                        map[r, c--] = mergeArr[i];
                        mergeArr[i] = 0;
                    }
                }
            }
        }


        #endregion

        /// <summary>
        /// 计算空位数量
        /// </summary>
        public void ComputeEmptyCount()
        {
            emptyCount = 0;
            Array.Clear(emptyArr, 0, 16);

            for (int r = 0; r < 4; r++)//行
            {
                for (int c = 0; c < 4; c++)//列
                {
                    if (map[r, c] == 0)
                    {
                        emptyArr[emptyCount++] = new Location(r, c);
                    }
                }
            }
        }

        /// <summary>
        /// 生成新数字
        /// </summary>
        public int GenerateNum(out Location location)
        {
            int index = random.Next(0, emptyCount);
             location = emptyArr[index];
             map[location.X, location.Y] = random.Next() % 10 == 0 ? 4 : 2;
             return map[location.X, location.Y];
        }

        /// <summary>
        /// 判断游戏是否结束
        /// </summary>
        /// <returns></returns>
        public bool IsGameOver()
        {
            ComputeEmptyCount();
            //如果还有空位,游戏未结束
            if (EmptyCount > 0)
                return false;
            //检查横纵相邻单元格中是否有相同的数字,
            for (int r = 0; r < 4; r++)
            {
                for (int c = 0; c < 3; c++)
                {
                    //横
                    if (map[r, c] == map[r, c + 1])
                        return false;

                    //纵
                    if (map[c, r] == map[c + 1, r])
                        return false;
                }
            }
            return true;

        }

        #region 绘制游戏画面
        /// <summary>
        /// 绘制游戏画面
        /// </summary>
        /// <returns></returns>
        public Image DrawMap()
        {
            //清空画板原有内容
            gp.Clear(Color.DarkGray);
            for (int r = 0; r < map.GetLength(0); r++)
            {
                for (int c = 0; c < map.GetLength(1); c++)
                {
                    DrawItem(r, c, GetColor(map[r, c]));
                }
            }
            return image;
        }


        /// <summary>
        /// 通过数字从程序集资源中找图片
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public Image GetColor(int num)
        {
            return Properties.Resources.
                      ResourceManager.
                      GetObject("_" + num.ToString()) as Image;
        }

        /// <summary>
        /// 绘制一个数字块
        /// </summary>
        /// <param name="rowindex">行索引</param>
        /// <param name="columnIndex">列索引</param>
        /// <param name="img">要绘制的图片</param>
        private void DrawItem(int rowindex, int columnIndex, Image img)
        {
            //画在哪 rowindex columnindex
            int x = (columnIndex + 1) * 8 + columnIndex * ITEMSIZE;

            int y = (rowindex + 1) * 8 + rowindex * ITEMSIZE;

            //绘制内容img                       画多大 itemSize
            gp.DrawImage(img, x, y, ITEMSIZE, ITEMSIZE);
        }

        #endregion

    }

 定义一个结构:

 struct Location
    {
        private int x;
        private int y;

        public Location(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
     

        public int X
        {
            get { return x; }
        }
        public int Y
        {
            get { return y; }
        }
    }

 窗体代码:

  public partial class FrmMain : Form
    {
        private GameCore gameCore = null;

        public FrmMain()
        {
            InitializeComponent();
        }

        public void DrawGameMap()
        {
            this.picMap.Image = gameCore.DrawMap();
        }

        //开始游戏
        private void FrmMain_Load(object sender, EventArgs e)
        {
            StartGame();
        }

        private void StartGame()
        {
            //得分清零
            lblScore.Text = "0";
            gameCore = new GameCore();
            DrawGameMap();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            StartGame();
        }

        //用键盘控制游戏动作
        private void FrmMain_KeyDown(object sender, KeyEventArgs e)
        {
            string keyString =   e.KeyData.ToString();
            switch (keyString)
            {
                case "Up":
                case "Down":
                case "Left":
                case "Right":
                    gameCore.Move(keyString);
                    //更新游戏地图
                    UpdateGameMap();
                    break;
            }
        }

        public void UpdateGameMap()
        {
            //游戏流程?
            //地图发生过变化
            if (gameCore.IsChange)
            {
                //绘制游戏地图
                DrawGameMap();
                //刷新得分
                this.lblScore.Text = gameCore.Score.ToString();
                //重新计算空位
                gameCore.ComputeEmptyCount();
                //如果空位数大于0
                if (gameCore.EmptyCount > 0)
                {
                    //产生新数
                    Location loc;
                     int num = gameCore.GenerateNum(out loc);
                    //开启绘制新数的动画 异步调用
                    Action<int,int,int> handler = DrawNewNumber;
                    handler.BeginInvoke(loc.X, loc.Y, num,
                                                        null, null);
                    
                }

                //判断游戏是否继续
                if (gameCore.IsGameOver())
                {
                    MessageBox.Show("GAME OVER");
                }
            }
            
        }


        public void DrawNewNumber(int r,int c,int num)
        {
            int xOfMap = (c + 1) * 8 + c * 80;
            int yOfMap = (r + 1) * 8 + r * 80;
            Graphics gp = this.picMap.CreateGraphics();

            Image img = gameCore.GetColor(num);
            //数字出现由小及大,最小宽为10  最大为80
            int w = 10;

            while (w <= 80)
            {
                int x =xOfMap+ 80 / 2 - w / 2;
                int y =yOfMap+ 80 / 2 - w / 2;
                gp.DrawImage(img, x, y, w, w);
                w += 5;
                System.Threading.Thread.Sleep(10);
            }
        }
    }

 OK ,完成了。