#include<time.h>
#include"snake.h"
void gotoxy(int x, int y)
{
COORD pos;
pos.X = x * 2;
pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
void initSnake(Snake* s)//初始化蛇
{
s->x = WIDTH/4+rand()% WIDTH/2;
s->y = LENGTH / 4 + rand() % LENGTH / 2;
s->prev = NULL;
s->next = NULL;
}
int isSnakeEatItself(Snake* head)//判断游戏是否结束
{
int gameover = 0;
if (head->x < 0 || head->x >= WIDTH || head->y < 0 || head->y >= LENGTH)
return 1;
Snake* pt = head->next;
while (pt)
{
if (head->x == pt->x && head->y == pt->y)
{
gameover = 1;
break;
}
pt = pt->next;
}
return gameover;
}
int isSnakeEatMeetFood(Snake* snake, Food* food)//判断蛇是否吃到食物
{
if (snake->x == food->x && snake->y == food->y)
return 1;
else
return 0;
}
Snake* snakeGrow(Snake* head)//蛇身变长
{
Snake* p = (Snake*)malloc(sizeof(Snake));
Snake* pt = head;
while (pt->next)
pt = pt->next;
p->prev = pt;
pt->next = p;
p->next = NULL;
return p;
}
void creatFood(Food* food)//生成食物
{
food->x = rand() % LENGTH;
food->y = rand() % WIDTH;
food->c = 65 + rand() % 26;
}
//避免食物坐标和蛇身重叠,重新生成食物
int avoidOverlap(Snake* head, Food* food)
{
int t = 0, flag = 1;
while (flag)
{
if (t > OVERLAP)
break;
flag = 0;
t++;
Snake* pt = head;
while (pt)
{
if (isSnakeEatMeetFood(pt, food))
{
flag = 1;
creatFood(food);
break;
}
pt = pt->next;
}
}
return t;
}
//如果生成食物和蛇身重叠次数超过阈值,则直接按蛇移动方向设置食物位置
void setFoodLocation(Food* food, Snake* head, int numOverlap, char c)
{
if (numOverlap > OVERLAP)
{
if (c == 'd')
{
food->x = head->x + 1;
food->y = head->y;
if (food->x >= LENGTH)
food->x -= LENGTH;
}
if (c == 'a')
{
food->x = head->x - 1;
food->y = head->y;
if (food->x <= 0)
food->x += LENGTH;
}
if (c == 'w')
{
food->x = head->x;
food->y = head->y - 1;
if (food->y <= 0)
food->y += WIDTH;
}
if (c == 's')
{
food->x = head->x;
food->y = head->y + 1;
if (food->y >= WIDTH)
food->y -= WIDTH;
}
}
}
char setCurKeyButton(char c)//设置当前按键
{
char c1 = _getch();
if (c1 == 27)return 'x';
if (c != 'd' && c1 == 'a')c = c1;
else if (c != 'a' && c1 == 'd')c = c1;
else if (c != 'w' && c1 == 's')c = c1;
else if (c != 's' && c1 == 'w')c = c1;
return c;
}
void snakeMove(Snake* head, Snake* rear, char c)//处理蛇的移动
{
Snake* pt = rear;
while (pt != head)
{
pt->x = pt->prev->x;
pt->y = pt->prev->y;
pt = pt->prev;
}
if (c == 's') {
head->y += 1;
//if (head->y >= WIDTH)
//head->y -= WIDTH;
}
else if (c == 'w') {
head->y -= 1;
//if (head->y <= 0)
//head->y += WIDTH;
}
else if (c == 'd') {
head->x += 1;
//if (head->x >= LENGTH)
//head->x -= LENGTH;
}
else if (c == 'a') {
head->x -= 1;
//if (head->x <= 0)
//head->x += LENGTH;
}
}
void drawWall() {
system("cls");
gotoxy(0, 0);
printf(" ———————————————\n");
for (int i = 0; i < WIDTH; i++) {
gotoxy(0, i + 1);
printf("|");
for (int j = 0; j < LENGTH; j++) {
printf(" ");
}
printf("|");
}
gotoxy(0, WIDTH+1);
printf(" ———————————————\n");
}
void drawPicture(Snake* head, int grow,Food* food,Snake *lastRear)//绘制蛇,食物
{
//绘制新食物
gotoxy(food->x, food->y);
putchar(food->c);
putchar(food->c);
if (grow == 0) {
gotoxy(lastRear->x, lastRear->y);
printf(" ");
}
gotoxy(head->x, head->y);
printf("■");
if (head->next != NULL) {
gotoxy(head->next->x, head->next->y);
printf("□");
}
}
int color(int c)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //更改文字颜色
return 0;
}
int main()
{
color(12);
int testNum = 0;
char c = 'd';
srand((unsigned)time(NULL));
Food food = { 5,8,'a' };
Snake snake, * head, * rear;
initSnake(&snake);
head = rear = &snake;
drawWall();
Snake* lastRear = (Snake*)malloc(sizeof(Snake));
int grow = 0;
while (1)
{
grow = 0;
lastRear->x = rear->x;
lastRear->y = rear->y;
if (isSnakeEatMeetFood(head, &food)) {
grow = 1;
rear = snakeGrow(head);
creatFood(&food);
testNum = avoidOverlap(head, &food);
setFoodLocation(&food, head, testNum, c);
}
if (_kbhit())c = setCurKeyButton(c);
if (c == 'x') {
puts("Game Over!\n");
break;
}
snakeMove(head, rear, c);
if (isSnakeEatItself(head)) {
puts("Game Over!\n");
break;
}
drawPicture(head,grow,&food,lastRear);
Sleep(250);
}
gotoxy(10, 10);
puts("\nThanks,Say you!\n");
system("pause");
return 0;
}