C语言-贪吃蛇

文章详细介绍了如何使用C++编程语言和curses库来创建一个简单的贪吃蛇游戏,包括实时获取键盘输入、显示游戏框架、打印蛇身、自动行走以及处理蛇的方向改变。还提到了如何通过多线程实现游戏的自动行走和用户键盘输入的同步,以及在游戏中添加食物元素和处理蛇吃到食物的情况。
摘要由CSDN通过智能技术生成

贪吃蛇

一,实时获取操控键盘

需要知道操控游戏上下左右,通常<stdio.h>宏,需要获取上下左右键的函数,这里有:getchar()、gets(*str)、scanf(),这里有个问题输入字符时需要回车函数才可以拿到字符。

实时获取就会需要<curses.h>宏中的,keypad(stdscr,1)、getch()

注意:       

        1.keypad(stdscr,1);//get keypad() function 获取键盘//1:open,2:off

        2.printw()//打印

        3.int key//声明变量时,char 1Byte =8bit  -128~127   

                                                int 4Byte =32bit

         所以不能使用char类型哦,太小了,小于0402

        4. getch()//显示curses屏幕。没有就不会显示屏幕

        5.endwin();//少了屏幕显示会崩溃

#include<curses.h>

int main()
{
        int key;
        initscr();//初始化scr

        keypad(stdscr,1);//get keypad() function //1:open,2:off
        while(1)
        {
                key=getch();//get input char
                switch(key)
                {
                        case KEY_DOWN:
                        printw("DOWN\n");
                        break;

                        case KEY_UP:
                        printw("UP\n");
                        break;

                        case KEY_LEFT:
                        printw("LEFT\n");
                        break;

                        case KEY_RIGHT:
                        printw("RIGHT\n");
                        break;
                }
        }
        endwin();//少了屏幕显示会崩溃

        return 0;
}

二.显示游戏框架

#include<curses.h>

void initNcurses()
{
        initscr();
        keypad(stdscr,1);//get keypad() function //1:open,2:off
}
void gamePic()
{
        int line,row;
        for(line=1;line<=19;line++)
        {
                if(line==1)
                {
                        for(row=1;row<20;row++)
                        {
                                printw("--");
                        }
                        printw("\n");
                }
                else
                {
                        for(row=1;row<=20;row++)
                        {
                                if(row==1||row==20)
                                {
                                        printw("|");
                                }
                                else
                                {
                                        printw("  ");
                                }
                        }
                        printw("\n");
                }
                if(line==19)
                {
                        for(row=1;row<20;row++)
                        {
                                printw("--");
                        }
                        printw("\n");
                }
        }
}
int main()
{
        initNcurses();
        gamePic();

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

三,打印蛇身

#include<curses.h>

struct Snake
{
        int line;
        int row;
        struct Snake *next;
};

struct Snake node1={2,16,NULL};
struct Snake node2={2,17,NULL};
struct Snake node3={2,18,NULL};

void initNcurses()
{
        initscr();
        keypad(stdscr,1);//get keypad() function //1:open,2:off
}

int snakeBodyNode(int i,int j)//
{
        struct Snake *p;
        p=&node1;
        while(p!=NULL)
        {
                if(p->line==i && p->row==j)
                {
                        return 1;
                }
                p=p->next;
        }
        return 0;
}
void gamePic()//游戏框架|_|
{
     int line,row;
        for(line=1;line<=19;line++)
        {
                if(line==1)
                {
                        for(row=1;row<20;row++)
                        {
                                printw("--");
                        }
                        printw("\n");
                }
                else
                {
                        for(row=1;row<=20;row++)
                        {
                                if(row==1||row==20)
                                {
                                        printw("|");
                                }
                                else if (snakeBodyNode(line,row))//调用snakeBodyNode()函数
                                {
                                        printw("[]");
                                }
                                else printw("  ");
                        }
                        printw("\n");
                }
                if(line==19)
                {
                        for(row=1;row<20;row++)
                        {
                                printw("--");
                        }
                        printw("\n");
                }
       }
}

int main()
{
        initNcurses();
        node1.next=&node2;
        node2.next=&node3;

        gamePic();
        
        getch();
        endwin();
        return 0;
} 

四.自动行走

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

struct Snake
{
	int line;
	int row;
	struct Snake *next;
};
//设置全局的蛇头蛇尾变量
struct Snake *head=NULL;
struct Snake *tail=NULL;

void initNcurses()
{
	initscr();	
	keypad(stdscr,1);//get keypad() function //1:open,2:off
}

int snakeBodyNode(int i,int j)//打印蛇身
{
	struct Snake *p;
	p=head;
	while(p!=NULL)
	{	
		if(p->line==i && p->row==j)
		{
			return 1;
		}
		p=p->next;
	}	
	return 0;
}
void gamePic()//打印屏幕
{
	move(0,0);
	int line,row;
	for(line=0;line<=20;line++)
	{
		if(line==0)
		{
			for(row=0;row<=19;row++)
			{
				printw("--");		
			}
			printw("\n");
		}
		else
		{
			for(row=0;row<=20;row++)
			{
				if(row==0||row==20)
				{
					printw("|");
				}
				else if (snakeBodyNode(line,row))
				{	
					printw("[]");	
				}
				else printw("  ");
			}
			printw("\n");
		}	
		if(line==20)
		{
			for(row=0;row<=19;row++)
			{
				printw("--");		
			}
			printw("\n");
		}
	}
}

void addSnakeNode()//添加蛇身
{
	struct Snake *new=(struct Snake*)malloc(sizeof(struct Snake));
	
	new->line=tail->line;
	new->row=tail->row+1;
	new->next=NULL;
	
	tail->next=new;
	tail = new;
}

void initSnake()//初始化蛇头
{
	struct Snake *p;
	while(head!=NULL)
	{
		p=head;
		head=p->next;
		free(p);
	}
	head=(struct Snake*)malloc(sizeof(struct Snake));
	head->line=1;
	head->row=1;
	head->next=NULL;

	tail=head;

	addSnakeNode();
	addSnakeNode();
}
void deleteSnake()//删除一个node
{
	struct Snake *p;
	p=head;
	head=p->next;
	free(p);
}
void rightMoveSnake()//向右移动
{
	addSnakeNode();
	deleteSnake();

	if(tail->line==0||tail->row==0||tail->line==20||tail->row==20)
	{
		initSnake();
	}
}
int main()
{
	int con;
	initNcurses();
	initSnake();
	gamePic();
	
		while(1)//自动行走
		{
			rightMoveSnake();
			gamePic();
			refresh();//刷新屏幕
			usleep(200000);//时间为200微秒 0.2秒
		}
	getch();
	endwin();
	return 0;
}

五.如何边边自动行走,边输入键盘,并获取键盘的值

#include<pthread.h>//引入线程

int key;

void* refreshPic()
{
    while(1)
    {
        rightMoveSnake();
        gamePic();
        refresh();        
        usleep(200000);
    }

}

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

int main()
{
    pthread_t th1;
    pthread_t th2;  
    pthread_create(&th1,NULL,refreshPic,NULL);
    pthread_create(&th2,NULL,changeDir,NULL);
    while(1);    
    getch();
    endwin();
    return 0;
}

六.改变方向

定义方向

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

void turn(int direction)//取绝对值,目的是为了过滤上下、左右方向切换的情况
{
    if(abs(dir) != abs(direction))//abs();函数为取绝对值
    {
        dir=direction;
    }
}

void addSnakeNode()//新加的蛇身,根据dir方向来加蛇身
{
    struct Snake *new=(struct Snake*)malloc(sizeof(struct Snake));
    switch(dir)
    {
        case RIGHT:
            new->line=tail->line;
            new->row=tail->row+1;        
        break;
        case LEFT:
            new->line=tail->line;
            new->row=tail->row-1;
        break;
        case UP:
            new->line=tail->line-1;
            new->row=tail->row;
        break;
        case DOWN:
            new->line=tail->line+1;
            new->row=tail->row;
        break;
    }
    new->next=NULL;
    tail->next=new;
    tail = new;
}

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

#define UP    -1
#define DOWN   1
#define LEFT  -2
#define RIGHT  2
 
struct Snake
{
	int line;
	int row;
	struct Snake *next;
};

struct Snake *head=NULL;
struct Snake *tail=NULL;
int key;
int dir;

void initNcurses()
{
	initscr();	
	keypad(stdscr,1);//get keypad() function //1:open,2:off
    noecho();
}

int snakeBodyNode(int i,int j)
{
	struct Snake *p;
	p=head;
	while(p!=NULL)
	{	
		if(p->line==i && p->row==j)
		{
			return 1;
		}
		p=p->next;
	}	
	return 0;
}
void gamePic()
{
	move(0,0);
	int line,row;
	for(line=0;line<=20;line++)
	{
		if(line==0)
		{
			for(row=0;row<=19;row++)
			{
				printw("--");		
			}
			printw("\n");
		}
		else if(line>0&&line<20)
		{
			for(row=0;row<=20;row++)
			{
				if(row==0||row==20)
				{
					printw("|");
				}
				else if (snakeBodyNode(line,row))
				{	
					printw("[]");	
				}
				else printw("  ");
			}
			printw("\n");
		}	
		if(line==20)
		{
			for(row=0;row<=19;row++)
			{
				printw("--");		
			}
			printw("\n");
			printw("chenlichen,key=%d,dir=%d\n",key,dir);
		}
	}
}

void addSnakeNode()//新加的蛇身,根据dir方向来加蛇身
{
	struct Snake *new=(struct Snake*)malloc(sizeof(struct Snake));
	
	switch(dir)
	{
		case RIGHT:
			new->line=tail->line;
			new->row=tail->row+1;		
		break;
		case LEFT:
			new->line=tail->line;
			new->row=tail->row-1;
		break;
		case UP:
			new->line=tail->line-1;
			new->row=tail->row;
		break;
		case DOWN:
			new->line=tail->line+1;
			new->row=tail->row;
		break;
	}
	
	new->next=NULL;
	tail->next=new;
	tail = new;
}

void initSnake()
{
	struct Snake *p;
	dir=RIGHT;//给一个默认的方向“右”
	while(head!=NULL)
	{
		p=head;
		head=p->next;
		free(p);
	}
	head=(struct Snake*)malloc(sizeof(struct Snake));
	head->line=1;
	head->row=1;
	head->next=NULL;

	tail=head;

	addSnakeNode();
	addSnakeNode();
	addSnakeNode();
}
void deleteSnake()
{
	struct Snake *p;
	p=head;
	head=p->next;
	free(p);
}
void rightMoveSnake()
{
	addSnakeNode();
	deleteSnake();

	if(tail->line==0||tail->row==0||tail->line==20||tail->row==20)
	{
		initSnake();
	}
}

void* refreshPic()
{
	while(1)
	{
		rightMoveSnake();
		gamePic();
		refresh();		
		usleep(200000);
	}

}

void turn(int direction)//取绝对值,目的是为了过滤上下、左右方向切换的情况
{
	if(abs(dir) != abs(direction))//abs();函数为取绝对值
	{
		dir=direction;
	}
}
void* changeDir()
{
	while(1)
	{
		key=getch();
		switch(key)
		{
			case KEY_RIGHT:
				turn(RIGHT);		
				break;
			case KEY_LEFT:
				turn(LEFT);		
				break;
			case KEY_UP:
				turn(UP);		
				break;
			case KEY_DOWN:
				turn(DOWN);		
				break;
		}
	}
}
int main()
{
	pthread_t th1;
	pthread_t th2;
	
	initNcurses();
	initSnake();
	gamePic();
	
	pthread_create(&th1,NULL,refreshPic,NULL);
	pthread_create(&th2,NULL,changeDir,NULL);
		
	while(1);	
	getch();
	endwin();
	return 0;
}

void initNcurses()
{
    initscr();    
    keypad(stdscr,1);//get keypad() function //1:open,2:off
    noecho();//初始化ncurses()时,防止其他不想要的键盘值,显示到屏幕上
}

七.吃到食物

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

#define UP    -1
#define DOWN   1
#define LEFT  -2
#define RIGHT  2
 
struct Snake
{
	int line;
	int row;
	struct Snake *next;
};

struct Snake *head=NULL;
struct Snake *tail=NULL;
int key;
int dir;

struct Snake food;


void initFood()//初始化食物坐标,目前不随机生成位置
{
	static int x=6;
	static int y=4;

	food.line=x;
	food.row=y;
	food.next=NULL;

	x+=1;
	y+=1;
}

void initNcurses()
{
	initscr();	
	keypad(stdscr,1);//get keypad() function //1:open,2:off
	noecho();
}

int haveSnakeNode(int i,int j)
{
	struct Snake *p;
	p=head;
	while(p!=NULL)
	{	
		if(p->line==i && p->row==j)
		{
			return 1;
		}
		p=p->next;
	}	
	return 0;
}
int haveFood(int i,int j)//扫描屏幕坐标,找到食物的位置打印##
{
	if(food.line==i && food.row==j)
	{
		return 1;
	}
	return 0;
}
void gamePic()
{
	move(0,0);
	int line,row;
	for(line=0;line<=20;line++)
	{
		if(line==0)
		{
			for(row=0;row<=19;row++)
			{
				printw("--");		
			}
			printw("\n");
		}
		else if(line>0&&line<20)
		{
			for(row=0;row<=20;row++)
			{
				if(row==0||row==20)
				{
					printw("|");
				}
				else if (haveSnakeNode(line,row))
				{	
					printw("[]");	
				}
				else if (haveFood(line,row))
				{
					printw("##");
				}
				else printw("  ");
			}
			printw("\n");
		}	
		if(line==20)
		{
			for(row=0;row<=19;row++)
			{
				printw("--");		
			}
			printw("\n");
			printw("chenlichen,key=%d,dir=%d\n",key,dir);
		}
	}
}

void addSnakeNode()
{
	struct Snake *new=(struct Snake*)malloc(sizeof(struct Snake));
	
	switch(dir)
	{
		case RIGHT:
			new->line=tail->line;
			new->row=tail->row+1;		
		break;
		case LEFT:
			new->line=tail->line;
			new->row=tail->row-1;
		break;
		case UP:
			new->line=tail->line-1;
			new->row=tail->row;
		break;
		case DOWN:
			new->line=tail->line+1;
			new->row=tail->row;
		break;
	}
	
	new->next=NULL;
	tail->next=new;
	tail = new;
}

void initSnake()
{
	struct Snake *p;
	dir=RIGHT;
	while(head!=NULL)
	{
		p=head;
		head=p->next;
		free(p);
	}
	initFood();
	head=(struct Snake*)malloc(sizeof(struct Snake));
	head->line=1;
	head->row=1;
	head->next=NULL;

	tail=head;

	addSnakeNode();
	addSnakeNode();
	addSnakeNode();
}
void deleteSnake()
{
	struct Snake *p;
	p=head;
	head=p->next;
	free(p);
}
void moveSnake()
{
	addSnakeNode();
	if(haveFood(tail->line,tail->row))//重点:判断蛇吃到食物不删掉身体node
	{
		initFood();
	}
	else
	{
		deleteSnake();
	}
	if(tail->line==0||tail->row==0||tail->line==20||tail->row==20)
	{
		initSnake();
	}
}

void* refreshPic()
{
	while(1)
	{
		moveSnake();
		gamePic();
		refresh();		
		usleep(200000);
	}

}

void turn(int direction)
{
	if(abs(dir) != abs(direction))
	{
		dir=direction;
	}
}
void* changeDir()
{
	while(1)
	{
		key=getch();
		switch(key)
		{
			case KEY_RIGHT:
				turn(RIGHT);		
				break;
			case KEY_LEFT:
				turn(LEFT);		
				break;
			case KEY_UP:
				turn(UP);		
				break;
			case KEY_DOWN:
				turn(DOWN);		
				break;
		}
	}
}
int main()
{
	pthread_t th1;
	pthread_t th2;
	
	initNcurses();
	initSnake();
	gamePic();
	
	pthread_create(&th1,NULL,refreshPic,NULL);
	pthread_create(&th2,NULL,changeDir,NULL);
		
	while(1);	
	getch();
	endwin();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值