提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
一、源码
无聊心血来潮写了个控制台的贪吃蛇,正常能玩。当然隐藏bug也有很多,比如食物位置与蛇身重合的情况判定,这里没有去实现了,如果感兴趣可以自己添加一下这部分功能。另外代码写的很烂勿喷,都是临时想到什么逻辑就写什么,没花啥时间去优化。总而言之参考学习的话可能没啥帮助,临时用来应付作业应该没问题。
#include <stdio.h>
#include <conio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
int map[20][20]={0};
int Score=0;
struct snack{
int x;
int y;
int pre_x;
int pre_y;
int direc;
struct snack *tail;
struct snack *pre;
};
struct food{
int x;
int y;
int pre_x;
int pre_y;
};
enum Direction{
LEFT=0,
RIGHT,
UP,
DOWN
};
void *delay(void *arg){
usleep(100000);
return NULL;
}
void initmap()
{
for(int i=0;i<20;i++)
{
map[0][i]=1;
map[19][i]=1;
map[i][0]=1;
map[i][19]=1;
}
}
void RefreshMap()
{
int i,j;
for(i=0;i<20;i++)
{
for(j=0;j<20;j++)
{
switch(map[i][j]){
case 1:printf("#");break;
case 0:printf(" ");break;
case 2:printf("*");break;
case 3:printf("0");break;
default:break;
}
}
if(i==4&&j==20){
printf(" press \'e\' to stop game");
}
if(i==3&&j==20){
printf(" Score:%d",Score);
}
putchar('\n');
}
}
void ClearSnackTail(struct snack *pcheck)
{
struct snack *p=pcheck;
struct snack *temp;
while(p->tail!=NULL){
p=p->tail;//先找到最后的节点
}
while(p!=pcheck){
temp=p;
p=p->pre;
map[p->x][p->y]=0;
free(temp);
}
map[p->x][p->y]=0;
free(p);//删除剩下的一个节点
}
int CloseGame(struct snack *pcheck,int IsAutoStop)
{
char value;
struct snack *p=pcheck;
struct snack *temp;
if(!IsAutoStop){
printf("do you want exit the game? [y/n]\n");
while(1){
value=getchar();
if(value=='y'){
if(pcheck==NULL){
return 1;
}
else{
goto exit_handle;
}
}
else if(value=='n'){
return 0;
}
else{
printf("enter error,please enter again\n");
}
}
}
else if(IsAutoStop){
if(pcheck==NULL){
return 1;
}
else{
goto exit_handle;
}
}
exit_handle://头部不是malloc的不需要释放
while(p->tail!=NULL){
p=p->tail;//先找到最后的节点
}
while(p!=pcheck){
temp=p;
p=p->pre;
map[p->x][p->y]=0;
free(temp);
}
map[p->x][p->y]=0;
free(p);//删除剩下的一个节点
return 1;
}
void play()
{
struct snack SnackHeader;
struct food fd={
.x=1,
.y=1,
.pre_x=1,
.pre_y=1
};
char getvalue;
SnackHeader.x=5;
SnackHeader.y=5;
SnackHeader.pre_y=5;
SnackHeader.pre_x=5;
SnackHeader.direc=RIGHT;
SnackHeader.tail=NULL;
SnackHeader.pre=NULL;
struct snack *snack_tail=&SnackHeader;
struct snack *snack_head=&SnackHeader;
fd.x=(rand()%18+1);
fd.y=(rand()%18+1);
map[fd.x][fd.y]=3;
while(1){
RefreshMap();
pthread_t delay_thread;
if(kbhit()){
getvalue=getch();
switch(getvalue){
case 'w':
if(SnackHeader.direc!=DOWN){
SnackHeader.direc=UP;
}
break;
case 's':if(SnackHeader.direc!=UP){
SnackHeader.direc=DOWN;
}
break;
case 'a':if(SnackHeader.direc!=RIGHT){
SnackHeader.direc=LEFT;
}
break;
case 'd':if(SnackHeader.direc!=LEFT){
SnackHeader.direc=RIGHT;
}
break;
case 'e':
if(CloseGame(SnackHeader.tail,0)==1){
return;
}
break;
default :
break;
}
}
SnackHeader.pre_y=SnackHeader.y;
SnackHeader.pre_x=SnackHeader.x;
if(SnackHeader.direc==UP)
{
SnackHeader.x--;
if(SnackHeader.x==0){
SnackHeader.x=18;
}
}
else if(SnackHeader.direc==DOWN){
SnackHeader.x++;
if(SnackHeader.x==19){
SnackHeader.x=1;
}
}
else if(SnackHeader.direc==LEFT){
SnackHeader.y--;
if(SnackHeader.y==0){
SnackHeader.y=18;
}
}
else if(SnackHeader.direc==RIGHT){
SnackHeader.y++;
if(SnackHeader.y==19){
SnackHeader.y=1;
}
}
map[SnackHeader.pre_x][SnackHeader.pre_y]=0;
map[SnackHeader.x][SnackHeader.y]=2;
if((SnackHeader.x==fd.x)&&(SnackHeader.y==fd.y)){
Score++;
fd.x=(rand()%18+1);
fd.y=(rand()%18+1);
map[fd.x][fd.y]=3;
struct snack *p_tail=(struct snack*)malloc(sizeof(struct snack));
p_tail->tail=NULL;
p_tail->x=snack_tail->pre_x;
p_tail->y=snack_tail->pre_y;
p_tail->pre_x=p_tail->x;
p_tail->pre_y=p_tail->y;
snack_tail->tail=p_tail;
p_tail->pre=snack_tail;
snack_tail=p_tail;
}
struct snack *pcheck=SnackHeader.tail;
while(pcheck!=NULL)
{
pcheck->pre_x=pcheck->x;
pcheck->pre_y=pcheck->y;
pcheck->x=pcheck->pre->pre_x;
pcheck->y=pcheck->pre->pre_y;
map[pcheck->x][pcheck->y]=2;
map[pcheck->pre_x][pcheck->pre_y]=0;
// printf("%d %d %d %d",pcheck->pre_x,pcheck->pre_y,pcheck->x,pcheck->y);
pcheck=pcheck->tail;
}
if(CollideCheck(&SnackHeader)==1){
printf("do you want to continue game? [y/n]\n");
char value;
while(1){
value=getchar();
if(value =='y'){
if(SnackHeader.tail!=NULL){
ClearSnackTail(SnackHeader.tail);
SnackHeader.tail=NULL;//删除完后重归NULL
map[SnackHeader.pre_x][SnackHeader.pre_y]=0;//头部也要归0
snack_tail=&SnackHeader;
}
break;
}
else if(value =='n'){
CloseGame(SnackHeader.tail,1);//退出时需要释放申请的内存
return;
}
else
{
printf("enter error! please enter again\n");
continue;
}
}
}
//sleep(1);
if(pthread_create(&delay_thread,NULL, delay, NULL)!=0)
{
printf("creat thread fail\r\n");
}
pthread_join(delay_thread,NULL);
system("cls");
//RefreshMap();
}
}
//碰撞检测
int CollideCheck(struct snack *phead)
{
int head_x,head_y,Iscollide=0;
head_x=phead->x;
head_y=phead->y;
struct snack *pcheck=phead->tail;
while(pcheck!=NULL)
{
if((pcheck->x==head_x)&&(pcheck->y==head_y))
{
Iscollide=1;
return Iscollide;
}
pcheck=pcheck->tail;
}
return Iscollide;
}
int main(int argc, char const *argv[])
{
//printf("Hello World!\n");
initmap();
play();
getchar();
return 0;
}