简易贪吃蛇游戏问题:调用Console.ReadKey()后蛇头不移动
C#控制台贪吃蛇:蛇头无法移动问题修复
问题情况
我写了一个简易控制台贪吃蛇游戏,按下方向键后代表蛇头的“0”完全不动。原代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleSnakeGame_ConsoleApp { internal class Program { public bool gameOver = true; public int width = 20; public int height = 20; //HEAD POS public int x, y; //FRUIT POS public int fruitX, fruitY; public int score; enum eDirection { STOP = 0, LEFT, RIGHT, UP, DOWN }; eDirection dir; static void Main(string[] args) { Program oyun = new Program(); oyun.Setup(); oyun.Draw(); oyun.Input(); oyun.Logic(); Console.ReadLine(); } public void Setup() { gameOver = false; string a = "!!!!! SİMPLE SNAKE GAME !!!!!"; Console.WriteLine(gameOver.ToString() + " " + a, "{0}" + "{1}"); dir = eDirection.STOP; x = width / 2; y = height / 2; Random rnd = new Random(); fruitX = rnd.Next(1, 19); fruitY = rnd.Next(1, 19); score = 0; } void Draw() { for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { if (i == y && j == x) { Console.Write("0"); } else if (i == fruitY && j == fruitX) { Console.Write("F"); } else if (j > 0 && j < height - 1 && i > 0 && i < width - 1) { Console.Write(" "); } else { Console.Write("#"); } } Console.WriteLine(); } Console.WriteLine(); } void Input() { ConsoleKey key; key = Console.ReadKey(true).Key; if (key == ConsoleKey.A) { dir = eDirection.LEFT; } else if (key == ConsoleKey.D) { dir = eDirection.RIGHT; } else if (key == ConsoleKey.W) { dir = eDirection.UP; } else if (key == ConsoleKey.S) { dir = eDirection.DOWN; } else if (key == ConsoleKey.X) { gameOver=true; } } void Logic() { switch (dir) { case eDirection.LEFT: x--; break; case eDirection.RIGHT: x++; break; case eDirection.UP: y--; break; case eDirection.DOWN: y++; break; default: break; } } } }
我一开始以为是Console.ReadKey()的问题,但不知道怎么改。
问题根源
不是Console.ReadKey()本身的问题,而是三个核心错误:
- 缺少游戏主循环:Main方法只执行了一次绘制、输入、逻辑更新,按键修改方向后不会重新渲染界面,也不会持续更新蛇的位置。
- 坐标逻辑颠倒:Draw方法中蛇头的判断是
i == y && j == x(i为列、j为行),但Logic方法里方向对应的坐标修改完全错误——比如LEFT应该修改列号y,UP应该修改行号x,原代码搞反了对应关系。 - 阻塞式输入:
Console.ReadKey(true)会阻塞程序直到有按键输入,导致游戏无法持续运行。
修复方案
- 添加游戏主循环:用
while(!gameOver)包裹绘制、输入、逻辑更新步骤,让游戏持续运行。 - 修正坐标移动逻辑:让方向对应的坐标修改与Draw中的判断一致:
- LEFT:y--(列号左移)
- RIGHT:y++(列号右移)
- UP:x--(行号上移)
- DOWN:x++(行号下移)
- 非阻塞输入判断:先检查
Console.KeyAvailable,有按键时再读取,避免阻塞游戏循环。 - 添加清屏和延时:每次循环开始用
Console.Clear()清屏,用Thread.Sleep()控制蛇的移动速度。
完整修复代码
using System; using System.Threading; namespace SimpleSnakeGame_ConsoleApp { internal class Program { public bool gameOver = true; public int width = 20; public int height = 20; // 蛇头坐标:x是行号,y是列号 public int x, y; // 水果坐标 public int fruitX, fruitY; public int score; enum eDirection { STOP = 0, LEFT, RIGHT, UP, DOWN }; eDirection dir; static void Main(string[] args) { Program oyun = new Program(); oyun.Setup(); // 游戏主循环 while (!oyun.gameOver) { Console.Clear(); oyun.Draw(); oyun.Input(); oyun.Logic(); // 控制移动速度,数值越小速度越快 Thread.Sleep(150); } Console.WriteLine("游戏结束!你的得分:{0}", oyun.score); Console.ReadLine(); } public void Setup() { gameOver = false; Console.WriteLine("!!!!! 简易贪吃蛇游戏 !!!!!"); dir = eDirection.STOP; // 初始蛇头放在屏幕中间 x = height / 2; y = width / 2; Random rnd = new Random(); fruitX = rnd.Next(1, height - 1); fruitY = rnd.Next(1, width - 1); score = 0; } void Draw() { // 绘制地图 for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { if (i == y && j == x) { Console.Write("0"); } else if (i == fruitY && j == fruitX) { Console.Write("F"); } else if (j > 0 && j < height - 1 && i > 0 && i < width - 1) { Console.Write(" "); } else { Console.Write("#"); } } Console.WriteLine(); } Console.WriteLine("得分:{0}", score); Console.WriteLine("按WASD移动,X退出游戏"); } void Input() { // 非阻塞读取按键 if (Console.KeyAvailable) { ConsoleKey key = Console.ReadKey(true).Key; switch (key) { case ConsoleKey.A: dir = eDirection.LEFT; break; case ConsoleKey.D: dir = eDirection.RIGHT; break; case ConsoleKey.W: dir = eDirection.UP; break; case ConsoleKey.S: dir = eDirection.DOWN; break; case ConsoleKey.X: gameOver = true; break; } } } void Logic() { switch (dir) { case eDirection.LEFT: y--; break; case eDirection.RIGHT: y++; break; case eDirection.UP: x--; break; case eDirection.DOWN: x++; break; } // 吃到水果逻辑 if (x == fruitX && y == fruitY) { score++; Random rnd = new Random(); fruitX = rnd.Next(1, height - 1); fruitY = rnd.Next(1, width - 1); } // 撞墙判定 if (x <= 0 || x >= height - 1 || y <= 0 || y >= width - 1) { gameOver = true; } } } }
说明
修复后的代码新增了撞墙判定和吃水果加分逻辑,蛇可以通过WASD正常移动,按下X键可退出游戏。
内容的提问来源于stack exchange,提问作者Programmable Physics
相关产品推荐
相关产品推荐

