自学C语言,想做个贪吃蛇,感觉逻辑没问题,但是实现就是有问题。

在吃第二个食物之后,蛇尾没消除,也没显示第三节身体。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <stdlib.h>
#include <time.h>

typedef struct Snake{
    int x;
    int y;
    struct Snake* next;
}snake;
char key,wait;
int score=0;
snake head = { 33,11,NULL };
snake* currents = NULL,*then=NULL;
int i, j;
void   gotoxy(int, int);
void   gotoprint(int, int, char*);
void   move(void);
int    food(void);
void   add(void);
void   moves(void);

int main()
{
    /*地图打印*/
    for (int i = 0; i < 66; i++)
    {
        gotoprint(i,0,  "▔");
        gotoprint(i,26, "▁");
    }
    for (int i = 0; i < 27; i++)
    {
        gotoprint(0,i, "┃");
        gotoprint(65,i,"┃");
    }
    //实现 
    key = _getch();
    while (key != 'w' && key != 's' && key != 'a' && key != 'd')
        key = _getch();
    gotoprint(head.x,head.y,"◆");
    int n=food();
    int a = n / 100, b = n - a * 100;
    int c = 0, d = 0;
    while (1)
    {
        move();
        moves();
        Sleep(145 - score * 2);
        c = a, d = b;
        if (head.x == a && head.y == b)
        {
            score++;          
            n = food();
            a = n / 100, b = n - a * 100;
            add();
        }
        else; 
        currents = &head;
        then = head.next;
        while (then != NULL)
        {
            if (then->next == NULL && head.x == c && head.y == d)
            {
                gotoprint(then->x, then->y, " ");
                then = then->next;
            }
            else
            {
                if (then->next == NULL)
                    gotoprint(then->x,then->y," ");
                else;
                then->x = currents->x;
                then->y = currents->y;
                currents = then;
                then = currents->next;
            }
        }
        if (_kbhit())
            wait = _getch();
        else;
        if (key != wait)
        {
            if (wait != 'w' && wait != 's' && wait != 'a' && wait != 'd')
                ;
            else if (key == 'w' && wait != 's')
                key = wait;
            else if (key == 's' && wait != 'w')
                key = wait;
            else if (key == 'a' && wait != 'd')
                key = wait;
            else if (key == 'd' && wait != 'a')
                key = wait;
            else;
        }
        else;
    }  
    gotoxy(0,27);
    printf("Your score is %d.", score);
    return 0;
}

void gotoxy(int x, int y)
{
    COORD pos = { x, y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
    CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void gotoprint(int x, int y, char* a)
{
    gotoxy(x, y);
    printf("%s", a);
}
int  food(void)
{
    srand((unsigned)(time(0) + rand()));
    int m, n;
    m = rand() % 64 + 1;
    n = rand() % 25 + 1;
    snake* current = &head;
    while (current != NULL)
    {
        if (current->x == m && current->y == n)
        {
            srand((unsigned)(time(0) + rand()));
            m = rand() % 64 + 1;
            n = rand() % 25 + 1;
            current = &head;
            continue;
        }
        else;
        current = current->next;       
    }
    gotoprint(m, n, "☆");
    return m * 100 + n;
}
void move(void)
{  
    gotoprint(head.x, head.y, " ");
    switch (key)
    {
    case 'w':
    {       
        (head.y)--;   
        break;
    }
    case 's':
    {
        (head.y)++;     
        break;
    }
    case 'a':
    {
        (head.x)--;      
        break;
    }
    case 'd':
    {
        (head.x)++;
        break;
    }
    default:
        break;
    }
    gotoprint(head.x, head.y, "◆");      
}
void add(void)
{
    snake* current = &head;   
    while (current->next!= NULL)
        current = current->next;
    int x = current->x, y = current->y;
    current->next = (snake*)malloc(sizeof(snake));
    current = current->next;
    current->x = x;
    current->y = y;
    current->next = NULL;
}
void moves(void)
{
    snake* current = head.next;
    while (current != NULL)
    {
        gotoprint(current->x, current->y, "◇");              
        current = current->next;  
    }  
    current = head.next;
    if (head.x == 0 || head.x == 65 || head.y == 0 || head.y == 26)
    {
        gotoxy(0, 27);
        printf("Your score is %d.", score);
        exit(0);
    }
    else;
    while (current != NULL)
    {
        if (head.x == current->x && head.y == current->y)
        {
            gotoxy(0, 27);
            printf("Your score is %d.", score);
            exit(0);
        }
        else;
        current = current->next;
    }   
}

![img](https://img-mid.csdnimg.cn/release/static/image/mid/ask/179875822686181.png "#left")




#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <stdlib.h>
#include <time.h>

typedef struct Snake {
    int x;
    int y;
    struct Snake* next;
} snake;

char key, wait;
int score = 0;
snake head = { 33,11,NULL };
snake* currents = NULL, *then = NULL;

// 光标定位到指定位置
void gotoxy(int, int);
// 在指定位置打印字符串
void gotoprint(int, int, char*);
// 控制蛇的移动
void move(void);
// 生成食物的坐标并返回
int food(void);
// 增加蛇的长度
void add(void);
// 控制蛇的整体移动
void moves(void);

int main()
{
    // 地图打印
    for (int i = 0; i < 66; i++) {
        gotoprint(i, 0, "▔");  // 画上方边框
        gotoprint(i, 26, "▁"); // 画下方边框
    }
    for (int i = 0; i < 27; i++) {
        gotoprint(0, i, "┃");  // 画左边框
        gotoprint(65, i, "┃"); // 画右边框
    }

    // 实现
    key = _getch();
    while (key != 'w' && key != 's' && key != 'a' && key != 'd')
        key = _getch();
    gotoprint(head.x, head.y, "◆"); // 画蛇头

    int n = food();
    int a = n / 100, b = n - a * 100;
    int c = 0, d = 0;

    while (1) {
        move();
        moves();
        Sleep(145 - score * 2); // 控制蛇移动的速度

        c = a, d = b;

        if (head.x == a && head.y == b) {
            score++;
            n = food();
            a = n / 100, b = n - a * 100;
            add();
        }
        else;

        currents = &head;
        then = head.next;

        while (then != NULL) {
            if (then->next == NULL && head.x == c && head.y == d) {
                gotoprint(then->x, then->y, " "); // 清除尾部
                then = then->next;
            }
            else {
                if (then->next == NULL)
                    gotoprint(then->x, then->y, " "); // 清除尾部

                then->x = currents->x;
                then->y = currents->y;
                currents = then;
                then = currents->next;
            }
        }

        if (_kbhit())
            wait = _getch();
        else;

        if (key != wait) {
            if (wait != 'w' && wait != 's' && wait != 'a' && wait != 'd')
                ;
            else if (key == 'w' && wait != 's')
                key = wait;
            else if (key == 's' && wait != 'w')
                key = wait;
            else if (key == 'a' && wait != 'd')
                key = wait;
            else if (key == 'd' && wait != 'a')
                key = wait;
            else;
        }
        else;
    }

    gotoxy(0, 27);
    printf("Your score is %d.", score);
    return 0;
}

void gotoxy(int x, int y)
{
    COORD pos = { x, y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
    CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

void gotoprint(int x, int y, char* a)
{
    gotoxy(x, y);
    printf("%s", a);
}

int food(void)
{
    srand((unsigned)(time(0) + rand()));
    int m, n;
    m = rand() % 64 + 1;
    n = rand() % 25 + 1;
    snake* current = &head;

    while (current != NULL) {
        if (current->x == m && current->y == n) {
            srand((unsigned)(time(0) + rand()));
            m = rand() % 64 + 1;
            n = rand() % 25 + 1;
            current = &head;
            continue;
        }
        else;
        current = current->next;
    }

    gotoprint(m, n, "☆"); // 画食物
    return m * 100 + n;
}

void move(void)
{
    gotoprint(head.x, head.y, " "); // 清除原来位置的蛇头

    switch (key) {
    case 'w':
        (head.y)--;
        break;
    case 's':
        (head.y)++;
        break;
    case 'a':
        (head.x)--;
        break;
    case 'd':
        (head.x)++;
        break;
    default:
        break;
    }

    gotoprint(head.x, head.y, "◆"); // 画新位置的蛇头
}

void add(void)
{
    snake* current = &head;

    while (current->next != NULL)
        current = current->next;

    int x = current->x, y = current->y;

    current->next = (snake*)malloc(sizeof(snake));
    current = current->next;
    current->x = x;
    current->y = y;
    current->next = NULL;
}

void moves(void)
{
    snake* current = head.next;

    while (current != NULL) {
        gotoprint(current->x, current->y, "◇"); // 画蛇身
        current = current->next;
    }

    current = head.next;

    if (head.x == 0 || head.x == 65 || head.y == 0 || head.y == 26) {
        gotoxy(0, 27);
        printf("Your score is %d.", score);
        exit(0);
    }
    else;

    while (current != NULL) {
        if (head.x == current->x && head.y == current->y) {
            gotoxy(0, 27);
            printf("Your score is %d.", score);
            exit(0);
        }
        else;
        current = current->next;
    }
}

以上是添加了注释的代码,希望能更加清晰地理解代码的功能和逻辑。如果有任何疑问,请随时提问

C语言编写贪吃蛇完整

#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
 
#define ROW 22
#define COL 42
 
#define BlANK 0
#define WALL 1
#define FOOD 2
#define HEAD 3
#define BODY 4
 
#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77
#define SPACE 32
#define ESC 27
 
 
int max, grade;
struct snakehead
{
    int x;
    int y;
    int len;
}snake;
 
struct snakebody
{
    int x;
    int y;
}body[ROW*COL];
 
int face[ROW][COL];
 
void HideCursor();//隐藏光标
void CursorJump(int x, int y);
void InitInterface();
void Initsnake();
void DrawSnake(int flag);
void MoveSneke(int x, int y);
void run(int x, int y);
void judgeFunc(int x, int y);
void RandFood();
 
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 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] = BlANK; //标记该位置为空
            }
        }
    }
}
 
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 DrawSnake(int flag)
{
    //system("cls");
    //InitInterface();
    if (flag == 1)
    {
        CursorJump(2 * snake.x, snake.y);
        printf("■");
        for (int i = 0; i < snake.len; i++)
        {
            CursorJump(2 * body[i].x, body[i].y);
            printf("□");
        }
    }
    else
    {
        if (body[snake.len - 1].x != 0)
        {
            CursorJump(2 * body[snake.len-1 ].x, body[snake.len-1 ].y);
            printf("  ");
 
        }
    }
}
 
void MoveSneke(int x, int y)
{
    DrawSnake(0);
    face[body[snake.len - 1].y][body[snake.len - 1].x] = BlANK;
    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 = 6000;
        }
        while (--t)
        {
            if (kbhit() != 0)
                break;
        }
        if (t == 0)
        {
            judgeFunc(x, y);
            MoveSneke(x, y);
        }
        else
        {
            break;
        }
    }
}
void judgeFunc(int x, int y)
{
    if (face[snake.y + y][snake.x + x] == FOOD)
    {
        snake.len++;
        grade += 10;
        RandFood();
 
    }
    else if (face[snake.y + y][snake.x + x] == WALL)
    {
        Sleep(1000);
        system("cls");
        CursorJump(2 * (COL / 3), ROW / 2 + 3);
        printf("game over,agin?  y/n");
        char n;
        scanf("%c", &n);
        if (n == 'y')
        {
            system("cls");
            main();
        }
        else
        {
            exit(0);
        }
    }
}
void RandFood()
{
    int i, j;
    do
    {
        i = rand() % ROW;
        j = rand() % COL;
 
    } while (face[i][j] != BlANK);
    face[i][j] = FOOD;
    CursorJump(2 * j, i);
    printf("●");
}
 
void game()
{
    //printf("贪吃蛇\n");
    //创建游戏区域
    HideCursor();
    InitInterface();
    Initsnake();
    DrawSnake(1);
    RandFood();
    game2();
 
}
 
int main()
{
 
 
    game();
    return 0;
}
void game2()
{
    int n = RIGHT;
    int tmp = 0;
    goto first;
    while (1)
    {
        n = getch();
        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;
            }
        case SPACE:
        case ESC:
        case 'r':
        case 'R':
            break;
        default:
            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");
            CursorJump(COL - 8, ROW / 2);
            printf("game over");
            CursorJump(COL - 8, ROW / 2);
            exit(0);
        case 'r':
        case 'R':
            system("cls");
            main();
        }
    }
}

https://img-mid.csdnimg.cn/release/static/image/mid/ask/211791032686123.png "#left")

你的贪吃蛇程序中出现了一些逻辑问题导致蛇尾没有正确消除和显示第三节身体。下面我将解释并修复这些问题。

问题1:蛇尾没有消除
在你的代码中,在蛇吃到食物后,你在循环中遍历蛇身部分并进行处理。但是你的逻辑判断有误,导致蛇尾没有正确消除。在以下代码中,你检查蛇头是否与蛇尾的坐标相同,如果相同则将蛇尾消除:

if (then->next == NULL && head.x == c && head.y == d)
{
    gotoprint(then->x, then->y, " ");
    then = then->next;
}


然而,这个逻辑有一个问题,即它只会在蛇尾节点是链表中的最后一个节点时才会执行消除操作。但实际上,你的蛇尾节点并不一定是链表中的最后一个节点,因为你在增加新的身体节点时,只是简单地将它添加到链表的末尾,而没有更新前一个节点的next指针。

解决方案:
为了正确消除蛇尾,你需要在遍历蛇身部分时,对于蛇身中的每个节点进行检查,并判断它是否是蛇尾节点。如果是蛇尾节点,则进行消除操作。

以下是修复后的代码片段:


currents = &head;
then = head.next;
while (then != NULL)
{
    if (then->next == NULL && then->x == c && then->y == d)
    {
        gotoprint(then->x, then->y, " ");
        free(then);
        currents->next = NULL;
        break;
    }
    else
    {
        currents = then;
        then = then->next;
    }
}

问题2:第三节身体没有显示
在你的代码中,你在循环中遍历蛇身部分并将每个身体节点打印出来。然而,在添加新的身体节点时,你没有为新节点的next指针赋予正确的值,导致链表断开,第三节身体无法正确显示。

解决方案:
在添加新的身体节点时,你需要为新节点的next指针赋予正确的值,即指向前一个节点。这样就能保持链表的连续性。

以下是修复后的代码片段:

void add(void)
{
    snake* current = &head;
    while (current->next != NULL)
        current = current->next;
    int x = current->x, y = current->y;
    current->next = (snake*)malloc(sizeof(snake));
    current = current->next;
    current->x = x;
    current->y = y;
    current->next = NULL;
}


这样,当你在游戏中吃到食物并增加身体节点时,新节点将正确地连接到链表中,并且第三节身体将显示出来。