手把手教你写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;


}

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wym_king

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值