贪吃蛇游戏
总体代码实现:
#include <curses.h>//ncurse的使用可以使按键迅速响应,不需要再按回车键
//curses编译需要加“-lcurses”
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>//linux线程
#define UP 1//绝对值数值设定,可以使贪吃蛇不能通过按键直接实现往相反方向移动
#define DOWN -1
#define LEFT 2
#define RIGHT -2
struct Snake//定义蛇身坐标
{
int hang;
int lie;
struct Snake *next;
};
struct Snake food;
struct Snake *head=NULL;//定义头指针
struct Snake *tail=NULL;//尾指针
int key;
int dir;
int hasSnakeNode(int i,int j)
{
struct Snake *p;
p = head;
while(p !=NULL){
if(p->hang == i && p->lie ==j){
return 1;
}
p = p->next;
}
return 0;
}
void initFood()
{
int x= rand()%20;//可以生成随机数
int y =rand()%20;
food.hang = x;
food.lie =y;
}
int hasFood(int i,int j)
{
if(food.hang == i && food.lie ==j){
return 1;
}
return 0;
}
void initNcurse()curses界面初始化
{
initscr();
keypad(stdscr,1);//“1”代表接收“0”代表不接收
noecho();//再“ncurses”中作用是不要把无关键值显示在界面上
}
void gamePic()//打印贪吃蛇界面显示
{
int hang;
int lie;
move (0,0);//改变光标位置,实现Snake的移动
for(hang=0;hang<=20;hang++){
if(hang==0){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
}
if(hang>=1 && hang<=19){
for(lie=0;lie<=20;lie++){
if(lie==0||lie==20){
printw("|");
}else if(hasFood(hang,lie)){
printw("##");
}
else if(hasSnakeNode(hang,lie)){
printw("[]");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang == 19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("food.han=%d,food.lie=%d\n",food.hang,food.lie);
}
}
}
void deleNode()
{
struct Snake *p;
p=head;
head=head->next;
free(p);
}
void addNode()
{
struct Snake *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;
dir = RIGHT;
while(head !=NULL){
p=head;
head=head->next;
free(p);
}
initFood();
head = (struct Snake *)malloc(sizeof(struct Snake));
head->hang= 1;
head->lie =1;
head->next =NULL;
tail=head;
addNode();
addNode();
addNode();
addNode();
}
int ifSnakeDie()
{
struct Snake *p;
p = head;
if(tail->hang==0||tail->lie==0||tail->hang==20||tail->lie==20){
return 1;
}
while(p->next!=NULL){
if(p->hang==tail->hang && p->lie==tail->lie){
return 1;
}
p=p->next;
}
return 0;
}
void moveSnake()
{
addNode();
if(hasFood(tail->hang,tail->lie)){
initFood();
}else{
deleNode();
}
if(ifSnakeDie()){
initSnake();
}
}
void refreshJiemian()
{
while(1){
moveSnake();
gamePic();
refresh();//刷新界面函数
usleep(100000);
}
}
void turn (int direction)
{
if(abs(dir) != abs(direction)){
dir = direction;
}
}
void changeDir()
{
while(1){
key = getch();
switch(key){
case KEY_DOWN:
turn(DOWN);
break;
case KEY_UP:
turn(UP);
break;
case KEY_LEFT:
turn(LEFT);
break;
case KEY_RIGHT:
turn(RIGHT);
break;
}
}
}
int main()
{
pthread_t t1;//线程1,刷新界面
pthread_t t2;//线程2,方向按键
initNcurse();
initSnake();
gamePic();
pthread_create(&t1,NULL,refreshJiemian,NULL);
pthread_create(&t2,NULL,changeDir,NULL);
while(1);
getch();
endwin();//防止破坏终端显示界面
return 0;
}
运行界面
运行效果演示:
贪吃蛇运行效果
相关知识点总结:
endwin();防止破坏终端界面
getchar();不希望进程退出
abs();取绝对值函数
ncurses的使用:
编译需要在后面加 -lcurses 因为ncurses库不是默认系统带有,需要自己添加;
使用ncurses好处是可以让按键快速响应;
noecho();不要把无关的键值显示在界面上;