Linux下C语言实现贪吃蛇
简单记录下贪吃蛇小游戏。
以下是源码:
1 #include <curses.h>
2 #include <stdlib.h>
3 #include <pthread.h>
4 #define UP 1
5 #define DOWN -1
6 #define LEFT 2
7 #define RIGHT -2
8
9 /*蛇和食物的结构体*/
10 struct Snake
11 {
12 int hang;
13 int lie;
14 struct Snake *next;
15 };
16
17 struct Snake *head = NULL; //链表头
18 struct Snake *tail = NULL; //链表尾
19 struct Snake food; //食物
20 int key; //记录键盘输入值
21 int dir; //记录输入的方向键
22
23 /*输入横坐标和纵坐标值,判断是否存在蛇的链表节点*/
24 int hasSnakeNode(int i,int j)
25 {
26 struct Snake *p; //临时变量,用于记录蛇的链表表头
27 p = head;
28
29 while(p != NULL) //当链表头不为空时,进入循环
30 {
31 if(p->hang == i && p->lie == j)
32 {
33 return 1; //输入的行纵坐标存在于蛇的链表中时返回1
34 }
35 p = p->next; //链表头指向下一个节点
36 }
37 return 0; //输入的横纵坐标不存在蛇的链表中时返回0
38 }
39
40 /*食物初始化*/
41 void initFoodnode()
42 {
43 int x; //定义横坐标临时变量
44 int y; //定义纵坐标临时变量
45 x = rand()%20; //在[0-20]范围内随机获取横坐标值
46 y = rand()%20; //在[0-20]范围内随机获取纵坐标值
47
48 if(y == 0)
49 {
50 y = rand()%20; //当纵坐标取值为0时,重新取值
51 }
52
53 food.hang = x; //将前面获取到的横坐标赋值为食物的横坐标
54 food.lie = y; //将前面获取到的纵坐标复制为食物的纵坐标
55 }
56
57 /*输入横纵坐标判断是否存在食物,用于地图刷新*/
58 int hasFoodnode(int i,int j)
59 {
60 if((food.hang == i)&&(food.lie == j))
61 {
62 return 1; //当输入横纵坐标为食物的横纵坐标时,返回1
63 }
64 return 0; //当输入横纵坐标不是食物的横纵坐标时,返回0
65 }
66
67 /*地图绘制*/
68 void gamePic()
69 {
70 int hang,lie; //行列临时变量
71 move(0,0); //每次界面刷新都将界面光标移动到(0,0)的位置
72 for(hang=0;hang<20;hang++) //历遍行
73 {
74 if(hang==0)
75 {
76 for(lie=0;lie<20;lie++)
77 {
78 printw("--"); //判断为第0行时,绘制‘--’边界符号
79 }
80 printw("\n");
81 }
82 if(hang>=0 || hang<=19)
83 {
84 for(lie=0;lie<=20;lie++)
85 {
86 if(lie==0 || lie==20)
87 {
88 printw("|");//第0和19列绘制‘|’边界符号
89 }
90 else if(hasSnakeNode(hang,lie))
91 {
92 printw("[]");//行列值满足蛇的节点坐标时,绘制‘[]’符号
93 }
94 else if(hasFoodnode(hang,lie))
95 {
96 printw("##");//行列之满足食物节点坐标时,绘制‘##’符号
97 }
98 else
99 {
100 printw(" ");//地图上空闲位置绘制‘ ’空格符号
101 }
102 }
103 printw("\n"); //每绘制完一行,该处添加一处换行符
104 }
105 if(hang==19)
106 {
107 for(lie=0;lie<20;lie++)
108 {
109 printw("--"); //判断为第19行时,绘制‘--’边界符号
110 }
111 printw("\n");
112 printw("By chenguanxiong\n");
113 printw("%d",key);
114 }
115 }
116 }
117
118 /*添加蛇身节点*/
119 void addNode()
120 {
121 struct Snake *new; //新节点变量
122 new = (struct Snake *)malloc(sizeof(struct Snake));//为新节点开辟内存空间
123
124 switch(dir) //方向键判断
125 {
126 case UP:
127 new->hang = tail->hang - 1; //向上,行减1,上移
128 new->lie = tail->lie; //列保持
129 break;
130 case DOWN:
131 new->hang = tail->hang + 1; //向下,行加1,下移
132 new->lie = tail->lie; //列保持不变
133 break;
134 case LEFT:
135 new->hang = tail->hang; //行保持不变
136 new->lie = tail->lie - 1; //向左,列减1,左移
137 break;
138 case RIGHT:
139 new->hang = tail->hang; //行保持不变
140 new->lie = tail->lie + 1; //向右,列加1,右移
141 break;
142 default:
143 break;
144
145 }
146
147 new->next = NULL; //新节点的下一个节点指向为NULL
148 tail->next = new; //尾部的下一个节点指向新节点
149 tail = new; //新节点复制给尾部节点
150 }
151
152 /*初始化蛇*/
153 void initSnake()
154 {
155 struct Snake *p; //临时变量,指向蛇的链表头
156 dir = RIGHT; //运动方向初始化为向右
157 while(head != NULL) //当链表头不为空时进入,用于释放蛇当前的链表占用内存空间
158 {
159 p = head; //p指向链表头
160 head = head->next; //链表头指向下一个节点
161 free(p); //释放链表头内存
162 }
163
164 initFoodnode(); //初始化食物
165 head = (struct Snake *)malloc(sizeof(struct Snake)); //为链表头开辟新的内存空间
166 head->hang = 2; //链表头行初始值为2
167 head->lie = 2; //链表头列初始值为2
168 head->next = NULL; //链表头的下一个节点指向为NULL
169 tail = head; //链表尾指向链表头
170
171 addNode(); //为链表添加新节点
172 addNode();
173 addNode();
174 addNode();
175 }
176
177 /*节点删除*/
178 void deleteNode()
179 {
180 struct Snake *p; //创建临时节点
181 p = head; //节点指向链表头
182 head = head->next; //链表头指向下一个节点
183 free(p); //释放p的空间(原链表头)
184 }
185
186 /*判断蛇是否越界或自残*/
187 int ifSnakedie()
188 {
189 struct Snake *p; //创建临时节点
190 p = head; //指向链表头
191
192 if(tail->hang<0 | tail->lie==0 | tail->hang==20 | tail->lie==20)
193 {
194 return 1; //当蛇链表的尾部坐标等于边界值时,返回1
195 }
196
197 while(p->next != NULL)
198 {
199 if((p->hang==tail->hang)&&(p->lie==tail->lie))
200 {
201 return 1; //当蛇链表其它的节点与尾部节点坐标相同,返回1
202 }
203 p = p->next;
204 }
205
206 return 0; //无越界,无自残,返回0
207 }
208
209 /*蛇移动*/
210 void moveSnake()
211 {
212 addNode(); //添加新节点
213 if(hasFoodnode(tail->hang,tail->lie))
214 {
215 initFoodnode(); //当蛇链表尾节点坐标值和食物坐标值一样,刷新食物位置
216 }
217 else
218 {
219 deleteNode(); //否则,删除蛇链表中的头节点
220 }
221
222 if(ifSnakedie())
223 {
224 initSnake(); //如果满足越界或者自残条件,重新初始化蛇链表
225 }
226 }
227
228 /*地图界面刷新线程函数*/
229 void* refreshjiemian()
230 {
231 while(1)
232 {
233 moveSnake(); //蛇链表移动
234 gamePic(); //地图刷新
235 refresh(); //执行刷新
236 usleep(150000); //线程休眠函数,150ms
237 }
238 }
239
240 /*方向函数*/
241 void turn(int direction)
242 {
243 if(abs(dir) != abs(direction))
244 {
245 dir = direction; //方向取绝对值比较,当左右运动时只有上下输入才生效
246 }
247 }
248
249 /*键盘方向输入监测线程函数*/
250 void* changeDir()
251 {
252 while(1)
253 {
254 key = getch(); //获取键盘输入
255 switch(key)
256 {
257 case KEY_UP:
258 turn(UP); //上
259 break;
260 case KEY_DOWN:
261 turn(DOWN); //下
262 break;
263 case KEY_LEFT:
264 turn(LEFT); //左
265 break;
266 case KEY_RIGHT:
267 turn(RIGHT); //右
268 break;
269 default:
270 break;
271 }
272 }
273 }
274
275 int main()
276 {
277 pthread_t t1; //创建线程变量t1
278 pthread_t t2; //创建线程变量t2
279
280 initscr(); //Ncurses初始化
281 keypad(stdscr,1); //在std中接受键盘的功能键
282 noecho(); //控制键盘输入进来的字符
283
284 initSnake(); //初始化蛇列表
285 gamePic(); //地图初始化
286
287 pthread_create(&t1,NULL,refreshjiemian,NULL); //创建界面刷新线程
288 pthread_create(&t2,NULL,changeDir,NULL); //创建键盘方向输入监测线程
289
290 while(1);
291
292 getch();
293 endwin();
294
295 return 0;
296 }
Linux下C语言实现贪吃蛇的更多相关文章
- linux 下C语言学习路线
UNIX/Linux下C语言的学习路线.一.工具篇“公欲善其事,必先利其器”.编程是一门实践性很强的工作,在你以后的学习或工作中,你将常常会与以下工具打交道, 下面列出学习C语言编程常常用到的软件和工 ...
- Linux下C语言编程实现spwd函数
Linux下C语言编程实现spwd函数 介绍 spwd函数 功能:显示当前目录路径 实现:通过编译执行该代码,可在终端中输出当前路径 代码实现 代码链接 代码托管链接:spwd.c 所需结构体.函数. ...
- Linux基础与Linux下C语言编程基础
Linux基础 1 Linux命令 如果使用GUI,Linux和Windows没有什么区别.Linux学习应用的一个特点是通过命令行进行使用. 登录Linux后,我们就可以在#或$符后面去输入命令,有 ...
- LINUX下C语言编程基础
实验二 Linux下C语言编程基础 一.实验目的 1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用 ...
- LINUX下中文语言包的安装(转)
在安装盘上已经有各种语言包了,我们只需要找到他们,并安装就可以了.中文的是fonts-chinese-3.02-9.6.el5.noarch.rpmfonts-ISO8859-2-75dpi-1.0- ...
- Unix和Linux下C语言学习指南
转自:http://www.linuxdiyf.com/viewarticle.php?id=174074 Unix和Linux下C语言学习指南 引言 尽管 C 语言问世已近 30 年,但它的魅力仍未 ...
- 笔记整理——Linux下C语言正则表达式
Linux下C语言正则表达式使用详解 - Google Chrome (2013/5/2 16:40:37) Linux下C语言正则表达式使用详解 2012年6月6日Neal627 views发表评论 ...
- linux下常用语言的语法检查插件整理
linux下常用语言的语法检查插件 可以结合vim语法检查插件syntastic使用,具体请参考syntastic使用说明 如php,sql,json,css,js,html,shell,c等语法插件 ...
- LINUX下C语言编程调用函数、链接头文件以及库文件
LINUX下C语言编程经常需要链接其他函数,而其他函数一般都放在另外.c文件中,或者打包放在一个库文件里面,我需要在main函数中调用这些函数,主要有如下几种方法: 1.当需要调用函数的个数比较少时, ...
- linux下C语言多线程编程实例
用一个实例.来学习linux下C语言多线程编程实例. 代码目的:通过创建两个线程来实现对一个数的递加.代码: //包含的头文件 #include <pthread.h> #include ...
随机推荐
- [Python]Python安装教程
anaconda Anaconda:python的一种软件发行版.Anaconda发行版会预装很多pydata生态圈里的软件,而Miniconda是最小的conda安装环境, 一个干净的conda环境 ...
- [Java/LeetCode]算法练习:二进制间距(868/simple)
1 题目描述 题目来源: https://leetcode-cn.com/problems/binary-gap/ 给定一个正整数 n,找到并返回 n 的二进制表示中两个 相邻 1 之间的 最长距离 ...
- [大数据]Hadoop常用命令合集
hadoop 查看hadoop版本 # hadoop version SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found ...
- GitHub Pulse 是什么?它是否能衡量 OpenTiny 开源项目的健康程度?
Pulse 是"脉搏"的意思,就像一个人要有脉搏才能算是一个活人,一个开源项目要有"脉搏"才能算是一个"活"的开源项目,这个单词非常形象地表 ...
- 从 1 秒到 10 毫秒!在 APISIX 中减少 Prometheus 请求阻塞
本文介绍了 Prometheus 插件造成长尾请求现象的原因,以及如何解决这个问题. 作者屠正松,Apache APISIX PMC Member. 原文链接 现象 在 APISIX 社区中,曾有部分 ...
- C# 从0到实战 基本类型
C#语言的基本类型 与大多数编程语言一样,C#也有自己的基本类型,也称为内置类型.下面的表格就简单阐述了这些类型. C# 类型关键字 .NET 类型 bool System.Boolean byte ...
- MySQL InnoDB Architecture 简要介绍
MySQL InnoDB 存储引擎整体架构图: 一.内存存储结构 1.Buffer Pool buffer pool 是主内存中的一块儿存储区域,用于存储访问的表及索引数据.这样从内存中直接访问获取使 ...
- Vue3 element-plus 下拉分页 select分页
由于用 input 实现下拉分页不太理想,转换了一个角度,用 select 实现,以下是具体实现(script-setup TS) script-setup <script lang=" ...
- 面试最常问的数组转树,树转数组 c++ web框架paozhu实现
刚毕业同学,找工作常被问 二维数组转树,树转二维数组 需要支持无限层级实现,如果你了解这个语言那么实现起来还要一番思考 c++ web框架 paozhu使用 需要实现数据库表数据到前台菜单实现,就是这 ...
- 简单记录下RestTemplate使用方法
1.设置get方法 ResponseEntity<JSONObject> responseEntity= restTemplate.getForEntity(url,JSONObject. ...