1.1头文件
点击查看代码
#include<stdio.h> #include<curses.h> //包含curses插件 #include<stdlib.h> //srand #include<unistd.h> //sleep头文件 #include<stdbool.h> //bool条件判断 #include <pthread.h> //线程头文件 #include <time.h> //时间头文件
define WIDHT 20 //地图长度
define HEIGHT 20 //地图宽度
define MIN 0 //最小值宏定义
define UP 1 //蛇的方向上
define DOWN -1 //下
define LEFT 2 //左
define RIGHT -2 //右
//定义一个结构体snake_t
typedef struct snake
{
int row;
int col;
struct snake *next;
}snake_t;
typedef struct food
{
int row;
int col;
}food_t;
snake_t *snake_head = NULL; //蛇的头指针
snake_t *snake_tail= NULL; //蛇的尾巴
food_t food; //初始化一个食物
int dir; //方向 //捕获的方向
int key; //按键的值
void add_snake_body(); //添加一个蛇的身子函数
void food_init(); //初始化食物
void start_init(); //开始初始化
snake_t* create_snake(int row, int col); //创建一条蛇,row行,col列
int has_snake_body(int row, int col); //判断当前坐标是否有蛇的身子
void map_init(int witdh, int height); //刷新地图
void initscr_func(); //初始化scr函数
void head_delete_snake_body(); //删除蛇身子
void snake_move(); //蛇的移动函数
bool snake_need_init(); //判断蛇是否撞墙,或者咬到自己,需要重开
void turn_abs(int dirction); //取绝对值函数
int food_location(int row,int col); //判断当前坐标是否有食物
bool snake_bite_itself(); //判断蛇是否咬到了自己
void initscr_func(){
initscr();
keypad(stdscr,true);
noecho(); //不回显
}
//贪吃蛇创建
snake_t* create_snake(int row, int col){
snake_head = (snake_t*)malloc(sizeof(snake_t)); //蛇头分配内存
snake_head->row = row;
snake_head->col = col;
snake_head->next = NULL;
snake_tail=snake_head;
add_snake_body(); //添加蛇身体
add_snake_body();
dir=RIGHT; //初始方向为右
return snake_head;
}
void start_init(){
initscr_func();
create_snake(2,3); //创建蛇
food_init(); //初始化食物
map_init(WIDHT,HEIGHT);
refresh(); //刷新窗口
}
void food_init(){
srand(time(NULL));
food.row=rand()%(HEIGHT-2)+1;
food.col=rand()%(WIDHT-1)+1;
}
//判断是否蛇吃到了食物
int has_food(int row,int col){
if(snake_tail->rowrow&&snake_tail->colcol){
return 1;
}
else{
return 0;
}
}
//判断食物位置
int food_location(int row,int col){
if (rowfood.row&&colfood.col){
return 1;
}
else{
return 0;
}
}
//判断蛇是否撞到了自己
bool snake_bite_itself(){
snake_t *p=snake_tail;
snake_t *q=snake_head;
while(q->next!=NULL){
if(p->rowq->row&&p->colq->col){
return true;
}
q=q->next;
}
}
//添加贪吃蛇身体
void add_snake_body(){
snake_t snake_body = (snake_t)malloc(sizeof(snake_t)); //蛇身体分配内存
while (snake_tail->next!=NULL){
snake_tail=snake_tail->next; //找到尾节点
}
snake_body->next = NULL; //蛇身体的下一个节点为空
//根据按键不同,蛇身体的位置不同 switch (dir) { case UP: snake_body->row = snake_tail->row - 1; snake_body->col = snake_tail->col; break; case DOWN: snake_body->row = snake_tail->row + 1; snake_body->col = snake_tail->col; break; case LEFT: snake_body->row = snake_tail->row; snake_body->col = snake_tail->col - 1; break; case RIGHT: snake_body->row = snake_tail->row; snake_body->col = snake_tail->col + 1; break; default: break; } snake_tail->next = snake_body; //尾节点的下一个节点指向蛇身体 snake_tail=snake_body; //更新尾节点
}
//delete snake body(head delete)
void head_delete_snake_body(){
snake_t *p;
if(snake_head!=NULL){
p=snake_head; //保存头节点
snake_head=snake_head->next; //头节点指向下一个节点
}
free(p); //释放头节点内存
}
//judge has snake body
int has_snake_body(int row, int col){
snake_t *p = snake_head;
while(p!=NULL){
if(p->rowrow&&p->colcol){
return 1;
}
p = p->next;
}
return 0;
}
bool snake_need_init(){
// if(snake_head->row0||snake_head->col0||snake_head->row20||snake_head->col20){
// return true;
// }
// else
if (snake_tail->rowMIN||snake_tail->colMIN||snake_tail->rowHEIGHT-1||snake_tail->colHEIGHT-1){
return true;
}
else{ return false; }
}
//right move
void snake_move(){
//判读是否需要重新开始游戏 if (snake_need_init()==true || snake_bite_itself()==true){ snake_t *old_sanke_head =NULL; //游戏初始前,回收上一次蛇身子 while(snake_head!=NULL){ old_sanke_head = snake_head; snake_head = snake_head->next; free(old_sanke_head); } create_snake(6,6); //创建蛇 food.col=2; food.row=2; map_init(WIDHT,HEIGHT); } //不需要重新开始游戏 else{ add_snake_body(); //添加蛇身体 //吃到了食物 if (has_food(food.row,food.col)){ food_init(); //初始化食物 } //没吃到食物 else{ head_delete_snake_body(); //删除蛇结点 } map_init(WIDHT,WIDHT); refresh(); //刷新窗口 }
}
//初始化地图
void map_init(int witdh, int height)
{
int row,col;
move(MIN,MIN); //复位光标 for (row = 0; row < witdh; row++){ if(row==0){ for (col = 0; col < height; col++){ printw("--"); } printw("\n"); } else if(row>0&&row<witdh-1){ for (col = 0; col <= height; col++){ if (col==0||col==height) { printw("|"); } //判断食物位置,如果有则打印出来 else if(food_location(row,col)){ printw("##"); } else if(has_snake_body(row,col)){ printw("[]"); } else{ printw(" "); } } printw("\n"); } if(row==witdh-1){ for (col = 0; col < height; col++){ printw("--"); } printw("\n"); printw("Make buy guo,Key val:%d food location: %d,%d \n",key,food.row,food.col); } } refresh(); //刷新窗口
}
//取绝对值函数
void turn_abs(int dirction){
if(abs(dir)!=abs(dirction)){
dir=dirction;
}
}
//按键处理函数
void key_handle(){
key = getch();
switch (key)
{
case KEY_UP:
turn_abs(UP);
break;
case KEY_DOWN: turn_abs(DOWN); break; case KEY_LEFT: turn_abs(LEFT); break; case KEY_RIGHT: turn_abs(RIGHT); break; default: break; }
}
void *thread_func_1(void *arg){
while (1){
snake_move();
map_init(WIDHT,HEIGHT); //刷新地图
refresh(); //刷新窗口
usleep(200000); //延时100ms
}
}
void *thread_func_2(void *arg){
while (1){
key_handle(); //处理按键
}
}
//main
int main(int argc, char *argv[])
{
pthread_t thread1,thread2;
start_init();
pthread_create(&thread1,NULL,thread_func_1,NULL);
pthread_create(&thread2,NULL,thread_func_2,NULL);
while (1)
{
} getch(); //等待用户输入 endwin(); //关闭窗口 return 0;
}
编译环境,gcc交叉编译,ubantu18.04
使用命令: gcc -Wall -o 你的文件名 你的文件名.c -lcurses -lpthread
运行: ./curses
一两天做的,有点匆忙,不足欢迎批评指正
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术