在编程的世界里,贪吃蛇游戏是一个经典且广受欢迎的入门级项目,它不仅能够锻炼编程基础,还能加深对游戏开发的理解。本文将带你从零开始,使用C#语言和.NET框架,一步步构建一个简单的贪吃蛇游戏。
项目展示
按键操作:
方向控制: WSAD
确定键: J
代码实现
一、游戏对象和场景更新接口
1.游戏类 —— Game
using CSharp核心实践小游戏_贪食蛇.Class2;
namespace CSharp核心实践小游戏_贪食蛇.Class1
{
/// <summary>
/// 场景类型枚举
/// </summary>
enum E_SceneType
{
/// <summary>
/// 开始场景
/// </summary>
Begin,
/// <summary>
/// 游戏场景
/// </summary>
Game,
/// <summary>
/// 结束场景
/// </summary>
End,
}
internal 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;
}
}
}
}
2.场景更新接口 ——ISceneUpdate
namespace CSharp核心实践小游戏_贪食蛇.Class1
{
/// <summary>
/// 场景更新接口
/// </summary>
internal interface ISceneUpdate
{
void Update();
}
}
三、实现多场景切换
1.游戏场景类
2.开始和结束场景基类
using CSharp核心实践小游戏_贪食蛇.Class1;
namespace CSharp核心实践小游戏_贪食蛇.Class2
{
abstract internal 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;
}
}
}
}
3.开始场景
using CSharp核心实践小游戏_贪食蛇.Class1;
namespace CSharp核心实践小游戏_贪食蛇.Class2
{
internal class BeginScene : BeginOrEndBaseScene
{
public BeginScene()
{
strTitle = "贪食蛇";
strOne = "开始游戏";
}
public override void EnterJDoSomthing()
{
// 按J键做什么的逻辑
if(nowSelIndex == 0)
{
Game.ChangeScene(E_SceneType.Game);
}
else
{
Environment.Exit(0);
}
}
}
}
4.结束场景
using CSharp核心实践小游戏_贪食蛇.Class1;
using CSharp核心实践小游戏_贪食蛇.Class6;
namespace CSharp核心实践小游戏_贪食蛇.Class2
{
internal class EndScene : BeginOrEndBaseScene
{
public EndScene()
{
Snake.Num = 0;
strTitle = "游戏结束";
strOne = "回到开始界面";
}
public override void EnterJDoSomthing()
{
// 按J键做什么的逻辑
if (nowSelIndex == 0)
{
Game.ChangeScene(E_SceneType.Begin);
}
else
{
Environment.Exit(0);
}
}
}
}
四、游戏场景逻辑实现
1.游戏对象基类的实现
绘制接口
namespace CSharp核心实践小游戏_贪食蛇.Class3
{
internal interface IDraw
{
void Draw();
}
}
游戏对象类
namespace CSharp核心实践小游戏_贪食蛇.Class3
{
abstract internal class GameObject : IDraw
{
// 游戏对象位置
public Position pos;
// 可以继承接口后把接口中的行为变成抽象行为
// 供子类去实现 因为是抽象行为所以子类中是必须去实现
public abstract void Draw();
}
}
位置结构体
namespace CSharp核心实践小游戏_贪食蛇.Class3
{
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;
}
}
}
2.继承游戏对象基类的对象
地图墙壁类
using CSharp核心实践小游戏_贪食蛇.Class3;
namespace CSharp核心实践小游戏_贪食蛇.Class4
{
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.Write("■");
}
}
}
食物类
using CSharp核心实践小游戏_贪食蛇.Class1;
using CSharp核心实践小游戏_贪食蛇.Class3;
using CSharp核心实践小游戏_贪食蛇.Class6;
namespace CSharp核心实践小游戏_贪食蛇.Class4
{
internal 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);
}
}
}
}
蛇身子类
using CSharp核心实践小游戏_贪食蛇.Class3;
namespace CSharp核心实践小游戏_贪食蛇.Class4
{
/// <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 ? "●" : "◎");
}
}
}
3.地图对象
using CSharp核心实践小游戏_贪食蛇.Class1;
using CSharp核心实践小游戏_贪食蛇.Class3;
using CSharp核心实践小游戏_贪食蛇.Class4;
namespace CSharp核心实践小游戏_贪食蛇.Class5
{
internal 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();
}
}
}
}
在GameScene实现Map中的方法
4.蛇对象
五、蛇对象移动
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 贪吃蛇.Lesson3;
using 贪吃蛇.Lesson4;
namespace 贪吃蛇.Lesson6
{
/// <summary>
/// 蛇的移动方向
/// </summary>
enum E_MoveDir
{
Up,
Down,
Left,
Right,
}
class Snake : IDraw
{
SnakeBody[] bodys;
//记录当前蛇的长度
int nowNum;
//当前移动方向
E_MoveDir dir;
public Snake(int x, int y)
{
//粗暴的方法 直接申明200个空间 来装蛇身体的数组
bodys = new SnakeBody[200];
bodys[0] = new SnakeBody(E_SnakeBody_Type.Head, x, y);
nowNum = 1;
dir = E_MoveDir.Down;
}
public void Draw()
{
//画一节一节的身子
for (int i = 0; i < nowNum; i++)
{
bodys[i].Draw();
}
}
#region Lesson7 蛇的移动
public void Move()
{
//移动前
//擦除最后一个位置
Console.SetCursorPosition(bodys[nowNum - 1].pos.x, bodys[nowNum - 1].pos.y);
Console.WriteLine(" ");
//再移动
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;
}
}
#endregion
}
}
六、蛇对象改变移动方向
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 贪吃蛇.Lesson3;
using 贪吃蛇.Lesson4;
namespace 贪吃蛇.Lesson6
{
/// <summary>
/// 蛇的移动方向
/// </summary>
enum E_MoveDir
{
Up,
Down,
Left,
Right,
}
class Snake : IDraw
{
SnakeBody[] bodys;
//记录当前蛇的长度
int nowNum;
//当前移动方向
E_MoveDir dir;
public Snake(int x, int y)
{
//粗暴的方法 直接申明200个空间 来装蛇身体的数组
bodys = new SnakeBody[200];
bodys[0] = new SnakeBody(E_SnakeBody_Type.Head, x, y);
nowNum = 1;
dir = E_MoveDir.Down;
}
public void Draw()
{
//画一节一节的身子
for (int i = 0; i < nowNum; i++)
{
bodys[i].Draw();
}
}
#region Lesson7 蛇的移动
public void Move()
{
//移动前
//擦除最后一个位置
Console.SetCursorPosition(bodys[nowNum - 1].pos.x, bodys[nowNum - 1].pos.y);
Console.WriteLine(" ");
//再移动
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;
}
}
#endregion
#region Lesson8 改变方向
public void ChangeDir(E_MoveDir dir)
{
//只有头部的时候 可以直接左转右 右转左 上转下 下转上
//有身体时 这些情况就不能直接转
if (this.dir == dir ||
nowNum > 1 &&
(this.dir == E_MoveDir.Up && dir == E_MoveDir.Down ||
this.dir == E_MoveDir.Down && dir == E_MoveDir.Up ||
this.dir == E_MoveDir.Left && dir == E_MoveDir.Right ||
this.dir == E_MoveDir.Right && dir == E_MoveDir.Left))
{
return;
}
//只要没有 return 就记录外面传入的方向 之后就会按照这个方向去移动
this.dir = dir;
}
#endregion
}
}
在GameScene里面实现调用
using CSharp核心实践小游戏_贪食蛇.Class1;
using CSharp核心实践小游戏_贪食蛇.Class4;
using CSharp核心实践小游戏_贪食蛇.Class5;
using CSharp核心实践小游戏_贪食蛇.Class6;
namespace CSharp核心实践小游戏_贪食蛇.Class2
{
internal 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);
Console.ForegroundColor = ConsoleColor.White;
Console.SetCursorPosition(2, 1);
Console.Write("当前得分:0");
}
public void Update()
{
if (updateIndex % 5555 == 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;
}
}
}
}
}
七、撞墙撞身体结束游戏
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 贪吃蛇.Lesson3;
using 贪吃蛇.Lesson4;
using 贪吃蛇.Lesson5;
namespace 贪吃蛇.Lesson6
{
/// <summary>
/// 蛇的移动方向
/// </summary>
enum E_MoveDir
{
Up,
Down,
Left,
Right,
}
class Snake : IDraw
{
SnakeBody[] bodys;
//记录当前蛇的长度
int nowNum;
//当前移动方向
E_MoveDir dir;
public Snake(int x, int y)
{
//粗暴的方法 直接申明200个空间 来装蛇身体的数组
bodys = new SnakeBody[200];
bodys[0] = new SnakeBody(E_SnakeBody_Type.Head, x, y);
nowNum = 1;
dir = E_MoveDir.Down;
}
public void Draw()
{
//画一节一节的身子
for (int i = 0; i < nowNum; i++)
{
bodys[i].Draw();
}
}
#region Lesson7 蛇的移动
public void Move()
{
//移动前
//擦除最后一个位置
Console.SetCursorPosition(bodys[nowNum - 1].pos.x, bodys[nowNum - 1].pos.y);
Console.WriteLine(" ");
//再移动
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;
}
}
#endregion
#region Lesson8 改变方向
public void ChangeDir(E_MoveDir dir)
{
//只有头部的时候 可以直接左转右 右转左 上转下 下转上
//有身体时 这些情况就不能直接转
if (this.dir == dir ||
nowNum > 1 &&
(this.dir == E_MoveDir.Up && dir == E_MoveDir.Down ||
this.dir == E_MoveDir.Down && dir == E_MoveDir.Up ||
this.dir == E_MoveDir.Left && dir == E_MoveDir.Right ||
this.dir == E_MoveDir.Right && dir == E_MoveDir.Left))
{
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
}
}
八、蛇吃食物
using CSharp核心实践小游戏_贪食蛇.Class1;
using CSharp核心实践小游戏_贪食蛇.Class3;
using CSharp核心实践小游戏_贪食蛇.Class4;
using CSharp核心实践小游戏_贪食蛇.Class5;
namespace CSharp核心实践小游戏_贪食蛇.Class6
{
#region Class7 蛇移动
/// <summary>
/// 蛇的移动方向
/// </summary>
enum E_MoveDir
{
/// <summary>
/// 上
/// </summary>
Up,
/// <summary>
/// 下
/// </summary>
Down,
/// <summary>
/// 左
/// </summary>
Left,
/// <summary>
/// 右
/// </summary>
Right,
}
#endregion
internal class Snake : IDraw
{
SnakeBody[] bodys;
// 来记录当前蛇的长度
int nowNum;
public static int Num = 0;
// 当前移动的方向
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 Class7 蛇的移动
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;
}
}
#endregion
#region Class8 改变方向
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 Class9 撞墙撞身体结束逻辑
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 Class10 吃食物相关
// 通过传入一个位置 来判断这个位置是不是和蛇重合
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();
Console.ForegroundColor = ConsoleColor.White;
Console.SetCursorPosition(2, 1);
Console.Write("当前得分:" + Snake.Num);
if (Snake.Num >= 20)
{
Console.SetCursorPosition(14, 1);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("★");
}
if (Snake.Num >= 40)
{
Console.SetCursorPosition(16, 1);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("★");
}
if (Snake.Num >= 60)
{
Console.SetCursorPosition(18, 1);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("★");
}
if (Snake.Num >= 80)
{
Console.SetCursorPosition(20, 1);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("★");
}
if (Snake.Num >= 100)
{
Console.SetCursorPosition(22, 1);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("★");
}
if (Snake.Num >= 200)
{
Game.ChangeScene(E_SceneType.End);
}
}
}
#endregion
}
}
九、蛇长身体
using CSharp核心实践小游戏_贪食蛇.Class1;
using CSharp核心实践小游戏_贪食蛇.Class3;
using CSharp核心实践小游戏_贪食蛇.Class4;
using CSharp核心实践小游戏_贪食蛇.Class5;
namespace CSharp核心实践小游戏_贪食蛇.Class6
{
#region Class7 蛇移动
/// <summary>
/// 蛇的移动方向
/// </summary>
enum E_MoveDir
{
/// <summary>
/// 上
/// </summary>
Up,
/// <summary>
/// 下
/// </summary>
Down,
/// <summary>
/// 左
/// </summary>
Left,
/// <summary>
/// 右
/// </summary>
Right,
}
#endregion
internal class Snake : IDraw
{
SnakeBody[] bodys;
// 来记录当前蛇的长度
int nowNum;
public static int Num = 0;
// 当前移动的方向
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 Class7 蛇的移动
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;
}
}
#endregion
#region Class8 改变方向
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 Class9 撞墙撞身体结束逻辑
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 Class10 吃食物相关
// 通过传入一个位置 来判断这个位置是不是和蛇重合
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();
Console.ForegroundColor = ConsoleColor.White;
Console.SetCursorPosition(2, 1);
Console.Write("当前得分:" + Snake.Num);
if (Snake.Num >= 20)
{
Console.SetCursorPosition(14, 1);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("★");
}
if (Snake.Num >= 40)
{
Console.SetCursorPosition(16, 1);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("★");
}
if (Snake.Num >= 60)
{
Console.SetCursorPosition(18, 1);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("★");
}
if (Snake.Num >= 80)
{
Console.SetCursorPosition(20, 1);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("★");
}
if (Snake.Num >= 100)
{
Console.SetCursorPosition(22, 1);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("★");
}
if (Snake.Num >= 200)
{
Game.ChangeScene(E_SceneType.End);
}
}
}
#endregion
#region Class11 长身体
private void AddBody()
{
SnakeBody frontBody = bodys[nowNum - 1];
// 先长
bodys[nowNum] = new SnakeBody(E_SnakeBody_Type.Body, frontBody.pos.x, frontBody.pos.y);
// 再加长度
++nowNum;
++Num;
}
#endregion
}
}
至此贪吃蛇制作的功能都已实现。
总结
通过本文的指导,你已经能够使用C#创建一个基本的贪吃蛇游戏了。这只是一个起点,你可以在此基础上继续探索和创新,比如添加计分板、游戏暂停和恢复、不同难度级别、声音效果、网络对战等,让你的游戏更加丰富和有趣。
📂 Unity 开发技能 | 目录索引
📂 Unity 常用插件 | 总目录
📂 Unity 开发资源 | 目录索引
📂 Unity 源码工程 | 总目录
🍉🍉🍉 如果觉得这篇文对你有帮助的话,请点个赞👍、收藏⭐️下吧,非常感谢! 💕💕💕
🥷🏻博主简介:20年软件开发经验,经历嵌入式驱动开发、Android开发、Unity游戏开发。积累收藏了大量游戏开发资源和素材,如有需要请联系我。
互3互推也请联系我…