自动寻路贪吃蛇C#
作者:互联网
using System;
using System.Collections;
using System.Threading;
using System.Collections.Generic;
//特殊情况 头走尾,尾不删,不置false
//遇食物,尾不动
namespace snakeai
{
class Program
{
static void Main(string[] args)
{
Console.CursorVisible = false;
Snake snake = new Snake(24, 24);
snake.eatFood();
}
}
class Snake
{
public struct Point
{
public int x;
public int y;
public Point(int xx, int yy)
{
x = xx; y = yy;
}
public static bool operator ==(Point a, Point b)
{
return (a.x == b.x && a.y == b.y);
}
public static bool operator !=(Point a, Point b)
{
return !(a == b);
}
};
public Point food;
const int Down = 1;
const int Up = 2;
const int Right = 3;
const int Left = 4;
public LinkedList<Point> body;//存蛇的身体
public int xlen;//x方向长度,偶数
public int ylen;//y方向长度,偶数
int[,] dir;
bool[,] hasBody;//
Random rd;
public void debug()
{
Console.SetCursorPosition(0, 24);
var t = front();
for (int i = 0; i < xlen; i++)
{
for (int j = 0; j < ylen; j++)
{
if (t == new Point(i, j))
{
Console.Write(" ");
continue;
}
switch (dir[i, j])
{
case Left:
Console.Write("L"); break;
case Right:
Console.Write("R"); break;
case Down:
Console.Write("D"); break;
case Up:
Console.Write("U"); break;
}
}
Console.WriteLine("");
}
}
public Snake(int x, int y)
{
xlen = x;
ylen = y;
dir = new int[x, y];
body = new LinkedList<Point>();
for (int i = 0; i < x; i += 2)
{
for (int j = 0; j < y; j += 2)
{
dir[i, j] = Right;
dir[i, j + 1] = Down;
dir[i + 1, j + 1] = Left;
dir[i + 1, j] = Up;
}
}
hasBody = new bool[x, y];
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
hasBody[i, j] = false;
rd = new Random();
Point p = generateNode();
push(p);
}
public void move()
{
var newHead = generateNewHead();
push(newHead);
Thread.Sleep(10);
if (newHead == food)
{
food = generateNode();
GenerateBody(food);
}
else
pop();
}
public void eatFood()
{
food = generateNode();
GenerateBody(food);
int[] tmpdir = new int[2];
while (body.Count < xlen * ylen)
{
var head = body.First.Value;
var foodlt = getLT(food);
var headlt = getLT(head);
if(foodlt.x>headlt.x)
for (int i = headlt.x; i < foodlt.x; i+=2)
ConnectDown(new Point(i, headlt.y));
if (foodlt.x < headlt.x)
for (int i = headlt.x; i > foodlt.x; i -= 2)
ConnectUp(new Point(i, headlt.y));
if (foodlt.y > headlt.y)
for (int i = headlt.y; i < foodlt.y; i += 2)
ConnectRight(new Point(foodlt.x, i));
if (foodlt.y < headlt.y)
for (int i = headlt.y; i > foodlt.y; i -= 2)
ConnectLeft(new Point(foodlt.x, i));
move();
move();
for(int i = 0; i < xlen; i+=2)
{
for(int j = 0; j < ylen; j+=2)
{
var p = new Point(i, j);
if (inCircle(p) && !HasBody(p)) {
var up = p;up.x -= 2;
if (LegalPoint(up) && inCircle(up)) DropDown(up);
var left = p;left.y -= 2;
if (LegalPoint(left) && inCircle(left)) DropRight(left);
var down = p; down.x += 2;
if (LegalPoint(down) && inCircle(down)) DropUp(down);
var right = p; right.y += 2;
if (LegalPoint(right) && inCircle(right)) DropLeft(right);
}
}
}
}
}
public bool LegalPoint(Point p) {
return p.x >= 0 && p.x < xlen && p.y >= 0 && p.y < ylen;
}
public Point generateNewHead()
{
var p = body.First.Value;
switch (dir[p.x, p.y])
{
case Up:
p.x -= 1; break;
case Down:
p.x += 1; break;
case Right:
p.y += 1; break;
case Left:
p.y -= 1; break;
default: break;
}
return p;
}
public bool inCircle(Point p)
{
p = getLT(p);
return !(dir[p.x, p.y] == Right && dir[p.x, p.y + 1] == Down
&& dir[p.x + 1, p.y + 1] == Left && dir[p.x + 1, p.y] == Up);
}
public Point generateNode()
{
Point p;
do
{
p.x = rd.Next(0, xlen - 1);
p.y = rd.Next(0, ylen - 1);
} while (hasBody[p.x, p.y]);
return p;
}
public Point getLT(Point p)
{
p.x -= p.x % 2;
p.y -= p.y % 2;
return p;
}
public void ConnectLeft(Point p)
{
p = getLT(p);
var t = p;
t.y -= 2;
if (inCircle(t)) return;
dir[p.x, p.y - 1] = Right;
dir[p.x + 1, p.y] = Left;
}
public void ConnectRight(Point p)
{
p = getLT(p);
var t = p;
t.y += 2;
if (inCircle(t)) return;
dir[p.x, p.y + 1] = Right;
dir[p.x + 1, p.y + 2] = Left;
}
public void ConnectUp(Point p)
{
p = getLT(p);
var t = p;
t.x -= 2;
if (inCircle(t)) return;
dir[p.x, p.y] = Up;
dir[p.x - 1, p.y + 1] = Down;
}
public void ConnectDown(Point p)
{
p = getLT(p);
var t = p;
t.x += 2;
if (inCircle(t)) return;
dir[p.x + 2, p.y] = Up;
dir[p.x + 1, p.y + 1] = Down;
}
public void DropLeft(Point p)
{
p = getLT(p);
dir[p.x, p.y - 1] = Down;
dir[p.x + 1, p.y] = Up;
}
public void DropRight(Point p)
{
p = getLT(p);
dir[p.x, p.y + 1] = Down;
dir[p.x + 1, p.y + 2] = Up;
}
public void DropUp(Point p)
{
p = getLT(p);
dir[p.x, p.y] = Right;
dir[p.x - 1, p.y + 1] = Left;
}
public void DropDown(Point p)
{
p = getLT(p);
dir[p.x + 2, p.y] = Right;
dir[p.x + 1, p.y + 1] = Left;
}
public static void GenerateBody(Point p)
{
Console.SetCursorPosition(p.x, p.y);
Console.Write("*");
}
public static void EraseTail(Point p)
{
Console.SetCursorPosition(p.x, p.y);
Console.Write(" ");
}
public void push(Point p)
{
body.AddFirst(p);
hasBody[p.x, p.y] = true;
GenerateBody(p);
}
public void pop()
{
var p = body.Last.Value;
body.RemoveLast();
if (p != body.First.Value)
{
hasBody[p.x, p.y] = false;
EraseTail(p);
}
}
public void Drop(Point d) {
Point n = body.Last.Value;
if (n.x < d.x) { DropDown(n); return; }
if (n.x > d.x) { DropUp(n); return; }
if (n.y < d.y) { DropRight(n); return; }
if (n.y > d.y) { DropLeft(n); return; }
}
public Point front()
{
return body.First.Value;
}
public bool HasBody(Point p)
{
p = getLT(p);
for (int i = 0; i <= 1; i++)
for (int j = 0; j <= 1; j++)
if (hasBody[p.x + i, p.y + j])
return true;
return false;
}
}
}
标签:return,Point,C#,void,int,贪吃蛇,寻路,public,dir 来源: https://blog.csdn.net/weixin_39057744/article/details/117674391