当前位置: 首页 > news >正文

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

目录

前言

原代码预览

解决方法⚠️

运行效果

总结


前言

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

(此图片为最终效果) 

原代码预览

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

#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()函数:

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

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

解决方法⚠️

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

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

#define UP    1
#define DOWN  2
#define LEFT  3
#define RIGHT 4
int dir;

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

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

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()语句就可以满足我们的要求。

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()函数:

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 

运行效果一🌧️:

运行效果二🍇:

运行效果三✅: 

总结

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

 

相关文章:

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

目录 前言 原代码预览 解决方法⚠️ 运行效果 总结 前言 我们上节通过Linux线程实现了两个while(1)同时运行&#xff0c;这样就可以一边控制方向一遍刷新出贪吃蛇的身体节点了。本节我们就来实现贪吃蛇四方向的移动。 (此图片为最终效果) 原代码预览 我们之前的代码是通过…...

Spring Boot + MyBatis 项目中常用注解详解(万字长篇解读)

Spring Boot MyBatis 项目中常用注解详解 在现代Java开发中&#xff0c;Spring Boot和MyBatis是两大热门框架&#xff0c;广泛应用于构建高效、可维护的企业级应用。两者结合使用&#xff0c;可以充分发挥各自的优势&#xff0c;提高开发效率和代码质量。在这个过程中&#x…...

AWS Network Firewall -NAT网关配置只应许白名单域名出入站

1. 创建防火墙 选择防火墙的归属子网&#xff08;选择公有子网&#xff09; 2. 创建规则白名单域名放行 3. 绑定相关规则 继续往下拉 绑定非托管规则 4. 配置网络路由 相关规则 参考图 解释 防火墙的归属公有子网路由表规则机器实例的规则子网路由表规则nat网管路…...

【C语言系统编程】【第二部分:并发编程】2.3 实践与案例分析

2.3 实践与案例分析 2.3.1 案例分析&#xff1a;多线程文件搜索程序 本文中&#xff0c;我们将通过一个多线程文件搜索程序的案例&#xff0c;展示如何在实际项目中应用多线程编程技术&#xff0c;并具体介绍任务分解、线程创建、结果汇总及锁机制的应用。 2.3.1.1 任务分解…...

React -AppVarContext.Provider 提供者组件

AppVarContext.Provider 是一个 React 上下文提供者&#xff0c;通常用于在组件树中提供共享的状态或数据。下面将详细解释 AppVarContext.Provider 的作用和如何使用它。展示如何使用 AppVarContext.Provider 来管理全局状态 1. 什么是上下文&#xff08;Context&#xff09;…...

【Python】解密用户代理:使用 Python User Agents 库探索浏览器和设备信息

Python User Agents 是一个专为解析 User Agent 字符串而设计的 Python 库。它能够轻松识别访问设备的类型&#xff08;如移动设备、桌面设备或平板&#xff09;&#xff0c;并获取设备、浏览器、操作系统等详细信息。借助它&#xff0c;开发者可以更好地了解访问用户的设备属性…...

以串口接口为例介绍关于BSP底层架构开发的迭代过程

以串口接口为例介绍关于BSP底层架构开发的迭代过程 文章目录 以串口接口为例介绍关于BSP底层架构开发的迭代过程架构概述初代BSP二代BSP:三代BSP:四代BSP:架构概述 单片机开发有四个阶段: 阶段一:单一单片机的功能实现阶段 此阶段你开始熟悉STM32F1系列的单片机,并利用…...

Label-Studio ML利用yolov8模型实现自动标注

引言 Label Studio ML 后端是一个 SDK&#xff0c;用于包装您的机器学习代码并将其转换为 Web 服务器。Web 服务器可以连接到正在运行的 Label Studio 实例&#xff0c;以自动执行标记任务。我们提供了一个示例模型库&#xff0c;您可以在自己的工作流程中使用这些模型&#x…...

【PostgreSQL】实战篇——用户管理、角色和权限控制的高级用法及技巧

数据库中用户管理、角色和权限控制不仅仅是基础的安全措施&#xff0c;更是实现复杂应用需求和优化数据库性能的重要手段。 通过深入理解这些概念&#xff0c;数据库管理员可以更有效地管理用户访问、确保数据安全&#xff0c;并优化系统性能。以下是对这些概念的详细介绍以及…...

Leetcode: 0011-0020题速览

Leetcode: 0011-0020题速览 本文材料来自于LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer&#xff08;第 2 版&#xff09;》、《程序员面试金典&#xff08;第 6 版&#xff09;》题解 遵从开源协议为知识共享 版权归属-相同方式…...

Hive数仓操作(七)

一、 Hive动态分区表 1. 动态分区与静态分区的区别 分区定义&#xff1a; 静态分区&#xff1a;在插入数据时&#xff0c;需要手动指定分区字段的值。动态分区&#xff1a;分区字段的值是根据数据中的某个字段自动生成的&#xff0c;用户只需指定分区字段的类型。 数据加载方…...

Redis进阶篇 - 缓存穿透、缓存击穿、缓存雪崩问题及其解决方案

文章目录 1 文章概述2 缓存穿透2.1 什么是缓存穿透&#xff1f;2.2 缓存穿透的解决方法2.2.1 做好参数校验2.2.2 缓存无效Key2.2.3 使用布隆过滤器2.2.4 接口限流 3 缓存击穿3.1 什么是缓存击穿&#xff1f;3.2 缓存击穿的解决方法3.2.1 调整热点数据过期时间3.2.2 热点数据预热…...

一天认识一个硬件之电源

无论是台式机还是笔记本&#xff0c;都离不开电源&#xff0c;台式机和笔记本电脑的电源都承担着将交流电转换为直流电&#xff0c;并为电脑内部各个部件提供稳定电力供应的重要任务。今天就来分享一下台式机和笔记本的电源区别 设计和功率 台式机电源&#xff1a;设计为内置…...

关于BSV区块链覆盖网络的常见问题解答(上篇)

​​发表时间&#xff1a;2024年9月20日 在BSV区块链上的覆盖网络服务为寻求可扩展、安全、高效交易处理解决方案的开发者和企业家开辟了新的视野。 作为开创性的曼达拉升级的一部分&#xff0c;覆盖网络服务提供了一个强大的框架&#xff0c;用于管理特定类型的交易和数据访问…...

VUE 开发——Node.js学习(一)

一、认识Node.js Node.js是一个跨平台JavaScript运行环境&#xff0c;使开发者可以搭建服务器端的JavaScript应用程序 使用Node.js编写服务器端程序——编写数据接口、前端工程化&#xff1b; Node.js环境没有BOM和DOM&#xff1b; Node.js安装&#xff1a;下载node-v16.19…...

角膜移植难题现,传统方式缺陷显,创新水凝胶破局

大家好&#xff01;今天来了解一篇天然聚合物衍生光固化生物粘附水凝胶研究——《Natural polymer-derived photocurable bioadhesive hydrogels for sutureless keratoplasty》发表于《Bioactive Materials》。本文介绍了一种用于无缝合角膜移植术的天然聚合物衍生光固化生物粘…...

探索Spring Boot:实现“衣依”服装电商平台

1系统概述 1.1 研究背景 如今互联网高速发展&#xff0c;网络遍布全球&#xff0c;通过互联网发布的消息能快而方便的传播到世界每个角落&#xff0c;并且互联网上能传播的信息也很广&#xff0c;比如文字、图片、声音、视频等。从而&#xff0c;这种种好处使得互联网成了信息传…...

使用 cron 来设置定时任务

使用 cron 来设置定时任务&#xff0c;以便定期运行这个脚本。 在 Linux 系统中设置定时任务的步骤&#xff1a; 1. 编辑 cron 任务 打开终端并输入以下命令以编辑 crontab 文件&#xff1a; crontab -e2. 设置每天 8 点运行脚本 在 crontab 文件的最后&#xff0c;添加以下…...

C# Blazor Server 调用海康H5Player播放摄像头画面

目标 调用海康综合安防平台api&#xff0c;通过摄像头的cameraIndexCode调用【获取监控点预览取流URLv2】api&#xff0c;得到websocket 的url&#xff0c;然后在blazor server中使用htplayer.js播放摄像头实时画面。 步骤 根据摄像头名字&#xff0c;调用【查询监控点列表v2…...

CSS实现服务卡片

CSS实现服务卡片 效果展示 CSS 知识点 回顾整体CSS知识点灵活运用CSS知识点 页面整体布局 <div class"container"><div class"card"><div class"box"><div class"icon"><ion-icon name"color-pal…...

问:如何判断系统环境是大端/小端存储?

大端存储&#xff08;Big Endian&#xff09;和小端存储&#xff08;Little Endian&#xff09;是两种不同的字节序&#xff08;即字节顺序&#xff09;规则&#xff0c;用于在计算机中存储和表示多字节数据类型&#xff08;例如整数&#xff09;。 概念解释 大端存储&#x…...

使用NumPy进行线性代数的快速指南

介绍 NumPy 是 Python 中用于数值计算的基础包。它提供了处理数组和矩阵的高效操作&#xff0c;这对于数据分析和科学计算至关重要。在本指南中&#xff0c;我们将探讨 NumPy 中可用的一些基本线性代数操作&#xff0c;展示如何通过运算符重载和内置函数执行这些操作。 元素级…...

uni-app之旅-day02-分类页面

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言创建cate分支4.1 渲染分类页面的基本结构4.2 获取分类数据4.3 动态渲染左侧的一级分类列表4.4 动态渲染右侧的二级分类列表4.5 动态渲染右侧的三级分类列表4.6 …...

鸿蒙harmonyos next flutter通信之BasicMessageChannel获取app版本号

本文将通过BasicMessageChannel获取app版本号&#xff0c;以此来演练BasicMessageChannel用法。 建立channel flutter代码&#xff1a; //建立通道 BasicMessageChannel basicMessageChannel BasicMessageChannel("com.xmg.basicMessageChannel",StringCodec());…...

【文件增量备份系统】MySQL百万量级数据量分页查询性能优化

&#x1f3af; 导读&#xff1a;本文针对大数据量下的分页查询性能问题进行了深入探讨与优化&#xff0c;最初查询耗时长达12秒&#xff0c;通过避免全表计数及利用缓存保存总数的方式显著提升了浅分页查询速度。面对深分页时依然存在的延迟&#xff0c;采用先查询倒数第N条记录…...

音视频入门基础:FLV专题(12)——FFmpeg源码中,解析DOUBLE类型的ScriptDataValue的实现

一、引言 从《音视频入门基础&#xff1a;FLV专题&#xff08;9&#xff09;——Script Tag简介》中可以知道&#xff0c;根据《video_file_format_spec_v10_1.pdf》第80到81页&#xff0c;SCRIPTDATAVALUE类型由一个8位&#xff08;1字节&#xff09;的Type和一个ScriptDataV…...

【AI知识点】分层可导航小世界网络算法 HNSW(Hierarchical Navigable Small World)

HNSW&#xff08;Hierarchical Navigable Small World&#xff09;分层可导航小世界网络算法 是一种高效的近似最近邻搜索&#xff08;Approximate Nearest Neighbor Search, ANN&#xff09; 算法&#xff0c;特别适用于大规模、高维数据集的相似性检索。HNSW 基于小世界网络&…...

ubuntu图形界面右上角网络图标找回解决办法

问题现象&#xff1a; ubuntu图形界面右上角网络图标消失了&#xff0c;不方便联网&#xff1a; 正常应该是下图&#xff1a; 网络寻找解决方案&#xff0c;问题未解决&#xff0c;对于某些场景可能有用&#xff0c;引用过来&#xff1a; 参考方案 Ubuntu虚拟机没有网络图标或…...

maven安装本地jar包到本地仓库

有时候我们需要把本地的 jar 包 install 到本地的 maven 仓库&#xff0c;这时就需要手动install依赖项。例如&#xff0c;把下面的 zhdx-license-1.0.jar 安装到本地 maven 仓库的操作如下&#xff1a; <dependency><groupId>com.zhdx</groupId><artifa…...

1panel申请https/ssl证书自动续期

参考教程 https://hin.cool/posts/sslfor1panel.html #Acme 账户 #1panel.腾讯云dns账号 这里有一步不需要参考,腾讯云dns账号,就是子帐号授权 直接控制台搜索 访问管理 创建用户 授权搜索dns,选择第一个 点击用户名,去掉AdministratorAccess权限 5.点击api密钥生成即可…...