火星学习C#第三周作业-2048

本周的周作业是2048,遗憾是没有时间做AI。



总结分为:  教训、思路、代码三个部分。

一.教训

1.第一次做还是采用老的编程思想,去琢磨算法,做了一个改良版的冒泡排序来交换每个块的数字,但是忙活了一天以失败而告终,因为好不容易换到边界,又被后面的循环换回来了;

2.第二次做还是采用了3层for循环的结构,单独做把非零数字交换到目标方向的操作,然后就研究网上一个可以实现矩阵旋转的方法,简单的说就是先按一个方向做好算法,然后写一个方法把整个二维数组顺时针倒转到写好算法的方向,排序完再逆时针倒转回去,这是个巧妙的办法,但是自己没弄完全弄懂,也没写出来。

3.周五下午老师开始讲怎么用面向对象的思想做这个游戏,先分析整个游戏世界的组成,找出最基础的元素,然后将这些共性写成一个基类,然后其他的块都在这个基类上画自己的,16个块的数字交换也是面向对象的,给每一个块做好自己的移动方向,这个方法根据移动方向接受一个目标块,然后向目标块移动和判断。主函数里只写了输入4个方向后二维数组遍历的顺序,其他都是整理数据,就这么简单的做完了。

4.其实在自己第一次做的时候就想过用面向对象的思想,给每个块写方法,但是不知道如何下手。

5.罗列一下周末自己重写卡住的地方:写继承于基类的CELL类时想不清继承后重写Draw方法的逻辑;画完记分板和16个块后发现数字投影下一小块的底色是黑色和设置颜色突兀,其实是重写时没有将前景色设置成属性里的forecolor;写每个块的移动方法时,想不清为啥写2个方法,然后为何互相调用,以及和主函数4个遍历for循环的关系;写死亡判定时卡在if和if else,后面完成后测试发现没区别;写随机数产生的方法时卡在如果没有等于0的块但是有能合并块时跳不出循环;当前分数和最高分数的逻辑;输入方向的x,y与数组下标[0,1]的对应关系;最后就是外部引用的调色基类colorsetter的使用。

二.思路

1.先分析游戏的规律,写下来

2.然后从共同的基类开始一层一层写下来

3.重点是写单个块的移动逻辑,根据输入方向给出一个目标块,使得朝目标块移动,交换数字或合并,标记状态是否移动或合并过,然后用for循环按既定方向调用每个块的方法,例如如果按下的是向左,就从左至右遍历,目标块在左。

4.常见BUG:一行或一列合并次数超过1次;有移动或合并才能产生新的随机数;数字满屏且没死亡时无法移动;真正死亡时无法结束游戏;清屏console.clear()带来的闪屏问题。


三.代码

一共有4个类:Program,GameObject,Cell,Board,另外还引用了一个调色的类库ColorSetter

Program:

class Program
    {
        public static Cell[,] cells; //定义静态字段Cell数组
        public static Board scoreBoard;//定义静态字段计分板
        public static GameObject go;//定义静态字段画大背景
        public static Random roll = new Random();//定义静态字段随机数
        public static int randomNum;//随机数变量
        public static int consoleX = GameObject.startPoint.x;//代替起始点
        public static int consoleY = GameObject.startPoint.y;//代替起始点
        public static bool isGameOver = false;//检测游戏是否结束
        public static bool isNewRound = false;//检测游戏是否结束

        static void Main(string[] args)
        {
            char input = ' ';
            bool isRightInput = false;
            int directionX = 0;//记录方向向量
            int directionY = 0;//记录方向向量


            Console.Title = "2048";
            Console.WindowWidth = 56;
            Console.WindowHeight = 26;
            Console.CursorVisible = false;//隐藏光标


            //初始化16个Cell
            SetCells();
            //起始为2个随机数
            RandomNum();
            RandomNum();
            //画大背景
            DrawBackGroud();
            //画小背景
            DrawSmallBackGroud();


               
            //循环开始 ↓
            while (!isGameOver)
            {
                //部分清理屏幕
                ClearPartConsole();
                //如果是重新开始,则给出2个开始数
                if (isNewRound)
                {
                    RandomNum();
                    RandomNum();
                }
                isNewRound = false;


                //画历史最高分数
                DrawRecordBoards();
                //画计分板
                DrawScoreBoard();
                //画数字和背景格
                DrawCells();


                //检测输入,选择方向
                #region 输入检测
                input = Console.ReadKey(true).KeyChar;
                while (!isRightInput)
                {
                    switch (input)
                    {
                        case 'w': isRightInput = true; directionX = GameObject.up.x; directionY = GameObject.up.y; break;
                        case 's': isRightInput = true; directionX = GameObject.down.x; directionY = GameObject.down.y; break;
                        case 'a': isRightInput = true; directionX = GameObject.left.x; directionY = GameObject.left.y; break;
                        case 'd'

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值