c#生成2048(2)

2048(1)的链接
修正BUG

如果无法进行移动和合并,就无法生成随机数字

增加功能

可以将最大的分数储存在本地,并读取

游戏界面
这里写图片描述
游戏文件密码: f3ma

代码主要更新了Grid类其他类没有改动
代码

using System;
using System.Collections.Generic;
using System.IO;

namespace Project2048
{
    /// <summary>
    /// 网格类
    /// </summary>
    public class Grid
    {
        int row = 4;//行数
        int cols = 4;//列数
        Box[,] boxList;//数组,储存
        bool isFirst = true; //判断是否是第一次生成随机数
        int count = 0; //选择产生每一次随机生成数字的数量,1or2
        int num = 2; //储存上次随机生成数
        int countNum = 0; //储存生成了的数字的数量,一到16个以便进行游戏输赢判断
        bool gameBegin; //游戏开关
        Queue<Box> isMerage;//判断是是否已经合并集合
        Random r;
        bool isMakeRandom; //无法移动格局上的数时,无法产生随机数
        int BoxNum; //存储当前格子里叠加的数,如果是2048则取得游戏胜利
        private int scorce;//当前分数
        private  int maxScore;//最高分数

        public Grid(int row, int cols)
        {
            this.row = row < 0 ? this.row : row;
            this.cols = cols < 0 ? this.cols : cols;
            boxList = new Box[row, cols];
            r = new Random();
            isMerage = new Queue<Box>();
            gameBegin = true; //初始化游戏开始
            isMakeRandom = false;
            scorce = 0;
            maxScore = getMaxScore() ;
        }
        /// <summary>
        /// 获取在文件里面的最高分数
        /// </summary>
        /// <returns></returns>
        private int  getMaxScore()
        {
            //55.txt用来储存最高分数
            byte[] scoreByte;
            try
            {
                scoreByte = File.ReadAllBytes("55.txt");
            }
            catch (FileNotFoundException e) //如果文件没有找到,说明还没有储存分数
            {
                return 0;
            }

            return  Int32.Parse(System.Text.UnicodeEncoding.UTF8.GetString(scoreByte));

        } 

        /// <summary>
        /// 返回游戏开关
        /// </summary>
        public bool GameBegin
        {
            get
            {
                return gameBegin;
            }
        }

        /// <summary>
        /// 初始化布局
        /// </summary>
        public void Init()
        {
            for (int i = 0; i < boxList.GetLength(0); i++)
            {
                for (int j = 0; j < boxList.GetLength(1); j++)
                {
                    Box box = new Box(i, j);
                    boxList[i, j] = box;
                }
            }
            RandomNum();
            Test();
        }

        /// <summary>
        /// 随机生成数字
        /// </summary>
        private void RandomNum()
        {
            //第一次生成两个数字
            if (isFirst)
            {
                count = 2;
                isFirst = false;
            }
            //后面每一次只生成一个数字
            else
            {
                count = 1;
            }
            countNum += count;//生成一个随机数字,个数加一,以便胜负的判断
            for (int i = 0; i < count;)//容易形成死循环,万一没有位置初始化随机数字容易陷入死循环
            {
                //随机生成下标
                int rObj = r.Next(0, row);
                int cObj = r.Next(0, cols);
                if (boxList[rObj, cObj].Num != 0) {
                    continue;

                }
                //避免出现两个4
                if (num == 4)
                {
                    num = 2;
                }
                else
                {
                    //随机生成2,4的概率 ,90%2,20%4
                    int chance = r.Next(1, 11);
                    if (chance > 10) num = 2;
                    else num = 4;
                }
                boxList[rObj, cObj].Num = num;
                i++;
            }
        }

        /// <summary>
        /// 用户输入了按键,根据按键选择移动方向的方法
        /// </summary>
        /// <param name="keyValue"></param>
       public void move(ConsoleKey keyValue)
        {
            switch (keyValue)
            {
                //W 向上
                case ConsoleKey.W: GoUp(); break;
                //S 向下
                case ConsoleKey.S: GoDown(); break;
                //A 向左
                case ConsoleKey.A: GoLetf(); break;
                //D 向右
                case ConsoleKey.D: GoRight(); break;

                default: Console.WriteLine("输入了错误的选择"); break;
            }
            ReSet();//做完一次操作后重置一下开关
        }

        /// <summary>
        /// 向右运动
        /// </summary>
        private void GoRight()
        {
                //行下标循环
                for (int r = 0; r < boxList.GetLength(0); r++)
                {
                    //列下标循环
                    for (int c = boxList.GetLength(1) - 2; c >= 0; c--) //按照每行有多少列来循环,从右边到左边
                    {
                        Box box = boxList[r, c];
                        if (box.Num == 0) continue;
                        for (int nc = c + 1; nc < boxList.GetLength(1); nc++)//数字移动的3种情况
                        {
                            Box nextBox = boxList[r, nc];
                            if (nextBox.Num == 0) //如果前面格子里没有数,就往前移
                            {
                                isMakeRandom = true;//可以移动就产生随机数
                                nextBox.Num = box.Num;
                                box.Num = 0;
                                box = nextBox;
                                continue;
                            }
                            if (box.Num == nextBox.Num && !nextBox.IsFirst)//如果格子里的数和要往前移的格子里的数是相同的,就可以合并
                            {
                                isMakeRandom = true;//可以合并,就可以产生随机数
                                //合并操作
                                nextBox.IsFirst = true;
                                nextBox.Num *= 2;
                                box.Num = 0;

                                scorce += nextBox.Num; //合并添加分数

                                countNum--;//合并后网格上的格子数减一
                                isMerage.Enqueue(nextBox);//添加了已经合并的数,便于修改合并开关
                            }
                            break;//不能移动格子,也不能合并,格子本身不做任何操作
                        }
                }
            }
            GameSwitch();//判断游戏输赢

        }

        /// <summary>
        /// 向左移动
        /// </summary>
        private void GoLetf()
        {
                //循环行下标
                for (int r = 0; r < boxList.GetLength(0); r++)
                {
                    //循环列下表
                    for (int c = boxList.GetLength(1) - 3; c < boxList.GetLength(1); c++)//按照每行有多少列来循环,从左边到右边
                    {
                        Box box = boxList[r, c];
                        if (box.Num == 0) continue;
                        for (int nc = c - 1; nc >= 0; nc--)
                        {
                        Box nextBox = boxList[r, nc];
                        if (box.Num == 0) continue;//检测当前盒子是否需要往下移动
                        if (nextBox.Num == 0)
                            {
                                isMakeRandom = true;
                                nextBox.Num = box.Num;
                                box.Num = 0;
                                box = nextBox;
                                continue;
                            }
                            if (nextBox.Num == box.Num && !nextBox.IsFirst)//合并操作
                            {
                                isMakeRandom = true;

                                nextBox.Num *= 2;
                                nextBox.IsFirst = true;
                                box.Num = 0;

                                scorce += nextBox.Num;

                                countNum--;//合并网格的元素减一
                                isMerage.Enqueue(nextBox);//添加已经合并的数,以便重置合并开关
                            }

                            break;
                        }
                }

            }
            GameSwitch();//判断游戏输赢

        }

        /// <summary>
        /// 向上移动
        /// </summary>
        private void GoUp()
        {
                //循环列下标 
                for (int c = 0; c < boxList.GetLength(1); c++)
                {
                    //循环行下标
                    for (int r = boxList.GetLength(0) - 3; r < boxList.GetLength(0); r++)  //从下到上
                    {
                        Box box = boxList[r, c];
                        if (box.Num == 0) continue;//检测当前盒子是否需要往下移动
                        for (int k = r - 1; k >= 0; k--)
                        {
                            Box nextBox = boxList[k, c];
                            if (nextBox.Num == 0)//如果上一格元素为空,则可以移动
                            {
                                isMakeRandom = true;//只要进行了移动就可以产生随机数
                                nextBox.Num = box.Num; //把前面的元素移动到后面的元素
                                box.Num = 0;
                                box = nextBox;
                                continue;
                            }
                            if (box.Num == nextBox.Num && !nextBox.IsFirst)
                            {
                                isMakeRandom = true;

                                nextBox.Num *= 2;
                                nextBox.IsFirst = true;
                                box.Num = 0;

                                 scorce += nextBox.Num;

                                countNum--;//合并网格,随机数的个数元素减一
                                isMerage.Enqueue(nextBox);//添加已经合并的数,以便修改开关
                            }

                            break;
                        }
                    }
            }

            GameSwitch();//判断游戏输赢
        }

        /// <summary>
        /// 向下的方法
        /// </summary>
        private void GoDown()
        {
                //循环列的下标
                for (var c = 0; c < boxList.GetLength(1); c++)
                {
                    for (var r = boxList.GetLength(0) - 2; r >= 0; r--)
                    {
                        Box box = boxList[r, c];//当前进行检测判断是否可以往下移动或者合并的格子
                        if (box.Num == 0) continue;
                        for (var k = r + 1; k < boxList.GetLength(0); k++)
                        {
                            Box nextBox = boxList[k, c];
                            //进行空白格子判断
                            if (nextBox.Num == 0)
                            {
                                isMakeRandom = true; //移动则可以残生随机数
                                //找到一个就往下移一个
                                nextBox.Num = box.Num;
                                box.Num = 0;
                                box = nextBox;
                                continue;
                            }
                            //进行格子合并的判断
                            if (nextBox.Num == box.Num && !nextBox.IsFirst)
                            {
                                isMakeRandom = true;
                                //合并一下
                                nextBox.Num *= 2;
                                nextBox.IsFirst = true;
                                box.Num = 0;

                                scorce += nextBox.Num;

                                isMerage.Enqueue(nextBox);//添加已经合并的数,以便重置开关
                                countNum--;//合并网格的元素减一
                            }
                            break;
                        }
                }

            }
            GameSwitch();//判断游戏输赢

        }

        /// <summary>
        /// 打印布局
        /// </summary>
        private void Test()
        {
            Console.WriteLine("当前分数:{0} 最高分数:{1}",scorce,maxScore);
            Console.WriteLine("-------------------------------");
            for (int i = 0; i < boxList.GetLength(0); i++)
            {
                for (int j = 0; j < boxList.GetLength(1); j++)
                {
                    if (boxList[i, j].Num==2048) //游戏胜利
                    {
                        BoxNum = boxList[i, j].Num;


                    }
                    Console.Write(boxList[i, j].Num + "\t");
                }
                Console.Write("\n");
            }
            Console.WriteLine("-------------------------------");
        }

        /// <summary>
        /// 重置开关
        /// </summary>
        private void ReSet()
        {
            while (isMerage.Count > 0)
            {
                isMerage.Dequeue().IsFirst = false;
            }
        }

        /// <summary>
        /// 选择实现随机数的的生成
        /// </summary>
        private void GameSwitch()
        {

            if (BoxNum == 2048)//游戏胜利
            {
                Console.WriteLine("游戏胜利");
                LayScorce();
                gameBegin = false;
            }
            if (isMakeRandom)//可以移动或者合并才能生成随机数,或者答应格局
            {
                RandomNum();
                Test();
            }

            isMakeRandom = false;//重置开关
            if (countNum == 16)//该判断一下输赢了
            {
                IsGameOver();
            }

        }

        /// <summary>
        /// 判断游戏是否输了了
        /// </summary>
        private void IsGameOver()
        {

            for (int r = 0; r < row; r++)
            {
                for (int c = 0; c < cols; c++)
                {
                    if (c + 1 < row)//如果该元素列相邻元素存在,就比较
                    {
                        if (boxList[r, c].Num == boxList[r, c+1].Num)
                        {
                            return;
                        }
                    }
                    if (r + 1 < cols)//如果该元素的行相邻元素存在,就比较
                    {
                        if (boxList[r, c].Num == boxList[r+1, c].Num)
                        {
                             return;//如果该数与行相邻相等,游戏还可以进行
                        }
                    }
                }
            }
            LayScorce();//存储分数
            gameBegin = false;
        }

        /// <summary>
        /// 储存游戏
        /// </summary>
        private void LayScorce()
        {
            if (scorce > maxScore)//只储存最大的分数
            {
                Byte[] scorceByte = System.Text.Encoding.UTF8.GetBytes(scorce.ToString());
                File.WriteAllBytes("55.txt",scorceByte);
            }
        }

    }
}

猜你喜欢

转载自blog.csdn.net/qq_38061677/article/details/81158114