源码
/** * FileName: snakec* Author:PowerKing * Version:V1.0* Date:2024.6.28* Description: 贪吃蛇小游戏*/#include <curses.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>/*贪吃蛇游戏
*/#define UP 1
#define DOWN -1
#define LEFT 2
#define RIGHT -2
struct Snake
{//蛇身子节点int row;int col;struct Snake *next;
};struct Snake food;void initFood()
{int x = rand()%20;int y = rand()%20;food.row = x;food.col = y;
}struct Snake *head = NULL;
struct Snake *tail = NULL;
int key;
int dir;
void initNcurse()
{initscr();keypad(stdscr,1);noecho();//防止地图乱。
}int hasSnakeNode(int i, int j)
{struct Snake *p;p = head;while(p !=NULL){if(p->row == i && p->col == j){return 1;}p = p->next;}return 0;
}int hasFood(int i, int j)
{if(food.row == i && food.col ==j){return 1;}return 0;
}void gamePic()
{ int row;int col;//移动光标,目的,覆盖原地图位置move(0,0);for(row = 0; row < 20; row++){if(row == 0){for(col = 0; col < 20; col++){printw("--");}printw("\n"); }if(row >=0 && row <=19 ){for(col = 0; col <= 20; col++){if(col == 0 || col == 20){printw("|");}else if(hasSnakeNode(row,col)){printw("[]");}else if(hasFood(row,col)){printw("##");}else{printw(" ");}} printw("\n");}if(row == 19){for(col = 0; col < 20; col++){printw("--");} printw("\n");printw("By PowerKing,key=%d,food x = %d,y=%d\n",key,food.row,food.col); }}
}
void addNode()
{struct Snake *new = (struct Snake *)malloc(sizeof(struct Snake));new->next = NULL;switch(dir){case UP:new->row = tail->row-1; new->col = tail->col;break;case DOWN:new->row = tail->row+1;new->col = tail->col;break;case LEFT://左的逻辑,跟刷新速度有关,刷新够快,同一行左键已经刷新了好几个,就感官上看着正常了new->row = tail->row;new->col = tail->col-1;break;case RIGHT:new->row = tail->row;new->col = tail->col+1;break;}tail->next = new;tail = new;
}
void initSnake()
{struct Snake *p = NULL;//初始方向dir = RIGHT;//撞墙会重新开局,重新开局需要把原来的蛇给释放掉while(head !=NULL){p = head;head = head->next;free(p);}head = (struct Snake *)malloc(sizeof(struct Snake));head->row = 2;head->col = 2;head->next= NULL;tail = head;addNode();addNode();
}
void deleNode(){struct Snake *p;p = head;head = head->next;free(p);
}int ifSnakeDie()
{struct Snake *p;p = head;//判断是否撞墙if(tail->row < 0 || tail->row == 20 || tail->col == 0 || tail->col == 20){return 1;}//判断是否自己头碰到身子while(p->next != NULL){if(p->row == tail->row && p->col == tail->col){return 1;}p = p->next;}return 0;
}void moveSnake(){addNode();//如果吃到食物,重新生成一个食物,不必删除节点if(hasFood(tail->row,tail->col)){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;pthread_t t2;initNcurse();initSnake();initFood();gamePic();pthread_create(&t1,NULL,refreshJieMian,NULL);//两个线程之间加个时延,这样不会同时瞬间操作,造成地图紊乱信息出现。usleep(1000);pthread_create(&t2,NULL,changeDir,NULL);while(1);getch();endwin();return 0;
}
运行
安装有gcc编译器。
执行编译命令:
gcc snake.c -o snake -lcurses -lpthread
./snake