Linux下基于ncurses的贪吃蛇

这里是基于nucrses库的贪吃蛇

所以下面先解释下nucrses库中的一些函数:

  1. printw(): 就是printf函数 使用基本一样,不同的是:printw()函数把字符串输出到“stdscr”的虚拟窗口
  2. initscr():这个函数初始化了curses 系统并且为当前屏幕(也就是“stdscr”)和相关的数据结构分配内存。
  3. endwin():endwin()函数释放了curses 子系统和相关数据结构占用的内存,使你能够正常返回控制台模式。
  4. refresh():告诉curses系统将缓冲区的内容输出到屏幕上。
  5. noecho():从键盘获取值但不显示
  6. keypad(stdscr,TRUE):使用curses里的特殊方向键,第一个参数是WINDOW类型,这里我们前面提到了是stdscr,第二个是bool类型,TRUE是允许。
  7. getch():获取用户输入

蛇的结构体定义:

struct Snake
{
	int x;
	int y;
	struct Snake *next;
}

头文件声明:

#include<curses.h>
#include <stdlib.h>
#include <pthread.h>
#include "snake.h"

#define MAP_LENGTH 20 //地图长
#define MAP_WIDETH 20//宽

extern struct Snake *g_snake;//定义蛇
struct Snake food;
int dir=KEY_RIGHT;//默认初始方向为右
int eat=0;//判断食物是否被吃到 0为没有,1为吃到
void initfood()//初始化食物
int Eat_food()//判断是否吃到食物
int init_Map()//初始化地图
void delete_snake(struct Snake *p)//蛇的滚动
int suicide()//咬到自己死
int Against_wall()//撞墙
void distory_snake()//若撞墙,初始化蛇的位置
int Determine_direction(int key)//判断方向
void handle_key()//按键控制
void snake_move()//蛇的移动
void add_snake(struct Snake **p,int x,int y)//增加蛇身
void Creat_snake()//创建蛇的初始位置
int find_snake(struct Snake *p,int x,int y)//在地图遍历寻找蛇身,找到返回0,找不到返回-1

实现思路:

这里我是用头插法实现蛇的变长:

void add_snake(struct Snake **p,int x,int y)//增加蛇身
{
	struct Snake *snake_body=(struct Snake*)malloc(sizeof(struct Snake));
	snake_body->x=x;
	snake_body->y=y;
	snake_body->next=NULL;

	snake_body->next=*p;
	*p=snake_body;
}

所以要让蛇滚动只需新添一个头节点,再删除尾节点:

void delete_snake(struct Snake *p)//蛇的滚动
{
	struct Snake *tmp;
	while(p!=NULL&&p->next!=NULL)
	{
		tmp=p->next;
		if(tmp->next==NULL)
		{
			p->next=NULL;
			free(tmp);
			break;
		}
		p=p->next;
	}
}
//然后只需新添一个头节点,再删除尾节点
add_snake(&g_snake,g_snake->x-1,g_snake->y);
delete_snake(g_snake);

吃食物呢,就是判断食物的点是否和蛇头重合,重合就新添一个点

int Eat_food()//判断是否吃到食物
{
	if(g_snake->x==food.x&&g_snake->y==food.y)
	{
		return 0;
	}
	return 1;
}

撞墙呢,就是判断蛇头的点是否和地图边缘相等

int Against_wall()//撞墙
{
	if(g_snake->x==0||g_snake->x==19||g_snake->y==0||g_snake->y==19)
	{
		return 0;
	}
	return -1;
}

最终代码实现:
main.c

#include<curses.h>
#include <stdlib.h>
#include <pthread.h>
#include "snake.h"

#define MAP_LENGTH 20 
#define MAP_WIDETH 20

extern struct Snake *g_snake;//定义蛇
struct Snake food;
int dir=KEY_RIGHT;//默认初始方向为右
int eat=0;//判断食物是否被吃到 0为没有,1为吃到
void initfood()//初始化食物
{
	int judge;
	srand((int)time(0));
	do
	{
		food.x=rand()%20+1;
		food.y=rand()%20+1;
		if(food.x==g_snake->x&&food.y==g_snake->y)
		{
			judge=1;
		}
	}while(food.x==0||food.x>18||food.y==0||food.y>18||judge==1);

}
int Eat_food()//判断是否吃到食物
{
	if(g_snake->x==food.x&&g_snake->y==food.y)
	{
		return 0;
	}
	return 1;
}
int init_Map()//初始化地图
{
    int i;
    int j;
    for(i=0;i<MAP_LENGTH;i++)
    {
        for(j=0;j<MAP_WIDETH;j++)
        {
            if(j==0||j==MAP_WIDETH-1)
            {
            	if(j==0)
            	{
            		 printw("| ");
            	}
               	else
               	{
               		printw(" |");
               	}
            }
            else
            {
                if(i==0||i==MAP_LENGTH-1)
                {
                    printw("--");
                }
                else
                {
                	if(find_snake(g_snake,i,j)==0)//显示蛇的位置
                	{
                		printw("[]");
                	}
                	else if(food.x==i&&food.y==j)
                	{
                		printw("$$");
                	}
                	else 
                	{
                		printw("  ");
                	}
                    
                }
            }
        }
        printw("\n");
    }
}
void delete_snake(struct Snake *p)//蛇的滚动
{
	struct Snake *tmp;
	while(p!=NULL&&p->next!=NULL)
	{
		tmp=p->next;
		if(tmp->next==NULL)
		{
			p->next=NULL;
			free(tmp);
			break;
		}
		p=p->next;
	}
}
int suicide()//咬到自己死
{
	struct Snake *head;
	struct Snake *body;
	head=g_snake;
	body=g_snake->next;
	while(body!=NULL)
	{
		
		if(head->x==body->x&&head->y==body->y)
		{
			return 0;
		}
		body=body->next;
	}
	return 1;
}
int Against_wall()//撞墙
{
	if(g_snake->x==0||g_snake->x==19||g_snake->y==0||g_snake->y==19)
	{
		return 0;
	}
	return -1;
}
void distory_snake()//初始化蛇的位置
{
    struct Snake *p;
    while(g_snake!=NULL)
    {
        p=g_snake;
        g_snake=g_snake->next;
        free(p);
    }
}
// 获取当前移动方向
// 判断是否跟上一次方向dir相反
// return;
//更新dir为当前方向
int Determine_direction(int key)//判断方向
{
	//判断按键是否为方向键
	if (key==KEY_UP||key==KEY_DOWN||key==KEY_LEFT||key==KEY_RIGHT)
	{
		//判断当前方向与之前是否相反
		if((dir==KEY_UP&&key==KEY_DOWN)||(dir==KEY_DOWN&&key==KEY_UP)||(dir==KEY_LEFT&&key==KEY_RIGHT)||(dir==KEY_RIGHT&&key==KEY_LEFT))
		{

			return 0;
		}
	}
	dir=key;
	return -1;
}
void handle_key()//按键控制
{
	int key;
	noecho();//从键盘获取值但不显示
	keypad(stdscr,TRUE);//使用curses里的特殊方向键,一般以KEY开头
	struct Snake *node=(struct Snake*)malloc(sizeof(struct Snake));
	while(1)
	{
		key=getch();
		if(Determine_direction(key)==0)
		{
			continue;
		}
	}
}
void snake_move()//蛇的移动
{
	while(1)
	{
		
		clear();
		switch(dir)
		{
			case KEY_UP:
			if(Eat_food()==0)
			{
				add_snake(&g_snake,g_snake->x-1,g_snake->y);
				eat=1;
			}
			else
			{
				add_snake(&g_snake,g_snake->x-1,g_snake->y);
				delete_snake(g_snake);
			}
			break;
			case KEY_DOWN:
			if(Eat_food()==0)
			{
				add_snake(&g_snake,g_snake->x+1,g_snake->y);
				eat=1;
			}
			else
			{
				add_snake(&g_snake,g_snake->x+1,g_snake->y);
				delete_snake(g_snake);
			}
			break;
			case KEY_LEFT:
			if(Eat_food()==0)
			{
				add_snake(&g_snake,g_snake->x,g_snake->y-1);
				eat=1;
			}
			else
			{
				add_snake(&g_snake,g_snake->x,g_snake->y-1);
				delete_snake(g_snake);
			}
			break;
			case KEY_RIGHT:
			if(Eat_food()==0)
			{
				add_snake(&g_snake,g_snake->x,g_snake->y+1);
				eat=1;
			}
			else
			{
				add_snake(&g_snake,g_snake->x,g_snake->y+1);
				delete_snake(g_snake);
			}
			break;
            default:
            break;
		}
		if(Against_wall()==0||suicide()==0)
		{
			distory_snake();
			Creat_snake();
		}
		if(eat==1)
		{
			initfood();
			eat=0;
		}
		init_Map();
		
		refresh();
		usleep(200000);
	}

}

int main()
{
	pthread_t _t_snake_move;//线程1:蛇的移动
	pthread_t _t_handle_key;//线程2:方向判断


    initscr();
   	Creat_snake();
   	initfood();
    init_Map();

    pthread_create(&_t_snake_move,NULL,(void *)snake_move,NULL);
    pthread_create(&_t_handle_key,NULL,(void *)handle_key,NULL);

    while(1);
    endwin();
    return 0;
}

snake.c(链表处理大部分在这里面所以我分出来了)

#include<curses.h>
#include <stdlib.h>
#include "snake.h"

struct Snake *g_snake=NULL;


void add_snake(struct Snake **p,int x,int y)//增加蛇身
{
	struct Snake *snake_body=(struct Snake*)malloc(sizeof(struct Snake));
	snake_body->x=x;
	snake_body->y=y;
	snake_body->next=NULL;

	snake_body->next=*p;
	*p=snake_body;
}

void Creat_snake()//创建蛇的初始位置
{
	g_snake=(struct Snake*)malloc(sizeof(struct Snake));
	g_snake->x=2;
   	g_snake->y=3;
   	g_snake->next=NULL;
    add_snake(&g_snake,2,4);
    add_snake(&g_snake,2,5);
}
//在地图遍历寻找蛇身,找到返回0,找不到返回-1
int find_snake(struct Snake *p,int x,int y)
{
	while(p!=NULL)
	{
		if(p->x==x&&p->y==y)
		{
			return 0;
		}
	
		p=p->next;
	}
	return -1;
}



snake.h

#ifndef SNAKE_H
#define SNAKE_H

struct Snake
{
	//蛇身对应坐标
	int x;
	int y;
	struct Snake* next;
};
int find_snake(struct Snake* p, int x, int y);//在地图遍历寻找蛇身,找到返回0,找不到返回-1
void Creat_snake();//创建蛇的初始位置
void add_snake(struct Snake** p, int x, int y);//增加蛇身
void handle_key();//按键控制
int init_Map();//初始化地图
#endif 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值