功能实现:
- 贪吃蛇的左右上下移动;
- 贪吃蛇吃食物;
- 贪吃蛇碰到墙或者身体死亡;
如下是 详细的代码:
using System;
using System.Threading;
namespace CmdSnake
{
class Program
{
static void Main(string[] args)
{
///
/// 初始化
///
Snake.Instance().Start();
Map.Instance().Start();
for (; ; )
{
Snake.Instance().Update();
Map.Instance().Update();
Map.Instance().Draw();
Snake.Instance().Draw();
Thread.Sleep(100); //延时
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace CmdSnake
{
class Map
{
private static Map instance = null;
//建立单例
public static Map Instance()
{
if (instance == null)
{
instance = new Map();
}
return instance;
}
///
///
///
public const int Blank = 0;
public const int Wall = 1;
public const int Food = 2;
int[,] map = null;
private Random rnd = new Random();
public int GetAt(Point pt)
{
return map[pt.y, pt.x];
}
public void SetAt(Point pt, int value)
{
map[pt.y, pt.x] = value;
}
///
/// 生成食物规则:
/// 1.只能在空地上生成
/// 2.不能在蛇的身体生成
///
public void GenFood()
{
Point pt;
for (; ; )
{
pt.x = rnd.Next(map.GetLength(1));
pt.y = rnd.Next(map.GetLength(0));
if (GetAt(pt) == Map.Blank)
{
map[pt.x, pt.y] = Map.Food;
return;
}
}
}
///
/// 初始化
///
public void Start()
{
map = new int[30, 30] //行 列
{
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,},
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},
};
GenFood();
}
///
/// 逻辑处理(数据运算)
///
public void Update()
{
}
///
/// 图形处理
///
public void Draw()
{
for (int i = 0; i < map.GetLength(0); i++) // i | 行
{
for (int j = 0; j < map.GetLength(1); j++) // j - 列
{
Console.SetCursorPosition(j*2,i); //j*2两个格子
//Console.ForegroundColor = ConsoleColor.Yellow;
switch (map[i, j])
{
case Map.Wall:
Console.BackgroundColor = ConsoleColor.Green;
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(' ');
break;
case Map.Food:
Console.BackgroundColor = ConsoleColor.Gray;
Console.ForegroundColor = ConsoleColor.DarkBlue;
Console.Write('●');
break;
case Map.Blank:
Console.BackgroundColor = ConsoleColor.Gray;
Console.ForegroundColor = ConsoleColor.Gray;
Console.Write(' ');
break;
}
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace CmdSnake
{
enum Direction
{
Left, //左
Right, //右
Up, //上
Down, //下
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace CmdSnake
{
//希望 S2 = S1 赋值的时候,是把S1的内容(x,y)拷贝给S2,而非让S2跟S1指向同一块内存(class),所以需要定义为struct
struct Point
{
public int x;
public int y;
public Point(int x,int y)
{
this.x = x;
this.y = y;
}
//+运算符重载
public static Point operator +(Point p1, Point p2)
{
return new Point(p1.x + p2.x, p1.y + p2.y);
}
//-运算符重载
public static bool operator == (Point p1, Point p2)
{
return p1.x == p2.x && p1.y == p2.y;
}
public static bool operator !=(Point p1, Point p2)
{
return !(p1 == p2);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace CmdSnake
{
class Snake
{
private static Snake instance = null;
public static Snake Instance()
{
if (instance == null)
{
instance = new Snake();
}
return instance;
}
List<Point> body = new List<Point>();
Direction dir = Direction.Right;
Point tail; //尾巴
///
/// 初始化
///
public void Start()
{
body.Add(new Point(4, 2));
body.Add(new Point(3, 2));
body.Add(new Point(2, 2));
}
///
/// 判断依据:
/// 1.蛇头是否碰上墙
/// 2.蛇头是否碰上身体
///
/// true:结束,false:进行中
private bool IsGameOver()
{
Point head = body[0]; //蛇头的坐标
//1.蛇头是否碰上墙
if (Map.Instance().GetAt(head) == Map.Wall)
return true;
//2.蛇头是否碰上身体
for (int i = 1; i < body.Count; i++)
{
if (body[i] == head) return true;
}
return false;
}
///
/// 处理转向判定
/// 注意:只能往蛇的前进的侧方向转向
/// 1.获取按键输入
/// 2.判定是否能移动
/// 改变dir
///
private void Turn()
{
//1.按键输入
if (Console.KeyAvailable)
{
ConsoleKey key = Console.ReadKey(true).Key;
//2.判定是否能移动
if (key == ConsoleKey.LeftArrow && dir != Direction.Right)
{
dir = Direction.Left;
}
else if (key == ConsoleKey.RightArrow && dir != Direction.Left)
{
dir = Direction.Right;
}
else if (key == ConsoleKey.UpArrow && dir != Direction.Down)
{
dir = Direction.Up;
}
else if (key == ConsoleKey.DownArrow && dir != Direction.Up)
{
dir = Direction.Down;
}
}
}
///
/// 根据蛇的移动方向dir在地图上前进
///
private void Move()
{
Point offset =new Point(0,0); //偏移量
switch (dir)
{
case Direction.Left:
offset = new Point(-1,0);break;
case Direction.Right:
offset = new Point(1,0); break;
case Direction.Up:
offset = new Point(0,-1); break;
case Direction.Down:
offset = new Point(0,1); break;
}
Point head = body[0];
head += offset;
body.Insert(0,head);
tail = body[body.Count-1];
body.RemoveAt(body.Count - 1);
}
///
/// 判定蛇头位置是否有一个食物,如果有,则:
/// 1.在地图上删除该位置的事物
/// 2.蛇的身体增长一节
/// 3.重新生成一个食物
///
private void Eat()
{
Point head = body[0];
if (Map.Instance().GetAt(head) == Map.Food)
{
//1.在地图上删除该位置的事物
Map.Instance().SetAt(head,Map.Blank);
//2.蛇的身体增长一节(尾部不删除)
body.Add(tail);
//3.重新生成一个食物
Map.Instance().GenFood();
}
}
public void Update()
{
if (IsGameOver())return;
Turn();
Move();
Eat();
}
public void Draw()
{
for (int i = body.Count-1; i >=0; i--) // j - 列 从蛇尾往蛇头画,防止蛇头被蛇尾覆盖
{
Point pt = body[i];
Console.SetCursorPosition(pt.x * 2, pt.y);
Console.ForegroundColor = i== 0 ? ConsoleColor.Red : ConsoleColor.Yellow;
Console.BackgroundColor = ConsoleColor.Gray;
Console.Write('●');
}
}
}
}