夜光带你走进C# 游戏开发等(七十二)擅长的领域

夜光序言:

 

凡事都有前因后果,笨鸟为什么先飞?缘于坚持不懈,勤奋练习;江郎为什么才尽?只因得意忘形,终日饱食。种豆得豆,种瓜得瓜,因果报应,环环相扣。

 

 

 

 

 

 

正文:

 

 

 

 

 

 

 

 

 

 

 

贪吃蛇完整的

     -- 夜光项目代码:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 测试1
{
    //夜光:定义一个方向
    //枚举值类型
    enum Direction
    {
        Left,
        Right,
        Up,
        Down,
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 测试1
{
    class Snake
    {

        //下面我们建立一个单例
        private static Snake instance = null;

        public static Snake Instance()
        {
            if (instance == null)
            {
                instance = new Snake();
            }

            return instance;
        }


        //这里,我们需要定义一个蛇的每一节
        //用泛型数组
        //一开始就把蛇的身体给创建出来
        List<Point> body = new List<Point>();
        //把蛇的方向给设置好
        Direction dir = Direction.Right;


        Point tail; //定义一个尾部,默认值就是(0,0)

        /// <summary>
        /// 用于做数据初始化
        /// </summary>
        public void Start()
        {
            //之前我们学过构造函数的吧
            //。。靓仔,写一下
            body.Add(new Point(4,2));
            body.Add(new Point(3,2));
            body.Add(new Point(2,2));


        }

        //判断游戏是否结束
        //肯定是布尔类型
        //判断依据
        //1.蛇头是否撞上墙
        //2.蛇头是否触碰到自己身体
        private bool IsGameOver()
        {
            /*            //我们可以抛出一个异常
                        throw new NotImplementedException();*/
            Point head = body[0];  //蛇头的坐标

            //1.蛇头是否撞上墙
            if (Map.Instance().GetAt(head) == Map.Wall)
                return true;

            //2.蛇头是否触碰到自己身体
            for(int i = 1; i < body.Count; i++)
            {
                if(body[i] == head)
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 夜光:处理转向判断
        /// 注意:只能往蛇的前进方向的侧方向
        /// 1.获取按键输入
        /// 2.判定是否可以移动
        /// 3.改变dir
        /// </summary>
        private void Turn()
        {
            //1.获取按键输入
            if (Console.KeyAvailable)
            {
                ConsoleKey key = Console.ReadKey(true).Key;

                //2.判定是否可以移动
                if(key == ConsoleKey.LeftArrow && dir != Direction.Right)
                {
                    dir = Direction.Left;
                }
                else if(key == ConsoleKey.RightArrow && dir != Direction.Left)
                {
                    dir = Direction.Right;

                }
                else if (key == ConsoleKey.UpArrow && dir != Direction.Down)
                {
                    dir = Direction.Up;

                }
                else if (key == ConsoleKey.DownArrow && dir != Direction.Up)
                {
                    dir = Direction.Down;

                }
            }

        }

        /// <summary>
        /// 根据蛇的移动方向dir,在地图上前行
        /// </summary>
        private void Move()
        {
            Point offset = new Point(0,0); //我们定义一个偏移的变量
            //并且给他一个默认值
            //夜光:我们switch一下
            switch (dir)
            {
                case Direction.Left:
                    offset = new Point(-1, 0);
                    break;
                case Direction.Right:
                    offset = new Point(1, 0);
                    break;
                case Direction.Up:
                    offset = new Point(0, -1);
                    break;
                case Direction.Down:
                    offset = new Point(0, 1);
                    break;
            }

            Point head = body[0]; //夜光(2,4)第二列第四行
            // head += offset  至于怎么写,后面再说
            head = head + offset;//(2,4)+(1,0)  需要写一个加运算符的重载

            //夜光:插入元素
            body.Insert(0, head);  //插入头部

            tail = body[body.Count -1]; // 增加蛇的身体
            //数组减1的位置
            body.RemoveAt(body.Count - 1);  //删除尾巴,操作

        }

        /// <summary>
        /// 判定蛇头位置是否有食物,如果有,则
        /// 1.在地图上删除该位置的食物
        /// 2.蛇的身体增加一节
        /// 3.重新生成一个食物
        /// </summary>
        private void Eat()
        {
            Point head = body[0]; //我们先把蛇头位置给取出来

            if(Map.Instance().GetAt(head) == Map.Food)
            {
                // 1.在地图上删除该位置的食物
                //设置成一个空地,blank
                Map.Instance().SetAt(head, Map.Blank);

                // 2.蛇的身体增加一节(尾部不删除,换个思路)
                body.Add(tail);

                // 3.重新生成一个食物
                Map.Instance().GenFood();  //直接调用这个生成食物的方法
            }

        }



        public void Update()
        {
            if (IsGameOver())
                return;


            Turn();
            Move();
            Eat();
        }

        public void Draw()
        {
            for (int i=0;i<body.Count;i++)
            {
                //先把蛇的身体给保存下来
                Point pt = body[i];

                Console.SetCursorPosition(pt.x * 2, pt.y);//一个是中文格子,一个是英文格子,所以需要乘以2
                //关于颜色的设置
                //此处给蛇头一个单独的红色
                //夜光

                Console.ForegroundColor = i == 0 ? ConsoleColor.Red:ConsoleColor.Yellow;//此处设定一个判断,头部和尾部的不同颜色
                //Console.BackgroundColor = ConsoleColor.Red;


                //只有中文的空格,长宽才是一样的
                Console.Write("●");

            }


        }


    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 测试1
{
    //我们希望s2 = s1 赋值的时候
    //是把s1的内容(x,y)拷贝给s2(x,y)
    //而非让s2和s1指向同一块内存

    struct Point
    {
        public int x;
        public int y;


        public Point(int x, int y)
        {
            //学编程,明白this指向当前上方的int x
            this.x = x; //把局部变量x 赋值给成员变量x
            this.y = y;
        }

        //+运算符重载

        public static Point operator +(Point p1, Point p2)
        {
            return new Point(p1.x + p2.x, p1.y + p2.y);
        
        }


        //-运算符重载
        public static bool operator==(Point p1, Point p2)
        {
            return p1.x == p2.x && p1.y == p2.y;
        }

        //取反一下,试试
        public static bool operator !=(Point p1, Point p2)
        {
            return !(p1 == p2);
        }

    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 测试1
{        //夜光
         //这个是地图类,主要用来绘制贪吃蛇地图
    class Map
    {

        //下面我们建立一个单例
        private static Map instance = null;

        public static Map Instance()
        {
            if(instance == null)
            {
                instance = new Map();
            }

            return instance;
        }

        /// <summary>
        /// 地图块类型
        /// </summary>
       /* enum TileType   想了想,做成枚举值,太麻烦,还是做成常量
        {
            Blank,
            Wall,
            Food,
        }*/
        public const int Blank = 0;
        public const int Wall = 1;
        public const int Food = 2;
        
        private int[,] map = null;  //夜光:设计思想
        //设置成私有的

        /// <summary>
        /// 为了生成食物,定义的一个随机数
        /// </summary>
        private Random rnd = new Random();

        public int GetAt(Point pt)
        {
            return map[pt.y,pt.x];
        }

        /// <summary>
        /// 写一个让食物消失的方法
        /// 没有返回值,是设定
        /// </summary>
        /// <param name="pt"></param>
        public void SetAt(Point pt,int value)
        {
            map[pt.y, pt.x] = value;
        }

        //我们写一个生成食物的方法
        //夜光:写在map类里面
        /// <summary>
        /// 规则:
        /// 1.只能在空地上生成
        /// 2.不可以在蛇的身体上生成(这个暂时不需要~~)
        /// </summary>
        public void GenFood()
        {
            Point pt;
            for(; ; )
            {
                //这就是死循环,那么什么时候退出呢
                //x和y的生成
                pt.x = rnd.Next(map.GetLength(1));
                pt.y = rnd.Next(map.GetLength(0));
                //下面就是判断
                if(GetAt(pt) == Map.Blank)
                {
                    map[pt.y, pt.x] = Map.Food;
                    return;
                }

            }
        }


        /// <summary>
        /// 用于做数据初始化
        /// </summary>
        public void Start()
        {
            //边缘一圈是墙
            map = new int[20, 20]
            {
            {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
            {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},
            };

            GenFood();

        }




        /// <summary>
        /// 存放逻辑处理(数据运算)
        /// </summary>
        public void Update()
        {
           /* //抛出异常
            throw new NotImplementedException(); //未实现的异常*/
            
        }



        /// <summary>
        /// 图形绘制
        /// </summary>
        public void Draw()
        {
            for(int i = 0;i < map.GetLength(0); i++)  //行
            {
                for(int j=0;j< map.GetLength(1); j++)  //列
                {
                    Console.SetCursorPosition(j*2,i);
                    //关于颜色的设置
                    //前景色和背景色
                    //Console.ForegroundColor = ConsoleColor.Yellow;
                   
                    switch (map[i, j])
                    {
                        case Map.Wall:
                            Console.BackgroundColor = ConsoleColor.Gray;
                            Console.ForegroundColor = ConsoleColor.Gray;
                            //只有中文的空格,长宽才是一样的
                            Console.Write("  ");
                            break;
                        case Map.Food:
                            Console.BackgroundColor = ConsoleColor.Gray;
                            Console.ForegroundColor = ConsoleColor.DarkCyan;
                            //只有中文的空格,长宽才是一样的
                            Console.Write("●");
                            break;
                        case Map.Blank:
                            Console.BackgroundColor = ConsoleColor.Gray;
                            Console.ForegroundColor = ConsoleColor.DarkCyan;
                            //只有中文的空格,长宽才是一样的
                            Console.Write("  ");
                            break;
                    }

                   

                }
            }
        }

    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace 测试1
{
    class Program
    {
        static void Main(string[] args)
        {
            //夜光:我们做一个贪吃蛇的游戏
            //首先,根据单例,初始化两个
            Snake.Instance().Start();
            Map.Instance().Start();

            //之后写一个for循环
            for(; ; )
            {
                //为什么晃得很厉害
                //一帧(frame)画面

                Snake.Instance().Update();
                Map.Instance().Update();

               
                Map.Instance().Draw();  //先画地图再画蛇
                Snake.Instance().Draw();

                //针对之前的闪烁问题
                //我们可以使用休眠的方式来缓解
                Thread.Sleep(100);

            }
     
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值