基于linux的贪吃蛇(新手最宜逐步代码编写)

 提醒

要看明白此代码的萌新,你需要对结构体,指针有比较多的了解,并且需要了解Linux线程,此代码可以很好的练习结构体,指针,后续会更新我学C语言的一些基础总结,linux的学习,在编辑中

首先,我们要了解ncurse函数,我们知道贪吃蛇肯定要使用键盘的按键进行方向控制,常规的输入输出函数是实现不了的。ncurse可以响应键盘的方向键,在此库中定义了

#define KEY_DOWN 0402

#define KEY_UP  0403

#define KEY_LEFT  0404

#define KEY_RIGHT  0405

线程创建pthread_create(&th,NULL,func1,NULL)//需要包含头文件#include <pthread.h>

认识函数:int keypad(WINDOW *win, bool bf);其中,win 是一个指向 WINDOW 结构的指针,表示一个 ncurses 窗口对象,bf 是一个布尔值,用于指定是否启用键盘特殊键捕捉(true 表示启用,false 表示禁用。也可以用1或者0代替)

如果缺少 ncurses 库: 请确保您的系统上安装了 ncurses 库。您可以使用以下命令安装:

sudo apt-get update sudo apt-get install libncurses5-dev libncursesw5-dev

缺少 ncurses 库: 请确保您的系统上安装了 ncurses 库。您可以使用以下命令安装:

sudo apt-get update sudo apt-get install libncurses5-dev libncursesw5-dev

在运行时应该是这样先告诉编译器gcc snake.c -o snake -lncurses你使用了 ncurses 库
然后编译gcc snake.c -lncurses ,再运行

第一阶段先从按键获取开始

#include <ncurses.h>

int main()
{
        int key;

        initscr(); // 初始化 ncurses
        keypad(stdscr,1);// 启用键盘特殊键捕捉
        while(1)
        {
                key = getch();//获取用户输入
                switch(key)
                {
                        case KEY_DOWN:
                                printw("DOWN\n");//注意linux的输出不是printf
                                break;
                        case KEY_UP:
                                printw("UP\n");
                                break;
                        case KEY_LEFT:
                                printw("LEFT\n");
                                break;
                        case KEY_RIGHT:
                                printw("RIGHT\n");
                                break;
                }
        }

        endwin(); // 结束 ncurses

        return 0;
}

第二阶段地图规划执行

第一步图框头

大小20X20。地图竖直方向上的边界“|”。地图水平方向上的边界”--”。贪吃蛇的身子”[ ]”。贪吃蛇的食物”##”

第一行打印“|-------------------------|”

#include <stdio.h>
#include <ncurses.h>

void initNcurse()//调用Ncurse库
{
        initscr(); // 初始化 ncurses
        keypad(stdscr,1);// 启用键盘特殊键捕捉
}

void gamePicture()//图框
{
    int hang;
    int lie;
    for(hang=0;hang<20;hang++)
    {
            if(hang == 0)
            {
                for(lie=0;lie<20;lie++)
                {
                   printw("--");
                }
                                   printw("\n");
                for(lie=0;lie<=20;lie++)//这里小于等于是为了图框更完美
                {
                    if(lie == 0 || lie == 20)//这里小于等于也是为了图框更完美
                    {
                        printw("|");
                    }
                    else
                    {
                        printw("  ");
                    }
                }
            }
    }
}

int main()
{
        //初始化
        initNcurse();
        gamePicture();
        getch();

        endwin(); // 结束 ncurses       
        return 0;
}

第二步图框完善

#include <stdio.h>
#include <ncurses.h>

void initNcurse()//调用Ncurse库
{
        initscr(); // 初始化 ncurses
        keypad(stdscr,1);// 启用键盘特殊键捕捉
}

void gamePicture()//图框
{
    int hang;
    int lie;
    for(hang=0;hang<20;hang++)
    {
        if(hang == 0)
		{
			for(lie=0;lie<20;lie++)
			{
			   printw("--");
			}
			   printw("\n");
			// for(lie=0;lie<=20;lie++)//这里小于等于是为了图框更完美
			// {
				// if(lie == 0 || lie == 20)//这里小于等于也是为了图框更完美
				// {
				//     printw("|");
				// }
				// else
				// {
				//     printw("  ");
				// }
			// }
			//printw("\n");
		}//上面这部分是第一行
		if(hang>0 && hang<=19)//如果这里是if(hang>=0 && hang<=19)则可以把上面注释部分去掉如果不是则要取消注释
		{
			for(lie=0;lie<=20;lie++)//这里小于等于也是为了图框更完美
			{
				if(lie == 0 || lie == 20)//这里小于等于也是为了图框更完美
				{
					printw("|");
				}
				else
				{
					printw("  ");
				}
			}
			printw("\n");
		}//上面这部分是中间其他行
		if(hang == 19)
		{
			for(lie=0;lie<20;lie++)
			{
			   printw("--");
			}
			   printw("\n");
			printw("qinzhifeng");
		}//
    }
}

int main()
{
        //初始化
        initNcurse();
        gamePicture();
        getch();

        endwin(); // 结束 ncurses       
        return 0;
}

第三步蛇的显示(静态)

#include <stdio.h>
#include <ncurses.h>

struct Snake
{
	int hang;;
	int lie;
	struct Snake* next;
};
struct Snake node1 = {2,2,NULL};//初始化蛇身
struct Snake node2 = {2,3,NULL};//初始化蛇身
struct Snake node3 = {2,4,NULL};//初始化蛇身


void initNcurse()//调用Ncurse库
{
        initscr(); // 初始化 ncurses
        keypad(stdscr,1);// 启用键盘特殊键捕捉
}

int snakeNode(int i,int j)//蛇身
{
	struct Snake* p;
	p = &node1;
	while(p != NULL)
	{
		if(p->hang == i && p->lie == j)
		{
			return 1;
		}
		p = p->next;
	}	
	return 0;
}

void gamePicture()//图框
{
    int hang;
    int lie;
    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(snakeNode(hang,lie))//初始化蛇身
				{
					printw("[]");
				}
				else
				{
					printw("  ");
				}
			}
			printw("\n");
		}//上面这部分是中间其他行
		if(hang == 19)
		{
			for(lie=0;lie<20;lie++)
			{
			   printw("--");
			}
			   printw("\n");
			printw("qinzhifeng");
		}//
    }
}

int main()
{
        //初始化
        initNcurse();
		
		node1.next = &node2;//把蛇的每一段身子链接起来
		node2.next = &node3;
		
        gamePicture();
        getch();

        endwin(); // 结束 ncurses       
        return 0;
}

第四步蛇的显示(动态)

#include <stdio.h>
#include <stdlib.h>
#include <ncurses.h>

struct Snake
{
	int hang;;
	int lie;
	struct Snake* next;
};
struct Snake* head;//把链表头尾变成全局变量
struct Snake* tail;

void initNcurse()//调用Ncurse库
{
        initscr(); // 初始化 ncurses
        keypad(stdscr,1);// 启用键盘特殊键捕捉
}

void gamePicture()//图框
{
    int hang;
    int lie;
    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(snakeNode(hang,lie))//初始化蛇身
				{
					printw("[]");
				}
				else
				{
					printw("  ");
				}
			}
			printw("\n");
		}//上面这部分是中间其他行
		if(hang == 19)
		{
			for(lie=0;lie<20;lie++)
			{
			   printw("--");
			}
			   printw("\n");
			printw("qinzhifeng");
		}//
    }
}

int snakeNode(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 addNode()//身体变长,尾部插入
{
	struct Snake* new = (struct Snake*)malloc(sizeof(struct Snake));//开辟新的身体
	
	new->hang  =  tail->hang;
	new->lie = tail->lie+1;
	new->next =  NULL;
	
	tail->next = new;
	tail =  new;
}
void initSnake()//动态蛇身
{
	head = (struct Snake*)malloc(sizeof(struct Snake));//开辟空间给头
	head->hang = 2;//初始蛇身
	head->lie = 2;
	head->next = NULL;
	
	tail  = head;
	
	addNode();//调用一次,最开始是身体就长一节
	addNode();
}


int main()
{
        //初始化
        initNcurse();
		
		//把蛇的每一段身子链接起来
		initSnake();
        gamePicture();
        getch();

        endwin(); // 结束 ncurses       
        return 0;
}

第五步蛇开始移动

#include <stdio.h>
#include <stdlib.h>
#include <ncurses.h>

struct Snake
{
	int hang;;
	int lie;
	struct Snake* next;
};
struct Snake* head;//把链表头尾变成全局变量
struct Snake* tail;

void initNcurse()//调用Ncurse库
{
        initscr(); // 初始化 ncurses
        keypad(stdscr,1);// 启用键盘特殊键捕捉
}

void gamePicture()//图框
{
    int hang;
    int lie;
	
	move(0,0);//ncurse的库里面的光标移动函数
	
    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(snakeNode(hang,lie))//初始化蛇身
				{
					printw("[]");
				}
				else
				{
					printw("  ");
				}
			}
			printw("\n");
		}//上面这部分是中间其他行
		if(hang == 19)
		{
			for(lie=0;lie<20;lie++)
			{
			   printw("--");
			}
			   printw("\n");
			printw("qinzhifeng");
		}//
    }
}

int snakeNode(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 addNode()//身体变长,尾部插入
{
	struct Snake* new = (struct Snake*)malloc(sizeof(struct Snake));//开辟新的身体
	
	new->hang  =  tail->hang;
	new->lie = tail->lie+1;
	new->next =  NULL;
	
	tail->next = new;
	tail =  new;
}
void initSnake()//动态蛇身
{
	head = (struct Snake*)malloc(sizeof(struct Snake));//开辟空间给头
	head->hang = 2;//初始蛇身
	head->lie = 2;
	head->next = NULL;
	
	tail  = head;
	
	addNode();//调用一次,最开始是身体就长一节
	addNode();
}
void deletNode()//移动身体(删除节点)
{
	struct Snake* p;//释放内存避免内存泄露
	 p = head;
	head = head->next;	
	free(p);
}

void moveSnake()//移动身体(增加节点)
{	
	addNode();
	deletNode();
}

int main()
{
	int con;
        //初始化
    initNcurse();
		
	//把蛇的每一段身子链接起来
	initSnake();
	gamePicture();
	getch();

	while(1)
	{
		con = getch();
		if(con ==  KEY_RIGHT)
		{
			moveSnake();
			gamePicture();//刷新
		}
		
	}

	endwin(); // 结束 ncurses       
	return 0;
}

第六步撞墙

#include <stdio.h>
#include <stdlib.h>
#include <ncurses.h>

struct Snake
{
	int hang;;
	int lie;
	struct Snake* next;
};
struct Snake* head = NULL;//把链表头尾变成全局变量
struct Snake* tail = NULL;

void initNcurse()//调用Ncurse库
{
        initscr(); // 初始化 ncurses
        keypad(stdscr,1);// 启用键盘特殊键捕捉
}

void gamePicture()//图框
{
    int hang;
    int lie;
	
	move(0,0);//ncurse的库里面的光标移动函数
	
    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(snakeNode(hang,lie))//初始化蛇身
				{
					printw("[]");
				}
				else
				{
					printw("  ");
				}
			}
			printw("\n");
		}//上面这部分是中间其他行
		if(hang == 19)
		{
			for(lie=0;lie<20;lie++)
			{
			   printw("--");
			}
			   printw("\n");
			printw("qinzhifeng");
		}//
    }
}

int snakeNode(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 addNode()//身体变长,尾部插入
{
	struct Snake* new = (struct Snake*)malloc(sizeof(struct Snake));//开辟新的身体
	
	new->hang  =  tail->hang;
	new->lie = tail->lie+1;
	new->next =  NULL;
	
	tail->next = new;
	tail =  new;
}
void initNcurse()//动态蛇身
{
	struct Snake* p;//防止下面free()时出错
	while(head != NULL)
	{
		p = head;
		head = head->next;//撞墙才执行,清理原来占用的空间
		free(p);
	}
	
	head = (struct Snake*)malloc(sizeof(struct Snake));//开辟空间给头
	head->hang = 2;//初始蛇身
	head->lie = 2;
	head->next = NULL;
	
	tail  = head;
	
	addNode();//调用一次,最开始是身体就长一节
	addNode();
}
void deletNode()//移动身体(删除节点)
{
	struct Snake* p;//释放内存避免内存泄露
	p = head;
	head = head->next;	
	free(p);
}

void moveSnake()//移动身体(增加节点)
{
	addNode();
	deletNode();	
	if(tail->hang ==0 || tail->lie == 0 || tail->hang == 0 || tail->lie == 20)//撞到边框重新开始
	{
		initSnake();
	}
}

int main()
{
	int con;
        //初始化
    initNcurse();
		
	//把蛇的每一段身子链接起来
	initSnake();
	gamePicture();
	getch();

	while(1)
	{
		con = getch();
		if(con ==  KEY_RIGHT)
		{
			moveSnake();
			gamePicture();//刷新
		}
		
	}

	endwin(); // 结束 ncurses       
	return 0;
}

第七步蛇一直动

将主函数的循环改成这样就可以了
	
while(1)
	{		
		moveSnake();
		gamePicture();//刷新
		refresh();//界面刷新
		usleep(9000);//9毫秒
		
	}

第八步随意改变移动方向

让蛇一开始向右动

#include <stdio.h>
#include <stdlib.h>
#include <ncurses.h>
#include <pthread.h>

#define UP    1
#define DOWN  2
#define LEFT  3
#define RIGHT 4

int key;
int dir;

struct Snake
{
	int hang;;
	int lie;
	struct Snake* next;
};
struct Snake* head = NULL;//把链表头尾变成全局变量
struct Snake* tail = NULL;

void initNcurse()//调用Ncurse库
{
        initscr(); // 初始化 ncurses
        keypad(stdscr,1);// 启用键盘特殊键捕捉
}

void gamePicture()//图框
{
    int hang;
    int lie;
	
	move(0,0);//ncurse的库里面的光标移动函数
	
    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(snakeNode(hang,lie))//初始化蛇身
				{
					printw("[]");
				}
				else
				{
					printw("  ");
				}
			}
			printw("\n");
		}//上面这部分是中间其他行
		if(hang == 19)
		{
			for(lie=0;lie<20;lie++)
			{
			   printw("--");
			}
			   printw("\n");
			printw("qinzhifeng");//可以把线程2里面的按键在这里打印
		}
    }
}

int snakeNode(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 addNode()//身体变长,尾部插入
{
	struct Snake* new = (struct Snake*)malloc(sizeof(struct Snake));//开辟新的身体
	
	new->hang  =  tail->hang;
	new->lie = tail->lie+1;
	new->next =  NULL;
	
	switch(dir)
	{
		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;
	}
	
	tail->next = new;
	tail =  new;
}
void initSnake()//动态蛇身
{
	struct Snake* p;//防止下面free()时出错
	
	dir = RIGHT;//让蛇一开始向右动
	
	while(head != NULL)
	{
		p = head;
		head = head->next;//撞墙才执行,清理原来占用的空间
		free(p);
	}
	
	head = (struct Snake*)malloc(sizeof(struct Snake));//开辟空间给头
	head->hang = 2;//初始蛇身
	head->lie = 2;
	head->next = NULL;
	
	tail  = head;
	
	addNode();//调用一次,最开始是身体就长一节
	addNode();
}
void deletNode()//移动身体(删除节点)
{
	struct Snake* p;//释放内存避免内存泄露
	p = head;
	head = head->next;	
	free(p);
}

void moveSnake()//移动身体(增加节点)
{
	addNode();
	deletNode();	
	if(tail->hang ==0 || tail->lie == 0 || tail->hang == 0 || tail->lie == 20)//撞到边框重新开始
	{
		initSnake();
	}
}

void* refreshJieMian()//线程1刷新界面
{
	while(1)
	{		
		moveSnake();
		gamePicture();//刷新
		refresh();//界面刷新
		usleep(300000);//9毫秒		
	}
}

void* changerDir()//线程2修改方向
{
	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();
	gamePicture();
	
	pthread_create(&t1,NULL,refreshJieMian,NULL);//调用线程
	pthread_create(&t2,NULL,changerDir,NULL);//调用线程
	
	while(1);//循环线程

	getch();
	endwin(); // 结束 ncurses       
	return 0;
}

第九步优化第八步的代码(掉头不合理的问题)

#include <stdio.h>
#include <stdlib.h>
#include <ncurses.h>
#include <pthread.h>

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

int key;
int dir;

struct Snake
{
	int hang;;
	int lie;
	struct Snake* next;
};
struct Snake* head = NULL;//把链表头尾变成全局变量
struct Snake* tail = NULL;

void initNcurse()//调用Ncurse库
{
        initscr(); // 初始化 ncurses
        keypad(stdscr,1);// 启用键盘特殊键捕捉
		noecho();//查阅资料如果没有这个函数,系统可能会打印一些乱码
}

void gamePicture()//图框
{
    int hang;
    int lie;
	
	move(0,0);//ncurse的库里面的光标移动函数
	
    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(snakeNode(hang,lie))//初始化蛇身
				{
					printw("[]");
				}
				else
				{
					printw("  ");
				}
			}
			printw("\n");
		}//上面这部分是中间其他行
		if(hang == 19)
		{
			for(lie=0;lie<20;lie++)
			{
			   printw("--");
			}
			   printw("\n");
			printw("qinzhifeng");//可以把线程2里面的按键在这里打印
		}
    }
}

int snakeNode(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 addNode()//身体变长,尾部插入
{
	struct Snake* new = (struct Snake*)malloc(sizeof(struct Snake));//开辟新的身体
	
	new->hang  =  tail->hang;
	new->lie = tail->lie+1;
	new->next =  NULL;
	
	switch(dir)
	{
		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;
	}
	
	tail->next = new;
	tail =  new;
}
void initSnake()//动态蛇身
{
	struct Snake* p;//防止下面free()时出错
	
	dir = RIGHT;//让蛇一开始向右动
	
	while(head != NULL)
	{
		p = head;
		head = head->next;//撞墙才执行,清理原来占用的空间
		free(p);
	}
	
	head = (struct Snake*)malloc(sizeof(struct Snake));//开辟空间给头
	head->hang = 2;//初始蛇身
	head->lie = 2;
	head->next = NULL;
	
	tail  = head;
	
	addNode();//调用一次,最开始是身体就长一节
	addNode();
}
void deletNode()//移动身体(删除节点)
{
	struct Snake* p;//释放内存避免内存泄露
	p = head;
	head = head->next;	
	free(p);
}

void moveSnake()//移动身体(增加节点)
{
	addNode();
	deletNode();	
	if(tail->hang ==0 || tail->lie == 0 || tail->hang == 0 || tail->lie == 20)//撞到边框重新开始
	{
		initSnake();
	}
}

void* refreshJieMian()//线程1刷新界面
{
	while(1)
	{		
		moveSnake();
		gamePicture();//刷新
		refresh();//界面刷新
		usleep(300000);//9毫秒		
	}
}

void turn(int direction)//优化转弯(线程2)
{
	if(abs(dir) != abs(direction))//abs函数用来取绝对值C库里面的
	{
		dir = direction;
	}
}
void* changerDir()//线程2修改方向
{
	while(1)
	{
		key = getch();//获取用户输入
		switch(key)
		{
			case KEY_DOWN:
					turn(DOWN);//改变运动方向
					break;
			case KEY_UP:
					turn(UP);
					break;
			case KEY_LEFT:
					turn(LEFT);
					break;
			case KEY_RIGHT:
					turn(RIGHT);
					break;
		}
	}
}

int main()
{
	//定义线程
	pthread_t t1;
	pthread_t t2;

    //初始化
    initNcurse();

	//把蛇的每一段身子链接起来
	initSnake();
	gamePicture();
	
	pthread_create(&t1,NULL,refreshJieMian,NULL);//调用线程
	pthread_create(&t2,NULL,changerDir,NULL);//调用线程
	
	while(1);//循环线程

	getch();
	endwin(); // 结束 ncurses       
	return 0;
}

第十步随机出现食物

#include <stdio.h>
#include <stdlib.h>
#include <ncurses.h>
#include <pthread.h>

#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;
int dir;

struct Snake food;
void initFood()//蛇的食物
{
	 int x = rand()%20;//边框是20x20的,不能让食物超出范围
	 int y = rand()%20;
	
	food.hang = x;
	food.lie = y;
	

}

void initNcurse()//调用Ncurse库
{
        initscr(); // 初始化 ncurses
        keypad(stdscr,1);// 启用键盘特殊键捕捉
		noecho();//查阅资料如果没有这个函数,系统可能会打印一些乱码
}

void gamePicture()//图框
{
    int hang;
    int lie;
	
	move(0,0);//ncurse的库里面的光标移动函数
	
    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(snakeNode(hang,lie))//初始化蛇身
				{
					printw("[]");
				}
				else if(snakeFood(hang,lie))//如果显示的是食物
				{
					printw("##");//两个食物,因为蛇身体的符号占用了两个字符位置
				}
				else
				{
					printw("  ");
				}
			}
			printw("\n");
		}//上面这部分是中间其他行
		if(hang == 19)
		{
			for(lie=0;lie<20;lie++)
			{
			   printw("--");
			}
			   printw("\n");
			printw("qinzhifeng,key,food.hang=%d,food.lie=%d",key,food.hang,food.lie);//可以把线程2里面的按键在这里打印
		}
    }
}

int snakeNode(int i,int j)//蛇身
{
	struct Snake* p;
	p = head;
	while(p != NULL)
	{
		if(p->hang == i && p->lie == j)

		{
			return 1;
		}
		p = p->next;
	}	
	
}
int snakeFood(int i,int j)//蛇的食物
{
	    if(food.hang == i && food.lie == j)
		{
			return 1;
		}
		return 0;
}

void addNode()//身体变长,尾部插入
{
	struct Snake* new = (struct Snake*)malloc(sizeof(struct Snake));//开辟新的身体
	
	new->hang  =  tail->hang;
	new->lie = tail->lie+1;
	new->next =  NULL;
	
	switch(dir)
	{
		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;
	}
	
	tail->next = new;
	tail =  new;
}
void initSnake()//动态蛇身
{
	struct Snake* p;//防止下面free()时出错
	
	dir = RIGHT;//让蛇一开始向右动
	
	while(head != NULL)
	{
		p = head;
		head = head->next;//撞墙才执行,清理原来占用的空间
		free(p);
	}
	
	initFood();//食物初始化
	
	head = (struct Snake*)malloc(sizeof(struct Snake));//开辟空间给头
	head->hang = 2;//初始蛇身
	head->lie = 2;
	head->next = NULL;
	
	tail  = head;
	
	addNode();//调用一次,最开始是身体就长一节
	addNode();
}
void deletNode()//移动身体(删除节点)
{
	struct Snake* p;//释放内存避免内存泄露
	p = head;
	head = head->next;	
	free(p);
}

int ifSnakeDie()
{
	struct Snake* p;
	p = head;
	if(tail->hang < 0 || tail->lie == 0 || tail->hang == 0 || tail->lie == 20)//撞到边框重新开始。如果tail->hang == 0去不了第一行
	{
		return 1;
	}
	while(p->next != NULL)
	{
		if(p->hang == tail->hang && p->lie == tail->lie)//咬到自己
		{
			return 1;
		}
		p = p->next;
	}
	return 0;
}

void moveSnake()//移动身体(增加节点)
{
	addNode();
	if(snakeFood(tail->hang,tail->lie))
	{
		initFood();//吃实物
	}else
	{
		deletNode();	//没吃到
	}
	if(ifSnakeDie())
	{
		initSnake();
	}
}

void* refreshJieMian()//线程1刷新界面
{
	while(1)
	{		
		moveSnake();
		gamePicture();//刷新
		refresh();//界面刷新
		usleep(300000);//9毫秒		
	}
}

void turn(int direction)//优化转弯(线程2)
{
	if(abs(dir) != abs(direction))//abs函数用来取绝对值C库里面的
	{
		dir = direction;
	}
}
void* changerDir()//线程2修改方向
{
	while(1)
	{
		key = getch();//获取用户输入
		switch(key)
		{
			case KEY_DOWN:
					turn(DOWN);//改变运动方向
					break;
			case KEY_UP:
					turn(UP);
				break;
			case KEY_LEFT:
					turn(LEFT);
					break;
			case KEY_RIGHT:
					turn(RIGHT);
					break;
		}
	}
}

int main()
{
	//定义线程
	pthread_t t1;
	pthread_t t2;

    //初始化
    initNcurse();

	//把蛇的每一段身子链接起来
	initSnake();
	gamePicture();
	
	pthread_create(&t1,NULL,refreshJieMian,NULL);//调用线程
	pthread_create(&t2,NULL,changerDir,NULL);//调用线程
	
	while(1);//循环线程

	getch();
	endwin(); // 结束 ncurses       
	return 0;
}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

漏洞嵌入式

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

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

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

打赏作者

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

抵扣说明:

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

余额充值