Mr_renjiajun 2022-08-12 11:00 采纳率: 66.7%
浏览 106
已结题

C语言:贪吃蛇bug问题

用Visual Studio做的贪吃蛇,为啥我的贪吃蛇的食物会出现两个,但是有一个就是闪一下就消失,还有我的弹出窗口有时候要点击两次或者三次才能进行下一步操,请问这些bug该怎么解决?

#include<stdio.h>
#include<graphics.h>
#include<time.h>
#include<conio.h>//使用getch()
#include<windows.h>//这个头文件要放在graphics.h的下面
#include<mmsystem.h>//包含多媒体设备接口头文件,用于播放音乐
#pragma comment(lib,"winmm.lib")//加载静态库
static unsigned int count;//用于判断蛇的速度等级
unsigned int speed;//蛇的具体速度,用于控制Sleep函数
#define MAX_Snake_Size 200
#define _CRT_SECURE_NO_WARNINGS
unsigned int Gameflag;//游戏运行情况,1表示正在运行,0表示暂停
unsigned int Musicflag;//音乐播放状态,1正在播放,0暂停播放
unsigned int Snakeflag;//蛇的状态,1表示存活,0表示死亡

enum
{
UP, DOWN, LEFT, RIGHT
};
//建立简单的蛇结构
struct Snake
{
int size;//蛇的节数
int speed;//蛇每个单位的速度
int dir;//蛇的方向
POINT coor[MAX_Snake_Size];//蛇每个单位的坐标coordinate
}snake;
//建立简单食物结构
struct Food
{
int x;//食物的x轴坐标
int y;//y坐标
int r;//食物尺寸大小
bool flag;//食物的状态,存在为true,被吃为false
int score;//分数
}food;

//游戏初始化
void InitGame()
{
srand((unsigned int)time(NULL));
//初始化游戏状态
Gameflag = 1;
//Musicflag = 1;
Snakeflag = 1;
//初始化蛇
snake.size = 3;
snake.speed = 10;
snake.dir = RIGHT;
for (int i = 0; i < snake.size; i++)
{
snake.coor[i].x = 40 - 10 * i;
snake.coor[i].y = 10;
}
snake.coor[0].x += snake.speed;
//初始化食物
food.x = rand() % 295 + 5;
food.y = rand() % 295 + 5;
food.r = rand() % 7 + 5;
//设立一个值表示食物的状态
food.flag = 0;//flag为1的时候是食物存在窗口内,0的时候是被吃掉了
food.score = 0;//起始得分为0
//蛇初始吃的食物数量
count = 0;
}
//绘制图形
void DrawGame()
{
BeginBatchDraw();
setbkcolor(WHITE);//建立窗口底色
cleardevice();
//绘制蛇
setfillcolor(GREEN);
for(int i = 0; i < snake.size; i++)
{
solidcircle(snake.coor[i].x, snake.coor[i].y, 5);
}
//EndBatchDraw();
//绘制食物
if (food.flag)
{
setfillcolor(GREEN);
solidcircle(food.x, food.y, food.r);
}
//绘制记分系统
setfillcolor(LIGHTBLUE);
solidrectangle(300, 0, 400, 300);
char score[100];
sprintf_s(score, "%d", food.score);//因为我们的分数是int类型,而我们outtextxy在窗口上输出的是char类型,所以要使用sprintf去把会时刻变化的int类型数改变为char类型
setbkmode(TRANSPARENT);
settextcolor(BLACK);
outtextxy(320, 20, "得分:");
outtextxy(370, 20, score);
//绘制提示语录
char arr1[15] = "提示信息:";
char arr2[15] = "Esc键 退出";
char arr3[18] = "空格键 暂停";
settextstyle(18, 0, "楷体");
outtextxy(310, 50, arr1);
outtextxy(305, 80, arr2);
outtextxy(300, 110, arr3);
FlushBatchDraw();
}
//游戏运行
void MoveGame()
{
//蛇的移动
for (int i = snake.size - 1; i > 0; i--)
{
snake.coor[i] = snake.coor[i - 1];
}
//下面标注的是另一种移动方式,但是我还没有解决让他自己移动的问题
/if (GetAsyncKeyState(VK_UP))
{
snake.coor[0].y -= snake.speed;
if (snake.coor[0].y <= 0)
snake.coor[0].y = 300;
}
if (GetAsyncKeyState(VK_DOWN))
{
snake.coor[0].y += snake.speed;
if (snake.coor[0].y >= 300)
snake.coor[0].y = 0;
}
if (GetAsyncKeyState(VK_LEFT))
{
snake.coor[0].x -= snake.speed;
if (snake.coor[0].x <= 0)
snake.coor[0].x = 300;
}
if (GetAsyncKeyState(VK_RIGHT))
{
snake.coor[0].x += snake.speed;
if (snake.coor[0].x >= 300)
snake.coor[0].x = 0;
}
/

switch (snake.dir)
{
case DOWN:
    snake.coor[0].y += snake.speed;
    if (snake.coor[0].y >= 300)
        snake.coor[0].y = 0;
    break;
case UP:
    snake.coor[0].y -= snake.speed;
    if (snake.coor[0].y <= 0)
        snake.coor[0].y = 300;
    break;
case LEFT:
    snake.coor[0].x -= snake.speed;
    if (snake.coor[0].x <= 0)
        snake.coor[0].x = 300;
    break;
case RIGHT:
    snake.coor[0].x += snake.speed;
    if (snake.coor[0].x >= 300)
        snake.coor[0].x = 0;
    break;
}
//食物的移动
if (snake.coor[0].x - food.x <= food.r && food.x - snake.coor[0].x <= food.r && snake.coor[0].y - food.y <= food.r && food.y - snake.coor[0].y <= food.r)
{
    snake.size++;
    food.flag = 0;
    count++;
    food.score += 10;
}

if (food.flag == 0)
{
    food.x = rand() % 295 + 5;
    food.y = rand() % 295 + 5;
    food.r = rand() % 7 + 5;
    food.flag = 1;
}
//控制蛇的死亡
for (int i = 1; i < snake.size; i++)//如果蛇碰到自己就死
{
    if (snake.coor[0].x == snake.coor[i].x && snake.coor[0].y == snake.coor[i].y)
        Snakeflag = 0;
    //绘制蛇死亡时的弹出窗口
    if (Snakeflag == 0)
    {
        HWND window_control = GetHWnd();
        printf("\a");
        int isok=MessageBox(NULL, "你已死亡,点击确认重新开始,点击取消关闭游戏游戏", "游戏提示:", MB_OKCANCEL);
        if (isok == IDOK);//选择了OK
        if (isok == IDCANCEL)//选择了CANCEL
        {
            closegraph();
            Gameflag = 0;
        }
    }    
}

}
//播放音乐
void BGM()
{
mciSendString("open ./贪吃蛇背景音乐.mp3", 0, 0, 0);
if (Musicflag == 1)
{
mciSendString("play ./贪吃蛇背景音乐.mp3 repeat", 0, 0, 0);
}
if (Musicflag == 0)
{
mciSendString("close ./贪吃蛇背景音乐.mp3", 0, 0, 0);
mciSendString("stop ./贪吃蛇背景音乐.mp3 repeat", 0, 0, 0);
}
}

//键盘参数
void KeySystem()
{
if (_kbhit())
{
switch (_getch())
{
case 72:
case 'w':
case 'W':
if (snake.dir != DOWN)
snake.dir = UP;
break;
case 80:
case 's':
case 'S':
if (snake.dir != UP)
snake.dir = DOWN;
break;
case 75:
case 'a':
case 'A':
if (snake.dir != RIGHT)
snake.dir = LEFT;
break;
case 77:
case 'd':
case 'D':
if (snake.dir != LEFT)
snake.dir = RIGHT;
break;
case 27://加中括号的目的是避免default造成的无法读取window_control数值初始化问题
{
closegraph();
HWND window_control = GetHWnd();
printf("\a");
MessageBox(window_control, "游戏结束", "游戏提示:",MB_OKCANCEL);
Musicflag = 0;
Gameflag = 0;
break;
}
case ' ':
{
HWND window_control = GetHWnd();
printf("\a");
MessageBox(window_control, "游戏暂停", "游戏提示:", MB_OKCANCEL);
Musicflag = 0;
break;
}
default:snake.dir = snake.dir; break;
}
}
}
//蛇的速度控制
void snake_speed()
{
if (count < 10)
speed = 200 - count * 5;
else if (count < 20)
speed = 155 - (count - 10) * 4;
else if (count < 30)
speed = 119 - (count - 10) * 3;
else if (count < 40)
speed = 92 - (count - 10) * 2;
else
speed = speed;
}

int main()
{
initgraph(400, 300, SHOWCONSOLE);
InitGame();
while (Gameflag)
{
InitGame();

    while(1)
    {    
        KeySystem();
        //BGM();
        MoveGame();
        DrawGame();
        snake_speed();
        Sleep(speed);
        if (Snakeflag == 0)
            break;
        if (Gameflag == 0)
            break;
    }
    rewind(stdin);
}
return 0;

}

  • 写回答

3条回答 默认 最新

  • 艾秋 2022-08-13 13:02
    关注

    蛇的长度+1是,蛇尾巴没有赋值,坐标为 (0,0),刚吃掉食物后的第一次刷新会在左上角显示一个蛇尾。
    解决办法:蛇长增加时给蛇尾坐标赋值

        //食物的移动
        if (snake.coor[0].x - food.x <= food.r && food.x - snake.coor[0].x <= food.r &&
            snake.coor[0].y - food.y <= food.r && food.y - snake.coor[0].y <= food.r)
        {
            snake.size++;
            snake.coor[snake.size - 1] = snake.coor[snake.size - 2];
            food.flag = 0;
            count++;
            food.score += 10;
        }
    

    蛇在死亡是有个 for 循环,当蛇死亡时 for 循环没退出,导致弹框会弹出几次,加个 break 就好了。

        //控制蛇的死亡
        for (int i = 1; i < snake.size; i++) //如果蛇碰到自己就死
        {
            if (snake.coor[0].x == snake.coor[i].x && snake.coor[0].y == snake.coor[i].y)
                Snakeflag = 0;
            //绘制蛇死亡时的弹出窗口
            if (Snakeflag == 0)
            {
                HWND window_control = GetHWnd();
                printf("\a");
                int isok = MessageBox(NULL, "你已死亡,点击确认重新开始,点击取消关闭游戏游戏", "游戏提示:", MB_OKCANCEL);
                if (isok == IDOK)
                    ;                 //选择了OK
                if (isok == IDCANCEL) //选择了CANCEL
                {
                    closegraph();
                    Gameflag = 0;
                }
                break;
            }
        }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 8月21日
  • 已采纳回答 8月13日
  • 创建了问题 8月12日

悬赏问题

  • ¥50 MATLAB APP 制作出现问题
  • ¥15 wannier复现图像时berry曲率极值点与高对称点严重偏移
  • ¥15 利用决策森林为什么会出现这样·的问题(关键词-情感分析)
  • ¥15 DispatcherServlet.noHandlerFound No mapping found for HTTP request with URI[/untitled30_war_e
  • ¥15 使用deepspeed训练,发现想要训练的参数没有梯度
  • ¥15 寻找一块做为智能割草机的驱动板(标签-stm32|关键词-m3)
  • ¥15 信息管理系统的查找和排序
  • ¥15 基于STM32,电机驱动模块为L298N,四路运放电磁传感器,三轮智能小车电磁组电磁循迹(两个电机,一个万向轮),怎么用读取的电磁传感器信号表示小车所在的位置
  • ¥15 如何解决y_true和y_predict数据类型不匹配的问题(相关搜索:机器学习)
  • ¥15 PB中矩阵文本型数据的总计问题。