贪吃蛇——Linux环境下,基于Ncurse图形库的c语言的小游戏

1.一些关于ncurse的知识

1)使用ncurses原因:按键响应速度快
(2)一些ncurse函数:
initscr()//ncurse界面初始化函数
printw()//在ncurse模式下的printf
getch();//等待用户输入,如果没有这句话程序就退出了,看不到运行结果
endwin();//程序退出,调用函数来恢复shell终端的显示,如果没有这句话,shell终端会字乱码,坏掉
keypad();//设置了可以从stdscr接收键盘的功能键(快捷键)
//使用keypad(stdtcr,1);
move();//改变光标的位置
//使用move(1,1);
refresh();//刷新
noecho();//不要把功能键的信息打印出来

2.制作贪吃蛇的思路

(1)地图规划

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

(2)蛇的身子的初始化(链表)
(3)蛇向右移动(链表的添加,删除)
(4)蛇碰到边界,重新开始(初始化蛇)
(5)引入线程(方向改变和刷新界面)
(6)蛇四方向的移动(要解决不合理走位)
(7)蛇吃食物(食物的随机,链表的增加)
(8)贪吃蛇的头碰到身子(注意链表的头结点)

3.代码实现:

#include <curses.h>
#include <stdlib.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;
	int y = rand()%20;
	food.hang = x;
	food.lie = y;
}
void initNcurse(){
	initscr();
	keypad(stdscr,1);
	noecho();
}

int hasSnakeNode(int i,int j){
	struct Snake *p = head;
	while(p != NULL){
		if(p->hang == i && p->lie == j){
			return 1;
		}
		p = p->next;
	}
	return 0;
}

int hasFood(int i,int j){
	if(food.hang == i && food.lie == j){
		return 1;
	}
	return 0;
}

void initPic(){
	int hang;
	int lie;
	move(0,0);
	for(hang = 0;hang<20;hang++){
		if(hang == 0){
			for(lie = 0;lie <= 19;lie++){
				printw("--");
			}
			printw("\n");
		}
		if(hang > 0 && hang <= 19){
			for(lie = 0;lie <= 20;lie++){
				if(lie == 0 || lie == 20){
					printw("|");
				}else if(hasSnakeNode(hang,lie)){
					printw("[]");
				}else if(hasFood(hang,lie)){
					printw("##");
				}
				else{
					printw("  ");
				}
			}
			printw("\n");
		}
		if(hang == 19){
			for(lie = 0;lie <= 19;lie++){
				printw("--");
			}
		printw("\n");
		}
	}
	printw("By chenweiqiang,key = %d\n",key);
}

void addNode(){
	struct Snake *new;
	new = (struct Snake*)malloc(sizeof(struct Snake));
	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 = NULL;
	initFood();
	dir = RIGHT;
	while(p != NULL){
		p = head;
		free(p);
		p = p->next;
	}
	head = (struct Snake*)malloc(sizeof(struct Snake));
	head->hang = 2;
	head->lie = 2;
	head->next = NULL;

	tail = head;

	addNode();
	addNode();
	addNode();

}

void deleteNode(){
	struct Snake *p;
	p = head;
	head = head->next;
	free(p);
}
int ifSnakeDie(){
	struct Snake *p = head;
// 	p = head;	
	if(tail->hang == 0 || tail->hang == 20 || tail->lie ==0 || tail->lie ==20){
		return 1;
	}
	while(p->next != NULL){
		if(tail->hang == p->hang && tail->lie == p->lie){
			return 1;
		}
		p = p->next;
	}
	return 0;
}
void moveSnake(){
	
	if(tail->hang == food.hang && tail->lie == food.lie){
		addNode();
		initFood();
	}
	addNode();
	deleteNode();
	
	if(ifSnakeDie()){
		initSnake();
	}
}

void turn(int drection){
	if(abs(dir) != abs(drection)){
		dir = drection;
	}
}
void* changeDir(){
	
	while(1){
		key = getch();
		switch(key){
			case KEY_UP:
				turn(UP);
				break;
			case KEY_DOWN:
				turn(DOWN);
				break;
			case KEY_LEFT:
				turn(LEFT);
				break;
			case KEY_RIGHT:
				turn(RIGHT);
				break;
		}
	}
}

void* refreshSnake(){
	while(1){
		moveSnake();
		initPic();
		refresh();
		usleep(100000);
	}

}

int main(){
	pthread_t t1;
	pthread_t t2;
	
	initNcurse();
	initPic();
	initSnake();	

	pthread_create(&t1,NULL,refreshSnake,NULL);
	pthread_create(&t2,NULL,changeDir,NULL);
	//pthread_create(&tid, NULL, fun, NULL);
	while(1);
	getch();
	endwin();
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值