(C语言贪吃蛇)16.贪吃蛇食物位置随机(完结撒花)

目录

前言

修改方向

修改内容

效果展示

两个新的问题🙋

1.问题1

2.问题2

代码如下:


前言

我们上一节实现了贪吃蛇吃食物身体节点变长,但是食物的刷新位置不是随机的,并且初始化几次后食物就刷不见了,本节我们就来解决这个问题。

修改方向

我们这个地图格子是20X20,随机数函数不能有界限,那么我们思考方向就是随机数然后对20进行取余,那么最终得到的数字一定是在区间内的。

修改内容

cpp 复制代码
void initfood()
{
    int x = rand()%20;
    int y = rand()%20;

    food.hang = x;
    food.lie = y;
}

我们之前地图下面还会打印出"by beiweiqiuAC",我们修改一下,可以打印出食物的行和列坐标。

cpp 复制代码
void gamePic()
{
    int hang;
    int lie;

    move(0,0);

    for(hang = 0;hang < 20;hang ++)
    {

        if(hang == 0)
        {
            for(lie = 0;lie < 20;lie ++)
               {
                   printw("--");
               }
            printw("\n");
        }
        if(hang >= 0 && hang <= 19)
        {
            for(lie = 0;lie <= 20;lie ++)
            {
                if(lie == 0 || lie == 20) printw("|");
                else if(hasSnakeNode(hang,lie)) printw("[]");
                else if(hasfood(hang,lie)) printw("##");
                else printw("  ");
            }
            printw("\n");
        }
        if(hang == 19)
        {
            for(lie = 0;lie < 20;lie ++)
               {
                   printw("--");
               }
               printw("\n");
               printw("by beiweiqiuAC,food.hang=%d,food.lie=%d\n",food.hang,food.lie);
        }
    }

}

效果展示

两个新的问题🙋

我们发现如果食物在地图的最上方的我们的贪吃蛇是吃不到,我们尝试解决这个问题,并且贪吃蛇可以从自己的身体中间穿过去,这很明显是不符合逻辑的,所以我们来优化这两个问题,贪吃蛇这个项目就完结了。

1.问题1

食物在地图的最上方,贪吃蛇就会直接撞墙死掉,原因是tail的行第一行就是0,所以只有最上面那一行不行,所以我们只需要修改让贪吃蛇在第0行的时候不死就行了:

cpp 复制代码
void moveSnake()
{
    addNode();
    if(hasfood(tail->hang,tail->lie))
    {
        initfood();
    }else{
        deleNode();
    }
    

    if(tail ->hang < 0 || tail->lie == 0 || tail->hang == 20 || tail ->lie == 20)
    {
        initSnake();
    }
}
2.问题2

贪吃蛇在运行的过程当中,贪吃蛇撞到自己的身体不会死掉,所以我们要优化这个问题,其实非常简单,我们只需要判断尾巴节点和身体节点是否重合即可。

cpp 复制代码
int ifSnakeDie()
{
    struct Snake *p;
    p = head;
    if(tail ->hang < 0 || tail->lie == 0 || tail->hang == 20 || tail ->lie == 20)
    {
        return 1;
    }
    while(p ->next != NULL){
        if(p->hang == tail->hang && p -> lie == tail->lie){
            return 1;
        }
        p = p -> next;
    }
    return 0;
}

通过遍历链表的位置再来与尾节点的位置做比较,如果相同就死掉,此时游戏的功能就齐全了。

代码如下:

cpp 复制代码
#include <curses.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#define UP    1
#define DOWN  -1
#define LEFT  2
#define RIGHT -2

struct Snake
{
    int hang;
    int lie;
    struct Snake * next;
};

struct Snake * head = NULL;
struct Snake * tail = NULL;
int key;
int dir;

struct Snake food;

void initfood()
{
    int x = rand()%20;
    int y = rand()%20;

    food.hang = x;
    food.lie = y;
}

void initNcurse()
{
    initscr();
    keypad(stdscr,1);
    noecho();
}

int hasSnakeNode(int i,int j)
{
    struct Snake * p;
    p = head;
    while(p != NULL)
    {
        if(p->hang == i && p->lie == j)
        {
            return 1;
        }
        p = p -> next;
    }
    return 0;    
}

int hasfood(int i,int j)
{

    if(food.hang == i && food.lie == j) return 1;
    return 0;    
}

void gamePic()
{
    int hang;
    int lie;

    move(0,0);

    for(hang = 0;hang < 20;hang ++)
    {

        if(hang == 0)
        {
            for(lie = 0;lie < 20;lie ++)
               {
                   printw("--");
               }
            printw("\n");
        }
        if(hang >= 0 && hang <= 19)
        {
            for(lie = 0;lie <= 20;lie ++)
            {
                if(lie == 0 || lie == 20) printw("|");
                else if(hasSnakeNode(hang,lie)) printw("[]");
                else if(hasfood(hang,lie)) printw("##");
                else printw("  ");
            }
            printw("\n");
        }
        if(hang == 19)
        {
            for(lie = 0;lie < 20;lie ++)
               {
                   printw("--");
               }
               printw("\n");
               printw("by beiweiqiuAC,food.hang=%d,food.lie=%d\n",food.hang,food.lie);
        }
    }

}

void addNode()
{
    struct Snake * new = (struct Snake *)malloc(sizeof(struct Snake));
    
    new->next = NULL;

    switch(dir)
    {
        case UP:
            new->hang = tail->hang - 1;
            new->lie = tail->lie;
            break;
        case DOWN:
            new->hang = tail->hang + 1;
            new->lie = tail->lie;
            break;
        case LEFT:
            new->hang = tail->hang;
            new->lie = tail->lie - 1;
            break;
        case RIGHT:
            new->hang = tail->hang;
            new->lie = tail->lie + 1;
            break;
    }
    tail->next = new;
    tail = new;
}

void initSnake(){
    struct Snake * p;
    dir = RIGHT;
    while(head != NULL)
    {
        p = head;
        head = head -> next;
        free(p);
    }

    initfood();

    head = (struct Snake *)malloc(sizeof(struct Snake));
    head->hang = 1;
    head->lie = 1;
    head->next = NULL;

    tail = head;
    addNode();
    addNode();
    addNode();
    addNode();
}

void deleNode()
{
 // struct Snake * p;
 // p = head;
    head = head ->next;
 // free(p);
}

int ifSnakeDie()
{
    struct Snake *p;
    p = head;
    if(tail ->hang < 0 || tail->lie == 0 || tail->hang == 20 || tail ->lie == 20)
    {
        return 1;
    }
    while(p ->next != NULL){
        if(p->hang == tail->hang && p -> lie == tail->lie){
            return 1;
        }
        p = p -> next;
    }
    return 0;
}

void moveSnake()
{
    addNode();
    if(hasfood(tail->hang,tail->lie))
    {
        initfood();
    }else{
        deleNode();
    }
    

    if(ifSnakeDie())
    {
        initSnake();
    }
}

void* refreshJieMian()
{
    while(1)
        {
            moveSnake();
            gamePic();
            refresh();
            usleep(100000);
        }
}

void turn(int direction)
{
    
    if(abs(dir) != abs(direction))
    {
        dir = direction;
    }
}

void* changeDir()
{
    while (1)
        {
            key = getch();
            switch (key)
            {
            case 0402:
                    turn(DOWN);
                    break;
            case 0403:
                    turn(UP);
                    break;
            case 0404:
                    turn(LEFT);
                    break;
            case 0405:
                    turn(RIGHT);
                    break;
            }
        }
}


int main()
{
    pthread_t t1;
    pthread_t t2;
    
    initNcurse();

    initSnake();

    gamePic();
    pthread_create( &t1, NULL,refreshJieMian, NULL);
    pthread_create( &t2, NULL, changeDir, NULL);
    
    while(1);
    getch();//防止程序退出
    endwin();
    return 0;
}

效果展示:

C语言贪吃蛇效果展示

此时,我们的C语言贪吃蛇项目就已经完成了「完结散花🌹🌹🌹」

相关推荐
转世成为计算机大神18 分钟前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
搬砖的小码农_Sky19 分钟前
C语言:数组
c语言·数据结构
宅小海37 分钟前
scala String
大数据·开发语言·scala
朝九晚五ฺ38 分钟前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
qq_3273427339 分钟前
Java实现离线身份证号码OCR识别
java·开发语言
锅包肉的九珍40 分钟前
Scala的Array数组
开发语言·后端·scala
自由的dream41 分钟前
Linux的桌面
linux
心仪悦悦44 分钟前
Scala的Array(2)
开发语言·后端·scala
yqcoder1 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
xiaozhiwise1 小时前
Makefile 之 自动化变量
linux