首页 > 其他分享 >控制台小游戏制作——贪吃蛇

控制台小游戏制作——贪吃蛇

时间:2024-07-20 10:24:56浏览次数:12  
标签:贪食蛇 int System pos 小游戏 贪吃蛇 using 控制台 public

Game.cs

using System;
using System.Collections.Generic;
using System.Text;
using 贪食蛇.Lesson2;

namespace 贪食蛇.Lesson1
{
    /// <summary>
    /// 场景类型枚举
    /// </summary>
    enum E_SceneType
    {
        /// <summary>
        /// 开始场景
        /// </summary>
        Begin,
        /// <summary>
        /// 游戏场景
        /// </summary>
        Game,
        /// <summary>
        /// 结束场景
        /// </summary>
        End,
    }

    class Game
    {
        //游戏窗口宽高
        public const int w = 80;
        public const int h = 20;
        //当前选中的场景
        public static ISceneUpdate nowScene;

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

            ChangeScene(E_SceneType.Begin);
        }

        //游戏开始的方法
        public void Start()
        {
            //游戏主循环 主要负责 游戏场景逻辑的更新
            while (true)
            {
                //判断当前游戏场景不为空 就更新
                if( nowScene != null )
                {
                    nowScene.Update();
                }
            }
        }

        public static void ChangeScene(E_SceneType type)
        {
            //切场景之前 应该把上一个场景的绘制内容擦掉
            Console.Clear();

            switch (type)
            {
                case E_SceneType.Begin:
                    nowScene = new BeginScene();
                    break;
                case E_SceneType.Game:
                    nowScene = new GameScene();
                    break;
                case E_SceneType.End:
                    nowScene = new EndScene();
                    break;
            }
        }
    }
}

ISceneUpdate.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace 贪食蛇.Lesson1
{
    
    /// <summary>
    /// 场景更新接口
    /// </summary>
    interface ISceneUpdate
    {
        void Update();
    }
}

BeginOrEndBaseScene.cs

using System;
using System.Collections.Generic;
using System.Text;
using 贪食蛇.Lesson1;

namespace 贪食蛇.Lesson2
{
    abstract class BeginOrEndBaseScene : ISceneUpdate
    {
        protected int nowSelIndex = 0;
        protected string strTitle;
        protected string strOne;

        public abstract void EnterJDoSomthing();

        public void Update()
        {
            //开始和结束场景的 游戏逻辑 
            //选择当前的选项 然后 监听 键盘输入 wsj
            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.S:
                    ++nowSelIndex;
                    if (nowSelIndex > 1)
                    {
                        nowSelIndex = 1;
                    }
                    break;
                case ConsoleKey.J:
                    EnterJDoSomthing();
                    break;
            }
        }
    }
}

BeginScene.cs

using System;
using System.Collections.Generic;
using System.Text;
using 贪食蛇.Lesson1;

namespace 贪食蛇.Lesson2
{
    class BeginScene : BeginOrEndBaseScene
    {
        public BeginScene()
        {
            strTitle = "贪食蛇";
            strOne = "开始游戏";
        }

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

EndScene.cs

using System;
using System.Collections.Generic;
using System.Text;
using 贪食蛇.Lesson1;

namespace 贪食蛇.Lesson2
{
    class EndScene : BeginOrEndBaseScene
    {
        public EndScene()
        {
            strTitle = "结束游戏";
            strOne = "回到开始界面";
        }

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

GameScene.cs

using System;
using System.Collections.Generic;
using System.Text;
using 贪食蛇.Lesson1;
using 贪食蛇.Lesson4;
using 贪食蛇.Lesson5;
using 贪食蛇.Lesson6;

namespace 贪食蛇.Lesson2
{
    class GameScene : ISceneUpdate
    {
        Map map;
        Snake snake;
        Food food;

        int updateIndex = 0;

        public GameScene()
        {
            map = new Map();
            snake = new Snake(40, 10);
            food = new Food(snake);
        }

        public void Update()
        {
            if(updateIndex % 4444 == 0)
            {
                map.Draw();
                food.Draw();

                snake.Move();
                snake.Draw();

                //检测是否撞墙
                if(snake.CheckEnd(map))
                {
                    //结束逻辑
                    Game.ChangeScene(E_SceneType.End);
                }

                snake.CheckEatFood(food);

                updateIndex = 0;
            }
            ++updateIndex;

            //在控制台中 检测玩家输入 让程序不被检测卡主
            //判断 有没有键盘输入 如果有 才为true
            if( Console.KeyAvailable )
            {
                //检测输入输出 不能再 间隔帧里面去处理 应该每次都检测 这样才准确
                switch (Console.ReadKey(true).Key)
                {
                    case ConsoleKey.W:
                        snake.ChangeDir(E_MoveDir.Up);
                        break;
                    case ConsoleKey.A:
                        snake.ChangeDir(E_MoveDir.Left);
                        break;
                    case ConsoleKey.S:
                        snake.ChangeDir(E_MoveDir.Down);
                        break;
                    case ConsoleKey.D:
                        snake.ChangeDir(E_MoveDir.Right);
                        break;
                }
            }
        }
    }
}

GameObject.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace 贪食蛇.Lesson3
{
    abstract class GameObject : IDraw
    {
        //游戏对象位置
        public Position pos;

        //可以继承接口后 把接口中的行为 编程 抽象行为
        //供子类去实现 因为是抽象行为 所以子类中是必须去实现
        public abstract void Draw();
    }
}

IDraw.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace 贪食蛇.Lesson3
{
    interface IDraw
    {
        void Draw();
    }
}

Position.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace 贪食蛇.Lesson3
{
    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 p1, Position p2)
        {
            if( p1.x == p2.x && p1.y == p2.y)
            {
                return true;
            }
            return false;
        }

        public static bool operator !=(Position p1, Position p2)
        {
            if (p1.x == p2.x && p1.y == p2.y)
            {
                return false;
            }
            return true;
        }
    }
}

Food.cs

using System;
using System.Collections.Generic;
using System.Text;
using 贪食蛇.Lesson1;
using 贪食蛇.Lesson3;
using 贪食蛇.Lesson6;

namespace 贪食蛇.Lesson4
{
    class Food : GameObject
    {
        public Food(Snake snake)
        {
            RandomPos(snake);
        }

        public override void Draw()
        {
            Console.SetCursorPosition(pos.x, pos.y);
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.Write("¤");
        }
        
        //随机位置的行为 行为 和蛇的位置 有关系 有了蛇再来考虑
        public void RandomPos(Snake snake)
        {
            //随机位置
            Random r = new Random();
            int x = r.Next(2, Game.w / 2 - 1) * 2;
            int y = r.Next(1, Game.h - 4);
            pos = new Position(x, y);
            //得到蛇
            //如果重合 就会进if语句
            if(snake.CheckSamePos(pos))
            {
                RandomPos(snake);
            }
        } 
    }
}

SnakeBody.cs

using System;
using System.Collections.Generic;
using System.Text;
using 贪食蛇.Lesson3;

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

    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 ? "●" : "◎");
        }
    }
}

Wall.cs

using System;
using System.Collections.Generic;
using System.Text;
using 贪食蛇.Lesson3;

namespace 贪食蛇.Lesson4
{
    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("■");
        }
    }
}

Map.cs

using System;
using System.Collections.Generic;
using System.Text;
using 贪食蛇.Lesson1;
using 贪食蛇.Lesson3;
using 贪食蛇.Lesson4;

namespace 贪食蛇.Lesson5
{
    class Map : IDraw
    {
        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();
            }
        }
    }
}

Snake.cs

using System;
using System.Collections.Generic;
using System.Text;
using 贪食蛇.Lesson3;
using 贪食蛇.Lesson4;
using 贪食蛇.Lesson5;

namespace 贪食蛇.Lesson6
{
    #region Lesson7 蛇移动
    /// <summary>
    /// 蛇的移动方向
    /// </summary>
    enum E_MoveDir
    {
        /// <summary>
        /// 上
        /// </summary>
        Up,
        /// <summary>
        /// 下
        /// </summary>
        Down,
        /// <summary>
        /// 左
        /// </summary>
        Left,
        /// <summary>
        /// 右
        /// </summary>
        Right,
    }
    #endregion

    class Snake : IDraw
    {
        SnakeBody[] bodys;
        //来记录当前蛇的长度
        int nowNum;
        //当前移动的方向
        E_MoveDir dir;

        public Snake(int x, int y)
        {
            //粗暴的 申明200个空间 游戏中 基本不会出现蛇长度达到200个身体
            bodys = new SnakeBody[200];

            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();
            }
        }

        #region Lesson7 蛇的移动
        public void Move()
        {
            //移动前
            //擦除最后一个位置
            //擦屁股
            SnakeBody lastBody = bodys[nowNum - 1];
            Console.SetCursorPosition(lastBody.pos.x, lastBody.pos.y);
            Console.Write("  ");

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

            //再动
            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;
            }
        }
        #endregion

        #region Lesson8 改变方向
        public void ChangeDir(E_MoveDir dir)
        {
            //只有头部的时候 可以直接左转右 右转左  上转下 下转上
            //有身体时 这种情况就不能直接转、
            if( dir == this.dir ||
                nowNum > 1 && 
                (this.dir == E_MoveDir.Left && dir == E_MoveDir.Right ||
                 this.dir == E_MoveDir.Right && dir == E_MoveDir.Left ||
                 this.dir == E_MoveDir.Up && dir == E_MoveDir.Down ||
                 this.dir == E_MoveDir.Down && dir == E_MoveDir.Up))
            {
                return;
            }

            //只要没有return 就记录外面传入的方向 之后就会按照这个方向去移动
            this.dir = dir;
        }
        #endregion

        #region Lesson9 撞墙撞身体结束逻辑
        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;
        }
        #endregion

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

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

        #region Lesson11 长身体
        private void AddBody()
        {
            SnakeBody frontBody = bodys[nowNum - 1];
            //先长 
            bodys[nowNum] = new SnakeBody(E_SnakeBody_Type.Body, frontBody.pos.x, frontBody.pos.y);
            //再加长度
            ++nowNum;
        }
        #endregion
    }
}

标签:贪食蛇,int,System,pos,小游戏,贪吃蛇,using,控制台,public
From: https://blog.csdn.net/Luo3255069063/article/details/140416928

相关文章

  • 【Qt】探索Qt框架:开发经典贪吃蛇游戏的全过程与实践
    文章目录引言项目链接:1.Qt框架的使用简介2.贪吃蛇游戏设计2.1游戏规则和玩法介绍2.2游戏界面设计概述3.核心代码解析3.1主界面(GameHall)3.1.1布局和功能介绍3.1.2代码实现分析3.2游戏选择界面(GameSelect)3.2.1功能介绍3.2.2代码实现分析3.3游戏房间(GameRoom......
  • 广告联盟APP小游戏开发养机
    广告联盟APP小游戏开发中的“养机”主要是指优化广告展示环境,提升广告效果,同时保障用户体验的过程。以下是一些关于广告联盟APP小游戏开发养机的具体建议:明确目标群体:了解游戏玩家的年龄、兴趣爱好以及使用习惯等信息,以便在游戏中植入符合他们需求的广告内容1。选择恰当的广告......
  • 真的求求点赞+关注+收藏了!!(c++小游戏3)(还有其它的)
    13、球球大作战//奇怪的游戏#include<bits/stdc++.h>#include<windows.h>#include<conio.h>usingnamespacestd;voidpass(){CONSOLE_CURSOR_INFOcursor_info={1,0};SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);}intjj......
  • log4net 在.NET Core 控制台程序中的应用(2)
    简介本文主要讲解log4net在.NETCore控制台程序中的应用步骤1.安装log4netNuget包2.增加配置文件3.直接调用4.验证结果实施1.安装log4netNuget包首先,需要在你的.NETCore项目中安装log4net包。可以通过NuGet包管理器来安装。打开你的项目,然后使用以下命令安装log4net:......
  • log4net 在.NET Core 控制台程序中的应用
    简介本文主要讲解log4net在.NETCore控制台程序中的应用步骤1.安装log4netNuget包2.增加配置文件3.增加封装的LogHelper的类4.调用5.验证结果实施1.安装log4netNuget包首先,需要在你的.NETCore项目中安装log4net包。可以通过NuGet包管理器来安装。打开你的项目,然后使......
  • HTML2048小游戏(最新版)
    比上一篇文章的2048更好一点。控制方法:WASD键(小写)或页面上四个按钮效果图如下:         源代码在图片后面  源代码 ·HTML·<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="wid......
  • 使用forEach循环异步方法,导致使用深拷贝时,得不到最新数据,控制台会打印出最新的数据
    在使用forEach循环遍历一个数组,如果循环时有异步方法,会导致最终深拷贝得不到最新数据,但是控制台会打印最新的数据constarr=[{name:"Jone",age:18},{name:"Tom",age:15},{name:"Liu",age:48}];functionfunTimeout(param){......
  • 贪吃蛇游戏
    前言本篇博客为大家介绍C语言中的一个比较重要的项目——贪吃蛇游戏,这个游戏的实现需要充分运用C语言的相关知识,所以大家一定要提前学好C语言的知识,再来做贪吃蛇的项目;如果你对本文内容感兴趣,请继续往下阅读,下面我们进入正文部分。1.游戏背景贪吃蛇是久负盛名的游戏,它也和俄......
  • Elastic的Kibana-8.13.4的控制台开发简单入门
    1.创建索引        在Elasticsearch中,创建索引的基本语法格式为:PUT/索引名称{ "settings":{  //索引的设置,如分片数量、副本数量、分词器等 }, "mappings":{  "properties":{   "字段名称":{    "type":"字段类型",//......
  • 微信小游戏 彩色试管 倒水游戏 逻辑 (二)
     最近开始研究微信小游戏,有兴趣的可以关注一下公众号,记录一些心路历程和源代码。定义一个Waterclass1.**定义接口和枚举**:  -`WaterInfo`接口定义了水的颜色、高度等信息。  -`PourAction`枚举定义了水的倒动状态,包括无动作、加水、倒水。2.**类`Wa......