You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

简易贪吃蛇游戏问题:调用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)会阻塞程序直到有按键输入,导致游戏无法持续运行。

修复方案

  1. 添加游戏主循环:用while(!gameOver)包裹绘制、输入、逻辑更新步骤,让游戏持续运行。
  2. 修正坐标移动逻辑:让方向对应的坐标修改与Draw中的判断一致:
    • LEFT:y--(列号左移)
    • RIGHT:y++(列号右移)
    • UP:x--(行号上移)
    • DOWN:x++(行号下移)
  3. 非阻塞输入判断:先检查Console.KeyAvailable,有按键时再读取,避免阻塞游戏循环。
  4. 添加清屏和延时:每次循环开始用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 18:05:25