源码
/**
* 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