哈哈哈,写的过程出现一堆bug,可以扭头的贪吃蛇,等过几天在改进改进,加判断条件!(看视频的时候觉得简单,自己一写就不行了,还是要敲代码的!
参考代码地址:snake贪吃蛇: C语言实现小游戏 (gitee.com)
一开始的代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <windows.h>
#include <locale.h>
#include <time.h>
//判断键盘是否被按过
#define PRESS(key) ((GetAsyncKeyState(key)&0x1)?1:0)
//蛇结构体
typedef struct snake{
short x;
short y;
struct snake* next;
}snake;
void setpos(short,short);
snake* printfood(snake *);
//初始化蛇
snake* initsnake(){
//蛇头
snake* head=(snake*)malloc(sizeof(snake));
head->x=20;
head->y=10;
head->next=NULL;
snake* tem=NULL;
int a=19;
for(int i=0;i<4;i++){
snake* newbody=(snake*)malloc(sizeof(snake));
if(head->next==NULL){
newbody->x=a;
newbody->y=10;
a--;
head->next=newbody;
tem=newbody;
continue;
}
newbody->x=a;
newbody->y=10;
newbody->next=NULL;
tem->next=newbody;
tem=newbody;
a--;
}
return head;
}
//打印蛇身
void printsnake(snake *head){
snake* tem=head;
while(tem){
setpos(tem->x,tem->y);
printf("O");
tem=tem->next;
}
}
//打印食物
snake* printfood(snake *head){
again: snake* food=(snake*)malloc(sizeof(snake));
food->x=rand()%58+1;
food->y=rand()%26+1;
food->next=NULL;
snake* tem=head;
while(tem){
if(tem->x==food->x&&tem->y==food->y){
free(food);
goto again;
}
tem=tem->next;
}
setpos(food->x,food->y);
printf("F");
return food;
}
//吃食物
snake* eatfood(snake **head,snake *food,int num){
if(PRESS(VK_UP)==1){
num=1;}
else if(PRESS(VK_DOWN)==1){
num=2;
}
else if(PRESS(VK_LEFT)==1){
num=3;
}
else if(PRESS(VK_RIGHT)==1){
num=4;
}
switch(num){
case 1:
if((*head)->x==food->x&&((*head)->y-1)==food->y){
food->next=*head;
*head=food;
printsnake(*head);
return printfood(*head);
}
break;
case 2:
if((*head)->x==food->x&&((*head)->y+1)==food->y){
food->next=*head;
*head=food;
printsnake(*head);
return printfood(*head);
}
break;
case 3:
if(((*head)->x-1)==food->x&&(*head)->y==food->y){
food->next=*head;
*head=food;
printsnake(*head);
return printfood(*head);
}
break;
case 4:
if(((*head)->x+1)==food->x&&(*head)->y==food->y){
food->next=*head;
*head=food;
printsnake(*head);
return printfood(*head);
}
break;}
return food;
}
//结束游戏
void endgame(snake *head){
if(head->x==0||head->y==25||head->x==58||head->y==0){
system("cls");
setpos(36,10);
printf("游戏结束!");
setpos(36,40);
exit(1);
}
}
//移动蛇 吃食物 结束游戏 等等
void movesnake(snake **head,snake* food){
int num=1;
while(1){
if(PRESS(VK_UP)==1){
num=1;}
else if(PRESS(VK_DOWN)==1){
num=2;
}
else if(PRESS(VK_LEFT)==1){
num=3;
}
else if(PRESS(VK_RIGHT)==1){
num=4;
}
food=eatfood(head,food,num);
switch(num){
case 1:
snake* another=(snake*)malloc(sizeof(snake));
another->y=(*head)->y-1;
another->x=(*head)->x;
another->next=*head;
*head=another;
snake *tem1=*head;
while(tem1->next->next){
tem1=tem1->next;
}
setpos(tem1->next->x,tem1->next->y);
printf(" ");
free(tem1->next);
tem1->next=NULL;
printsnake(*head);
break;
case 2:
snake* another2=(snake*)malloc(sizeof(snake));
another2->y=(*head)->y+1;
another2->x=(*head)->x;
another2->next=*head;
*head=another2;
snake *tem2=(*head);
while(tem2->next->next){
tem2=tem2->next;
}
setpos(tem2->next->x,tem2->next->y);
printf(" ");
free(tem2->next);
tem2->next=NULL;
printsnake(*head);
break;
case 3:
snake* another3=(snake*)malloc(sizeof(snake));
another3->y=(*head)->y;
another3->x=(*head)->x-1;
another3->next=*head;
*head=another3;
snake *tem3=(*head);
while(tem3->next->next){
tem3=tem3->next;
}
setpos(tem3->next->x,tem3->next->y);
printf(" ");
free(tem3->next);
tem3->next=NULL;
printsnake(*head);
break;
case 4:
snake* another4=(snake*)malloc(sizeof(snake));
another4->y=(*head)->y;
another4->x=(*head)->x+1;
another4->next=*head;
*head=another4;
snake *tem4=(*head);
while(tem4->next->next){
tem4=tem4->next;
}
setpos(tem4->next->x,tem4->next->y);
printf(" ");
free(tem4->next);
tem4->next=NULL;
printsnake(*head);
break;}
Sleep(200);
endgame(*head);
}
}
//隐藏鼠标函数
void hidemouse(){
HANDLE output=NULL;
output=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO info;
GetConsoleCursorInfo(output,&info);
info.bVisible=false;
SetConsoleCursorInfo(output,&info);
}
//设置光标位置
void setpos(short x,short y){
COORD pos={x,y};
HANDLE output=NULL;
output=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output,pos);
}
void gametable(){
//隐藏鼠标
hidemouse();
//打印欢迎界面
setpos(36,10);
printf("欢迎来到贪吃蛇小游戏!");
setpos(38,20);
system("pause");
system("cls");
//打印提示界面
setpos(36,10);
printf("提示:↑ ↓ ← →移动");
setpos(38,20);
system("pause");
system("cls");
//打印地图
for(int i=0;i<=58;i++){
setpos(i,0);
printf("@");
}
for(int i=0;i<=58;i++){
setpos(i,26);
printf("@");
}
for(int i=1;i<=25;i++){
setpos(0,i);
printf("@");
}
for(int i=1;i<=25;i++){
setpos(58,i);
printf("@");
}
setpos(66,8);
printf("提示:↑ ↓ ← →移动");
}
int main(){
//设置随机种子
srand(time(0));
//设置命令行界面
system("mode con cols=100 lines=30");
system("title 贪吃蛇");
gametable();
snake* head=initsnake();
printsnake(head);
snake* food=printfood(head);
movesnake(&head,food);
}
修改后的代码:
修复了可以直接回头的bug,增加了分数,按F键加速,按S减速,按空格键暂停,可以重新游戏,并销毁了内存(应该销毁干净了),并且做了意义不明的分离。
snake.h
头文件
#ifndef SNAKE_H
#define SNAKE_H
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <windows.h>
#include <locale.h>
#include <time.h>
typedef struct snake snake;
//设置打印光标位置
void setpos(short,short);
//打印食物
snake* printfood(snake *);
//初始化蛇
snake* initsnake();
//打印蛇身
void printsnake(snake*);
//吃食物
snake* eatfood(snake **,snake *,int);
//结束游戏
char endgame(snake *,snake *);
//销毁内存
void destorysnake(snake *,snake *);
//移动蛇
char movesnake(snake **,snake* );
//隐藏光标
void hidemouse();
//打印开始界面
void gametable();
#endif
snake.c
实现函数文件
#include "snake.h"
//判断键盘是否被按过
#define PRESS(key) ((GetAsyncKeyState(key)&0x1)?1:0)
int score=0;
//蛇结构体
typedef struct snake{
short x;
short y;
struct snake* next;
}snake;
//初始化蛇
snake* initsnake(){
//蛇头
snake* head=(snake*)malloc(sizeof(snake));
head->x=20;
head->y=10;
head->next=NULL;
snake* tem=NULL;
int a=19;
for(int i=0;i<4;i++){
snake* newbody=(snake*)malloc(sizeof(snake));
if(head->next==NULL){
newbody->x=a;
newbody->y=10;
a--;
head->next=newbody;
tem=newbody;
continue;
}
newbody->x=a;
newbody->y=10;
newbody->next=NULL;
tem->next=newbody;
tem=newbody;
a--;
}
return head;
}
//打印蛇身
void printsnake(snake *head){
snake* tem=head;
while(tem){
setpos(tem->x,tem->y);
printf("O");
tem=tem->next;
}
}
//打印食物
snake* printfood(snake *head){
again: snake* food=(snake*)malloc(sizeof(snake));
food->x=rand()%56+1;
food->y=rand()%25+1;
food->next=NULL;
snake* tem=head;
while(tem){
if(tem->x==food->x&&tem->y==food->y){
free(food);
goto again;
}
tem=tem->next;
}
setpos(food->x,food->y);
printf("F");
return food;
}
//吃食物
snake* eatfood(snake **head,snake *food,int num){
if(PRESS(VK_UP)==1){
num=1;}
else if(PRESS(VK_DOWN)==1){
num=2;
}
else if(PRESS(VK_LEFT)==1){
num=3;
}
else if(PRESS(VK_RIGHT)==1){
num=4;
}
switch(num){
case 1:
if((*head)->x==food->x&&((*head)->y-1)==food->y){
food->next=*head;
*head=food;
printsnake(*head);
score+=10;
return printfood(*head);
}
break;
case 2:
if((*head)->x==food->x&&((*head)->y+1)==food->y){
food->next=*head;
*head=food;
printsnake(*head);
score+=10;
return printfood(*head);
}
break;
case 3:
if(((*head)->x-1)==food->x&&(*head)->y==food->y){
food->next=*head;
*head=food;
printsnake(*head);
score+=10;
return printfood(*head);
}
break;
case 4:
if(((*head)->x+1)==food->x&&(*head)->y==food->y){
food->next=*head;
*head=food;
printsnake(*head);
score+=10;
return printfood(*head);
}
break;}
return food;
}
//毁尸灭迹!
void destorysnake(snake *head,snake *food){
snake* tem=head;
while(tem){
tem=head->next;
head=head->next;
free(tem);
}
free(food);
score=0;
}
//结束游戏
char endgame(snake*head,snake*food){
//判断是否撞墙了
if(head->x==0||head->y==25||head->x==58||head->y==0){
system("cls");
setpos(36,10);
printf("你撞到墙啦!游戏结束!");
setpos(36,15);
system("pause");
setpos(36,40);
destorysnake(head,food);
system("cls");
setpos(36,10);
printf("你想要重新开始游戏吗?");
setpos(38,11);
printf(" Y or N:");
char choice=0;
scanf("%c",&choice);
while(choice!='Y'&&choice!='y'&&choice!='N'&&choice!='n'){
system("cls");
setpos(36,10);
printf("请重新输入!");
setpos(38,11);
printf("Y or N:");
scanf("%c",&choice);
}
system("cls");
return choice;
}
//判断是否撞到自己
snake* tem=head->next;
while(tem){
if(head->x==tem->x&&head->y==tem->y){
system("cls");
setpos(36,10);
printf("你撞到自己啦!游戏结束!");
setpos(36,15);
system("pause");
setpos(36,40);
destorysnake(head,food);
system("cls");
setpos(36,10);
printf("你想要重新开始游戏吗?");
setpos(38,11);
printf(" Y or N:");
char choice=0;
scanf("%c",&choice);
while(choice!='Y'&&choice!='y'&&choice!='N'&&choice!='n'){
system("cls");
setpos(36,10);
printf("请重新输入!");
setpos(38,11);
printf("Y or N:");
scanf("%c",&choice);
}
system("cls");
return choice;
}
tem=tem->next;
}
return 'C';
}
//移动蛇 吃食物 结束游戏 等等
char movesnake(snake **head,snake* food){
int num=1;
while(1){
if(num!=2&&PRESS(VK_UP)==1){
num=1;}
else if(num!=1&&PRESS(VK_DOWN)==1){
num=2;
}
else if(num!=4&&PRESS(VK_LEFT)==1){
num=3;
}
else if(num!=3&&PRESS(VK_RIGHT)==1){
num=4;
}
food=eatfood(head,food,num);
switch(num){
case 1:
snake* another=(snake*)malloc(sizeof(snake));
another->y=(*head)->y-1;
another->x=(*head)->x;
another->next=*head;
*head=another;
snake *tem1=*head;
while(tem1->next->next){
tem1=tem1->next;
}
setpos(tem1->next->x,tem1->next->y);
printf(" ");
free(tem1->next);
tem1->next=NULL;
printsnake(*head);
break;
case 2:
snake* another2=(snake*)malloc(sizeof(snake));
another2->y=(*head)->y+1;
another2->x=(*head)->x;
another2->next=*head;
*head=another2;
snake *tem2=(*head);
while(tem2->next->next){
tem2=tem2->next;
}
setpos(tem2->next->x,tem2->next->y);
printf(" ");
free(tem2->next);
tem2->next=NULL;
printsnake(*head);
break;
case 3:
snake* another3=(snake*)malloc(sizeof(snake));
another3->y=(*head)->y;
another3->x=(*head)->x-1;
another3->next=*head;
*head=another3;
snake *tem3=(*head);
while(tem3->next->next){
tem3=tem3->next;
}
setpos(tem3->next->x,tem3->next->y);
printf(" ");
free(tem3->next);
tem3->next=NULL;
printsnake(*head);
break;
case 4:
snake* another4=(snake*)malloc(sizeof(snake));
another4->y=(*head)->y;
another4->x=(*head)->x+1;
another4->next=*head;
*head=another4;
snake *tem4=(*head);
while(tem4->next->next){
tem4=tem4->next;
}
setpos(tem4->next->x,tem4->next->y);
printf(" ");
free(tem4->next);
tem4->next=NULL;
printsnake(*head);
break;}
//控制移动速度
if(((GetAsyncKeyState(0x46)&0x8000)?1:0)){
Sleep(100);
}
else if(((GetAsyncKeyState(0x53)&0x8000)?1:0)){
Sleep(300);
}
else{
Sleep(200);
}
//结束游戏
char a=endgame(*head,food);
if(a=='Y'||a=='y'){
return 'Y';
}
else if(a=='N'||a=='n'){
return 'N';
};
//显示分数
setpos(66,5);
printf("你的分数为:%5d",score);
//暂停游戏
if(PRESS(VK_SPACE)){
while(1){
Sleep(300);
if(PRESS(VK_SPACE)){
break;
}
}
}
}
}
//隐藏鼠标函数
void hidemouse(){
HANDLE output=NULL;
output=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO info;
GetConsoleCursorInfo(output,&info);
info.bVisible=false;
SetConsoleCursorInfo(output,&info);
}
//设置光标位置
void setpos(short x,short y){
COORD pos={x,y};
HANDLE output=NULL;
output=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output,pos);
}
void gametable(){
//隐藏鼠标
hidemouse();
//打印欢迎界面
setpos(36,10);
printf("欢迎来到贪吃蛇小游戏!");
setpos(38,20);
system("pause");
system("cls");
//打印提示界面
setpos(36,10);
printf("提示:↑ ↓ ← →移动");
setpos(38,20);
system("pause");
system("cls");
//打印地图
for(int i=0;i<=58;i++){
setpos(i,0);
printf("@");
}
for(int i=0;i<=58;i++){
setpos(i,26);
printf("@");
}
for(int i=1;i<=25;i++){
setpos(0,i);
printf("@");
}
for(int i=1;i<=25;i++){
setpos(58,i);
printf("@");
}
setpos(66,8);
printf("提示:↑ ↓ ← →移动");
setpos(66,10);
printf("提示:一直按F键可以加速");
setpos(66,11);
printf(" 一直按S键可以减速");
setpos(66,12);
printf(" 按空格键可以暂停开始游戏");
}
game.c
主函数文件
#include "snake.h"
typedef struct snake snake;
int main(){
//设置随机种子
srand(time(0));
//设置命令行界面
system("mode con cols=100 lines=30");
system("title 贪吃蛇");
char choice='Y';
while(choice=='Y'){
gametable();
snake* head=initsnake();
printsnake(head);
snake* food=printfood(head);
choice=movesnake(&head,food);
}
system("cls");
setpos(40,10);
printf("游戏结束啦!");
setpos(38,20);
system("pause");
}
总结:
咳咳,偷懒了,在原有函数上疯狂加功能,并没有把其他功能封装为函数,估计几天后我就看不懂自己写的贪吃蛇了,希望没有什么其他的bug。