zoukankan      html  css  js  c++  java
  • 2048 控制台版(C#)

    开篇

            2048游戏现在很火啊,很多人应该已经玩过了。在博客园上也看见有人模仿做的GDI+版 2048游戏,鄙人暂且不做那么多动画的东西,毕竟是个小东东,在此奉上一个《控制台版2048》。

    本文程序源码下载:http://pan.baidu.com/s/1mg8zntu 

    程序结构相对简单,一共200+行代码,注释很少,大家大概也看得懂,我在这解释下程序中各个方法的含义:
    Main 方法程序入口,
    RePaint 类似Win32程序中的刷新界面,
    SquareRot90 矩形矩阵顺时针旋转90度角(参数可以为负,表示逆时针)。
    Merge 向左移动,合并单元格中值相同的元素,并进行整理(将所有元素靠左放置)
    RandomPoint 随机生成点,从矩阵的空位置(值为0)中随机生成一个点,若不存在空位置返回null。
    CanMove 判断是否可以继续移动,也是判断游戏是否结束的方法。
    IsEquals 判断两矩阵的值是否相同。
    CopyToB 将矩阵复制一份。
    流程图如下:
    上代码
     
    主函数Main
    static void Main(string[] args)
    {
        int[,] a = new int[4, 4];
        a[1, 2] = 2;
        a[2, 2] = 2;
        a[2, 1] = 2;
        RePaint(a);
        while (true)
        {
            ConsoleKeyInfo key = Console.ReadKey();
            switch (key.Key)
            {
                case ConsoleKey.UpArrow:
                    a = SquareRot90(a, 3);
                    a = Merge(a);
                    a = SquareRot90(a, -3);
                    break;
                case ConsoleKey.DownArrow:
                    a = SquareRot90(a, 1);
                    a = Merge(a);
                    a = SquareRot90(a, -1);
                    break;
                case ConsoleKey.LeftArrow:
                    a = Merge(a);
                    break;
                case ConsoleKey.RightArrow:
                    a = SquareRot90(a, 2);
                    a = Merge(a);
                    a = SquareRot90(a, -2);
                    break;
            }
            Point cp = RandomPoint(a);
            if (cp != null)
            {
                a[cp.X, cp.Y] = 2;
                RePaint(a);
            }
            if (cp == null && !CanMove(a))
            {
                RePaint(a, "Game Over");
            }
        }
    }
    

      

    矩阵旋转方法
    /// 矩形顺时针旋转90°
    /// </summary>
    /// <param name="rotNum">旋转次数</param>
    public static int[,] SquareRot90(int[,] a, int rotNum)
    {
        while (rotNum < 0)
        {
            rotNum += 4;
        }
        for (int rot_i = 0; rot_i < rotNum; rot_i++)
        {
            int[,] b = new int[a.GetLength(1), a.GetLength(0)];
            for (int i = 0; i < a.GetLength(0); i++)
            {
                for (int j = 0; j < a.GetLength(1); j++)
                {
                    b[j, a.GetLength(0) - i - 1] = a[i, j];
                }
            }
            a = b;
        }
        return a;
    }
    

      

    随机点方法
    public static Point RandomPoint(int[,] a)
    {
        List<Point> lstP = new List<Point>();
        for (int i = 0; i < a.GetLength(0); i++)
        {
            for (int j = 0; j < a.GetLength(1); j++)
            {
                if (a[i, j] == 0)
                {
                    lstP.Add(new Point(i, j));
                }
            }
        }
        if (lstP.Count == 0)
        {
            return null;
        }
        int rnd = new Random().Next(lstP.Count);
        return lstP[rnd];
    }
    

      

    矩阵向左合成方法
    public static int[,] Merge(int[,] a)
    {
        for (int i = 0; i < a.GetLength(0); i++)
        {
            int lastNum = 0;
            int last_j = 0;
            for (int j = 0; j < a.GetLength(1); j++)//合并
            {
                if (lastNum != a[i, j] && a[i, j] != 0)
                {
                    lastNum = a[i, j];
                    last_j = j;
                }
                else if (lastNum == a[i, j])
                {
                    a[i, last_j] = 0;
                    a[i, j] = lastNum + a[i, j];
                }
            }
            last_j = 0;
            for (int j = 0; j < a.GetLength(1); j++)//整理
            {
                if (a[i, j] != 0)
                {
                    a[i, last_j] = a[i, j];
                    if (last_j != j)
                        a[i, j] = 0;
                    last_j++;
                }
            }
        }
        return a;
    }
    

      

    是否可以继续移动CanMove方法
    public static bool CanMove(int[,] a)
    {
        bool res = false;
        int[,] b = CopyToB(a);
        b = Merge(b);
        if (!IsEquals(a, b))
            res = true;
        b = CopyToB(a);
        b = SquareRot90(b, 1);
        b = Merge(b);
        b = SquareRot90(b, -1);
        if (!IsEquals(a, b))
            res = true;
        b = CopyToB(a);
        b = SquareRot90(b, 2);
        b = Merge(b);
        b = SquareRot90(b, -2);
        if (!IsEquals(a, b))
            res = true;
        b = CopyToB(a);
        b = SquareRot90(b, 3);
        b = Merge(b);
        b = SquareRot90(b, -3);
        if (!IsEquals(a, b))
            res = true;
        return res;
    }
    

      

    CanMove中用到的IsEquals方法,判断矩阵相等
    public static bool IsEquals(int[,] a, int[,] b)
    {
        bool res = true;
        for (int i = 0; i < a.GetLength(0); i++)
        {
            for (int j = 0; j < a.GetLength(1); j++)
            {
                if (b[i, j] != a[i, j])
                {
                    res = false;
                    break;
                }
            }
            if (!res)
                break;
        }
        return res;
    }
    

      

    CanMove中用到的矩阵复制方法CopyToB
    public static int[,] CopyToB(int[,] a)
    {
        int[,] b = new int[a.GetLength(0), a.GetLength(1)];
        for (int i = 0; i < a.GetLength(0); i++)
        {
            for (int j = 0; j < a.GetLength(1); j++)
            {
                b[i, j] = a[i, j];
            }
        }
        return b;
    }
    

      

    两个RePain方法,重新打印,前面的表示GameOver
    public static void RePaint(int[,] a, string s)
    {
        while (true)
        {
            Console.Clear();
            RePaint(a);
            Console.WriteLine("
    
    
    
    		" + s + "
    
    ");
            Console.ReadKey();
        }
    }
    public static void RePaint(int[,] a)
    {
        Console.Clear();
        for (int j = 0; j < a.GetLength(1); j++)
        {
            Console.Write("───");
        }
        Console.Write("
    ");
        for (int i = 0; i < a.GetLength(0); i++)
        {
            Console.Write("│");
            for (int j = 0; j < a.GetLength(1); j++)
            {
                string s = "";
                if (a[i, j] == 0)
                    s = "   ";
                else if (a[i, j] < 10)
                    s = " " + a[i, j] + " ";
                else if (a[i, j] < 100)
                    s = "" + a[i, j] + " ";
                else
                    s = "" + a[i, j];
                Console.Write(s + "│");
            }
            Console.Write("
    ");
            for (int j = 0; j < a.GetLength(1); j++)
            {
                Console.Write("───");
            }
            Console.Write("
    ");
        }
    }
    

      

    辅助类Point
    class Point
    {
        public Point(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
        public int X
        {
            get;
            set;
        }
        public int Y
        {
            get;
            set;
        }
    }
    

      

    结束语
         其实要写一个游戏并不是像想像中那么容易,要处理算法等问题,必须要事先仔细的设计,需要一张草纸作为设计图,这样会让工作效率大大提高。之前贴过毕设的游戏《保卫萝卜》,由于时间关系迟迟没有整理,等毕设答辩完成后,一定好好整理,给大家分享。现在功能基本完成了,在这先贴一个缩减版的游戏程序,链接: http://pan.baidu.com/s/1sjvxO7N 。程序有什么问题、BUG,希望大家多多留言。源码整理后再上传。
         过几天是蓝桥杯比赛,哈哈,北京我来了。
    本文程序源码下载:http://pan.baidu.com/s/1mg8zntu 
     
  • 相关阅读:
    maven项目的构建命令
    linux的find命令
    python函数中参数前面的*和**的含义
    python中字典和集合的使用
    python中列表和元组的基本操作
    在Python中写中文注释格式
    linux 文件操作基本命令
    linux脚本实现递归阶乘
    base64
    从DispatcherServlet中的doService了解spring组件之间的处理流程
  • 原文地址:https://www.cnblogs.com/yinlong1991/p/3754846.html
Copyright © 2011-2022 走看看