【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 ,完成了。

时间: 2024-10-22 17:21:40

【Winform开发2048小游戏】的相关文章

C# 开发2048小游戏

这应该是几个月前,闲的手痒,敲了一上午代码搞出来的,随之就把它丢弃了,当时让别人玩过,提过几条更改建议,但是时至今日,我也没有进行过优化和更改(本人只会作案,不会收场,嘎嘎),下面的建议要给代码爱好的童鞋完成了. 更改建议: a.当数字超过四位数时,显示的时候有部分被它的容器TextBox遮挡了,能不能把显示的数值变小点?答案是可以的.代码里有一段通过矩阵数据填充TextBox值的操作,可以在填充时,判断下数值长度,然后修改TextBox的文字大小. b.玩游戏的时候,使用方向键移动时,焦点可能

JQuery实现2048小游戏

最近用Jqery写了一个2048小游戏,由于是第一次写小游戏,所以就选了一个基础的没什么难度游戏.具体实现如下: 首先在开发时将整个游戏分成两层(自认为),底层是游戏的数据结构以及对数据的操作,上层是显示出来的用户界面.底层选择使用一个4x4的二维数组,整个游戏的数据操作都围绕着这个二维数组进行. [一]游戏基础界面 1 <div id="game"> 2 <div id="header"> 3 <h1>1024</h1&g

2048小游戏(C语言版)

1 #include <climits> 2 #include <cstdio> 3 #include <cstring> 4 #include <stack> 5 #include <string> 6 #include <map> 7 #include <vector> 8 #include <cmath> 9 10 11 /* 12 玩法说明:编译运行后,输入一个整数n,表示自己想玩的游戏中是n*n的表格

canvas随笔之2048小游戏

HTML: <!DOCTYPE HTML> <html> <head> <title>2048小游戏</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=0.5, maximum-scale=2.0, u

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

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

Swift实战之2048小游戏

上周在图书馆借了一本Swift语言实战入门,入个门玩一玩^_^正好这本书的后面有一个2048小游戏的实例,笔者跟着实战了一把. 差不多一周的时间,到今天,游戏的基本功能已基本实现,细节我已不打算继续完善,就这么整理一下过程中一些值得记录的点吧. 用的Swift版本是2.0,原书中的Swift版本会低一些,所以实践起来有些地方语法并不一样. 一.开始页面   在程序的第一张页面(Main.storyboard)上,只放了一个“开始游戏”按钮,点击按钮,弹出一个提示对话框,确认后,进入游戏页面. 1

2048小游戏-JS实现(BUG调试中)

刚刚学习JS的菜鸟,游戏没有实现滑动效果.希望有前辈能指点一下······ 定义的主要方法: 1.fuzhi()生成一对随机数,然后根据这对随机数取得一个随机单元格,先判断其是否为空,不为空,对其进行赋值为2的操作:为空,则再次调用fuzhi(). 2.secai()遍历表格,根据单元格的数值改变单元格的背景颜色. 3.score()遍历单元格,计算实时总得分. 4.keyDown()主要方法,根据用户按上下左右键来进行不同的数值相加.消除动作.这一段代码写得很冗余····· 1 <!DOCTY

2048小游戏用例图

用例图主要用来描述"用户.需求.系统功能单元"之间的关系.它展示了一个外部用户能够观察到的系统功能模型图. 下面是我们2048小游戏的用例图:

2048小游戏(变态版哦)

近日,由于博主同学暑假有个作业是写个2048小游戏,我一听挺好玩的..然后就开始了.. 首先,2048在移动过程中的规则其实也没有特别难,但是感觉也不是一句话就能说完的.(不过玩的多--感觉总是有的) 废话不多说,其实博主同学提供了pdf描述了2048的算法. 各位筒子入坑前请先过几眼这个规则,以及其算法(当然我觉得算法第二点有点问题,后述) 那么在游戏的编写前,可以先对细枝末节做一些准备. 1.出现数字2/4的概率 int getRand() { int i = rand() % 10; if