#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <stdbool.h>
#include <string.h>
#define U 1
#define D 2
#define L 3
#define R 4 //蛇的状态,U:上 ;D:下;L:左 R:右
#define width 100
#define height 30
typedef struct BLOCK
{
int x;
int y;
struct BLOCK *next;
}Block;
Block *snakeHead; //蛇头指针
Block *p;//遍历蛇身的指针
Block *food; //食物指针
int speed = 200;
void drawBlock(int x,int y);
void eraseBlock(int x,int y);
void createWindow();
void createMap();
void createSnake();
void createFood();
void moveSnake();
void endGame();
int main()
{
createWindow();
createMap();
createSnake();
createFood();
moveSnake();
return 0;
}
void drawBlock(int x,int y) //画方块
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(handle, coord); //设置控制台光标的位置
//CONSOLE_CURSOR_INFO curInfo; //定义光标信息的结构体变量
//curInfo.dwSize = 1; //如果没赋值的话,隐藏光标无效
//curInfo.bVisible = FALSE; //将光标设置为不可见
//SetConsoleCursorInfo(handle, &curInfo); //设置光标信息
printf("□");//一个方块占两个位置 //● ■ ▲ ★ ▁ ▁
}
void eraseBlock(int x,int y) //擦除方块
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(handle, coord); //设置控制台光标的位置
printf(" ");//一个方块占两个位置
}
void createWindow()
{
char s[30];
sprintf(s,"mode con cols=%d lines=%d",width,height);
//system("mode con cols=100 lines=30"); //创建窗口
system(s);
system("title 贪食蛇游戏"); //设置窗口标题
system("color b");
}
void createMap()
{
int i;
for(i=0;i<width-2;i+=2)
{
drawBlock(i,0); //画上墙
drawBlock(i,height-1); //画下墙
}
for(i=0;i<height-1;i++)
{
drawBlock(0,i);//画左墙
drawBlock(width-2,i);//画右墙
}
}
void createSnake()
{
snakeHead = (Block *)malloc(sizeof(Block));
snakeHead->x = 44;
snakeHead->y = 15;
snakeHead->next = NULL;
drawBlock(snakeHead->x,snakeHead->y);
p = snakeHead;
int i;
for(i=1;i<5;i++)
{
Block *body = (Block *)malloc(sizeof(Block));
body->x = p->x + 2;
body->y = p->y;
body->next = NULL;
drawBlock(body->x,body->y);
p->next = body;
p = body;
}
}
void createFood()
{
int x;
int y;
while(1){
//srand((unsigned)time(NULL));//为了防止每次产生的随机数相同,种子设置为time
srand(time(0));
x = (rand() % (width/2-2)) * 2 + 2;//设置x为偶数
y = rand() % (height-2) + 1;
//食物不能与蛇身重合
bool inSnake = false;
p=snakeHead;
while(p->next != NULL) //遍历循环
{
if(p->x == x && p->y == y)
{
inSnake = true;
break;
}
p = p->next;
}
if(inSnake == false){
break;
}
}
food = (Block *)malloc(sizeof(Block));
food->x = x;
food->y = y;
food->next = NULL;
drawBlock(x,y);
}
void moveSnake()
{
int state = L;
int x = snakeHead->x;
int y = snakeHead->y;
while(1){
Sleep(speed);
if(state == U){
y =y-1;
}else if(state == D){
y =y+1;
}else if(state == R){
x = x+2;
}else if(state == L){
x = x-2;
}
if(x==food->x && y==food->y){ //遇到食物
food->next = snakeHead;
snakeHead = food; //吃掉食物
createFood();//再建一个食物
}else{ //没有遇到食物 创建新的蛇头 接入蛇身 抹除蛇尾 实现移动
Block *newHead = (Block *)malloc(sizeof(Block));
newHead->x = x;
newHead->y = y;
newHead->next = snakeHead;
drawBlock(newHead->x,newHead->y);
p = snakeHead;
while(p->next->next != NULL){ //指针指向倒数第二节
p=p->next;
}
eraseBlock(p->next->x,p->next->y); //抹除蛇尾
free(p->next);
p->next = NULL;
snakeHead=newHead;
}
// >>>>>>>>>>判定游戏结束
bool gameOver = false;
//撞墙
if(snakeHead->x == 0 || snakeHead->x == width-2 ||snakeHead->y == 0||snakeHead->y ==height-1){
gameOver = true;
}
//碰到自己
p=snakeHead->next;
while(p->next != NULL){
if(p->x == snakeHead->x && p->y == snakeHead->y){
gameOver = true;
break;
}
p=p->next;
}
if(gameOver){
endGame();
break;
}
//<<<<<<<<<<<判定游戏结束
//>>>>>>>>>>>响应键盘控制
if(GetAsyncKeyState(VK_UP) && state != D){
state = U;
}else if(GetAsyncKeyState(VK_DOWN) && state != U){
state = D;
}else if(GetAsyncKeyState(VK_RIGHT) && state != L){
state = R;
}else if(GetAsyncKeyState(VK_LEFT) && state != R){
state = L;
}
//<<<<<<<<<<<响应键盘控制
}
}
void endGame()
{
system("cls"); //清屏
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord;
coord.X = 30;
coord.Y = 10;
SetConsoleCursorPosition(handle, coord); //设置控制台光标的位置
printf("Game Over!\n");
//system("pause");
}