C#Console版本贪吃蛇

        这次在工作之余用C#写了一个简单的贪吃蛇程序,一般的都是WinForm形式的,这次弄了个控制台版本的,因为C# Console全部都是输入输出流,要在CMD窗口做这种有前台UI界面的程序应该是不适合的,但是想起之前的DOS版本的系统,我觉得应该是可以做到了,所以就花了几个晚上弄了这么一个东西,先上个截图:

界面比较简单,一个CMD窗口,其他的就是由字符构成的各种形状,做这种Console的贪吃蛇有以下几个需要注意的地方:

1.理解Console这个东西,它是一个标准的I/O输入输出流;

2.控制台有2个术语 :屏幕缓冲区和控制台窗口,我们一般获取的大小是控制台大小而不是缓冲区大小,这个可以看看MSDN;

3.关于贪吃蛇本身的有一下几个问题:如何让蛇移动?如何判断蛇吃了食物?如何判断蛇碰了边框?等等,下面就详细的说说。

 

首先,我想说,不管做什么程序或者软件,设计数据结构非常重要,数据结构设计好了,问题也就变的简单了,真的如此!

按照面向对象的要求,设计Snake类,由于Console程序中全部是以字符形式的,所以画Snake必须要有点,点构成线,首先设计Point类如下:

1.Point.cs

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

namespace Snake
{
    /// <summary>
    /// Class Point
    /// </summary>
    public class Point : IComparable<Point>
    {
        private int x = 0;
        /// <summary>
        /// Gets or sets the x
        /// </summary>
        public int X
        {
            get { return x; }
            set { x = value; }
        }
        private int y = 0;
        /// <summary>
        /// Gets or sets the y
        /// </summary>
        public int Y
        {
            get { return y; }
            set { y = value; }
        }
        /// <summary>
        /// Compare the two point
        /// </summary>
        /// <param name="other">Other point</param>
        /// <returns>-1 if x < other.X && y < other.Y , 0 if x == other.X && y == other.Y , otherwise 1</returns>
        public int CompareTo(Point other)
        {
            if (x < other.X && y < other.Y)
            {
                return -1;
            }
            else if (x == other.X && y == other.Y)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        }
    }
}


 

这里需要说一下这个point继承了IComparable接口,是为了下面的比较和判断蛇是否触碰了其他物体或者自己本身,好了下面就可以设计Snake.cs类了。

2.Snake.cs

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

namespace Snake
{
    /// <summary>
    /// Class Snake
    /// </summary>
    public class Snake
    {
        private Point head = null;
        /// <summary>
        /// Gets or sets the snake's head
        /// </summary>
        public Point Head
        {
            get { return head; }
            set { head = value; }
        }
        private Point[] body = null;
        /// <summary>
        /// Gets or sets the snake's body
        /// </summary>
        public Point[] Body
        {
            get { return body; }
            set { body = value; }
        }
        private Point tail = null;
        /// <summary>
        /// Gets or sets the snake's tail
        /// </summary>
        public Point Tail
        {
            get { return tail; }
            set { tail = value; }
        }
    }
}


为什么要有蛇头、蛇身和蛇尾呢?简单的来说,按照面向对象的话你会想到的,复杂的就要看代码的逻辑处理了,这里不多说了,自己体会。接下来就是食物类Food.cs。

3.Food.cs

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

namespace Snake
{
    /// <summary>
    /// Class Food
    /// </summary>
    public class Food
    {
        private Point position = null;
        /// <summary>
        /// Gets or sets the food's position
        /// </summary>
        public Point Position
        {
            get { return position; }
            set { position = value; }
        }
    }
}


 

食物就是一个位置上的一个点就足够了,没有其他属性。这样基本的数据结构就构造好了,剩下的就是怎么将这些结构联系起来构造这个游戏的逻辑了,首先,进入游戏,肯定是要按方向键来控制蛇的移动的,Console里面就有这样判断键盘输入的方法和属性,如下:

ConsoleKey key = Console.ReadKey(true).Key;
ConsoleKey这个类里面就有属性判断是属于按下了键盘上的哪个键,这个可以看MSDN。ConsoleKey这个搞定了之后再来看看如何画出游戏界面,这个就不是太复杂,Console类里面有这样的一个方法如下:
Console.SetCursorPosition(i, j);

设置光标所在的位置,这样就可以再这个为写入字符了,如果没有了这个方法,那我们就需要每次蛇移动都要重新画整个界面,这样会导致一个问题:控制台窗口屏幕会一直闪,因为我们是绘制整个控制台,有了这个方法,我们只需要刷新局部区域就可以了,比如蛇移动我们只需要更新蛇的位置就可以了。 最后说一下蛇碰到食物和边框之后怎么处理,当蛇碰到食物,这时候我们就可以将食物作为当前的蛇头,之前的蛇头作为蛇的身体的第一个节点,这样蛇身长度加1,蛇尾还是原来的蛇尾;当蛇头碰到边框游戏就结束。还有,当蛇移动且没碰到食物也没碰到边框的时候,这时蛇头就变成蛇当前移动到的点,蛇身的第一个点就变成了之前的蛇头的那个点,以此类推,蛇就像前移动了一个位置。 好了,大概就这么多了,最后就是画界面,代码如下:
      
        /// <summary>
        /// Draw console ui
        /// </summary>
        private void DrawConsoleUI()
        {
            Console.Clear();
            Point tempPoint = null;

            Console.SetCursorPosition(0, 0);
            Console.WriteLine("Name : " + name);
            Console.SetCursorPosition(0, 1);
            Console.WriteLine("Score : " + score);
            Console.SetCursorPosition(0, 2);
            Console.WriteLine("Press R to restart game after you losed the game, press E to exit game");
            for (int i = 0; i < uiWidth; i += 2)
            {
                Console.SetCursorPosition(i, 3);
                Console.Write(".");
            }

            for (int i = 2; i < uiHeight; i++)
            {
                for (int j = 0; j < uiWidth; j++)
                {
                    tempPoint = new Point();
                    tempPoint.X = j;
                    tempPoint.Y = i;

                    if (tempPoint.CompareTo(currentFood.Position) == 0)
                    {
                        Console.SetCursorPosition(j, i);
                        Console.Write(GetFoodElement());
                    }
                    else if (tempPoint.CompareTo(currentSnake.Head) == 0)
                    {
                        Console.SetCursorPosition(j, i);
                        Console.Write(GetHeadElement());
                    }
                    else if (IsSnakeBodyCoverPoint(currentSnake.Body, tempPoint))
                    {
                        Console.SetCursorPosition(j, i);
                        Console.Write(GetBodyElement());
                    }
                    else if (tempPoint.CompareTo(currentSnake.Tail) == 0)
                    {
                        Console.SetCursorPosition(j, i);
                        Console.Write(GetTailElement());
                    }
                }
            }
        }


其中一些方法看到名字就知道什么意思了,这个实现起来比较简单,这里就不上代码了。。。

 

源码下载

 

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
以下是使用C#编写的简单贪吃蛇游戏代码,仅供参考: ```csharp using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace ConsoleApp1 { class Program { static int width = 20; static int height = 20; static int score = 0; static int[,] grid = new int[width, height]; static List<Point> snake = new List<Point>(); static Point food = new Point(); static Random rnd = new Random(); static void Main(string[] args) { InitGame(); while (true) { DrawGrid(); DrawSnake(); DrawFood(); MoveSnake(); if (CheckCollision()) { Console.Clear(); Console.WriteLine("Game over!"); Console.WriteLine("Score: " + score); Console.ReadKey(); break; } Thread.Sleep(100); } } static void InitGame() { snake.Add(new Point(width / 2, height / 2)); grid[snake[0].x, snake[0].y] = 1; food = GenerateFood(); } static void DrawGrid() { Console.Clear(); for (int i = 0; i < height + 2; i++) { for (int j = 0; j < width + 2; j++) { if (i == 0 || i == height + 1 || j == 0 || j == width + 1) Console.Write("#"); else Console.Write(" "); } Console.WriteLine(); } Console.WriteLine("Score: " + score); } static void DrawSnake() { foreach (Point p in snake) { Console.SetCursorPosition(p.x + 1, p.y + 1); Console.Write("*"); } } static void DrawFood() { Console.SetCursorPosition(food.x + 1, food.y + 1); Console.Write("@"); } static void MoveSnake() { Point head = new Point(snake[0].x, snake[0].y); switch (Console.ReadKey().Key) { case ConsoleKey.LeftArrow: head.x--; break; case ConsoleKey.RightArrow: head.x++; break; case ConsoleKey.UpArrow: head.y--; break; case ConsoleKey.DownArrow: head.y++; break; } snake.Insert(0, head); if (head.x == food.x && head.y == food.y) { score++; food = GenerateFood(); } else { snake.RemoveAt(snake.Count - 1); } } static bool CheckCollision() { if (snake[0].x == 0 || snake[0].x == width + 1 || snake[0].y == 0 || snake[0].y == height + 1) return true; for (int i = 1; i < snake.Count; i++) { if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) return true; } return false; } static Point GenerateFood() { Point p = new Point(rnd.Next(1, width + 1), rnd.Next(1, height + 1)); while (grid[p.x, p.y] == 1) { p.x = rnd.Next(1, width + 1); p.y = rnd.Next(1, height + 1); } return p; } class Point { public int x; public int y; public Point(int x, int y) { this.x = x; this.y = y; } } } } ```
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值