C语言贪吃蛇(队列思想)
用到了队列的出队和入队,对队列不清楚的可以网上看看关于什么是队列
注:其中用到了双缓冲来解决闪屏问题
效果如下
话不多说,代码如下:
/********************
*队列思想,根据每移动就吧下一个位置压入队列,把尾部位置变为空,并出队
*
*
*****************/
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define WIDTH 30 //蛇移动的屏幕数组的宽高
#define HIGHT 20
#define WALL 1 //墙
#define SNAKE 2 //蛇,空用0表示
#define FOOD 3 //食物
#define VK_UP 72 //方向键上下左右的第二个值,方向键有两个值,第一个是224,分别是72,...
#define VK_DOWN 80
#define VK_LEFT 75
#define VK_RIGHT 77
struct SnakeNode{
int x;
int y; //蛇结点,横纵坐标
};
struct SnakeQueue{ //蛇的队列,用一个队列来存储蛇
int MAXNUM; //队列的最大有多少个蛇结点
int f,r; //头尾指针
struct SnakeNode *snake;
};
typedef struct SnakeQueue * PSnakeQueue;
typedef struct SnakeNode * PSnakeNode;
PSnakeQueue creakeSnakeQueue(int m); //创建一个空队
int enSnakeQueue(PSnakeQueue P, int x, int y); //将新的结点压入蛇队列
int deSnakeQueue(PSnakeQueue P); //出队,删除队头元素
int frontSnakeQueue(PSnakeQueue p, int *a); //取队头元素,取队尾蛇的结点的x,y,把x赋给a[0],y赋给a[1]
PSnakeQueue creakeSnakeQueue(int m)
{
PSnakeQueue p = (PSnakeQueue)malloc(sizeof(struct SnakeQueue));
if(p != NULL)
{
p->snake = (struct SnakeNode *)malloc(sizeof(struct SnakeNode)*m);
if(p -> snake)
{
p->MAXNUM = m;
p->f = p->r = 0;
return p;
}
else free(p);
}
return NULL;
}
int enSnakeQueue(PSnakeQueue p, int x, int y)
{//将新的结点压入蛇队列
if(p->r + 1 % p->MAXNUM == p->f) return 0;//队列满了
else
{
p->snake[p->r].x = x;
p->snake[p->r].y = y;
p->r = (p->r+1) % p->MAXNUM;
}return 1;
}
int deSnakeQueue(PSnakeQueue p)
{//出队,删除队头元素
if(p->f == p->r) return 0; //队空
else
{
p->f = (p->f+1) % p->MAXNUM; return 1;
}
}
int frontSnakeQueue(PSnakeQueue p, int *a)
{//取队头元素,取队尾蛇的结点的x,y,把x赋给a[0],y赋给a[1]
if(p == NULL) return 0;
else
{
*a = p->snake[p->f].x;
*(a+1) = p->snake[p->f].y;
}
return 1;
}
//以上是队列的基本操作,可以单独写成一个.c文件
int arr[HIGHT][WIDTH];
int fangxiang = VK_RIGHT;
int x = 5,y = 4,score = 0; //蛇头的横纵坐标 ,成绩
void init(); //初始化的一些操作
void moveSnake(PSnakeQueue p, int fx); //蛇的移动
void fangXiangChoice();
void produceFood();
void setCursorPosition(int x,int y); //设置光标的位置
void main()
{
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //得到标准输出设备的句柄
CONSOLE_CURSOR_INFO cci; //隐藏两个缓冲区的光标
cci.bVisible = 0;
cci.dwSize =1;
SetConsoleCursorInfo(hOutput, &cci);
PSnakeQueue paqu,t;
paqu = creakeSnakeQueue((int)(HIGHT-2)*(WIDTH-2));
//蛇的初始化
enSnakeQueue(paqu, 3, 4); arr[4][3] = SNAKE;
enSnakeQueue(paqu, 4, 4); arr[4][4] = SNAKE;
enSnakeQueue(paqu, 5, 4); arr[4][5] = SNAKE;
init();
while(1)
{
if(kbhit()) fangXiangChoice();
moveSnake(paqu,fangxiang);
Sleep(300);
}
}
void init()
{
int i,j;
for(i = 0; i < HIGHT; i++)
{
for(j = 0; j < WIDTH; j++)
{
if(i == 0 || i == HIGHT-1 || j == 0 || j == WIDTH-1)
arr[i][j] = WALL;
}
}
srand(time(NULL));
//屏幕输出的初始化
printf("\n请按方向键 ↑ ↓ ← → 的控制上下左右 ,退出按ESC键\n");
for(i = 0; i < HIGHT; i++)
{
printf("\n ");
for(j = 0; j < WIDTH; j++)
{
switch(arr[i][j])
{
case 0: printf(" ");
break;
case WALL: printf("▉");
break;
case SNAKE: printf("●");
break;
}
}
}produceFood();
setCursorPosition((WIDTH+1)*2, 5);
printf(" 得分:%d", score);
}
void moveSnake(PSnakeQueue p, int fx)
{ //蛇的移动
int a[2]; //尾部的坐标
switch(fx)
{
case VK_UP: y--; break;
case VK_DOWN: y++; break;
case VK_LEFT: x--; break;
case VK_RIGHT: x++; break;
}
if(arr[y][x] == 0)
{
enSnakeQueue(p,x,y); arr[y][x] = SNAKE;
setCursorPosition((x+1)*2, y+3); printf("●");
frontSnakeQueue(p, a); arr[a[1]][a[0]] = 0;
deSnakeQueue(p); //蛇尾变零
setCursorPosition((a[0]+1)*2, a[1]+3);
printf(" ");
}
else if(arr[y][x] == FOOD)
{//吃食物,不用删蛇尾
enSnakeQueue(p,x,y); arr[y][x] = SNAKE;
setCursorPosition((x+1)*2, y+3);
printf("●");
produceFood(); score++;
setCursorPosition((WIDTH+1)*2, 5);
printf(" 得分:%d", score);
}
else
{
system("cls");printf("你输了"); exit(0);
}
}
void fangXiangChoice()
{
int key1,key2;
key1 = getch();
if(key1 == 27)//ESC建退出
exit(0);
if(key1 == 224)
{
key2 = getch();
switch(key2)
{
case VK_UP: if(fangxiang != VK_DOWN) fangxiang = VK_UP; //如果在向下移动,那蛇就不能向上移动,下面的相同
break;
case VK_DOWN: if(fangxiang != VK_UP) fangxiang = VK_DOWN;
break;
case VK_LEFT: if(fangxiang != VK_RIGHT) fangxiang = VK_LEFT;
break;
case VK_RIGHT: if(fangxiang != VK_LEFT) fangxiang = VK_RIGHT;
}
}
}
void produceFood()
{
int fy,fx; //食物的坐标
fy = rand() % HIGHT;
fx = rand() % WIDTH;
while(arr[fy][fx] != 0)
{
fy = rand() % HIGHT;
fx = rand() % WIDTH;
}
arr[fy][fx] = FOOD;
setCursorPosition((fx+1)*2,fy+3);
printf("●");
}
void setCursorPosition(int x,int y)
{
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = {x,y};
SetConsoleCursorPosition(hOutput, pos);
}