贪吃蛇

1.最近在了解ncurses这个字符终端处理库,使用这个库写了一个简单的贪吃蛇游戏w,s,a,d控制上下左右,代码如下:


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


typedef struct _tagDirect
{
	int x;
	int y;
}Direct;


typedef struct _tagSnakeNode
{
	int x;
	int y;
	struct _tagSnakeNode* pre;
	struct _tagSnakeNode* next;

}SnakeNode,Snake;


static Direct dir;
static int fx;
static int fy;
static int length = 0;

static Snake* SnakeInit()
{
	SnakeNode* sn = (SnakeNode*)malloc(sizeof(SnakeNode));
	if (sn == NULL)
	{
		return NULL;
	}
	memset(sn,0,sizeof(SnakeNode));

	sn->next = sn->pre = sn;

	return sn;
}

//add head pos 
static int SnakeInsert(Snake* sn,int x,int y)
{
	if (sn == NULL)
	{
		return -1;
	}

	SnakeNode* node = (SnakeNode*)malloc(sizeof(SnakeNode));
	if (node == NULL)
	{
		return -2;
	}

	node->x = x;
	node->y = y;

	node->next = sn->next;
	sn->next->pre = node;

	sn->next = node;
	node->pre = sn;

	return 0;
}

//del tail pos 
static int SnakeDelete(Snake* sn)
{
	if (sn == NULL)
	{
		return -1;
	}

	
	SnakeNode* tail = sn->pre;

	tail->pre->next  = sn;
	sn->pre = tail->pre;

	free(tail);
	tail = NULL;

	return 0;
}


static void SnakeDeinit(Snake* sn)
{
	if (sn == NULL)
	{
		return;
	}
	SnakeNode* p = sn->next;
	SnakeNode* tmp = NULL;
	while(p && p->next != sn)
	{
		tmp = p;
		p = p->next;

		free(tmp);
		tmp = NULL;
	}

	free(sn);
	sn = NULL;
}

static void MakeFood()
{
	
	int x = rand()%COLS;
	if(x == 0)
		x = 1;
	int y = rand()%(LINES-2);
	if (y == 0)
		y = 1;
	move(y,x);
	printw("O");
	fx = x;
	fy = y;
}

//蛇的每一次前进,在链表的头部增加一个节点,在尾部删除一个节点
//如果蛇吃了一个食物,就不用删除节点了
static int SnakeShow(Snake* sn)
{
	int isEat = 0;
	if (sn == NULL)
	{
		return -1;
	}

	move(fy,fx);
	printw("O");

	if(sn->next->x+dir.x == COLS || sn->next->x+dir.x == 0 ||
		sn->next->y+dir.y == LINES || sn->next->y+dir.y == -1)
	{
		move(LINES/2,COLS/2);
		addstr("crash the wall,game over!");
		refresh();
		return -2;
	}

	//如果蛇头砬到自己的身体,则游戏结束
    if('@' == mvinch(sn->next->y+dir.y, sn->next->x+dir.x) )
    {
    	move(LINES/2,COLS/2);
    	addstr("crash itself,game over!");
		refresh();
    	return -3;
    }


	SnakeInsert(sn,sn->next->x+dir.x,sn->next->y+dir.y);
	
	if(sn->next->x == fx && sn->next->y == fy)
	{
		isEat = 1;
		MakeFood();
		length++;
		if(length == 20)
		{
			move(LINES/2,COLS/2);
			addstr("you are win!");
			refresh();
			return 1;
		}
	}

	if(isEat == 0)
	{
		move(sn->pre->y,sn->pre->x);
		printw(" ");
		SnakeDelete(sn);
	}
	

	move(sn->next->y,sn->next->x);
	printw("@");

	refresh();
	return 0;
}

static int  UpdateDirect(char ch)
{
	if('a' == ch)
    {
    	if(dir.x == 1)
    		return 0;
        dir.x = -1;
        dir.y = 0;
    }
    else if('w' == ch)
    {
    	if(dir.y == 1)
    		return 0;
        dir.x = 0;
        dir.y = -1;
    }
    else if('d' == ch)
    {
    	if(dir.x == -1)
    		return 0;
        dir.x = 1;
        dir.y = 0;
    }
    else if('s' == ch)
    {
    	if(dir.y == -1)
    		return 0;
        dir.x = 0;
        dir.y = 1;
    }
    else if('q' == ch)
    {
        return 1;
    }
    return 0;
}

int main(int argc, char const *argv[])
{
	/* code */
	char c = 0;
	int ret = 0;
	struct timeval timeout;

	initscr();
	cbreak();                    //把终端的CBREAK模式打开
    noecho();                    //关闭回显
    curs_set(0);                //把光标置为不可见

    srand(time(NULL));  //seed

	Snake* sn = SnakeInit();
	if (sn == NULL)
	{
		return -1;
	}
	SnakeInsert(sn,10,20);
	MakeFood();
	dir.x = 1;
	dir.y = 0;


	for(;;)
	{
		fd_set rdfds;
		FD_ZERO(&rdfds);
		FD_SET(0,&rdfds); //input
		timeout.tv_sec = 0;
		timeout.tv_usec = 500000; //500ms
		ret = select(1,&rdfds,NULL,NULL,&timeout);
		if (ret < 0)
		{
			continue;
		}

		if(FD_ISSET(0,&rdfds))
		{
			fread(&c,1,1,stdin);
			// fprintf(stderr,"have %02x\n",c);
			if(UpdateDirect(c) == 1)
			{
				move(LINES/2,COLS/2);
		    	addstr("quit!");
				refresh();
				break;
			}
		}

		// main loop
		if((ret = SnakeShow(sn)) < 0)
			break;
		if(ret == 1)
			break;
		move(0,(COLS-strlen("SCORE:XX"))/2);
		printw("SCORE:%02d",length);
		refresh();
	}

	SnakeDeinit(sn);
	getch();
	endwin();
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值