_烟雨画桥_ 2022-08-30 22:22 采纳率: 100%
浏览 56
已结题

第一次做“贪吃蛇”项目无法正常运行,求解惑。

学C不久,在网上看见“贪吃蛇”的教程,感觉有意思跟着做了一下。
目前程序可以运行,但是当我用“a”“s”“d”“w”控制蛇的方向时,
蛇就不动,对着教程看了好几遍还是看不出哪里错了,求帮忙解答,
已经折腾一天了。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>
#include<conio.h>


#define ROW 22
#define COL 42
#define KONG 0
#define WALL 1
#define FOOD 2
#define HEAD 3
#define BODY 4
#define UP 'w'
#define DOWN 's'
#define LEFT 'a'
#define RIGHT 'd'
#define SPACE 32
#define ESC 27

struct Snake
{
    int len;
    int x;
    int y;
}snake;

struct body{
    int x;
    int y;
}body[ROW*COL];

int face[ROW][COL];

void HideCursor();
void CursorJump(int x, int y);
void InitInterface();
void color(int c);
void ReadGrade();
void WriteGrade();
void InitSnake();
void RandFood();
void JudgFunc(int x, int y);
void DrawSnake(int flag);
void MoveSnake(int x, int y);
void run(int x, int y);
void Game();

int max,grade;
int main()
{
#pragma warning (disable:4996)
    max = 0, grade = 0;
    system("title 贪吃蛇");
    system("mode con cols=84 lines=23");
    HideCursor();
    ReadGrade();
    InitInterface();
    InitSnake();
    srand((unsigned int)time(NULL));
    RandFood();
    DrawSnake(1);
    Game();
    return 0;
}
void HideCursor()//隐藏光标
{
    CONSOLE_CURSOR_INFO curInfo;
    curInfo.dwSize = 1;
    curInfo.bVisible = FALSE;
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorInfo(handle, &curInfo);
}

void CursorJump(int x,int y)//定位光标
{
    COORD pos;
    pos.X = x;
    pos.Y = y;
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(handle, pos);
}

void color(int c)//颜色
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);
}

void InitInterface()//构建框架
{
    color(6);
    for (int i = 0; i < ROW; i++)
    {
        for (int j = 0; j < COL; j++)
        {
            if (j == 0 || j == COL - 1)
            {
                face[i][j] = WALL;
                CursorJump(2*j, i);
                printf("回");
            }
            else if (i == 0 || i == ROW - 1)
            {
                face[i][j] = WALL;
                printf("回");
            }
            else
            {
                face[i][j] = KONG;
            }
        }
    }
    color(7);
    CursorJump(0, ROW);
    printf("当前得分:%d", grade);
    CursorJump(COL, ROW);
    printf("历史最高分:%d", max);
}

void InitSnake()
{
    snake.len = 2;
    snake.x = COL / 2;
    snake.y = ROW / 2;
    body[0].x = COL / 2 - 1;
    body[0].y = ROW / 2;
    body[1].x = COL / 2 - 2;
    body[1].y = ROW / 2;
    face[snake.y][snake.x] = HEAD;
    face[body[0].y][body[0].x] = BODY;
    face[body[1].y][body[1].x] = BODY;
}

    
void ReadGrade()//读入文件中的最高纪录或生成文件
{
    FILE* pf = fopen("贪吃蛇最高得分记录.txt", "r");
    if (pf == NULL)
    {
        pf = fopen("贪吃蛇最高得分记录.txt", "w");
        fwrite(&max, sizeof(int),1,pf);
    }
    fseek(pf, 0, SEEK_SET);
    fread(&max, sizeof(int), 1, pf);
    fclose(pf);
    pf = NULL;
}

void WriteGrade()
{
    FILE* pf = fopen("贪吃蛇最高得分记录.txt", "w");
    if (pf == NULL)
    {
        printf("保存最高得分记录失败\n");
        exit(0);
    }
}

void RandFood()//随机生成食物
{
    int i, j;
    do
    {
        i = rand() % ROW;
        j = rand() % COL;
    } while (face[i][j] != KONG);
    face[i][j] = FOOD;
    color(12);
    CursorJump(2 * j, i);
    printf("@");
}

void DrawSnake(int flag)//打印蛇
{
    if (flag == 1)
    {
        color(10);
        CursorJump(2 * snake.x, snake.y);
        printf("Q");
        for (int i = 0; i < snake.len; i++)
        {
            CursorJump(2 * body[i].x, body[i].y);
            printf("O");
        }
    }
    else
    {
        if (body[snake.len - 1].x != 0)
        {
            CursorJump(2 * body[snake.len - 1].x, body[snake.len - 1].y);
            printf(" ");
        }
    }
}
    

void MoveSnake(int x, int y)//移动蛇
{
    DrawSnake(0);
    face[body[snake.len - 1].y][ body[snake.len - 1].x ] = KONG;

    for (int i = snake.len - 1; i > 0; i--)
    {
        body[i].x = body[i - 1].x;
        body[i].y = body[i - 1].y;
    }
    body[0].x = snake.x;
    body[0].y = snake.y;
    snake.x = snake.x + x;
    snake.y = snake.y + y;
    DrawSnake(1);
}

void run(int x, int y)//使蛇能够自动向前移动
{
    int t = 0;
    while (1)
    {
        if (t == 0)
            t = 30000;
        while (--t)
        {    
                if (kbhit() != 0)//如果按下键盘,跳出此循环,感觉这里有点问题
                {
                break;
            }
        }
        if (t == 0)//如果没有接收任何指令,则向原来方向移动,反之跳出循环离开函数。
        {
            JudgFunc(x, y);//检查蛇头状态
            MoveSnake(x, y);//使蛇进行下一步动作
        }
        else
        {
            break;
        }
    }
}

void Game()
{
    int n = RIGHT;
    int tmp = 0;
    goto first;//默认开始向右移动
    while (1)
    {
        n = getch();//跳出run函数后读取输入
        switch (n)//防止向反方向移动
        {
        case UP:
        case DOWN:
            if (tmp != LEFT && tmp != RIGHT)
            {
                n = tmp;
            }
            break;
        case LEFT:
        case RIGHT:
            if (tmp != UP && tmp != DOWN)
            {
                n = tmp;
                break;
            }
        first:
            switch (n)
            {
            case UP:
                run(0, -1);
                tmp = UP;
                break;
            case DOWN:
                run(0, 1);
                tmp = DOWN;
                break;
            case LEFT:
                run(-1, 0);
                tmp = LEFT;
                break;
            case RIGHT:
                run(1, 0);
                tmp = RIGHT;
                break;
            case SPACE:
                system("pause>nul");
                break;
            case ESC:
                system("cls");
                color(7);
                CursorJump(COL - 8, ROW / 2);
                printf(" 游戏结束 ");
                CursorJump(COL - 8, ROW / 2 + 2);
            case'r':
            case'R':
                system("cls");
                main();
            }
        }
    }
}
    
void JudgFunc(int x, int y)//检查蛇头状态
{
    if (face[snake.y + y][snake.x + x ] == FOOD)//吃到食物长度加一
    {
        snake.len++;
        grade += 10;
        color(7);
        CursorJump(0, ROW);
        printf("当前得分:%d", grade);
        RandFood();
    }
    else if (face[snake.y + y][snake.x + x] == WALL || face[snake.y + y][snake.x + x] == BODY)//撞身/墙游戏结束
    {
        Sleep(1000);
        system("cls");
        color(7);
        CursorJump(2 * (COL / 3), ROW / 2 - 3);
        if (grade > max)
        {
            printf("恭喜你打破记录,最高记录更新为%d", grade);
            WriteGrade();
        }
        else if (grade == max)
        {
            printf("与最高记录持平,加油再创佳绩", grade);
        }
        else
        {
            printf("请继续加油,当前与最高记录相差%d", max - grade);
        }
        CursorJump(2 * (COL / 3), ROW / 2);
        printf("GAME OVER");
        while (1)//询问是否继续游戏
        {
            char ch;
            CursorJump(2 * (COL / 3), ROW / 2 + 3);
            printf("再来一局?(y/n):");
            scanf("%c", &ch);
            if (ch == 'y' || ch == 'Y')
            {
                system("cls");
                main();
            }
            else if (ch == 'n' || ch == 'N')
            {
                CursorJump(2 * (COL / 3), ROW / 2 + 5);
                exit(0);
            }
            else
            {
                CursorJump(2 * (COL / 3), ROW / 2 + 5);
                printf("选择错误,请再次选择");
            }
        }
    }
}


感觉问题就在这两个函数里



void run(int x, int y)//使蛇能够自动向前移动
{
    int t = 0;
    while (1)
    {
        if (t == 0)
            t = 30000;
        while (--t)
        {    
                if (kbhit() != 0)//如果按下键盘,跳出此循环,感觉这里有点问题
                {
                break;
            }
        }
        if (t == 0)//如果没有接收任何指令,则向原来方向移动,反之跳出循环离开函数。
        {
            JudgFunc(x, y);//检查蛇头状态
            MoveSnake(x, y);//使蛇进行下一步动作
        }
        else
        {
            break;
        }
    }
}

void Game()
{
    int n = RIGHT;
    int tmp = 0;
    goto first;//默认开始向右移动
    while (1)
    {
        n = getch();//跳出run函数后读取输入
        switch (n)//防止向反方向移动
        {
        case UP:
        case DOWN:
            if (tmp != LEFT && tmp != RIGHT)
            {
                n = tmp;
            }
            break;
        case LEFT:
        case RIGHT:
            if (tmp != UP && tmp != DOWN)
            {
                n = tmp;
                break;
            }
        first:
            switch (n)
            {
            case UP:
                run(0, -1);
                tmp = UP;
                break;
            case DOWN:
                run(0, 1);
                tmp = DOWN;
                break;
            case LEFT:
                run(-1, 0);
                tmp = LEFT;
                break;
            case RIGHT:
                run(1, 0);
                tmp = RIGHT;
                break;
            case SPACE:
                system("pause>nul");
                break;
            case ESC:
                system("cls");
                color(7);
                CursorJump(COL - 8, ROW / 2);
                printf(" 游戏结束 ");
                CursorJump(COL - 8, ROW / 2 + 2);
            case'r':
            case'R':
                system("cls");
                main();
            }
        }
    }
}

  • 写回答

1条回答 默认 最新

  • wwc2017 2022-08-31 09:22
    关注
            switch (n)//防止向反方向移动
            {
            case UP:
            case DOWN:
                if (tmp != LEFT && tmp != RIGHT)
                {
                    n = tmp;
                }
                break;
            case LEFT:
            case RIGHT:
                if (tmp != UP && tmp != DOWN)
                {
                    n = tmp;
                    break;
                }
            first:
    

    大括号写错了,switch (n)的右大括号应在first上面。然后删掉first下面对应的右大括号就好了

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 9月10日
  • 已采纳回答 9月2日
  • 修改了问题 8月30日
  • 创建了问题 8月30日

悬赏问题

  • ¥15 python使用pulp线性优化时报错
  • ¥15 开源或低价数据中台哪个最好
  • ¥15 arduino编程出现字符串疑似覆盖现象
  • ¥15 我的b站在没有碰到屏幕的情况下偶尔会自动跳出进度条,就像在屏幕上点了一下一样,但我并没有点。而且视频进度并没有变。这可能是什么原因造成的?
  • ¥30 STK matlab python仿真
  • ¥15 关于IMageEnView 图标定位问题
  • ¥20 求解答(matlab)
  • ¥30 ffmpeg库使用过程中遇到的问题
  • ¥15 pyqt5 中python如何通过Qtwebchannel主动发消息给web前端
  • ¥15 关于HTML中title获取xml内容的问题