前提环境准备
- Linux开发环境(虚拟机)
- 安装NCurses库
对C语言学习的阶段性总结
使用:C语言的基本语法,链表,Linux基础,NCurses库等
为什么要用到NCurses
NCurses是一个程序库,它提供了 API,可以允许程序员编写独立于终端的基于文本的用户界面。它是一个虚拟终端中的“类 GUI”应用软件工具箱。它还优化了屏幕刷新方法,以减少使用远程 shell 时遇到的延迟。(转载)
简单来说:这个贪吃蛇的项目要用到方向键的移动,要对操作的灵敏度和画面的刷新有一定的要求,如果用传统的scanf()来获取用户的输入,用户输入后还要回车才能完成,不利于游戏的运行,而且贪吃蛇的游戏页面时刻在扫描刷新,对页面刷新要求高,对键盘的输入反应要求也高
NCurses的安装就不介绍了,可以去自行搜索安装
NCurses的简单使用
#include <curses.h>
int main()
{
int key;
initscr(); //初始化Ncurses (必须有)
keypad(stdscr,1);//Reject from stdscr ,1 (allow Reject) //允许接收特殊按键(如上下左右)
while(1)//循环扫描按键按下情况
{
key=getch();
switch(key)
{
case KEY_DOWN:
printw("Down\n");//相当于<stdio.h>库中的printf()
break;
case KEY_UP:
printw("Up\n");
break;
case KEY_LEFT:
printw("Left\n");
break;
case KEY_RIGHT:
printw("Right\n");
break;
}
// printw("your input: %d\n",key);
}
endwin(); //一定要写,不写页面退出时可能会崩溃乱码
return 0;
}
~
很多人会发现case 的参数是什么,可以打开curses头文件查看说明
里面用数字标识了键盘按下的结果,当然数字对我们使用很不友好,所以用宏定义创建好了,供我们使用
当然我们也要知道Ncurses怎么运行
运行结果
前序准备
#include <curses.h>
#include <stdlib.h>
#include <pthread.h>
#define Up 1
#define Down -1
#define Left 2
#define Right -2
int cmd;
int dir;
void initNncurse()
{
initscr();
keypad(stdscr,1);
noecho();
}
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head=NULL;
struct Snake *tail=NULL;
struct Snake food;
简单的知道怎么使用,我们可以开始贪吃蛇游戏的制作
贪吃蛇游戏界面
//检查是否有界面
int hasSnakeNode(int i,int j)
{
struct Snake *p =head;
while(p!=NULL)
{
if(p->hang==i && p->lie ==j)
{
return 1;
}
p=p->next;
}
return 0;
}
//检查是否有食物
int hasFood(int i,int j)
{
if(food.hang==i && food.lie ==j)
{
return 1;
}
return 0;
}
void initPic() //初始化地图 20*20
{
int Row;
int Column;
move(0,0);
for(Row=0;Row<20;Row++)
{
if(Row==0)
{
for(Column=0;Column<20;Column++)
{
printw("--");
}
printw("\n");
}//0 Row
if(Row>=0 &&Row<=19)
{
for(Column=0;Column<=20;Column++)
{
if(Column==0 ||Column==20)
{
printw("|");
}
else if(hasSnakeNode(Row,Column))
{
printw("[]");
}
else if(hasFood(Row,Column))
{
printw("$$");
}
else
{
printw(" ");
}
}
printw("\n");
}
if(Row==19)
{
for(Column=0;Column<20;Column++)
{
printw("--");
}
printw("\nAuthor: Xwd\n");
}
}
}
贪吃蛇身体创建、食物创建
void initSnake()
{
initFood();
struct Snake *p;
dir=Right;
while(head!=NULL)
{
p=head;
head=head->next;
free(p);
}
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=1;
head->lie=1;
head->next=NULL;
tail=head;
addNode();
addNode();
addNode();
}
void initFood()
{
int x=rand()%20; //在20*20格子中随机生成
int y=rand()%20;
food.hang=x;
food.lie=y;
}
贪吃蛇身体增加
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 deleteNode()
{
struct Snake *p=head;
head=head->next;
free(p);
}
蛇的移动
void moveSnake()
{
addNode();
if(hasFood(tail->hang,tail->lie))
{
initFood();
}
else
{
deleteNode();
}
if(isDie())
{
initSnake();
}
}
蛇是否死亡(撞墙、吃自己)
int isDie()
{
struct Snake *p=head;
if(tail->lie==0 || tail->hang<0 ||tail->lie==20 ||tail->hang==20)
{
return 1;
}
while(p->next!=NULL)
{
if((p->hang==tail->hang) && (p->lie==tail->lie))
{
return 1;
}
p=p->next;
}
return 0;
}
蛇的方向的改变
void turn(int direction)//turn snake if Up and Down(Left and Right) putin no turn
{
if(abs(direction)!=abs(dir))//绝对值判断蛇是否有方向上的变化
//例如在右移的时候按方向左是无效的
{
dir=direction;
}
}
void *changeDir()
{
while(1)
{
cmd=getch();
switch(cmd)
{
case KEY_DOWN:
turn(Down);
break;
case KEY_UP:
turn(Up);
break;
case KEY_LEFT:
turn(Left);
break;
case KEY_RIGHT:
turn(Right);
break;
}
// printw("your input: %d\n",key);
}
}
时刻刷新页面
void *refresheFace()
{
while(1){
moveSnake();
initPic();
refresh();
usleep(100000);
}
}
当然我们想要在贪吃蛇运行的同时,时刻扫描键盘方向有没有改变,还有程序要保持时刻运行,这里我们不得不用到线程的创建
int main()
{
initNncurse();
initSnake();
initFood();
initPic();
pthread_t th1,th2;
pthread_create(&th1,NULL,refresheFace,NULL);//线程1创建 刷新界面
pthread_create(&th2,NULL,changeDir,NULL);//线程2创建 扫描方向键
while(1);
getch();
endwin();
return 0;
}
效果展示
write date:202212172310