public const int snakeFullHealth = 1;
public static int snakeHealth = snakeFullHealth;
public static int snakeStartLength = 10;
public const int windowWidth = 20;
public const int windowHeight = 16;
// 便于修改围墙大小
public static int time = 0;
public static int score = 0;
public static char[,] map = new char[windowHeight, windowWidth];
// 0=blank, 1=snakebody, 2=snakehead, 3=apple, 4=wall
public static string? message;
public static Boolean gameOver = false;
public static string direction = "right";
public static Timer? timer;
public static List<(int x, int y)> snakeLocation = new List<(int x, int y)>();
// 蛇的位置,蛇头在最后一行
public static (int x, int y) appleLocation;
// 苹果坐标
private static int _snakeSpeed = 500; //ms
public static int snakeSpeed {
get {
return _snakeSpeed;
}
set {
if (value >= 60) {
_snakeSpeed = value;
}
}
}
snakeSpeed 使用了 C# 的属性,保证速度不会过高(刷新间隔 <=60ms)
初始化
internal static void InitializingGameWindow() {
Console.OutputEncoding = Encoding.UTF8;
// 设定控制台编码以便输出 Emoji
message = "游戏开始!";
for (int i = 0; i < snakeStartLength; i++) {
snakeLocation.Add((0, i));
} // 开始将蛇放在左上角
RandomApple(); //初始化苹果
UpdateOnMap(); //刷新地图
RenderFrame(); //渲染到控制台
message = "";
}
internal static void RandomApple() {
Random random = new Random();
appleLocation = (random.Next(0, windowHeight), random.Next(0, windowWidth));
foreach (var x in snakeLocation) {
if (appleLocation == x) {
RandomApple();
}
} // 如果和蛇重叠就重新生成
}
按键监听
这部分还未掌握,是由 GPT 给出的。
if (Console.KeyAvailable) {
var key = Console.ReadKey(intercept: true).Key;
switch (key) {
case ConsoleKey.UpArrow:
case ConsoleKey.W:
ControlDirection("up");
break;
case ConsoleKey.DownArrow:
case ConsoleKey.S:
ControlDirection("down");
break;
case ConsoleKey.LeftArrow:
case ConsoleKey.A:
ControlDirection("left");
break;
case ConsoleKey.RightArrow:
case ConsoleKey.D:
ControlDirection("right");
break;
}
}
public static void ControlDirection(string newDirection) {
if ((newDirection == "up" && direction != "down") ||
(newDirection == "down" && direction != "up") ||
(newDirection == "left" && direction != "right") ||
(newDirection == "right" && direction != "left")) {
direction = newDirection;
} // 防止头转 180°
}
逻辑处理
地图刷新和逻辑处理写在一起了。
public static void UpdateMap() {
// 控制蛇的方向:每次根据当前方向更新蛇头的位置,并将其插入 List 的开头位置;
// 移除 List 的最后一个元素,以模拟前进的效果。
var lastSnakeHead = snakeLocation[snakeLocation.Count - 1];
switch (direction) {
case "up":
snakeLocation.Add((lastSnakeHead.x - 1, lastSnakeHead.y));
break;
case "down":
snakeLocation.Add((lastSnakeHead.x + 1, lastSnakeHead.y));
break;
case "left":
snakeLocation.Add((lastSnakeHead.x, lastSnakeHead.y - 1));
break;
case "right":
snakeLocation.Add((lastSnakeHead.x, lastSnakeHead.y + 1));
break;
}
var newSnakeHead = snakeLocation[snakeLocation.Count - 1];
// 苹果判定
if (newSnakeHead == appleLocation) {
score += 1;
snakeSpeed -= 20;
RandomApple();
} else {
snakeLocation.RemoveAt(0); //移除最后一个
}
UpdateOnMap();
/*foreach (var snake in snakeLocation) {
Console.WriteLine(snake.ToString());
} 调试用*/
// 位置更新完成,下面开始判定是否撞墙/自己
var positionSet = new HashSet<(int x, int y)>();
bool duplicatePosition = false;
foreach (var position in snakeLocation) {
// 如果添加失败,说明有重复位置,撞自己了
if (!positionSet.Add(position)) {
duplicatePosition = true;
break;
}
}
if (newSnakeHead.x == -1 || newSnakeHead.x == windowHeight || newSnakeHead.y == -1 || newSnakeHead.y == windowWidth || duplicatePosition) {
message = "游戏结束!";
RenderFrame();
gameOver = true;
Console.ReadLine();
} else {
message = "继续!";
}
}
评论