命令行贪吃蛇2.0
实现过程 & 遇到的问题
-
最开始想用动态数组来记录蛇,后来改成只记录头尾,发现只记录头尾没办法实现, 所以用队列来记录蛇。
-
地图Map为X行Y列,但是Console.SetCursorPoisition()函数的X轴是横,y轴是纵轴。Console.SetCursorPosition(HeadY, HeadX);
-
Console.KeyAvailable 用来检测按键是否按下,如果没按下保持现方向不变。
-
private int[] MoveTo=new int[8] { -1, 0, 1, 0, 0, -1, 0, 1 };根据输入将wasd映射为整数对应,前四个为HeadX的改变量,后四个为HeadY的改变量。将不同方向的函数整合为一个函数
5.定义了 LastFoodX 和 LastFoodY 来实现 吃近食物的效果,当食物到了蛇尾时,蛇长度加一。
链接: http://pan.baidu.com/s/1jIsOZrS 密码: qq8u
玩家体验
根据玩家建议加入了可重新开始和蛇反方向移动时游戏该结束。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Threading;
namespace Snake
{
class snake
{
private int x;
private int y;
public bool isHead;
public snake(int a,int b,bool h)
{
x = a;
y = b;
isHead = h;
}
public int getx()
{
return x;
}
public int gety()
{
return y;
}
}
class Map
{
const int WALL = -1;
const int BODY = 1;
const int HEAD = 2;
const int FOOD = 3;
const int MapHeight = 20;
const int MapWidth = 40;
private int [,] map =new int [50,50];
private int HeadX = 5;
private int HeadY = 6;
private int dir = 3;
private int FoodX;
private int FoodY;
private int LastFoodX = -1;
private int LastFoodY = -1;
private bool end = false ;
private int[] MoveTo=new int[8] { -1, 0, 1, 0, 0, -1, 0, 1 };
private Queue <snake >s = new Queue<snake>();
public Map()
{
int i, j;
snake a = new snake(HeadX, HeadY-2, false);
snake b = new snake(HeadX, HeadY-1, false);
snake c = new snake(HeadX, HeadY, true);
s.Enqueue(a);
s.Enqueue(b);
s.Enqueue(c);
for (i = 0; i <=MapHeight; i++)
for (j = 0; j <= MapWidth; j++)
{
if (i == 0 || i == MapHeight || j == 0 || j == MapWidth)
map[i,j] = WALL ;
}
foreach (snake item in s)
{
if (item.isHead)
map[item.getx(), item.gety()] = HEAD ;
else map[item.getx(), item.gety()] = BODY ;
}
}
public void AddFood()
{
Random rnd = new Random();
do
{
FoodX =rnd.Next(1,MapHeight);
FoodY = rnd.Next (1,MapWidth);
} while (map[FoodX, FoodY] != 0);
map[FoodX, FoodY] = FOOD;
Console.SetCursorPosition(FoodY, FoodX);
Console.Write("$");
}
public void show()
{
Console.SetCursorPosition(0, 0);
int i, j;
for (i = 0; i <= MapHeight; i++)
{
for (j = 0; j <= MapWidth; j++)
{
if (map[i, j] == WALL)
Console.Write("#");
else if (map[i, j] == HEAD)
Console.Write("O");
else if (map[i, j] == BODY)
Console.Write("o");
else Console.Write(" ");
}
Console.WriteLine();
}
AddFood();
}
public void HandleInput()
{
ConsoleKeyInfo op = new ConsoleKeyInfo();
if (Console.KeyAvailable)
{
op = Console.ReadKey(true);
switch (op.KeyChar)
{
case 'w':
case 'W':
dir = 0;
break;
case 'a':
case 'A':
dir = 1;
break;
case 's':
case 'S':
dir = 2;
break;
case 'd':
case 'D':
dir = 3;
break;
}
}
}
public void Move()
{
if (map[HeadX+MoveTo[dir] ,HeadY + MoveTo[dir+4] ]!= WALL && map[HeadX + MoveTo[dir], HeadY + MoveTo[dir + 4]] != BODY )
{
Console.SetCursorPosition(HeadY, HeadX);
Console.Write("o");
map[HeadX, HeadY] = BODY ;
if (LastFoodX > 0 && LastFoodY>0)
{
Console.SetCursorPosition(LastFoodY, LastFoodX);
Console.Write("0");
}
HeadX += MoveTo[dir];
HeadY += MoveTo[dir + 4];
map[HeadX, HeadY] = HEAD ;
snake newHead = new snake(HeadX, HeadY, true);
s.Enqueue(newHead);
Console.SetCursorPosition(HeadY, HeadX);
Console.Write("O");
if(HeadX==FoodX && HeadY==FoodY)
{
LastFoodX = HeadX;
LastFoodY = HeadY;
AddFood();
}
snake tail = s.Peek();
if (LastFoodX== tail.getx() && LastFoodY== tail.gety())
{
LastFoodX = -1;
LastFoodY = -1;
}
else
{
s.Dequeue();
Console.SetCursorPosition(tail.gety(), tail.getx());
map[tail.getx(), tail.gety()] = 0;
Console.Write(" ");
}
}
else
{
end = true;
Console.SetCursorPosition((MapWidth-9)/2, MapHeight/2-1);
Console.Write("Game Over");
Console.SetCursorPosition( 8, MapHeight / 2);
Console.Write("Press any key to restart...");
}
}
public bool isEnd()
{
return end;
}
}
class Program
{
static void Main(string[] args)
{
while(true )
{
Map m = new Map();
m.show();
while (!m.isEnd())
{
m.HandleInput();
m.Move();
Thread.Sleep(200);
}
Console.ReadKey(true);
}
}
}
}