手把手教你写linux系统下贪吃蛇(二)

转载请注明出处

完善后的代码:贪吃蛇过关版

在上一篇博客的基础上完成贪吃蛇(上一篇)。

需求:c语言基础。

这里需要线程的东西,不需要很了解,会用就行。

对线程不理解直接看第六部分主函数。

创建线程后把第一篇用到的refresh()函数都删除,不然因为缓存区的原因产生乱码

此时全局变量值要改变

第二部分写好以下几个函数

一)方向函数;(改变方向dirch)

二)删除头结点函数;(链表插入是尾插法,删除头节点,前进的‘头’是链表的‘尾部’。然后再增加结点,实现移动)

三)移动蛇身函数;(moveSnake())

四)线程函数一:(refresh_thread(),实现蛇的移动,调用第三个函数)

五)线程函数二;(operation_thread(),实现方向的改变,调用函数一)

六)主函数

为什么要用线程?

我们的c语言程序一般是单线程的,从主函数开始,一行一行执行,遇到函数就跳进函数,线程是让两个函数同时执行。

就像你现在看我的博客又在玩qq,这就是多线程。

 如果不用线程,就会让操作不能立刻显现,显得你的蛇很'笨'。

一)方向函数;(改变方向dirch)

void turn(int direction) { if(abs(direction) != dir){ dir = direction; } return ;

}

二)删除头结点函数;

void deleteHead() { node *tmp = head; head = head->next; free(tmp); tmp=NULL;

}

三)移动蛇身函数;

void moveSnake() { addSnakeBody(); if(food->x==tail->x && food->y==tail->y){ createFood(); num++; }else{ deleteHead(); } printw("score:%d",num); refreshInterface();

}

四)线程函数一:

void refresh_thread() { usleep(300000);//延时300000毫秒 moveSnake();

}

五)线程函数二

void operate_thread() { int op; // int num = 0; initCurses(); initDir(); createFood(); initSnake(); refreshInterface();         while(1){ op = getch(); switch(op){ case KEY_UP: turn(UP); break; case KEY_DOWN: turn(DOWN); break; case KEY_LEFT: turn(LEFT); break; case KEY_RIGHT: turn(RIGHT); break; } usleep(300000); moveSnake(); } }

六 。主函数

int main() { initCurses(); initDir(); createFood(); initSnake(); refreshInterface(); pthread_t pt_operate; pthread_t pt_refresh; pthread_create(&pt_operate,NULL,(void *)operate_thread,NULL);

pthread_create(&pt_refresh,NULL,(void *)refresh_thread,NULL);

//创建线程函数,原型:

/*int  pthread_create(pthread_t  *  thread,

pthread_attr_t * attr,

void * (*start_routine)(void *),

void * arg)*/

//第一个参数: 创建线程的ID     第二个参数: 线程属性,调度策略,优先级都在这里设置,如果NULL为默认属性

//第三个参数: 线程入口函数,可返回一个(void*)类型的返回值,该返回值可由pthread_join接收

//第四个参数:设置为NULL就好

pthread_join(pt_operate,NULL); pthread_join(pt_refresh,NULL);

/*一般来讲,进程中各个函数都是独立的,线程的终止并不会通知,也不会影响其他线程,终止的线程占用的资源也不会随着线程的终止得到释放,正如进程可以用wait()系统调用来同步终止并释放一切内存一样,在linux中没有进程,却有类似的函数

pthread_join();

函数原型:int pthread_join(pthread_t th, void **thread_return)

第一个参数线程ID,第二个设置为NULL就行

*/

        endwin();         return 0;

}

这个代码还不完善,根据需要自行修改。

汇总:

#include <curses.h> #include <stdlib.h> #include <pthread.h> #define BOADSIZE 20 #define UP       1 #define DOWN     -1 #define LEFT     2 #define RIGHT    -2 typedef struct SnakeBody { int x; int y; struct SnakeBody *next; }node; node *head; node *tail; node *food; int dir; int num = 0; void initCurses() {     initscr();     noecho();     keypad(stdscr,TRUE);     timeout(1); } void refreshInterface() { int x; int y;         mvprintw(0,0,""); printw("---------------Snake Game-----------------\n"); for(y=0;y<BOADSIZE;y++){ if(y==0){ for(x=0;x<=BOADSIZE;x++){ printw("--"); } printw("\n"); } for(x=0;x<BOADSIZE;x++){ if(x==0){ printw("|"); } if(hasSnake(x,y)==1){ printw("[]"); }else if((food->x==x)&&(food->y==y)){ printw("##"); }else{ printw("  "); } if(x==BOADSIZE-1){ printw("|"); } } printw("\n"); if(y==BOADSIZE-1){ for(x=0;x<=BOADSIZE;x++){ printw("--"); } printw("\n"); } } } void addSnakeBody() { node *new; node *tmp; tmp = (node *)malloc(sizeof(node)); new = (node *)malloc(sizeof(node)); tail->next = new; tmp = tail; tail = new; new->next = NULL; switch(dir){ case UP: new->x = tmp->x; new->y = tmp->y-1; break; case DOWN: new->x = tmp->x; new->y = tmp->y+1; break; case LEFT: new->x = tmp->x-1; new->y = tmp->y; break; case RIGHT: new->x = tmp->x+1; new->y = tmp->y; break; } } void initDir() { dir = RIGHT; } int hasSnake(int x,int y) { node *tmp; tmp = (node *)malloc(sizeof(node)); tmp = head; while(tmp!=NULL){ if(tmp->x==x && tmp->y==y){ return 1; } tmp = tmp->next; } return 0; } void initSnake() { head = tail = (node *)malloc(sizeof(node)); head->x = 0; head->y = 0; addSnakeBody(); addSnakeBody(); addSnakeBody(); } void createFood() { food = (node *)malloc(sizeof(node)); food->x = rand()&BOADSIZE-1; food->y =1 + rand()%BOADSIZE-1; } void deleteHead() { node *tmp = head; head = head->next; free(tmp); tmp=NULL; } void moveSnake() { // int num = 0; addSnakeBody(); if(food->x==tail->x && food->y==tail->y){ createFood(); num++; }else{ deleteHead(); } // if(tail->x<0||tail->x>BAODSIZE||tail->y<0||tail->y>BOADSIZE){ // } printw("score:%d",num); refreshInterface(); } void turn(int direction) { if(abs(direction) != dir){ dir = direction; // moveSnake(); } return ; } /*void updateScore() { printw("") } */ /* char *getTime() { time_t t; t = time(&t); return ctime(&t); } */ void operate_thread() { int op; // int num = 0; initCurses(); initDir(); createFood(); initSnake(); refreshInterface();         while(1){ op = getch(); switch(op){ case KEY_UP: turn(UP); // moveSnake(); break; case KEY_DOWN: turn(DOWN); // moveSnake(); break; case KEY_LEFT: turn(LEFT); // moveSnake(); break; case KEY_RIGHT: turn(RIGHT); // moveSnake(); break; } usleep(300000); moveSnake(); } } void refresh_thread() { usleep(300000); moveSnake(); } int main() { // int op; // int num = 0; initCurses(); initDir(); createFood(); initSnake(); refreshInterface(); /*         while(1){ op = getch(); switch(op){ case KEY_UP: turn(UP); // moveSnake(); break; case KEY_DOWN: turn(DOWN); // moveSnake(); break; case KEY_LEFT: turn(LEFT); // moveSnake(); break; case KEY_RIGHT: turn(RIGHT); // moveSnake(); break; } usleep(300000); moveSnake(); */ pthread_t pt_operate; pthread_t pt_refresh; pthread_create(&pt_operate,NULL,(void *)operate_thread,NULL); pthread_create(&pt_refresh,NULL,(void *)refresh_thread,NULL); pthread_join(pt_operate,NULL); pthread_join(pt_refresh,NULL); // operate(); // refresh();         endwin();         return 0; }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT可乐

mybatis 详解(五)------动态SQL

  前面几篇博客我们通过实例讲解了用mybatis对一张表进行的CRUD操作,但是我们发现写的 SQL 语句都比较简单,如果有比较复杂的业务,我们需要写复杂的 ...

377100
来自专栏Leetcode名企之路

【设计模式】单例模式

前几天面试一个校招的小朋友,让他写单例模式,没写出来,所以这里把两年前我的学习笔记发一下。这应该是所有设计模式中最简单的设计模式了,从它讲起。

12030
来自专栏求教

哪位大神指点下

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\logging\...

11200
来自专栏李智的专栏

Mysql进阶

1) 内连接 select a.*,b.* from a inner join b on a.id=b.parent_i...

8210
来自专栏北京马哥教育

10分钟学会理解和解决MySQL乱码问题

本文将详细介绍MySQL乱码的成因和具体的解决方案。在阅读本文之前,强烈建议对字符集编码概念还比较模糊的同学 阅读下博主之前对相关概念的一篇科普:十分钟搞清字符...

31780
来自专栏不想当开发的产品不是好测试

mysql @value := 用法

背景 有这么一张表,记录名字和分数,现在需要按照成绩排名,存在并列名次的情况 ? 解决方法 思路:按照score从大到小排序,第一行数据就是第一名,第二行就是第...

31780
来自专栏Java进阶之路

IK分词器访问远程词典功能实现

IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出了3个大版本。最...

36220
来自专栏乐沙弥的世界

MongoDB 多键索引

更多参考 MongoDB 单键(列)索引 MongoDB 复合索引 MongoDB执行计划获取(db.collection.explain()) ...

18630
来自专栏禹都一只猫博客

Python的flask:models.py来创建mysql数据库

24560
来自专栏禹都一只猫博客

Python的flask:models.py来创建mysql数据库

1.4K90

扫码关注云+社区

领取腾讯云代金券