(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语言贪吃蛇项目就已经完成了「完结散花🌹🌹🌹」

相关推荐
gywl39 分钟前
openEuler VM虚拟机操作(期末考试)
linux·服务器·网络·windows·http·centos
轻口味43 分钟前
命名空间与模块化概述
开发语言·前端·javascript
晓纪同学2 小时前
QT-简单视觉框架代码
开发语言·qt
威桑2 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
飞飞-躺着更舒服2 小时前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
明月看潮生2 小时前
青少年编程与数学 02-004 Go语言Web编程 16课题、并发编程
开发语言·青少年编程·并发编程·编程与数学·goweb
明月看潮生2 小时前
青少年编程与数学 02-004 Go语言Web编程 17课题、静态文件
开发语言·青少年编程·编程与数学·goweb
Java Fans2 小时前
C# 中串口读取问题及解决方案
开发语言·c#
日记跟新中2 小时前
Ubuntu20.04 修改root密码
linux·运维·服务器
盛派网络小助手2 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#