C链表 Ncurses 制作贪吃蛇小游戏

关键点:

1:地图界面的刷新 用22x22的方格,作为地图空间,第一和最后一行(列),作为边界;
边界:*
蛇身:【】
食物:##
2:蛇身的制作及移动规则,方向控制(按键响应)
3:食物刷新
4:按键响应、

为了实现上下左右的按键响应控制和界面显示,调用了ncurses库,因为简单易用。
initscr():设定并初始化ncurses要用到的一些值;
endwin():恢复终端机到使用前的状态,和initscr作用呼应;
getch():等待获取用户输入;
printw:打印,ncurses库封装好的printf
keypad(stdscr,1):功能按键设定
refersh():刷新界面,有时候界面不会马上刷新出来

要用到的功能按键:

#define KEY_DOWN        0402            /* down-arrow key */
#define KEY_UP          0403            /* up-arrow key */
#define KEY_LEFT        0404            /* left-arrow key */
#define KEY_RIGHT       0405            /* right-arrow key */

ncurses 按键响应代码模板:

#include<curses.h>




int main()
{
	initscr();
	keypad(stdscr,1);
		
	int key;

	while(1){
	
		key = getch();

		printw("key = %d\n",key);
	
	}


	endwin();

	return 0;

}

完整代码如下:

#include<stdio.h>
#include<curses.h>
#include <stdlib.h>
#include <unistd.h>
#include<pthread.h>
#include<string.h>

struct snake{		//小蛇结构体

	int hang;

	int lie;

	struct snake *next;

};



struct snake *head = NULL;	//蛇头节点
struct snake *tail = NULL;	//蛇尾节点

struct snake food;	//食物	

int dir ;	//键盘输入方向

char *Dir ;	//当前方向

int score;	//游戏得分

void initncurses(){	//初始化ncurses库

	initscr();		
	keypad(stdscr,1);	//按键响应
}


void gamepic(){

	int hang;
	int lie;

	struct snake *p;
	p = head;
	int k = 0;

	move(0,0);
	for(hang = 0;hang < 22;hang++){

		if(hang == 0){

			printw("\n\nSNAKE            score:%d\n",score);

			for(lie = 0;lie < 22;lie++){
				if(lie > 0 && lie < 21){

					printw("**");

				}else if(lie == 0 || lie == 21){

					printw("*");

				}

			}

			printw("\n");

		}else if(hang > 0 && hang < 21){


			for(lie = 0;lie < 22;lie++){

				if(lie == 0 || lie == 21){

					printw("*");

				}else {


					while(p != NULL){

						if(p->hang == hang && p->lie == lie){

							printw("[]"); 


							k = 1;		

						}

						p = p->next;

					}

					if(k != 1){

						if(hang == food.hang && lie == food.lie){

							printw("##");

						}else{
							printw("  ");
						}

					}				

					k = 0;

					p = head;	

				}

			}

			printw("\n");

		}else if(hang == 21){

			for(lie = 0;lie <  22;lie++){

				if(lie > 0 && lie < 21){

					printw("**");

				}else if(lie == 0 || lie == 21){

					printw("*");

				}


			}

			printw("\n\n");
			printw("make by zengtiejiang	Direction: %s ",Dir);

		}	

	}




}

void initfood(){

	struct snake *p;
	p = head;

	int hang = rand()%21;	//随机一个0到20的数
	int lie  = rand()%21;

	while(p != NULL){
		if((hang == p->hang && lie == p->lie) || hang == 0 || lie == 0){
			hang = rand()%21;	
			lie  = rand()%21;
			p = head;
		}

		p = p->next;
	}


	food.hang = hang;
	food.lie  = lie;

}


void initDir(){

	Dir = (char *)malloc(16);
	memset(Dir,'\0',16);
	Dir ="RIGHT";
	dir =KEY_RIGHT ;

}

void addnode(){

	struct snake *new;


	new = (struct snake *)malloc(sizeof(struct snake));
	switch(dir){

		case KEY_DOWN:
			if(Dir != "UP   "){			//防止小蛇反向走位,将方向改正,并向前加一个节点
				new->hang = head->hang+1;
				new->lie = head->lie ;
				Dir = "DOWN ";
			}else{
				dir = KEY_UP;
				Dir != "UP   ";
                                new->hang = head->hang-1;
                                new->lie = head->lie ;
				

			}
			break;	
		case KEY_UP:
			if(Dir != "DOWN "){
				new->hang = head->hang-1;
				new->lie = head->lie ;
				Dir = "UP   ";
			}else{
			
				dir = KEY_DOWN;
				Dir != "DOWN ";
                                new->hang = head->hang+1;
                                new->lie = head->lie ;
				
			
			}
			break;			
		case KEY_LEFT:
			if(Dir != "RIGHT"){
				new->hang = head->hang;
				new->lie = head->lie - 1;
				Dir = "LEFT ";
			}else{
			
				dir = KEY_RIGHT ;
				Dir != "RIGHT";
                                new->hang = head->hang;
                                new->lie = head->lie + 1;
				

			}
			break;	
		case KEY_RIGHT:
			if(Dir != "LEFT "){
				new->hang = head->hang;
				new->lie = head->lie + 1;
				Dir = "RIGHT";
			}else{
			
				dir = KEY_LEFT;
				Dir != "LEFT ";
                                new->hang = head->hang;
                                new->lie = head->lie - 1;
				

			}
			break;	
	}

	new->next = head;

	head = new;

}

void deletenode(){

	struct snake *p;
	p = head;

	while(p != NULL){

		if(p->next->next == NULL){

			tail = p;
			tail->next = NULL;
			p = p->next;
			free(p);

		}else {

			p = p->next;
		}	

	}


}


void initsnake(){
	
	struct snake *p;
	initDir();

	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();
	score = 0;


}
int eatitself(){

         struct snake *p;
         struct snake *q;
         p = head->next;

		while( p != NULL){

			if(p->hang == head->hang && p->lie == head->lie){	//蛇撞到自己

				return 1;

			}

			p = p->next;

		}

	return 0;
}

void movesnake(){

	if(head->hang == 0 || head->hang == 21 || head->lie == 0 || head->lie == 21){	//撞墙

		initsnake();
		initfood();

	}else if(head->hang == food.hang && head->lie == food.lie){	//吃到食物

		initfood();
		score = score+1;
		addnode();

	}else if(eatitself() == 1){	//吃到自己

		initsnake();
		initfood();

	}else{		//正常移动

		addnode();
		deletenode();
		

	}

}


void *changedir(){

	while(1){

		dir = getch();


	}



}

void *refreshface(){

	while(1){


		movesnake();

		if(head->hang != 0 && head->hang != 21 && head->lie != 0 && head->lie != 21  ){  //撞墙时不刷新地图
			
			if(eatitself() == 0){	
				gamepic();
			}	

		}

		refresh();
		usleep(200000);

	}



}




int main(){

	pthread_t t1;
	pthread_t t2;  //定义线程名字

	initncurses();  //初始化ncurses

	initDir();	//初始化方向

	initsnake();	//创建蛇身链表

	initfood();	//随即刷新食物

	gamepic();	//初始化地图 

	pthread_create(&t1,NULL,refreshface,NULL);//刷新界面线程
	pthread_create(&t2,NULL,changedir,NULL);//按键响应线程



	while(1);	//防止主进程退出

	getch();
	endwin();


	return 0;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

elaot

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

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

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

打赏作者

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

抵扣说明:

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

余额充值