(六)贪吃蛇 自行游走、方向转换 及 线程 实现双循环问题

 一、边界死亡 刷新初始化 refresh( ) ulseep( )

        睡眠时间函数 #include <unsitd.h>

        用与延迟挂起进程,进程被挂起放倒ready queue

        usleep和sleep    usleep以微秒为单位       sleep以秒为单位

//界面刷新
void* refreshInterface()
{	
	while(1){
		moveSnake();//移动
		gamePic();//打印输出
		refresh();//更新终端屏幕
		usleep(100000);//控制蛇的运动速度,以微秒为单位,100毫秒睡眠一次,执行挂起不动
	}
}

二、循环 自行游走

//扫描键入的值判断方向
void* changeDirection()
{
	while(1){
        key = getch();
        switch(key){
            case KEY_DOWN:
                dir = DOWN;
                break;
            case KEY_UP:
                dir = UP;
                break;
            case KEY_LEFT:
                dir = LEFT;
                break;
            case KEY_RIGHT:
                dir = RIGHT;
                break;
        }
	}
}

三、循环 方向转换

四、双循环 用线程 #include <pthread.h>

        多核是同时运行,单核是争夺CPU的资源。

gcc a.c -lcurses -lpthread -o a        编译
man malloc                             man手册 
:set nu                               行号
vim a.c +89                            定位到89行
#include <curses.h>//不是标准库 1.sudo apt-get install libncurses5-dev 2.vi /usr/include/crses.h 3.gcc my_snake,c -lcurses
#include <stdio.h>
#include <stdlib.h>//malloc
#include <pthread.h>//Linux线程
#include <unistd.h>//睡眠时间函数usleep()与sleep()类似,用于延迟挂起进程。进程被挂起放到ready queue。
//提供对 POSIX 操作系统(可移植系统)接口 API 的访问功能的头文件的名称,是一组定义了UNIX-like操作系统接口标准的规范,旨在增加移植性和兼容性。

#define UP     1
#define DOWN  -1
#define LEFT   2
#define RIGHT -2

//定义贪吃蛇节点结构体
struct Snake
{
    int hang;
    int lie;
    struct Snake *next;
};

struct Snake *head = NULL;//定义蛇尾(链表头) 
struct Snake *tail = NULL;//定义蛇头(链表尾)
int key;//记录键入的值 changeDirection()函数中使用到
int dir;//记录方向的值 addNode()函数中使用到

//函数封装初始化Ncurse界面
void initNcurse()
{
    initscr();//ncurse界面的初始化函数
    keypad(stdscr,1);//从标准stdscr中接受功能键,TRUE代表是否接收
    noecho();//大多数的交互式应用程序在初始化时会调用noecho()函数,用于在进行控制操作时不显示输入的控制字符。
}

//判断地图上的点是否是蛇身节点
int judgeSnakeNode(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);//将光标定位到0行0列 ncurses的性质

    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(judgeSnakeNode(hang,lie)){
                    printw("[]");
                }else{
                    printw("  ");
                }    
            }
            printw("\n");
        }
        if(hang==19)
        {
            for(lie=0;lie<20;lie++){
                printw("--");
            }
            printw("\n");
        }        
    }
    printw("by tanyang!");
}

//增加新节点(通过方向判断加在哪)
void addNode()
{
	struct Snake *new = (struct Snake *)malloc(sizeof(struct Snake));

    switch (dir){//根据键入的值来增加节点,修改tail所指结点中hang,lie并将修改后的值赋值给新节点 
        case UP:
            new->hang=tail->hang-1;
            new->lie=tail->lie;
            break;
        case DOWN:
            new->hang=tail->hang+1;
            new->lie=tail->lie;
            break;
        case LEFT:
            new->hang=tail->hang;
            new->lie=tail->lie-1;
            break;                        
        case RIGHT:
            new->hang=tail->hang;
            new->lie=tail->lie+1;
            break;
    }

    new->next=NULL;
    tail->next=new;
    tail=new;
}

//初始化蛇身
void initSnake()
{   
    struct Snake *p;

	dir = RIGHT;//蛇头初始方向为RIGHT

    while (head!=NULL)
    {
        p=head;
        head=head->next;
        free(p);
    }
    
    head=(struct Snake *)malloc(sizeof(struct Snake));
    head->hang=4;
    head->lie=4;
    head->next=NULL;

    tail=head;//初始时尾指针指向头
    addNode();
    addNode();
    addNode();//增加3节点,设置初始蛇身长度
}

//删除蛇尾(头结点)
void deleteNode()
{
	struct Snake *p;
	p = head;
	head = head->next;
	free(p);//释放p=head原先头节点
}

//蛇的移动(蛇头增加新节点,删除蛇尾节点) 
void moveSnake()
{
	addNode();//增加新节点
	deleteNode();//删除蛇尾(头结点)

    if(tail->hang==1 || tail->lie==1 || tail->hang==20 || tail->lie==20){//边界
        initSnake();
    }
}

//界面刷新
void* refreshInterface()
{	
	while(1){
		moveSnake();//移动
		gamePic();//打印输出
		refresh();//更新终端屏幕
		usleep(100000);//控制蛇的运动速度,以微秒为单位,100毫秒睡眠一次,执行挂起不动
	}
}

//扫描键入的值判断方向
void* changeDirection()
{
	while(1){
        key = getch();
        switch(key){
            case KEY_DOWN:
                dir = DOWN;
                break;
            case KEY_UP:
                dir = UP;
                break;
            case KEY_LEFT:
                dir = LEFT;
                break;
            case KEY_RIGHT:
                dir = RIGHT;
                break;
        }
	}
}

int main()
{
	pthread_t t1;
	pthread_t t2;

    initNcurse();
    initSnake();
    gamePic();

	pthread_create(&t1, NULL, refreshInterface, NULL);
	pthread_create(&t2, NULL, changeDirection, NULL);

	while(1);

    getch();//获取用户的输入
    endwin();//没有会破坏show的界面

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

咖喱年糕

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

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

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

打赏作者

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

抵扣说明:

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

余额充值