• SWUST 2021 —— 数据结构课程设计 贪吃蛇


    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    #include <conio.h>
    #include <time.h>
    const int Width = 50;
    const int Height = 25;
    int Speed = 200;//全局-记录速度 
    int Point;//全局-记录分数 
    int Level = 1;
    int Count = 1;
    int Number = 1;
    typedef struct Snake {
        int x, y;
        Snake* prev;
        Snake* next;
    }Snake, * Snakee;
    typedef struct Food {
        int x, y;
        bool isEat;
    }Food;
    //获取蛇坐标 
    void gotoxySnake(Snakee snake) {
        COORD position = { snake->x,snake->y };
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), position);
    }
    //获取实体坐标
    void gotoxyEntity(int x, int y) {
        COORD position = { x,y };
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), position);
    }
    Snakee snake_move(Snakee snake, int dir, Food& food);
    void snake_grow(Snakee snake, int x, int y);
    void free_snake(Snakee snake);
    bool snake_die_itself(Snakee snake);
    bool snake_die_edge(int x, int y);
    bool snake_eat(int s_x, int s_y, int f_x, int f_y);
    int snake_get_dir(int old_dir);
    Snakee init_snake();
    void generate_food(Food& food, Snakee* snake);
    bool food_is_eat(Food& food, Snakee* snake);
    void level_add();
    void speed_add();
    void init_game(Snakee snake, Food& food);
    int main() {
        HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_CURSOR_INFO CursorInfo;
        GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息
        CursorInfo.bVisible = false; //隐藏控制台光标
        SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态
        Snakee snake;
        Food food;
        snake = init_snake();
        int new_dir = 75;//向左
        init_game(snake, food);
        while (true) {
            if (_kbhit()) {
                new_dir = snake_get_dir(new_dir);
            }
            if (snake) {
                snake = snake_move(snake, new_dir, food);
            }
            if (food.isEat == true) {
                generate_food(food, &snake);
            }
        }
    }
    void init_game(Snakee snake, Food& food) {
    
        Snakee p = snake;
        do {
            gotoxySnake(p), printf("O");
            p = p->next;
        } while (p != snake);
        gotoxyEntity(Width, Height / 4), printf("  Point:  %d", Point);
        gotoxyEntity(Width, Height / 4 + Height / 8), printf("  Speed:  %d", Speed);
        gotoxyEntity(Width, (Height / 4) - Height / 8), printf("  Level:  %d", Level);
        gotoxyEntity(Width + 20, Height), printf("By 5121095644 周麟志");
        gotoxyEntity(Width + 20, Height/3), printf(" 本人博客园  ");
        gotoxyEntity(Width + 20, (Height/2)), printf("https://www.cnblogs.com/lightWh1te/");
        for (int i = Width; i < Width + Width / 3; i++) {
            gotoxyEntity(i, Height / 2), printf("*");
            gotoxyEntity(i, 1), printf("*");
            gotoxyEntity(i, Height), printf("*");
        }
        for (int i = 1; i <= Width; i++) {
            gotoxyEntity(i, 1), printf("*");
            gotoxyEntity(i, Height), printf("*");
        }
        for (int i = 1; i <= Height; i++) {
            gotoxyEntity(1, i), printf("*");
            gotoxyEntity(Width, i), printf("*");
            gotoxyEntity(Width + Width / 3, i), printf("*");
        }
        food.isEat = false;
        food.x = 10;
        food.y = 10;
        gotoxyEntity(food.x, food.y), printf("#");
    }
    void generate_food(Food& food, Snakee* snake) {
        srand(time(NULL));
        bool generate = true;
        if (generate == true) {
            generate = false;
            food.x = (rand() % (Width - 2 - 5 + 1)) + 5;
            food.y = (rand() % (Height - 2 - 5 + 1)) + 5;
            if (food_is_eat(food, snake)) {
                generate = true;
            }
        }
        food.isEat = false;
        gotoxyEntity(food.x, food.y);
        printf("#");
    }
    bool food_is_eat(Food& food, Snakee* snake) {
        Snakee p = *snake;//这里获得了一级指针
        food.isEat = true;
        if (food.x == p->x && food.y == p->y) {
            return true;
        }
        else
            return false;
    }
    void snake_grow(Snakee snake, int x, int y) {
        Snakee head = (Snakee)malloc(sizeof(Snake));
        head->prev = snake->prev;
        head->next = snake;
        head->x = x;
        head->y = y;
        snake->prev->next = head;
        snake->prev = head;
    }
    Snakee init_snake() {
        Snakee head = (Snakee)malloc(sizeof(Snake));
        head->x = 36;
        head->y = 5;
        head->next = head;//双向循环链表初始化 
        head->prev = head;
        for (int i = 36; i < 40; i++) {
            snake_grow(head, i, 5);
        }
        return head;
    }
    int snake_get_dir(int old_dir) {
        int new_dir = old_dir;
        if (_kbhit()) {
            _getch();
            new_dir = _getch();//第二次getch才是实际字符
            if (abs(new_dir - old_dir == 2) || abs(new_dir - old_dir) == 8) {
                new_dir = old_dir;
            }
        }
        return new_dir;
    }
    Snakee snake_move(Snakee snake, int dir, Food& food) {
        Snakee head;
        head = (Snakee)malloc(sizeof(Snake));
        head->prev = snake->prev;
        head->next = snake;
        head->x = snake->x;
        head->y = snake->y;
        snake->prev->next = head;
        snake->prev = head;
        Snakee p = head->prev;
        int tail_x = p->x;
        int tail_y = p->y;
        gotoxySnake(p);
        printf(" ");
        p->prev->next = p->next;
        p->next->prev = p->prev;
        free(p);
        int new_dir = snake_get_dir(dir);
        if (dir) {
            switch (new_dir)
            {
            case 72://
                head->y--;
                break;
            case 77://
                head->x++;
                break;
            case 75://
                head->x--;
                break;
            case 80://
                head->y++;
                break;
            default:
                break;
            }
        }
    
        if (snake_die_edge(head->x, head->y) == true || snake_die_itself(snake) == true) {
            system("cls");
            gotoxyEntity((Width + 10) / 2, (Height) / 2);
            printf("Game Over
    ");
            free_snake(snake);
            return 0;
        }
        if (snake_eat(head->x, head->y, food.x, food.y) == true) {
            food.isEat = true;
            Snakee tail = (Snakee)malloc(sizeof(Snake));
            tail->prev = head->prev;
            tail->next = head;
            tail->x = tail_x;
            tail->y = tail_y;
            head->prev->next = tail;
            head->prev = tail;
        }
        gotoxySnake(head), printf("O");
        Sleep(Speed);
        return head;
    }
    bool snake_die_edge(int x, int y) {
        if (x == 1 || x == Width || y == 1 || y == Height) {
            return true;
        }
        else
            return false;
    }
    bool snake_die_itself(Snakee snake) {
        Snakee t;
        t = snake->next->next;
        do {
            if (snake->x == t->x && snake->y == t->y) {
                return true;
            }
            t = t->next;
        } while (t != snake);
        return false;
    }
    bool snake_eat(int s_x, int s_y, int f_x, int f_y) {
    
        if (Number % 3 == 0) {
            Level++;
            Number = 1;
            gotoxyEntity(Width, (Height / 4) - Height / 8), printf("  Level:  %d", Level);
            speed_add();
        }
        if (s_x == f_x && s_y == f_y) {
            Count++;
            Number++;
            Point += 10;
            gotoxyEntity(Width, Height / 4), printf("  Point:  %d", Point);
            return true;
        }
        else
            return false;
    }
    void free_snake(Snakee snake) 
    {
        Snakee p = snake;
        do {
            Snakee t = p;
            p = p->next;
            free(t);
        } while (p != snake);
    }
    void speed_add() 
    {//速度逻辑
        Speed -= 20;
        gotoxyEntity(Width, Height / 4 + Height / 8), printf("  Speed:  %d", Speed);
    }
    View Code

    V1.0 

    • 建模:程序界面是一个二维平面图

    • 蛇:蛇的身体可以看作是链表的节点,当蛇吃到食物时,就增加一节链表长度++;

    • 食物:随机生成

    • 蛇的移动:取得上下左右键的ASCII码的键值,通过switch语句响应相应的键值对,实现蛇的方向获取

    • 闪烁问题:通过局部打印空格与蛇身节点的移动,来实现局部更新可避免全局绘制造成的闪烁问题,也能提高性能

    • 获取实体:获取游戏一个实体的坐标需要得到当前窗口的句柄,并重写gotoxy()函数,在绘制时也要注意绘制重合的问题

    • 结构:把相应的功能模块化,结构化,封装成一个个函数,像蛇逻辑有自噬死亡,撞墙死亡,吃食,变长等

    • 交互:在相应的自定义逻辑函数中调用各自的函数,主函数则主要写下简短的循环框架,直到游戏结束

    • Windows窗口
  • 相关阅读:
    二分查找
    django 中间件
    logging 模块
    linux ssh keys
    spark(一) build
    hadoop中遇到的问题。
    算法----字符串拷贝
    phpmailer 实现发送邮件
    thinkphp操作数据库
    thinkphp 使用过程中遇到的一个小函数
  • 原文地址:https://www.cnblogs.com/lightWh1te/p/14743819.html
Copyright © 2020-2023  润新知