从零开始的c语言之旅 (1) 贪吃蛇

您所在的位置:网站首页 c语言如何按任意键继续 从零开始的c语言之旅 (1) 贪吃蛇

从零开始的c语言之旅 (1) 贪吃蛇

2024-01-24 01:47| 来源: 网络整理| 查看: 265

window下 纯c 实现 贪吃蛇 小游戏

游戏说明

按方向键上下左右(w a s d),可以实现蛇移动方向的改变。 短时间长按方向键上下左右其中之一,可实现蛇向该方向的短时间加速移动。 按空格键可实现暂停,暂停后按任意键继续游戏。 拥有计分系统

游戏效果展示 请添加图片描述 游戏实现核心思想 每一块身体都有 属于自己的行为队列 使用 队列数据结构实现 每一块新身体 都会copy 一份前一位身体 的行为队列 并在队列头添加 空行为

实现每一块身体永远比前一位慢一拍 永远执行前一位身体的上一个动作 以此实现 蛇行走位

游戏代码

#include #include #include #include #define mapX 20 #define mapY 20 int map[mapY][mapX]; typedef struct{ int x; int y; }target; typedef struct funNode{ void(*pfun)(struct bodyNode*); struct funNode*next; }shakeMove; typedef struct bodyNode{ int x; int y; shakeMove *pfun_head; shakeMove *pfun_end; struct bodyNode * pnext; }shakebody; inline void MoveUp(shakebody*pbody); inline void MoveDown(shakebody*pbody); inline void MoveLeft(shakebody*pbody); inline void MoveRight(shakebody*pbody); inline void MoveEmpty(shakebody*pbody); shakebody* copylink(const shakebody*pbefore); target tar; int flagUpAndDown =1; int flagLeftAndRight =1; int socre = 0; shakebody shake_head; shakebody *shake_head_p; shakebody *shake_end_p; void(*shake_Now)(struct bodyNode*); int main(void) { srand(time(NULL)); initMap(); initShake(); hideCursor(); createTarget(); while (1) { gotoxy(0,0); DrowShake(); DrowBg(); showSroce(); // MoveUp(&shake_head); // MoveDown(&shake_head); // MoveLeft(&shake_head); // MoveRight(&shake_head); for(int i=0;i char ch1=_getch(); char ch2; switch (ch1) { case 'w': flagUpAndDown?createAndaddShakeMove(&shake_head,MoveUp):NULL;break; case 's': flagUpAndDown?createAndaddShakeMove(&shake_head,MoveDown):NULL;break; case 'a': flagLeftAndRight?createAndaddShakeMove(&shake_head,MoveLeft):NULL;break; case 'd': flagLeftAndRight?createAndaddShakeMove(&shake_head,MoveRight):NULL;break; case ' ': _getch();break; case '1': addShakebody();break; case -32: ch2 = _getch(); switch (ch2) { case 72: createAndaddShakeMove(&shake_head,MoveUp);break; case 80: createAndaddShakeMove(&shake_head,MoveDown);break; case 75: createAndaddShakeMove(&shake_head,MoveLeft);break; case 77: createAndaddShakeMove(&shake_head,MoveRight);break; }break; } runAndrmShakeMove(&shake_head); gotoxy(0,0); DrowShake(); DrowBg(); showSroce(); } } if(shake_Now != NULL){ createAndaddShakeMove(&shake_head,shake_Now); runAndrmShakeMove(&shake_head); } // rmTarget(); } return 0; } void deadAndsorce(shakebody*pbody,int x,int y){ if(map[pbody->y + y][pbody->x + x] == 2){ addShakebody(); rmTarget(); createTarget(); }else if(map[pbody->y + y][pbody->x +x]){ gotoxy(mapX/2,mapY+1); printf("Dead"); Sleep(100000); } } void addShakebody(){ shakebody *p = copylink(shake_end_p); p->pnext = NULL; shake_end_p->pnext = p; shake_end_p = p; shake_end_p->pnext = NULL; } shakebody* copylink(const shakebody*pbefore){ shakebody* p = malloc(sizeof(shakebody)); p->x = pbefore->x; p->y = pbefore->y; if(pbefore->pfun_head ==NULL){ shakeMove *pM = malloc(sizeof(shakeMove)); pM->next = NULL; pM->pfun = MoveEmpty; p->pfun_head =pM; p->pfun_end = p->pfun_head; return p; } shakeMove *pM = malloc(sizeof(shakeMove)); shakeMove *fp = pM; shakeMove *fpcp = pbefore->pfun_head; p->pfun_head = fp; fp->pfun =MoveEmpty; pM = malloc(sizeof(shakeMove)); fp->next = pM; fp = fp->next; fp->pfun =fpcp->pfun; fp->next =NULL; while(fpcp->next!=NULL){ fpcp = fpcp->next; pM = malloc(sizeof(shakeMove)); fp->next = pM; fp = fp->next; fp->next =NULL; fp->pfun =fpcp->pfun; } p->pfun_end = fp; p->pnext =NULL; return p; } void createAndaddShakeMove(shakebody*pbody,void(*pfun)(shakebody*)){ if(pbody->pfun_head == NULL){ shakeMove*p =malloc(sizeof(shakeMove)); p->next=NULL; p->pfun = pfun; pbody->pfun_head = p; pbody->pfun_end = p; }else{ shakeMove*p =malloc(sizeof(shakeMove)); p->next=NULL; p->pfun = pfun; pbody->pfun_end->next = p; pbody->pfun_end = p; } while(pbody->pnext!=NULL){ pbody = pbody->pnext; if(pbody->pfun_head == NULL){ shakeMove*p =malloc(sizeof(shakeMove)); p->next=NULL; p->pfun = pfun; pbody->pfun_head = p; pbody->pfun_end = p; }else{ shakeMove*p =malloc(sizeof(shakeMove)); p->next=NULL; p->pfun = pfun; pbody->pfun_end->next = p; pbody->pfun_end = p; } } return 1; } void runAndrmShakeMove(shakebody*pbody){ if(pbody->pfun_head == NULL){ return; }else{ shakeMove*p = pbody->pfun_head; if(pbody->pfun_head->next == NULL){ pbody->pfun_head->pfun(pbody); shake_Now = pbody->pfun_head->pfun; pbody->pfun_head = NULL; free(p); }else{ pbody->pfun_head->pfun(pbody); shake_Now = pbody->pfun_head->pfun; pbody->pfun_head = pbody->pfun_head->next; free(p); } } while(pbody->pnext!=NULL){ pbody = pbody->pnext; if(pbody->pfun_head == NULL){ return; }else{ shakeMove*p = pbody->pfun_head; if(pbody->pfun_head->next == NULL){ pbody->pfun_head->pfun(pbody); pbody->pfun_head = NULL; free(p); }else{ pbody->pfun_head->pfun(pbody); pbody->pfun_head = pbody->pfun_head->next; free(p); } } } } void MoveRight(shakebody*pbody){ deadAndsorce(pbody,1,0); map[pbody->y][pbody->x] = 0; pbody->x++; if(pbody==shake_head_p){ flagUpAndDown =1; flagLeftAndRight =0; } } void MoveLeft(shakebody*pbody){ deadAndsorce(pbody,-1,0); map[pbody->y][pbody->x] = 0; pbody->x--; if(pbody==shake_head_p){ flagUpAndDown =1; flagLeftAndRight =0; } } void MoveUp(shakebody*pbody){ deadAndsorce(pbody,0,-1); map[pbody->y][pbody->x] = 0; pbody->y--; if(pbody==shake_head_p){ flagUpAndDown =0; flagLeftAndRight =1; } } void MoveDown(shakebody*pbody){ deadAndsorce(pbody,0,1); map[pbody->y][pbody->x] = 0; pbody->y++; if(pbody==shake_head_p){ flagUpAndDown =0; flagLeftAndRight =1; } } void MoveEmpty(shakebody*pbody){ } void DrowShake(shakebody*pbody){ shakebody * p =&shake_head; while (p->pnext!=NULL) { map[p->y][p->x] = 3; p=p->pnext; } map[p->y][p->x] = 3; } void initShake(){ shake_Now = NULL; shake_head.pnext = NULL; shake_head.pfun_head =NULL; shake_head.pfun_end = shake_head.pfun_head; shake_head_p =&shake_head; shake_end_p = shake_head_p; while(1){ shake_head.x = rand()%(mapX-3)+1; shake_head.y = rand()%(mapY-3)+1; if(map[shake_head.y][shake_head.x]==0){ map[shake_head.y][shake_head.x]=3; break; } } } void createTarget(){ while(1){ tar.x = rand()%(mapX-3)+1; tar.y = rand()%(mapY-3)+1; if(map[tar.y][tar.x]==0){ map[tar.y][tar.x]=2; break; } } } void rmTarget(){ socre ++ ; map[tar.y][tar.x]=0; } void showSroce(){ gotoxy(mapX,mapY+1); printf("Score :: %d",socre); } void initMap(){ for(int i=0;i if(i==0||j==0||i==mapY-1||j==mapX-1){ map[i][j] =1; } // printf("%d",map[i][j]); } // printf("\n"); } } void DrowBg(){ for(int i=0;i if(map[i][j]==1){ printf("■"); }else if(map[i][j]==2){ printf("★"); }else if(map[i][j]==3){ printf("■"); } else{ printf(" "); } } printf("\n"); } } //printf("★"); //printf("■"); void gotoxy(int x,int y) { //让printf,回到x, y点,x, y是坐标,如果打印位置到原点,x 0,y 0,,gotoxy(0, 0); int z=0x0b; HANDLE hOutput; COORD loc; loc.X = x; loc.Y=y; hOutput = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCursorPosition(hOutput, loc); } //隐藏光标 void hideCursor() { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_CURSOR_INFO CursorInfo; GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息 CursorInfo.bVisible = 0; //隐藏控制台光标 SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态 }

游戏代码详解 游戏框架构建 首先定义游戏界面的大小,定义游戏区行数和列数。 map 为游戏实际显示区域

#define mapX 20 #define mapY 20 int map[mapY][mapX];

在命令行中对光标和打印位置的一些处理

```c void gotoxy(int x,int y) { //让printf,回到x, y点,x, y是坐标,如果打印位置到原点,x 0,y 0,,gotoxy(0, 0); int z=0x0b; HANDLE hOutput; COORD loc; loc.X = x; loc.Y=y; hOutput = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCursorPosition(hOutput, loc); } //隐藏光标 void hideCursor() { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_CURSOR_INFO CursorInfo; GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息 CursorInfo.bVisible = 0; //隐藏控制台光标 SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态 }

初始化 map,hake和创建目标

void initMap(){ for(int i=0;i if(i==0||j==0||i==mapY-1||j==mapX-1){ map[i][j] =1; } // printf("%d",map[i][j]); } // printf("\n"); } } void initShake(){ shake_Now = NULL; shake_head.pnext = NULL; shake_head.pfun_head =NULL; shake_head.pfun_end = shake_head.pfun_head; shake_head_p =&shake_head; shake_end_p = shake_head_p; while(1){ shake_head.x = rand()%(mapX-3)+1; shake_head.y = rand()%(mapY-3)+1; if(map[shake_head.y][shake_head.x]==0){ map[shake_head.y][shake_head.x]=3; break; } } } void createTarget(){ while(1){ tar.x = rand()%(mapX-3)+1; tar.y = rand()%(mapY-3)+1; if(map[tar.y][tar.x]==0){ map[tar.y][tar.x]=2; break; } } }

shake行为

void MoveRight(shakebody*pbody){ deadAndsorce(pbody,1,0); map[pbody->y][pbody->x] = 0; pbody->x++; if(pbody==shake_head_p){ flagUpAndDown =1; flagLeftAndRight =0; } } void MoveLeft(shakebody*pbody){ deadAndsorce(pbody,-1,0); map[pbody->y][pbody->x] = 0; pbody->x--; if(pbody==shake_head_p){ flagUpAndDown =1; flagLeftAndRight =0; } } void MoveUp(shakebody*pbody){ deadAndsorce(pbody,0,-1); map[pbody->y][pbody->x] = 0; pbody->y--; if(pbody==shake_head_p){ flagUpAndDown =0; flagLeftAndRight =1; } } void MoveDown(shakebody*pbody){ deadAndsorce(pbody,0,1); map[pbody->y][pbody->x] = 0; pbody->y++; if(pbody==shake_head_p){ flagUpAndDown =0; flagLeftAndRight =1; } } void MoveEmpty(shakebody*pbody){ }

删除与生成新的目标

void createTarget(){ while(1){ tar.x = rand()%(mapX-3)+1; tar.y = rand()%(mapY-3)+1; if(map[tar.y][tar.x]==0){ map[tar.y][tar.x]=2; break; } } } //移除标记 void rmTarget(){ socre ++ ; map[tar.y][tar.x]=0; }

将蛇嵌入 map 中

void DrowShake(shakebody*pbody){ shakebody * p =&shake_head; while (p->pnext!=NULL) { map[p->y][p->x] = 3; p=p->pnext; } map[p->y][p->x] = 3; }

为每个身体行为队列生成与添加行为

void createAndaddShakeMove(shakebody*pbody,void(*pfun)(shakebody*)){ if(pbody->pfun_head == NULL){ shakeMove*p =malloc(sizeof(shakeMove)); p->next=NULL; p->pfun = pfun; pbody->pfun_head = p; pbody->pfun_end = p; }else{ shakeMove*p =malloc(sizeof(shakeMove)); p->next=NULL; p->pfun = pfun; pbody->pfun_end->next = p; pbody->pfun_end = p; } while(pbody->pnext!=NULL){ pbody = pbody->pnext; if(pbody->pfun_head == NULL){ shakeMove*p =malloc(sizeof(shakeMove)); p->next=NULL; p->pfun = pfun; pbody->pfun_head = p; pbody->pfun_end = p; }else{ shakeMove*p =malloc(sizeof(shakeMove)); p->next=NULL; p->pfun = pfun; pbody->pfun_end->next = p; pbody->pfun_end = p; } } return 1; }

运行每个身体的行为队列

void runAndrmShakeMove(shakebody*pbody){ if(pbody->pfun_head == NULL){ return; }else{ shakeMove*p = pbody->pfun_head; if(pbody->pfun_head->next == NULL){ pbody->pfun_head->pfun(pbody); shake_Now = pbody->pfun_head->pfun; pbody->pfun_head = NULL; free(p); }else{ pbody->pfun_head->pfun(pbody); shake_Now = pbody->pfun_head->pfun; pbody->pfun_head = pbody->pfun_head->next; free(p); } } while(pbody->pnext!=NULL){ pbody = pbody->pnext; if(pbody->pfun_head == NULL){ return; }else{ shakeMove*p = pbody->pfun_head; if(pbody->pfun_head->next == NULL){ pbody->pfun_head->pfun(pbody); pbody->pfun_head = NULL; free(p); }else{ pbody->pfun_head->pfun(pbody); pbody->pfun_head = pbody->pfun_head->next; free(p); } } } }

添加新的身体 与copy 前一个身体行为 并在队首添加空行为

//增加新的身体 void addShakebody(){ shakebody *p = copylink(shake_end_p); p->pnext = NULL; shake_end_p->pnext = p; shake_end_p = p; shake_end_p->pnext = NULL; } //为新的身体添加前一个身体的行为 shakebody* copylink(const shakebody*pbefore){ shakebody* p = malloc(sizeof(shakebody)); p->x = pbefore->x; p->y = pbefore->y; if(pbefore->pfun_head ==NULL){ shakeMove *pM = malloc(sizeof(shakeMove)); pM->next = NULL; pM->pfun = MoveEmpty; p->pfun_head =pM; p->pfun_end = p->pfun_head; return p; } shakeMove *pM = malloc(sizeof(shakeMove)); shakeMove *fp = pM; shakeMove *fpcp = pbefore->pfun_head; p->pfun_head = fp; fp->pfun =MoveEmpty; pM = malloc(sizeof(shakeMove)); fp->next = pM; fp = fp->next; fp->pfun =fpcp->pfun; fp->next =NULL; while(fpcp->next!=NULL){ fpcp = fpcp->next; pM = malloc(sizeof(shakeMove)); fp->next = pM; fp = fp->next; fp->next =NULL; fp->pfun =fpcp->pfun; } p->pfun_end = fp; p->pnext =NULL; return p; } //添加身体行为

显示得分 与死亡

//死亡与获得分数 void deadAndsorce(shakebody*pbody,int x,int y){ if(map[pbody->y + y][pbody->x + x] == 2){ addShakebody(); rmTarget(); createTarget(); }else if(map[pbody->y + y][pbody->x +x]){ gotoxy(mapX/2,mapY+1); printf("Dead"); Sleep(100000); } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3