(C语言贪吃蛇)13.实现贪吃蛇四方向的移动

目录

前言

原代码预览

解决方法⚠️

运行效果

总结


前言

我们上节通过Linux线程实现了两个while(1)同时运行,这样就可以一边控制方向一遍刷新出贪吃蛇的身体节点了。本节我们就来实现贪吃蛇四方向的移动。

(此图片为最终效果)

原代码预览

我们之前的代码是通过moveSnake()函数实现贪吃蛇的移动的:

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

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

struct Snake * head = NULL;
struct Snake * tail = NULL;

int key;

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

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;    
}

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 printw("  ");
            }
            printw("\n");
        }
        if(hang == 19)
        {
            for(lie = 0;lie < 20;lie ++)
               {
                   printw("--");
               }
               printw("\n");
               printw("by beiweiqiuAC,%d\n",key);
        }
    }

}

void addNode()
{
    struct Snake * new = (struct Snake *)malloc(sizeof(struct Snake));
    new->hang = head->hang;
    new->lie = tail->lie+1;

    new->next = NULL;
    tail->next = new;
    tail = new;
}

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

    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);
}

void moveSnake()
{
    addNode();
    deleNode();

    if(tail ->hang == 0 || tail->lie == 0 || tail->hang == 20 || tail ->lie == 20)
    {
        initSnake();
    }
}

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

void* changeDir()
{
    while (1)
        {
            key = getch();
            switch (key)
            {
            case 0402:
                    printw("DOWN\n");
                    break;
            case 0403:
                    printw("UP\n");
                    break;
            case 0404:
                    printw("LEFT\n");
                    break;
            case 0405:
                    printw("RIGHT\n");
                    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;
}

那么我们详细看一下moveSnake()函数:

cpp 复制代码
void moveSnake()
{
    addNode();
    deleNode();

    if(tail ->hang == 0 || tail->lie == 0 || tail->hang == 20 || tail ->lie == 20)
    {
        initSnake();
    }
}

可以很明显的看出主要是由addNode()和deleNode()两个函数控制。

解决方法⚠️

那我们有没有办法使这两个函数更智能呢?

(新节点的行和列坐标要根据方向来确定)那么我们来定义出方向的全局变量 。

cpp 复制代码
#define UP    1
#define DOWN  2
#define LEFT  3
#define RIGHT 4
int dir;

并且我们在初始化贪吃蛇的时候加上初始方向(initsnake())。

下面为修改后的initSnake()函数

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

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

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

上文可以知道,我们显示贪吃蛇的节点,改变贪吃蛇的节点是通过addNode()和deleNode()两个函数,那么我们只需要在addNode()增加上下一节点位置的判断即可。

在贪吃蛇移动的过程中只有四种情况,上下左右,所以简单的switch()语句就可以满足我们的要求。

cpp 复制代码
void addNode()
{
    struct Snake * new = (struct Snake *)malloc(sizeof(struct Snake));
    
    new->next = NULL;

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

于此同时我们也需要修改changeDir()函数:

cpp 复制代码
void* changeDir()
{
    while (1)
        {
            key = getch();
            switch (key)
            {
            case 0402:
                    dir = DOWN;
                    break;
            case 0403:
                    dir = UP;
                    break;
            case 0404:
                    dir = LEFT;
                    break;
            case 0405:
                    dir = RIGHT;
                    break;
            }
        }
}

运行效果

该文件默认命名为snake11.c

打开终端输入以下指令编译该文件:

gcc snake11.c -lcurses

系统会默认生成一个名为"a.out"的可执行文件,输入以下指令执行该程序:

./a.out

运行效果一🌧️:

运行效果二🍇:

运行效果三✅:

总结

我们本节实现了贪吃蛇四方向移动,按住上下左右四个键就会做出相同的反馈,是我们想要的效果😘。

相关推荐
长天一色4 小时前
【C语言系统编程】【第三部分:网络编程】3.1 套接字编程(TCP/UDP基础)
c语言·网络·tcp/ip
丁丁Tinsley11176 小时前
数据结构——顺序表(基础代码题)
c语言·数据结构·算法
winddevil6 小时前
[rCore学习笔记 029] 动态内存分配器实现-以buddy_system_allocator源码为例
rust·嵌入式·rcore
GoppViper7 小时前
Linux 性能调优技巧
linux·运维·服务器
小叶学C++7 小时前
【Linux】Linux环境基础开发工具使用
linux
育种数据分析之放飞自我8 小时前
GWAS分析中显著位点如何注释基因:excel???
linux·算法·excel
Grayson_Zheng8 小时前
【解决方案】关于 UART 接收数据时丢失数据的解决办法——环形缓冲存储区
c语言·数据结构·stm32·单片机
小鹿( ﹡ˆoˆ﹡ )8 小时前
Python 并发新境界:探索 `multiprocessing` 模块的无限可能
linux·服务器·python
潜※者9 小时前
C语言 动态数据结构的C语言实现内存映像
c语言
Zfox_10 小时前
【Linux】进程地址空间、环境变量:从理论到实践(三)
java·linux·运维