『本尊』 2019-06-27 01:06
浏览 312

纯C贪吃蛇运行有时会卡死,求大佬帮助?

#include
#include
#include
#include

#define U 1 //上
#define D 2 //下
#define L 3 //左
#define R 4 //右

typedef struct SNAKE //蛇身的一个节点
{
int x;
int y;
struct SNAKE *next;
}snake;

/*****全局变量定义*****/
short c; //颜色设置
int score=0,add=10; //总得分与每次吃食物得分
int status,sleeptime=200; //每次运行的时间间隔
snake *head, *food; //蛇头指针,食物指针
snake *q; //遍历蛇的时候用到的指针
int endgamestatus=0; //游戏结束的情况 1:撞到墙;2:咬到自己;3:主动退出游戏

/******函数声明******/
void Pos(int x,int y); //设置光标位置
void color(short x) ; //颜色
void welcometogame(); //开始界面
void snakecolor(); //蛇身颜色选择
void createMap(); //创建地图
void scoreandtips(); //游戏界面右侧的得分和小提示
void newsnake(); //初始化蛇身
void createfood(); //生成食物
int biteself(); //判断是否咬到了自己
void cantcrosswall(); //设置蛇撞墙的情况
void speedup(); //加速
void speeddown(); //减速
void snakemove(); //控制蛇前进方向
void keyboardControl(); //控制键盘按键
void endgame(); //游戏结束
void choose(); //游戏失败之后的选择
void explation(); //游戏说明
void color(short x) ; //颜色
void snakecolor(); //蛇身颜色选择

/*****光标定位*****/
void Pos(int x,int y)//设置光标位置
{
COORD pos;
HANDLE handle;
CONSOLE_CURSOR_INFO cci;
pos.X=x;
pos.Y=y;
handle=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(handle,pos);
GetConsoleCursorInfo(handle,&cci);
cci.bVisible = 0;
SetConsoleCursorInfo(handle,&cci);
}

/****颜色****/
void color(short c)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //更改文字颜色
}

/****开始界面****/
void welcometogame()
{
int n;
color(11);
Pos(43,10);
printf("贪 吃 蛇");
Pos(25, 22);
printf("1.开始游戏");
Pos(45, 22);
printf("2.游戏说明");
Pos(65, 22);
printf("3.退出游戏");
Pos(40,25);
printf("请选择 1 2 3:");

scanf("%d", &n); //输入选项
switch (n)
{
case 1:
system("cls");
snakecolor();
system("cls");
createMap(); //创建地图
newsnake(); //初始化蛇身
createfood(); //创建食物
keyboardControl(); //按键控制
break;
case 2:
explation(); //游戏说明函数
break;
case 3:
exit(0); //退出游戏
break;
default:
color(4);
Pos(40,26);
printf("请输入1—3之间的数!");
Pos(40,27);
printf("按任意键继续");
getch(); //输入任意键
system("cls"); //清屏
welcometogame();
}
}

/****蛇身颜色选择****/
void snakecolor()
{
Pos(41,10);
printf("请选择蛇的颜色\n");
Pos(37,12);
color(1);
printf("蓝色--1\n");
Pos(51,12);
color(2);
printf("绿色--2\n");
Pos(37,14);
color(4);
printf("红色--4\n");
Pos(51,14);
color(5);
printf("紫色--5\n");
Pos(37,16);
color(6);
printf("黄色--6\n");
Pos(51,16);
color(7);
printf("白色--7\n");
Pos(37,18);
color(4);
printf("请输入颜色后对应数字:");
scanf("%d",&c);
if(c!=1&&c!=2&&c!=4&&c!=5&&c!=6&&c!=7)
{
Pos(37,19);
printf("请输入正确的数字!");
Pos(37,20);
printf("按任意键继续");
getch();
system("cls");
snakecolor();
}
}

/****创建地图****/
void createMap()
{
int i, j;
for(i=0;i<58;i+=2)//打印上下边界
{
Pos(i,0);
color(2);
printf("□");
Pos(i,26);
printf("□");
}
for(i=1;i<26;i++)//打印左右边界
{
Pos(0,i);
printf("□");
Pos(56,i);
printf("□");
}
for(i = 2;i<56;i+=2) //打印中间网格
{
for(j = 1;j<26;j++)
{
Pos(i,j);
color(3);
printf("■");
}
}
}

/****得分及提示****/
void scoreandtips()
{

Pos(64,8);
color(2);
printf("得分:%d  ",score);

Pos(64,14);
printf("每个食物得分:%d分",add);
Pos(64,16);
printf("不能穿墙,不能咬到自己");
Pos(64,18);
printf("用↑ ↓ ← →分别控制蛇的移动");
Pos(64,20);
printf("游戏速度会随吃到食物而加快");
Pos(64,22);
printf("F1 为加速,F2 为减速");
Pos(64,24);
printf("space:暂停游戏");
Pos(64,26);
printf("ESC :退出游戏");

}

/****初始化蛇身****/
void newsnake()
{
snake tail;
int i;
tail=(snake
)malloc(sizeof(snake));//从蛇尾开始创建链表,以x,y设定开始的位置
tail->x=24;
tail->y=5;
tail->next=NULL;
for(i=1;i<=4;i++)
{
head=(snake*)malloc(sizeof(snake));
head->next=tail;
head->x=24+2*i;
head->y=5;
tail=head;
}
while(tail!=NULL)//从头到尾,输出蛇身
{
Pos(tail->x,tail->y);
color(c);
printf("■");
tail=tail->next;
}
}

/****食物生成****/
void createfood()
{
snake fod;
srand((unsigned)time(NULL));
fod=(snake
)malloc(sizeof(snake));
while((fod->x%2)!=0) //保证x为偶数,使得食物能与蛇头对齐
{
fod->x=rand()%52+2;
}
fod->y=rand()%24+1;
q=head;
while(q!=NULL)
{
if(q->x==fod->x && q->y==fod->y) //判断蛇身是否与食物重合
{
fod=NULL;
free(fod);
createfood();
}
q=q->next;
}
food=fod;
Pos(fod->x,fod->y);
color(4);
printf("★");
}

/****咬到自己****/
int biteself()
{
snake *self; //定义self为蛇身上的一个节点
self=head->next; //self是蛇头之外的蛇身上的节点
while(self!=NULL)
{
if(self->x==head->x && self->y==head->y) //如果self和蛇身上的节点重合
{
endgamestatus=2; //返回第二种情况
endgame(); //出现游戏结束界面
}
else
{
self=self->next;
}
}
return 0;
}

/****不能穿墙****/
void cantcrosswall()
{

if(head->x==0 || head->x==56 ||head->y==0 || head->y==26) //如果蛇头碰到了墙壁
{
endgamestatus=1; //返回第一种情况
endgame(); //出现游戏结束界面
}
}

/****加速****/
void speedup()
{
if(sleeptime>=50)
{
sleeptime=sleeptime-5;
add=add+1;

}

}

/****减速****/
void speeddown()
{
if(sleeptime<350) //如果时间间隔小于350
{
sleeptime=sleeptime+20; //时间间隔加上20
add=add-2; //每吃一次食物的得分减2

}

}

/****移动****/
void snakemove() //蛇前进,上U,下D,左L,右R
{
snake nexthead;
cantcrosswall();
nexthead=(snake
)malloc(sizeof(snake)); //为下一步开辟空间
if(status==U)
{
nexthead->x=head->x; //向上前进时,x坐标不动,y坐标-1
nexthead->y=head->y-1;
nexthead->next=head;
head=nexthead;
q=head; //指针q指向蛇头
if(nexthead->x==food->x && nexthead->y==food->y) //如果下一个有食物 下一个位置的坐标和食物的坐标相同
{

        while(q!=NULL)
        {
            Pos(q->x,q->y);
            color(c);
            printf("■");       //原来食物的位置
            q=q->next;          //指针q指向的蛇身的下一位也执行循环里的操作

        }
        score=score+add;        //吃了一个食物,在总分上加上食物的分
        speedup();              //加速
        createfood();           //创建食物
    }
    else                        
    {
        while(q->next->next!=NULL)  //如果没遇到食物
        {
            Pos(q->x,q->y);
            color(c);
            printf("■");           //蛇正常往前走,输出当前位置的蛇身
            q=q->next;              //继续输出整个蛇身
        }
        Pos(q->next->x,q->next->y);  //经过上面的循环,q指向蛇尾,蛇尾的下一位,就是蛇走过去的位置
        color(3);
        printf("■");
        free(q->next);      //进行输出■之后,释放指向下一位的指针
        q->next=NULL;       //指针下一位指向空
    }
}
if(status==D)
{
    nexthead->x=head->x;        //向下前进时,x坐标不动,y坐标+1
    nexthead->y=head->y+1;
    nexthead->next=head;
    head=nexthead;
    q=head;
    if(nexthead->x==food->x && nexthead->y==food->y)  //有食物
    {

        while(q!=NULL)
        {
            Pos(q->x,q->y);
            color(c);
            printf("■");
            q=q->next;
        }
        score=score+add;
        speedup();
        createfood();
    }
    else                               //没有食物
    {
        while(q->next->next!=NULL)
        {
            Pos(q->x,q->y);
            color(c);
            printf("■");
            q=q->next;
        }
        Pos(q->next->x,q->next->y);
        color(3);
        printf("■");
        free(q->next);
        q->next=NULL;
    }
}
if(status==L)
{
    nexthead->x=head->x-2;        //向左前进时,x坐标向左移动-2,y坐标不动
    nexthead->y=head->y;
    nexthead->next=head;
    head=nexthead;
    q=head;
    if(nexthead->x==food->x && nexthead->y==food->y)//有食物
    {
        while(q!=NULL)
        {
            Pos(q->x,q->y);
            color(c);
            printf("■");
            q=q->next;
        }
        score=score+add;
        speedup();
        createfood();
    }
    else                                //没有食物
    {
        while(q->next->next!=NULL)
        {
            Pos(q->x,q->y);
            color(c);
            printf("■");
            q=q->next;        
        }
        Pos(q->next->x,q->next->y);
        color(3);
        printf("■");
        free(q->next);
        q->next=NULL;
    }
}
if(status==R)
{
    nexthead->x=head->x+2;        //向右前进时,x坐标向右移动+2,y坐标不动
    nexthead->y=head->y;
    nexthead->next=head;
    head=nexthead;
    q=head;
    if(nexthead->x==food->x && nexthead->y==food->y)//有食物
    {
        while(q!=NULL)
        {
            Pos(q->x,q->y);
            color(c);
            printf("■");
            q=q->next;
        }
        score=score+add;
        speedup();
        createfood();
    }
    else                                         //没有食物
    {
        while(q->next->next!=NULL)
        {
            Pos(q->x,q->y);
            color(c);
            printf("■");
            q=q->next;        
        }
        Pos(q->next->x,q->next->y);
        color(3);
        printf("■");
        free(q->next);
        q->next=NULL;
    }
}
if(biteself()==1)       //判断是否会咬到自己
{
    endgamestatus=2;
    endgame();
}

}

/****控制****/
void keyboardControl()
{
status=R; //初始蛇向右移动
while(1)
{
scoreandtips();
if(GetAsyncKeyState(VK_UP) && status!=D) //GetAsyncKeyState函数用来判断函数调用时指定虚拟键的状态,VK_UP代表↑
{
status=U; //如果蛇不是向下前进的时候,按上键,执行向上前进操作
}
else if(GetAsyncKeyState(VK_DOWN) && status!=U) //如果蛇不是向上前进的时候,按下键,执行向下前进操作
{
status=D;
}
else if(GetAsyncKeyState(VK_LEFT)&& status!=R) //如果蛇不是向右前进的时候,按左键,执行向左前进
{
status=L;
}
else if(GetAsyncKeyState(VK_RIGHT)&& status!=L) //如果蛇不是向左前进的时候,按右键,执行向右前进
{
status=R;
}
if(GetAsyncKeyState(VK_SPACE)) //按暂停键,执行pause暂停函数
{
while(1)
{
Sleep(300); //sleep()函数,头文件#include 令进程暂停,直到达到里面设定的参数的时间。
if(GetAsyncKeyState(VK_SPACE)) //按空格键暂停
{
break;
}

        }       
    }
    else if(GetAsyncKeyState(VK_ESCAPE))
    {
        endgamestatus=3;    //按esc键,直接到结束界面
        break;
    }
    else if(GetAsyncKeyState(VK_F1))    //按F1键,加速
    {
        speedup();
    }
    else if(GetAsyncKeyState(VK_F2))    //按F2键,减速
    {
        speeddown();

    }
    Sleep(sleeptime);
    snakemove();
}

}

/****游戏说明****/
void explation()
{

system("cls");
Pos(30,8);
printf("1. 不能穿墙,不能咬到自己");
Pos(30,11);
printf("2. 用↑.↓.←.→分别控制蛇的移动");
Pos(30,14);
printf("3. 游戏速度会随吃到食物而加快");
Pos(30,17);
printf("4. F1 为加速,F2 为减速");
Pos(30,20);
printf("5. 按空格键暂停游戏,再按空格键继续");
Pos(30,21);
printf("6. ESC :退出游戏");
_getch();                //按任意键返回主界面
system("cls");
welcometogame();

}

/****游戏结束****/
void endgame()
{
system("cls");
if(endgamestatus==1)
{
color(4);
Pos(43,9);
printf("GAME OVER !");
Pos(43,12);
printf("您撞到墙了");
}
else if(endgamestatus==2)
{
Pos(43,9);
color(4);
printf("GAME OVER !");
Pos(43,12);
printf("您咬到自己了");
}
else if(endgamestatus==3)
{
Pos(43,9);
color(4);
printf("已结束游戏");
}
Pos(43,15);
printf("您的得分是: %d",score);
choose();
}

/****结束选择****/
void choose()
{
int n;
Pos(25,23);
printf("Continue ------ 1");
Pos(52,23);
printf("Exit ------ 2");
Pos(45,25);
printf("选择: ");
scanf("%d", &n);
switch (n)
{
case 1:
system("cls"); //清屏
score=0; //分数归零
sleeptime=200; //设定初始速度
add = 10; //使add设定为初值,吃一个食物得分10,然后累加
welcometogame();
break;
case 2:
exit(0); //退出游戏
break;
default:
Pos(35,27);
printf("输入有误 重新输入!");
Pos(35,28);
printf("按任意键继续");
system("pause >nul");
endgame();
choose();
break;
}

}

/****主函数****/
int main()
{

system("mode con cols=100 lines=30"); //设置控制台的宽高
welcometogame();
keyboardControl();
endgame();
return 0;
}

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 flink cdc无法实时同步mysql数据
    • ¥100 有人会搭建GPT-J-6B框架吗?有偿
    • ¥15 求差集那个函数有问题,有无佬可以解决
    • ¥15 【提问】基于Invest的水源涵养
    • ¥20 微信网友居然可以通过vx号找到我绑的手机号
    • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
    • ¥15 解riccati方程组
    • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
    • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
    • ¥50 树莓派安卓APK系统签名