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

相关推荐
qq_5432485215 分钟前
Linux网络配置与测试
linux·运维·网络
钡铼技术物联网关16 分钟前
下一代楼宇自控的中枢神经:ARM终端的生态
大数据·linux·人工智能
依旧风轻32 分钟前
深入理解 rsync daemon 模式(守护进程)
linux·ios·rsync·daemon·sqi
憋废话_开码38 分钟前
phpstrom 配置调试 php 项目全流程,弄清一些概念
开发语言·php
ou.cs39 分钟前
c# 企业级ADB通信示例
开发语言·adb·c#
孙桂月1 小时前
Python爬取数据(二)
开发语言·python
小峰编程1 小时前
谈Linux之磁盘管理——万字详解
linux·运维·服务器·经验分享·笔记·centos·运维开发
好奇的菜鸟2 小时前
Scoop + Kotlin 极简开发环境搭建指南
android·开发语言·kotlin
滴答滴答嗒嗒滴2 小时前
Python 小练习系列 | Vol.14:掌握偏函数 partial,用函数更丝滑!
开发语言·python
leluckys2 小时前
swift-oc和swift block和代理
开发语言·ios·swift