简述:利用控制台实现贪吃蛇游戏,可以退出,刷新,暂停,继续。
代码部分:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace GreedySnake
{
class Program
{
public static ConsoleKey inputKey;
static void Main(string[] args)
{
int var = 20;
unsafe
{
int* p = &var;
Console.WriteLine("Data is: {0} ", var);
Console.WriteLine("Data is: {0} ", var.GetType().ToString());
Console.WriteLine("Data is: {0} ", *p);
Console.WriteLine("Address is: {0} ", (int)p);
}
var snake = new Snake();
var screen = new Screen(20,40);
Console.SetCursorPosition(3, 2);
Console.ForegroundColor = ConsoleColor.White;
Console.BackgroundColor = ConsoleColor.Blue;
Console.Title = "Juke's Snake Game";
Console.SetWindowSize(41, 26);
screen.Update(snake, false);
if (Console.ReadKey(true).Key == ConsoleKey.S)
{
//New thread to detect user input
Thread thread_ReadKey = new Thread(ReadKey);
thread_ReadKey.Start();
//New controller.
var controller = new Controller();
controller.Run(snake, screen);
}
}
static void ReadKey()
{
while (true)
{
inputKey = Console.ReadKey(true).Key;
if (inputKey==ConsoleKey.X)return;
Thread.Sleep(50);
}
}
}
class Controller
{
direction dir = direction.right;
bool pause = false;
bool reset = false;
bool dead = false;
ConsoleKey keyValue=ConsoleKey.A;
ConsoleKey keyTemp = ConsoleKey.A;
public void Run(Snake snake, Screen screen)
{
while (true)
{
//Check user input key info.
keyTemp = keyValue;
keyValue = Program.inputKey;
if (keyValue!=keyTemp)
{
switch (keyValue)
{
case ConsoleKey.LeftArrow:
dir = direction.left;
break;
case ConsoleKey.UpArrow:
dir = direction.up;
break;
case ConsoleKey.RightArrow:
dir = direction.right;
break;
case ConsoleKey.DownArrow:
dir = direction.down;
break;
case ConsoleKey.X:
return;
case ConsoleKey.P:
pause = true;
break;
case ConsoleKey.C:
pause = false;
break;
case ConsoleKey.F1:
reset = true;
break;
default:
break;
}
}
//reset
if (reset)
{
snake = new Snake();
screen = new Screen(20, 40);
screen.Update(snake, false);
dir = direction.right;
pause = false;
reset = false;
dead = false;
Program.inputKey = ConsoleKey.RightArrow;
}
//dead
if (dead)continue;
//pause
if (pause) continue;
//snake move, dead check,eat check,update display.
if (snake.Die(screen.xSize,screen.ySize))//if snake dies.
{
screen.Update(snake, true);
dead = true;
}
else
{
if (snake.body[1].Equals(screen.foodPos))//move or eat and move
{
snake.Move(dir,true);
screen.foodExist = false;
screen.Update_Eco(snake, false);//update display...
}
else
{
snake.Move(dir,false);
screen.Update_Eco(snake, true);//update display...
}
}
Thread.Sleep(300);
}
}
}
class Snake
{
public Dictionary<int, Pos> body;
public Pos tail=new Pos(0,0);
public Snake()
{
body = new Dictionary<int, Pos>();
body.Add(1, new Pos(10, 20));
body.Add(2, new Pos(10, 19));
body.Add(3, new Pos(10, 18));
body.Add(4, new Pos(10, 17));
}
public void Move(direction dir,bool eat)
{
var tempx = body[body.Count].x;
var tempy = body[body.Count].y;
//tail.x = body[body.Count].x;
//tail.y = body[body.Count].y;
for (int i = body.Count; i >=2; i--)
{
body[i].x = body[i - 1].x;
body[i].y = body[i - 1].y;
}
switch (dir)
{
case direction.up:
body[1].x--;
break;
case direction.down:
body[1].x++;
break;
case direction.left:
body[1].y--;
break;
case direction.right:
body[1].y++;
break;
default:
break;
}
tail = new Pos(tempx, tempy);
if (eat)
{
body.Add(body.Count + 1, tail);
}
}
public bool Die(int xSize,int ySize)
{
// die from crash on walls
if (body[1].x>=xSize-1 || body[1].y>=ySize-1 ||body[1].x<=0 || body[1].y<=0)return true;
// die from eating itself,Linq used,此处新建了一个匿名类型new{int,int},做成集合,
// 然后判断新类型在集合中的个数。如用Pos类型,数不出来。。。
var col = body.Values.GroupBy(xyPair => new { xyPair.x, xyPair.y }).Where(xyPair => xyPair.Count() > 1);
if (col.Count() >= 1)
{
return true;
}
return false;
}
}
class Screen
{
public string[,] pixes;
public int xSize;
public int ySize;
public bool foodExist;
public Pos foodPos;
public Screen(int xSize,int ySize)
{
this.xSize = xSize;
this.ySize = ySize;
pixes = new string[xSize, ySize];
foodExist = false;
foodPos = new Pos(2, 2);
}
public void Update(Snake snake, bool dead)
{
for (int i = 0; i < xSize; i++)//清空
{
for (int j = 0; j < ySize; j++)
{
pixes[i, j] = " ";
}
}
if (!dead)//打印蛇及食物
{
for (int i = 1; i <= snake.body.Count; i++)
{
pixes[snake.body[i].x, snake.body[i].y] = "*";
}
if (!foodExist)
{
RandomFood();
while (snake.body.ContainsValue(foodPos)) RandomFood();
}
pixes[foodPos.x, foodPos.y] = "#";
foodExist = true;
}
else//打印结束语
{
var xMiddle = xSize / 2;
var yMiddle = ySize / 2;
pixes[xMiddle, yMiddle - 4] = "G";
pixes[xMiddle, yMiddle - 3] = "A";
pixes[xMiddle, yMiddle - 2] = "M";
pixes[xMiddle, yMiddle - 1] = "E";
pixes[xMiddle, yMiddle] = " ";
pixes[xMiddle, yMiddle + 1] = "O";
pixes[xMiddle, yMiddle + 2] = "V";
pixes[xMiddle, yMiddle + 3] = "E";
pixes[xMiddle, yMiddle + 4] = "R";
}
Console.Clear();
for (int i = 0; i < xSize; i++)//打印所有行
{
for (int j = 0; j < ySize; j++)
{
bool wall = i == 0 || i == xSize - 1 || j == 0 || j == ySize - 1;//Print walls by symbol
Console.Write(wall ? "@" : pixes[i, j]);
}
Console.Write('\n');
}
Console.WriteLine(" Operation:");
Console.WriteLine(" 按上下左右操作蛇的动作.");
Console.WriteLine(" Press S = Start ,X = Exit, F1 = Reset.");
Console.WriteLine(" Press P = Pause.,C = Continue.");
Console.WriteLine("@ Valmet Juke @");
Console.SetCursorPosition(0, 0);
}
public void Update_Eco(Snake snake, bool notEat)
{ //print head.
pixes[snake.body[1].x, snake.body[1].y] = "*";
Console.SetCursorPosition(snake.body[1].y, snake.body[1].x);
Console.Write("*");
//print tail.
if (notEat)
{
pixes[snake.tail.x, snake.tail.y] = " ";
Console.SetCursorPosition(snake.tail.y, snake.tail.x);
Console.Write(" ");
}
//print food to * if eaten, while # after created.
if (!foodExist)
{ //create food
RandomFood();
while (snake.body.ContainsValue(foodPos)) RandomFood();
foodExist = true;
//print food
pixes[foodPos.x, foodPos.y] = "#";
Console.SetCursorPosition(foodPos.y, foodPos.x);
Console.Write("#");
}
Console.SetCursorPosition(0, 0);
}
private void RandomFood()
{
var rdm = new Random();
foodPos.x = rdm.Next(1, xSize-2);
foodPos.y = rdm.Next(1, ySize-2);
}
}
class Pos:IComparable
{
public int x = 0;
public int y = 0;
public Pos(int a, int b)
{
x = a;
y = b;
}
public int CompareTo(object obj)
{
var a=obj as Pos;
if (a.x==this.x && a.y==this.y)
{
return 1;
}
return 0;
}
public override bool Equals(object obj)
{
var a = obj as Pos;
if (a.x == this.x && a.y == this.y)
{
return true;
}
return false;
}
}
enum direction
{
up = 1,
down = 2,
left = 3,
right = 4
}
}