首页 > 编程语言 >C# 贪吃蛇

C# 贪吃蛇

时间:2025-01-05 09:35:19浏览次数:1  
标签:Console C# System pos int 贪吃蛇 using public

UML

image-20250104100105069

image-20250104100121568

image-20250104104405816

image-20250104104707355

面向对象的七大原则

image-20250104104814137

image-20250104104917108

单一职责原则

image-20250104110000198

开闭原则

image-20250104110042532

里氏替换原则

image-20250104110135611

依赖倒转原则

image-20250104110159280

迪米特法则

image-20250104110343799

接口隔离原则

image-20250104110434025

合成复用原则

image-20250104110546070

总结

image-20250104110637584

贪吃蛇小项目

image-20250104112202729

image-20250104113234225

image-20250105092004013

BeginOrEndScene

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 贪吃蛇.lesson1;
namespace 贪吃蛇.lesson1
{
   abstract class BeginOrEndScene : IsceneUpdate
    {
        protected int nowSelIndex = 0;
        protected string strTitle;
        protected string StrOne;
        public abstract void EnterJDoSomthing();
        public void Update()
        {
            // 开始或结束游戏逻辑
            //选择当前选项,监听键盘输入

            Console.ForegroundColor = ConsoleColor.White;
            // 显示标题
            Console.SetCursorPosition(Game.w/2-strTitle.Length,5);
            Console.Write(strTitle);
            Console.SetCursorPosition(Game.w / 2 - StrOne.Length, 8);
            Console.ForegroundColor = nowSelIndex==0?ConsoleColor.Red:ConsoleColor.White;
            Console.Write(StrOne);
            Console.SetCursorPosition(Game.w / 2 -4, 10);
            Console.ForegroundColor = nowSelIndex == 1 ? ConsoleColor.Red : ConsoleColor.White;
            Console.Write("结束游戏");
            switch (Console.ReadKey(true).Key)
            {
                case ConsoleKey.W:
                    --nowSelIndex;
                    if (nowSelIndex <0)
                    {
                        nowSelIndex = 0;
                    }
                    break;
                case ConsoleKey.A:
                    ++nowSelIndex;
                    if (nowSelIndex >1)
                    {
                        nowSelIndex = 1;
                    }
                    break;
                case ConsoleKey.S:
                    ++nowSelIndex;
                    if (nowSelIndex > 1)
                    {
                        nowSelIndex = 1;
                    }
                    break;
                case ConsoleKey.D:
                    --nowSelIndex;
                    if (nowSelIndex < 0)
                    {
                        nowSelIndex = 0;
                    }
                    break;
                case ConsoleKey.J:
                    EnterJDoSomthing();
                    break;


            }

            // 显示下方选项


            // 检测输入


        }

        
    }
}

BeginScene.cs

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


namespace 贪吃蛇.lesson1
{
    internal class BeginScene : BeginOrEndScene

    {
        public BeginScene() {
            strTitle = "贪吃蛇";
            StrOne = "开始游戏";
        }

        public override void EnterJDoSomthing()
        {
            // 按J键做什么
            if (nowSelIndex == 0)
            {
                Game.ChangeScene(E_SceneType.Game);
            }
            else {
                Environment.Exit(0);
            }
        }
    }
}

Draw

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

namespace 贪吃蛇.lesson1
{
    internal interface Draw

    {
        void Draw();
    }
}

EndScene

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

namespace 贪吃蛇.lesson1
{
    internal class EndScene : BeginOrEndScene
    {
        public EndScene() {
            strTitle = "结束游戏";
            StrOne = "回到开始界面";
                
        }
        public override void EnterJDoSomthing()
        {
            // 按J键做什么
            if (nowSelIndex == 0)
            {
                Game.ChangeScene(E_SceneType.Begin);
            }
            else
            {
                Environment.Exit(0);
            }
        }
    }
}

Food

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 贪吃蛇.lesson1;

namespace 贪吃蛇.lesson1
{
    internal class Food : GameObject
    {
        public Food(Snake snake) {

            RandomPos(snake);
        }

        public override void Draw()
        {
            Console.SetCursorPosition(pos.x, pos.y);
            Console.ForegroundColor = ConsoleColor.DarkCyan;
            Console.Write("卐");
        }
        // 随机位置的行为和蛇的位置有关系

        public void RandomPos( Snake snake) {
            // 得到蛇

            // 随机位置
            Random random = new Random();
            int x = random.Next(2, Game.w/2-1)*2;
            int y = random.Next(1, Game.h / 2 - 4);
            pos = new Position(x, y);
            // 得到蛇
            // 如果重合
            if (snake.CheckSamePos(pos))
            {
                RandomPos(snake);
            }

        }

    }
}

GameObject

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

namespace 贪吃蛇.lesson1
{
    abstract class GameObject : Draw
    {
        // 可以继承接口后,可以把接口中的行为抽象行为
        //供子类实现因为是抽象行为,所以子类中是必须去实现
        // 游戏对象位置
        public Position pos;
        public abstract void Draw();
      
    }
}

游戏主逻辑

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

namespace 贪吃蛇.lesson1
{
    enum E_SceneType
    { 
        /// <summary>
        /// 开始
        /// </summary>
        Begin,
        /// <summary>
        /// 游戏
        /// </summary>
        Game,
        /// <summary>
        /// 结束
        /// </summary>
        End
    
    }
    class Game
    {
        public const int w = 80;
        public const int h = 40;
        public static IsceneUpdate nowSecene;

        public Game()
        {
            Console.CursorVisible = false;
            Console.SetWindowSize(w, h);
            Console.SetBufferSize(w, h);
            ChangeScene(E_SceneType.Begin);

        
        }
        public void Start() {
            while (true)
            {
                if (nowSecene != null)
                {
                    nowSecene.Update();
                }

            }
        }
        public static void ChangeScene(E_SceneType type)
        {
            // 切场景之前把上一个场景绘制清理
            Console.Clear();
            switch (type)
            {
                case E_SceneType.Begin:
                    nowSecene = new BeginScene();

                    break;
                case E_SceneType.Game:
                    nowSecene = new GameScene();
                    break;
                case E_SceneType.End:
                    nowSecene = new EndScene();
                    break;
               
            }
        }

    }
    
}

GameScene.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 贪吃蛇.lesson1;

namespace 贪吃蛇.lesson1
{
   
    class GameScene: IsceneUpdate
         
    {
      
        int updateIndex = 0;
        int SpeedIndex = 0;
        
        Map map;
        Snake snake;
        Food food;
        public GameScene() { 
        
            map = new Map();
            snake = new Snake(40,10);
            food = new Food(snake);
        }
        public void Update() {
         
            if (updateIndex % 100000 == 0)
            {
                map.Draw();
                food.Draw();
                snake.Move();
                snake.Draw();
                // 检测是否撞墙
                if (snake.CheckEnd(map))
                {
                    Game.ChangeScene(E_SceneType.End);
                }
                snake.CheckEatFood(food);
               
                updateIndex = 0;
            }
            updateIndex += 1;

            // 在控制台中检测玩家输入,让程序不被卡主
            if (Console.KeyAvailable)
            { 
                // 检测输入输出不能在间隔帧里面处理
                switch (Console.ReadKey(true).Key)
                {
                    case ConsoleKey.W:
                        snake.ChangDir(E_MoveDir.up);
                        break;
                    case ConsoleKey.A:
                        snake.ChangDir(E_MoveDir.left);
                        break;
                    case ConsoleKey.S:
                        snake.ChangDir(E_MoveDir.down);
                        break;
                    case ConsoleKey.D:
                        snake.ChangDir(E_MoveDir.right);
                        break;

                }

            }
        }
        // 
    }
}

IsceneUpdate 场景更新接口

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

namespace 贪吃蛇.lesson1
{
    // 场景更新接口
    internal interface IsceneUpdate
    {
        void Update();

    }
}

地图Map

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using 贪吃蛇.lesson1;

namespace 贪吃蛇.lesson1
{
    internal class Map:Draw
    {
        public Wall[] walls;
        public Map() { 
         walls = new Wall[Game.w+(Game.h-3)*2 ];
            int index = 0;
            for (int i = 0; i < Game.w; i+=2)
            {
                walls[index] = new Wall(i,0);
                index++;
            }
            for (int i = 0; i < Game.w; i+=2)
            {
                walls[index] = new Wall(i, Game.h-2);
                index++;

            }
            for (int i = 1; i < Game.h-2; i++)
            {
                walls[index] = new Wall(0,i);
                index++;
            }
            for (int i = 1; i < Game.h - 2; i++)
            {
                walls[index] = new Wall(Game.w-2, i);
                index++;
            }

        }

        public void Draw()
        {
            for (int i = 0; i < walls.Length; i++)
            {
                walls[i].Draw();
            }
           
        }
    }
}

坐标Position

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

namespace 贪吃蛇.lesson1
{
    internal struct Position
    {
        public int x;
        public int y;
        public Position(int x, int y) { 
            this.x = x; this.y = y;
        }
        // 各个游戏对象都会去比较位置是不是重合
        public static bool operator ==(Position a, Position b)
        {
            if (a.x == b.x && a.y == b.y) return true;
            return false;
        }
        public static bool operator !=(Position a, Position b)
        {
            if (a.x == b.x && a.y == b.y) return true;
            return false;
        }
    }
    
}

主接口

using System;
using 贪吃蛇.lesson1;
namespace 贪吃蛇;
class Program
{
    static void Main(string[] args)
    {
        Game games = new Game();
        games.Start();
        //games.ChangeScene(E_SceneType.Game);
   


    }
}

蛇类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using 贪吃蛇.lesson1;
namespace 贪吃蛇.lesson1
{
    enum E_MoveDir
    {
        /// <summary>
        /// 上
        /// </summary>
        up,
        /// <summary>
        /// 下
        /// </summary>
        down,
        /// <summary>
        /// 左
        /// </summary>
        left,
        /// <summary>
        /// 右
        /// </summary>
        right

    }
    internal class Snake : Draw
    {


        SnakeBody[] bodys;
        //记录蛇身体长度
        int nowNum;
        E_MoveDir dir;
        public Snake(int x, int y)
        {
            bodys = new SnakeBody[10000];
            bodys[0] = new SnakeBody(E_SnakeBody_Type.Head, x, y);
            nowNum = 1;
            dir = E_MoveDir.right;

        }
        public void Draw()
        {
            for (int i = 0; i < nowNum; i++)
            {
                bodys[i].Draw();
            }
        }
        public void Move()
        {
            // 擦除最后一个位置
            SnakeBody lastBody = bodys[nowNum - 1];
            Console.SetCursorPosition(lastBody.pos.x, lastBody.pos.y);
            // 擦屁股
            Console.Write("   ");


            // 在蛇头移动之前,从蛇尾开始,不停的让后一个位置等于前一个位置
            for (int i = nowNum-1; i > 0; i--)
            {
                bodys[i].pos = bodys[i-1].pos;
            }

            switch (dir)
            {
                case E_MoveDir.up:
                    --bodys[0].pos.y;
                    break;
                case E_MoveDir.down:
                    ++bodys[0].pos.y;
                    break;
                case E_MoveDir.left:
                    bodys[0].pos.x -= 2;
                    break;
                case E_MoveDir.right:
                    bodys[0].pos.x += 2;
                    break;
                default:
                    break;
            }


        }
        // 改变方向
        public void ChangDir(E_MoveDir dir)
        {

            // 只有头部时候可以直接左转右,右转左,上转下,下转上
            //有身体时,这种情况就不能直接转
            if (dir == this.dir || nowNum > 1 &&
                dir == E_MoveDir.left && dir == E_MoveDir.right ||
                dir == E_MoveDir.right && dir == E_MoveDir.left ||
                dir == E_MoveDir.up && dir == E_MoveDir.down ||
                dir == E_MoveDir.down && dir == E_MoveDir.up
               )
            {
                return;
            }
            this.dir = dir;

        }

        // 撞墙撞身体
        public bool CheckEnd(Map map)
        {
            for (int i = 0; i < map.walls.Length; i++)
            {
                if (bodys[0].pos == map.walls[i].pos)
                {
                    return true;
                }
            }
            for (int i = 1; i < nowNum; i++)
            {
                if (bodys[0].pos == bodys[i].pos)
                {
                    return true;
                }

            }
            return false;
        }
        //吃食物
        // 通过传入一个位置判断这个位置是否和蛇重合
        public bool CheckSamePos(Position position)
        {
            for (int i = 0; i < nowNum; i++)
            {
                if (bodys[i].pos == position)
                {
                    return true;
                }

            }
            return false;


        }
        public void CheckEatFood(Food food)
        {
            if (bodys[0].pos == food.pos ) {
                // 吃到了就应该让食物位置随机,增加蛇的身体长度
                food.RandomPos(this);
                ADDBody();
               

            }
           
           

        }
        // 长身体
        private void ADDBody() {
            SnakeBody frontBody = bodys[nowNum-1];
            // 先长

            bodys[nowNum] = new SnakeBody(E_SnakeBody_Type.Body,frontBody.pos.x,frontBody.pos.y);
            // 加长度
            ++nowNum;
        }
    }
}

蛇身体

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 贪吃蛇.lesson1;

namespace 贪吃蛇.lesson1
{
    /// <summary>
    /// 蛇身体类型
    /// </summary>
    enum E_SnakeBody_Type
    { 
        /// <summary>
        /// 头
        /// </summary>
       Head,
       /// <summary>
       /// 身体
       /// </summary>
       Body
        
    }

    internal class SnakeBody : GameObject
    {
        private E_SnakeBody_Type Type;
        public SnakeBody( E_SnakeBody_Type type ,int x, int y ) { 
            //
            this.Type = type;
            this.pos = new Position(x,y);
        }
       

        public override void Draw()
        {
            Console.SetCursorPosition(pos.x,pos.y );
            Console.ForegroundColor = Type == E_SnakeBody_Type.Head ? ConsoleColor.Yellow : ConsoleColor.Green;
            Console.Write(Type == E_SnakeBody_Type.Head ? "●" : "◎");



        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 贪吃蛇.lesson1;

namespace 贪吃蛇.lesson1
{
    internal class Wall : GameObject
    {

        public  Wall(int x ,int y)
        {
            pos = new Position(x,y);
        }
       

        public override void Draw()
        {
            Console.SetCursorPosition(pos.x,pos.y);
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("▆");
        }
    }
}

标签:Console,C#,System,pos,int,贪吃蛇,using,public
From: https://www.cnblogs.com/abldh12/p/18653056

相关文章

  • 使用js写一个方法对css进行压缩
    在前端开发中,对CSS进行压缩通常意味着移除空白字符、换行、注释,以及可能的话,缩短属性和选择器名称。然而,缩短属性和选择器名称可能会导致CSS不可维护,并且可能不兼容某些浏览器,因此这种做法并不常见。更常见的做法是移除不必要的字符,如空格、换行和注释。以下是一个简单的JavaScri......
  • Java 中的 getDeclaredMethod() 方法:使用与原理详解
    在Java反射机制中,getDeclaredMethod()是一个非常重要的方法,用于获取类中声明的特定方法(包括公共、保护、默认和私有方法)。与getMethod()不同,getDeclaredMethod()可以访问类的所有方法,而不仅仅是公共方法。本文将深入探讨getDeclaredMethod()的使用方法、原理以及实......
  • CLUE复现记录
    1基本函数---defrun_unsupervised_da(model,src_train_loader,tgt_sup_loader,tgt_unsup_loader,train_idx,num_classes,device,args):输入model:预训练的模型或者使用源域数据训练得到的source_modelsource_model=get_model(args.cnn,num_cls=num_classes)s......
  • Nexus 9K 交换机接口 CRC 排查
    交换机接口出现CRC计数,通常数据帧意味着在数据传输过程中出现了错误。但是N9K上接口计数是历史累计值,那么接下来如何排查呢?故障现象错误计数增加:多次showinterface排查中,会发现计数在同步增长。数据传输异常:出现数据包丢失或传输速率下降等情况。连接状态不稳定:接......
  • 你有写过vs code插件吗?
    很抱歉,虽然我可以提供关于编写VSCode插件的建议和指导,但我本身并没有实际编写过VSCode插件。不过,我可以向你介绍一些编写VSCode插件的基本概念和步骤,帮助你入门和提高。VSCode插件通常使用TypeScript或JavaScript编写,并且需要遵循VSCode扩展API的规范。以下......
  • 【最新原创毕设】基于SpringBoot的企业综合业务审批管理系+37708(免费领源码)可做计算机
    目 录摘要1绪论1.1选题背景与意义1.2国内外研究现状1.3论文结构与章节安排2 企业综合业务审批管理系统系统分析2.1可行性分析2.1.1技术可行性分析2.1.2 经济可行性分析2.1.3法律可行性分析2.2功能需求分析2.2.1功能性分析2.2.2非功能性......
  • DVWA靶场Command Injection(命令注入) 漏洞所有级别通关教程详解及源码审计
    目录标题前言命令注入low源码审计medium源码审计high源码审计impossible源码审计前言本人公众号:泷羽Sec-track,感兴趣的师傅可以看看命令注入命令注入漏洞是一种安全漏洞,攻击者可以通过向应用程序输入恶意命令,诱使系统执行这些命令,从而达到未授权访问、数据篡......
  • 在TypeScript中枚举和常量枚举有什么区别?
    在TypeScript中,枚举(Enums)和常量枚举(ConstEnums)都是用于定义一组命名的常量值的数据类型。然而,它们在编译时的行为和使用上存在一些关键差异。1.枚举(Enums)枚举是TypeScript提供的一种特殊的数据类型,它允许我们为一组数值定义友好的名字。默认情况下,枚举中的第一个成员被赋......
  • 在TypeScript中如何实现继承?
    在TypeScript中,可以通过extends关键字来实现类的继承。以下是一个简单的示例:classAnimal{name:string;constructor(name:string){this.name=name;}speak(){console.log(`${this.name}makesanoise.`);}}classDogext......
  • 在TypeScript中as语法是什么?
    在TypeScript中,as是一个类型断言操作符,它允许开发者明确地告诉TypeScript编译器某个值的类型。类型断言在TypeScript中是一种告诉编译器“我知道我在做什么,这个值就是这个类型”的方式。当你在TypeScript中遇到类型不明确的情况,或者TypeScript的类型推断与你的预期不符时,你可以......