C# 之 380行代码写出命令行版-2048

C# 之 380行代码写出命令行版2048

游戏规则:

游戏的规则很简单,你需要控制所有方块向同一个方向运动,两个相同数字方块撞在一起之后合并成为他们的和,每次操作之后会随机生成一个2或者4,最终得到一个“2048”的方块就算胜利了。


主要逻辑:

  1. 4*4的数组, 然后遍历里面的元素,统计所有的0,放到一个list里面,然后Random.next(0,list.count)随机一个赋成2.
  2. 循环开始,初始化命令行.
  3. 键盘输入上下左右 对应四种操作的函数 操作之后先遍历一下有没有空格 如果有就继续 没有空格还得再判断一下能不能再动了 如果不能就死了
  4. 如果有任何一个元素是2048 即获胜

看看效果:
2048.gif


using System;
using System;
using System.Collections.Generic;//  4*4的数组, 然后遍历里面的元素,统计所有的0,放到一个list里面,然后Random.next(0,list.count)随机一个赋成2.
//  循环开始.
//  键盘输入上下左右 对应四种操作的函数  操作之后先遍历一下有没有空格 如果有就继续 没有空格还得再判断一下能不能再动了 如果不能就死了
//  如果有任何一个元素是2048 即获胜​namespace CSharp_2048
{
    class Program
    {
        static void Main(string[] args)
        {
            Class2048 class2048 = new Class2048();
            class2048.GameStart();
        }
        /// <summary>
        /// 游戏类2048
        /// </summary>
        class Class2048
        {
            public int[,] arr = new int[4, 4];
            public Random rd = new Random();
            public List<CoordinateTools> listOfCoo = new List<CoordinateTools>();
            /// <summary>
            /// 输出当前状态
            /// </summary>
            public void Output()
            {
                string str = "    ";
                Console.Clear();
                Console.WriteLine("┏┉┉┉┉┉┉┉┉┳┉┉┉┉┉┉┉┉┳┉┉┉┉┉┉┉┉┳┉┉┉┉┉┉┉┉┓");
                Console.WriteLine("┋        ┋        ┋        ┋        ┋");
                Console.WriteLine("┋ {0}   ┋  {1}  ┋  {2}  ┋  {3}  ┋", arr[0, 0] == 0 ? str : arr[0, 0].ToString().PadLeft(4, ' '), 
                    arr[0, 1] == 0 ? str : arr[0, 1].ToString().PadLeft(4, ' '), arr[0, 2] == 0 ? str : arr[0, 2].ToString().PadLeft(4, ' '), arr[0, 3] == 0 ? str : arr[0, 3].ToString().PadLeft(4, ' '));
                Console.WriteLine("┋        ┋        ┋        ┋        ┋");
                Console.WriteLine("┣┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉┫");
                Console.WriteLine("┋        ┋        ┋        ┋        ┋");
                Console.WriteLine("┋  {0}  ┋  {1}  ┋  {2}  ┋  {3}  ┋", arr[1, 0] == 0 ? str : arr[1, 0].ToString().PadLeft(4, ' '), 
                    arr[1, 1] == 0 ? str : arr[1, 1].ToString().PadLeft(4, ' '), arr[1, 2] == 0 ? str : arr[1, 2].ToString().PadLeft(4, ' '), arr[1, 3] == 0 ? str : arr[1, 3].ToString().PadLeft(4, ' '));
                Console.WriteLine("┋        ┋        ┋        ┋        ┋");
                Console.WriteLine("┣┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉┫");
                Console.WriteLine("┋        ┋        ┋        ┋        ┋");
                Console.WriteLine("┋  {0}  ┋  {1}  ┋  {2}  ┋  {3}  ┋", arr[2, 0] == 0 ? str : arr[2, 0].ToString().PadLeft(4, ' '),
                    arr[2, 1] == 0 ? str : arr[2, 1].ToString().PadLeft(4, ' '), arr[2, 2] == 0 ? str : arr[2, 2].ToString().PadLeft(4, ' '), arr[2, 3] == 0 ? str : arr[2, 3].ToString().PadLeft(4, ' '));
                Console.WriteLine("┋        ┋        ┋        ┋        ┋");
                Console.WriteLine("┣┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉┫");
                Console.WriteLine("┋        ┋        ┋        ┋        ┋");
                Console.WriteLine("┋  {0}  ┋  {1}  ┋  {2}  ┋  {3}  ┋", arr[3, 0] == 0 ? str : arr[3, 0].ToString().PadLeft(4, ' '),
                    arr[3, 1] == 0 ? str : arr[3, 1].ToString().PadLeft(4, ' '), arr[3, 2] == 0 ? str : arr[3, 2].ToString().PadLeft(4, ' '), arr[3, 3] == 0 ? str : arr[3, 3].ToString().PadLeft(4, ' '));
                Console.WriteLine("┋        ┋        ┋        ┋        ┋");
                Console.WriteLine("┗┉┉┉┉┉┉┉┉┻┉┉┉┉┉┉┉┉┻┉┉┉┉┉┉┉┉┻┉┉┉┉┉┉┉┉┛");
​
                Console.WriteLine("\n<<命令行版2048>> 请按上下左右(↑←↓→)方向键操作");
            }
            /// <summary>
            /// 遍历非零元素 随机把一个赋为2
            /// </summary>
            public void Add2()
            {
                listOfCoo.Clear();
                for (int i = 0; i < 4; i++)   //遍历所有零元素的坐标
                {
                    for (int j = 0; j < 4; j++)
                    {
                        if (arr[i, j] == 0)
                        {
                            CoordinateTools coo = new CoordinateTools(i, j);      //把遍历到的坐标 当成参数 实例化
                            listOfCoo.Add(coo);                         //把实例化的结果add到list里
                        }
                    }
                }
                if (listOfCoo.Count == 0)                               //如果列表里一个元素都没存进来 说明表里没有空格了 直接退出
                {
                    return;
                }
                int cooPlus = rd.Next(0, listOfCoo.Count);              //从表里随机取一个位置 
​
                arr[listOfCoo[cooPlus].x, listOfCoo[cooPlus].y] = 2;    // 把这个位置赋值改写为2
            }
            /// <summary>
            /// 游戏开始
            /// </summary>
            public void GameStart()
            {
                Add2();
                Add2();
                Output();
                while (true)
                {
                    bool flag = false;            //用于遍历检测按下按键之后和之前有没有区别用的bool型变量
                    foreach (int item in arr)     //胜利条件 遍历
                    {
                        if (item == 2048)
                        {
                            Console.WriteLine("\n(ノ´▽`)ノ♪ ------ 游戏胜利 ------ (ノ´▽`)ノ♪");
                            Last();
                        }
                    }
                    int[,] arrtmp = new int[4, 4];  //这是用于检测按下按键之后和之前有没有区别用的备份数组for (int i = 0; i < 4; i++)    //遍历给备份数组赋值
                    {
                        for (int j = 0; j < 4; j++)
                        {
                            arrtmp[i, j] = arr[i, j];
                        }
                    }ConsoleKeyInfo info = Console.ReadKey(true);  //选择功能
                    switch (info.Key)
                    {
                        case ConsoleKey.UpArrow:
                            MoveUp();
                            break;
                        case ConsoleKey.DownArrow:
                            MoveDown();
                            break;
                        case ConsoleKey.LeftArrow:
                            MoveLeft();
                            break;
                        case ConsoleKey.RightArrow:
                            MoveRight();
                            break;
                    }for (int i = 0; i < 4; i++)        //遍历检测 按下方向键前的状态 和  按下方向键之后的状态是不是完全一样的
                    {
                        for (int j = 0; j < 4; j++)
                        {
                            if (arrtmp[i, j] != arr[i, j])
                            {
                                flag = true;          //一旦有任意一个元素在之前之后不一样  那么falg改为TRUE
                            }
                        }
                    }
                    if (flag)
                    {
                        Add2();    //如果falg是true 说明变了, 如果变了 就刷一个2出来,  反之就什么也不干
                    }
                    Output();     //输出if (!End())   //检测按下方向键之后死没死
                    {
                        Console.WriteLine("\n(;´д`)ゞ  ------ 游戏失败 ------ (;´д`)ゞ");
                        Last();
                    }
                }
            }#region 核心逻辑 --> 向四个方向移动的控制
            //向下 非0数向下移动,遇到非0数,相同则累加,不同则保存到当前位置
            public void MoveDown()
            {
                for (int j = 0; j < 4; j++)
                {
                    for (int i = 2; i >= 0; i--)
                    {
                        if (arr[i, j] == 0) continue;
                        for (int k = i + 1; k < 4; k++)
                        {
                            if (arr[k, j] != 0)
                            {
                                if (arr[i, j] == arr[k, j])
                                {
                                    arr[k, j] += arr[i, j];
                                    arr[i, j] = 0;
                                    break;
                                }
                                else if (arr[i, j] != arr[k, j] && k - 1 != i)
                                {
                                    arr[k - 1, j] = arr[i, j];
                                    arr[i, j] = 0;
                                    break;
                                }
                                else if (arr[i, j] != arr[k, j] && k - 1 == i)
                                {
                                    break;
                                }
                            }
                            if (k == 3)
                            {
                                arr[k, j] = arr[i, j];
                                arr[i, j] = 0;
                                break;
                            }
                        }
                    }
                }
            }
            //向上移动: 先把数组上下翻转 然后向下移动  移动完了再翻转回来
            public void MoveUp()
            {
                for (int i = 0; i < 2; i++)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        int tmp = 0;
                        tmp = arr[i, j];
                        arr[i, j] = arr[3 - i, j];
                        arr[3 - i, j] = tmp;
                    }
                }
                MoveDown();
                for (int i = 0; i < 2; i++)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        int tmp = 0;
                        tmp = arr[i, j];
                        arr[i, j] = arr[3 - i, j];
                        arr[3 - i, j] = tmp;
                    }
                }}
            //向左移动 
            public void MoveLeft()
            {
                for (int i = 0; i < 4; i++)
                {
                    for (int j = 1; j < 4; j++)
                    {
                        if (arr[i, j] == 0) continue;
                        for (int k = j - 1; k >= 0; k--)
                        {
                            if (arr[i, k] != 0)
                            {
                                if (arr[i, j] == arr[i, k])
                                {
                                    arr[i, k] += arr[i, j];
                                    arr[i, j] = 0;
                                    break;
                                }
                                else if (arr[i, j] != arr[i, k] && k + 1 != j)
                                {
                                    arr[i, k + 1] = arr[i, j];
                                    arr[i, j] = 0;
                                    break;
                                }
                                else if (arr[i, j] != arr[i, k] && k + 1 == j)
                                {
                                    break;
                                }
                            }
                            if (k == 0)
                            {
                                arr[i, k] = arr[i, j];
                                arr[i, j] = 0;
                                break;
                            }
                        }}
                }
            }
            //向右移动: 先把数组左右翻转 然后向左移动  移动完了再翻转回来
            public void MoveRight()
            {
                for (int j = 0; j < 2; j++)
                {
                    for (int i = 0; i < 4; i++)
                    {
                        int tmp = 0;
                        tmp = arr[i, j];
                        arr[i, j] = arr[i, 3 - j];
                        arr[i, 3 - j] = tmp;
                    }
                }
                MoveLeft();
                for (int j = 0; j < 2; j++)
                {
                    for (int i = 0; i < 4; i++)
                    {
                        int tmp = 0;
                        tmp = arr[i, j];
                        arr[i, j] = arr[i, 3 - j];
                        arr[i, 3 - j] = tmp;
                    }
                }
​
​
​
            }
            #endregion
            /// <summary>
            /// 判断是否失败
            /// </summary>
            /// <returns></returns>
            public bool End()
            {
                //遍历数组 有任何一个空元素都说明不可能死
                foreach (int item in arr)
                {
                    if (item == 0)
                        return true;
                }//从2开始到2048进行遍历   目的是检测 每一个数字 他上下左右相邻有没有和他一样的数字 
                for (int num = 2; num <= 2048; num *= 2)
                {
​
                    List<CoordinateTools> listOfget2 = new List<CoordinateTools>();for (int i = 0; i < 4; i++)
                    {
                        for (int j = 0; j < 4; j++)
                        {
                            if (arr[i, j] == num)
                            {
                                CoordinateTools coo = new CoordinateTools(i, j);   //先把所有值为NUM的元素的下标 存到list里
                                listOfget2.Add(coo);
                            }
                        }
                    }if (listOfget2 == null)   //如果这个list 是空的  就说明当前表里没有num 回到FOR继续
                    {
                        continue;
                    }//从列表里的第一个元素开始 (每一个元素存的都是一组下标x,y)
                    foreach (CoordinateTools item in listOfget2)
                    {
                        foreach (CoordinateTools item2 in listOfget2)
                        {if ((item.y == item2.y && Math.Abs(item.x - item2.x) == 1) || (item.x == item2.x && Math.Abs(item.y - item2.y) == 1))  //判断 同一行的是不是列坐标差的绝对值是1  同一列的是不是行坐标差的绝对值是1
                            {
                                return true;    //如果有一个 就不用再循环了 肯定没死
                            }
                        }
                    }
                }
                return false;  //全遍历完了还一个TURE都没有 就说明已经死了 返回false
            }
            /// <summary>
            /// 胜利或失败之后的选择
            /// </summary>
            public void Last()
            {
                Console.WriteLine("\n输入X退出 输入R重新开始\n");
                while (true)
                {
                    string str = Console.ReadLine();
                    if (str == "x")
                    {
                        Environment.Exit(0);
                    }
                    //重新开始 --> 初始化
                    if (str == "r")
                    {
                        for (int i = 0; i < 4; i++)
                        {
                            for (int j = 0; j < 4; j++)
                            {
                                arr[i, j] = 0;
                            }
                        }
                        GameStart();
                    }
                }
            }
        }
        /// <summary>
        /// 工具类 用于存储搜索到的数组的下标
        /// </summary>
        class CoordinateTools
        {
            public int x { set; get; }
            public int y { set; get; }
            public CoordinateTools(int i, int j)
            {
                this.x = i;
                this.y = j;
            }
        }
    }
}

效果图

发布了475 篇原创文章 · 获赞 682 · 访问量 52万+

猜你喜欢

转载自blog.csdn.net/Czhenya/article/details/105009540