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 ...
随机推荐
- Junit5 pom依赖
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter- ...
- 在web浏览器中如何操作复合IC卡
在web浏览器中如何操作复合IC卡呢, 对于使用javascript的工程师而言,非常简单,只需要几行代码即可实现.当然在写代码之前, 需要安装友我NFC读写器web插件, 然后插上NFC读写器YW- ...
- RTSP Server(LIVE555)源码分析(二)-服务器创建
一. 设置RTSP服务器配置 步骤1.5:rtspServer_Init--->BasicTaskScheduler::createNew()时序图如下: 1)步骤1.54,BasicTaskS ...
- Godot 4.0 文件读取(C#)
搞半天才弄明白Godot文件操作. Godot的文档总是试图让我使用自定义Resource来支持文件操作,但是我只需要读取纯文本. 读取纯文本 读取纯文本的方式如下: //Godot.FileAcce ...
- 原来Spring能注入集合和Map的computeIfAbsent是这么好用!
大家好,我是3y,今天继续来聊我的开源项目austin啊,但实际内容更新不多.这文章主是想吹下水,主要聊聊我在更新项目中学到的小技巧. 今天所说的小技巧可能有很多人都会,但肯定也会有跟我一样之前没用过 ...
- 数据库定时备份winserver2012篇
目录 1 序言 2 任务计划相关知识点介绍 2.1 任务计划 是什么? 2.2 批处理文件 2.2.1 批处理文件简介 2.2.2 批处理常用命令介绍 3 各个数据库备份脚本 3.1 Oracle数据 ...
- Git&GitHub简介与入手(三)
五.eclipse中的git使用 1.eclipse中本地库操作 (检测显示创建成功): (设置本地库范围签名): (一些git里的图标,保存着不同内容): https://github.com/gi ...
- stl------stack与queue
stack与queue 一.stack 二.queue 例题:详见我的另一篇博文: 栈------表达式求值 http://www.cnblogs.com/Cloud-king/p/8453703.h ...
- 2022-11-12:以下rust语言代码中,结构体S实现了crate::T1::T2的方法,如何获取方法列表?以下代码应该返回[“m1“,“m2“,“m5“],顺序不限。m3是S的方法,但并不属于c
2022-11-12:以下rust语言代码中,结构体S实现了crate::T1::T2的方法,如何获取方法列表?以下代码应该返回["m1","m2"," ...
- 2022-04-08:在一张 无向 图上,节点编号0~N-1。老鼠开始在1节点,猫在2节点,0号节点是洞,老鼠想进洞, 老鼠第先出发,猫后出发,轮流行动。 在每个玩家的行动中,他们 必须 沿着图中与所
2022-04-08:在一张 无向 图上,节点编号0~N-1.老鼠开始在1节点,猫在2节点,0号节点是洞,老鼠想进洞, 老鼠第先出发,猫后出发,轮流行动. 在每个玩家的行动中,他们 必须 沿着图中与所 ...