贪吃蛇
ncurse的使用
需要包含头文件
#include<curses.h>
ncurse的介绍
C语言的ncurses库是一个用于控制终端屏幕的库。它提供了一组函数和数据结构,可以用于在终端上创建文本界面和图形界面。
ncurses库允许你在终端上进行以下操作:
- 控制光标的位置
- 设置文本颜色和背景色
- 在屏幕上绘制文本和图形
- 处理键盘输入和鼠标事件
- 创建菜单和对话框等用户界面元素
使用ncurses库,你可以编写交互式的终端应用程序,如文本编辑器、游戏、终端界面的图形化工具等。
ncurses库在Unix-like系统上广泛使用,包括Linux和macOS。它是一个非常强大和灵活的库,可以帮助你创建复杂的终端应用程序。
常用的ncurse的函数
initscr();
该函数可以调用ncurse的引擎
printw();
printw();使用方式和printf一样,原样输出
getch();
防止程序退出,应该和getchar()使用起来差不多
endwin();
程序退出后防止乱码
详细解释上面函数
练习使用上面的函数
代码:
#include<curses.h>
int main()
{
char data;//一个字符变量
initscr();//初始化界面
printw("plase scanf of data\n");
data=getch();//获取字符
printw("\n you scanf of %c\n",data);
getch();//防止程序退出
endwin();//防止出现乱码
return 0;
}
ncurses获取上下左右键
在C语言中,keypad函数是ncurses库中的一个函数,用于启用或禁用终端键盘的特殊键盘码。
keypad(stdscr, 1)是将ncurses库中的stdscr窗口启用特殊键盘码的函数调用。
stdscr是ncurses库中的一个全局变量,表示标准屏幕窗口。通过调用keypad(stdscr, 1),我们可以启用特殊键盘码,使得getch()函数可以返回特殊键盘码。
通过上面函数我们可以准确获得上下左右键的命令,用于控制贪吃蛇的行动
代码:
#include<curses.h>
上面的头文件对上下左右键进行了引用
上:KEY_UP
下:KEY_DOWN
左:KEY_LEFT
右:KEY_RIGHT
#include<curses.h>
int main() {
int data;
initscr();//界面初始化
keypad(stdscr, 1); //使用界面的键盘输入
while (1) {
data = getch(); //获取data的值进行输入
switch (data) {
case KEY_DOWN:
printw("DOWN\n");
break;
case KEY_UP:
printw("UP\n");
break;
case KEY_LEFT:
printw("LEFT\n");
break;
case KEY_RIGHT:
printw("RIGHT\n");
break;
}
}
getch();//防止程序退出
endwin();//防止乱码
return 0;
}
运行结果:
贪吃蛇地图绘制
绘制一个20x20的地图
地图的第一行
代码:注意看注释
#include<curses.h>//需要包含这个头文件
void ncurses1() {
initscr();//界面初始化的函数
keypad(stdscr, 1); //使用特殊键盘
}
void gamemap() {
//定义行和列
int hang, lie;
//地图是20行,建立循环20次
for (hang = 0; hang < 20; hang++) {
if (hang == 0) { //对第一行进行绘制
for (lie = 0; lie < 20; lie++) {
printw("--");//打印20次--
}
printw("\n");
for (lie = 0; lie <= 20; lie++) {
//第0列和第20列打印一个“|”
if (lie == 0 || lie == 20) {
printw("|");
} else {
//其他位置用空格代替
printw(" ");
}
}
}
}
}
int main() {
//定义一个函数用来初始化界面和使用特殊键盘
ncurses1();
//地图的第一行进行绘制
gamemap();
getch();//防止程序退出
endwin();//防止乱码
return 0;
}
运行结果:
完整地图绘制
代码:
#include<curses.h>//需要包含这个头文件
void ncurses1() {
initscr();//界面初始化的函数
keypad(stdscr, 1); //使用特殊键盘
}
void gamemap() {
//定义行和列
int hang, lie;
//地图是20行,建立循环20次
for (hang = 0; hang < 20; hang++) {
if (hang == 0) { //第一行地图的绘制
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
if (hang >= 0 && hang <= 19) { //中间0-19行地图绘制
for (lie = 0; lie <= 20; lie++) {
if (lie == 0 || lie == 20) {
printw("|");
} else {
printw(" ");
}
}
printw("\n");
}
//最后一行地图的绘制
if (hang == 19) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
}
printw("by xxx\n");
}
int main() {
//定义一个函数用来初始化界面和使用特殊键盘
ncurses1();
//地图的第一行进行绘制
gamemap();
getch();//防止程序退出
endwin();//防止乱码
return 0;
}
运行结果:
贪吃蛇显示蛇的头
蛇的一个节点的显示
蛇头用“[ ]”来表示
贪吃蛇的节点是一个结构体,包含,行和列坐标以及下一个节点的指针
struct snake{
int hang;
int lie;
struct snake*next;
}
代码:
#include<curses.h>//需要包含这个头文件
//定义出蛇的节点的结构体
typedef struct snakes{
int hang;
int lie;
struct snakes*next;
}node;
//蛇的节点显示在
node t1={2,2,NULL};
void ncurses1() {
initscr();//界面初始化的函数
keypad(stdscr, 1); //使用特殊键盘
}
void gamemap() {
//定义行和列
int hang, lie;
//地图是20行,建立循环20次
for (hang = 0; hang < 20; hang++) {
if (hang == 0) { //第一行地图的绘制
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
if (hang >= 0 && hang <= 19) { //中间0-19行地图绘制
for (lie = 0; lie <= 20; lie++) {
if (lie == 0 || lie == 20) {
printw("|");
}else if(t1.hang==hang&&t1.lie==lie)//满足条件打印
{
printw("[]");//打印蛇的节点
}
else {
printw(" ");
}
}
printw("\n");
}
//最后一行地图的绘制
if (hang == 19) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
}
printw("by xxx\n");
}
int main() {
//定义一个函数用来初始化界面和使用特殊键盘
ncurses1();
//地图的第一行进行绘制
gamemap();
getch();//防止程序退出
endwin();//防止乱码
return 0;
}
运行结果:
分装一个函数显示3个蛇的节点(静态添加)
代码:
#include<curses.h>
typedef struct snakes{
int hang;//蛇的行坐标
int lie;//列坐标
struct snakes*next;//可以指向下一个节点的位置
}node;//蛇,节点结构体
node t1={2,2,NULL};
node t2={2,3,NULL};
node t3={2,4,NULL};
node t5={2,5,NULL};//设置四个节点的位置
int shejie(int hang,int lie)
{
node*point=&t1;//保留蛇节点t1的地址
while(point!=NULL)
{
//行和列的值和上面4个节点的行和列的值是否相等,满足返回1不满足返回0
if(point->hang==hang&&point->lie==lie)
{
return 1;
}
point=point->next;//访问下一个节点
}
return 0;
}
void ncurses1()
{
initscr();
keypad(stdscr,1);//调用键盘
}
void gamemap()
{
int hang,lie;//行和列
for(hang=0;hang<20;hang++)//绘制20x20的地图需要的循环20次
{
//第一行地图的绘制
if(hang==0)
{
for(lie=0;lie<20;lie++)
{
printw("--");//打印20次--
}
printw("\n");//进行换行
}
//中间部分的绘制
if(hang>=0&&hang<=19)
{
for(lie=0;lie<=20;lie++)
{
if(lie==0||lie==20)
{
printw("|");//第0列和第20列打印一个|
}else if(shejie(hang,lie))//建立函数是否满足条件,满足打印,把hang和lie的值进行传递,
{
printw("[]");
}
else{
printw(" ");//其余部分打印空格两个
}
}
printw("\n");
}
//最后一行地图的绘制
if(hang==19)
{
for(lie=0;lie<20;lie++)
{
printw("--");//打印20次--
}
printw("\n");
}
}
}
int main()
{
ncurses1();//初始化界面和调用特殊键盘
//t1-t5之间节点形成链表
t1.next=&t2;
t2.next=&t3;
t3.next=&t4;
t4.next=&t5;
//绘制出贪吃蛇的地图
gamemap();
getch();//防止退出
endwin();//防止乱码
return 0;
}
运行结果:
贪吃蛇身子的改进,使用malloc来创造空间添加节点
代码:
#include<curses.h>
#include<stdlib.h>
//建立一个蛇节点的结构体
typedef struct node {
int hang;
int lie;//节点的行和列坐标
struct node*next;//指向下一个节点的指针
} snakes;
//定义两个全局变量,头和尾
snakes*head = NULL; //链表头(蛇头)
snakes*tail = NULL; //链表尾(蛇尾)
void ncurses1() {
initscr();//初始化界面
keypad(stdscr,1);//使用特殊键盘
}
void addsnakes() {
//新节点开辟空间
snakes*new = (snakes*)malloc(sizeof(snakes));
new->hang = tail->hang;
new->lie = tail->lie + 1; //地图第2行的位置往右添加节点
new->next = NULL;
tail->next = new; //尾巴指向新的节点
tail = new; //新开辟的节点用永远是尾巴
}
void initsnakes() {
//1.给蛇头开辟一个空间,赋值
head = (snakes*)malloc(sizeof(snakes));
head->hang = 2;
head->lie = 2;
head->next = NULL;
//2.蛇尾赋值
tail = head;
//3.建立一个函数进行新节点的添加
int i = 3; //想添加3个节点
while (i > 0) {
//新节点开辟的函数
addsnakes();
i--;
}
}
int shejie(int hang, int lie) {
snakes*point = head; //保留头的位置
while (point != NULL) {
if (point->hang == hang && point->lie == lie) {
return 1;//找到节点返回1
}
point = point->next;
}
return 0;//没有节点返回0
}
void gamemap() {
//行和列组成地图,20x20的地图行用--,列用|和空格
int hang, lie;
for (hang = 0; hang < 20; hang++) { //20行地图循环20次
//绘制第1行的情况
if (hang == 0) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
//绘制中间0-19行
if (hang >= 0 && hang <= 19) {
for (lie = 0; lie <= 20; lie++) {
if (lie == 0 || lie == 20) {
printw("|");
//中间部分打印一下蛇的节点,判断条件是否满足,根据返回值
} else if (shejie(hang, lie)) {
printw("[]");
} else {
printw(" ");
}
}
printw("\n");
}
//最后一行绘制
if (hang == 19) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
}
printw("by xxxxxx\n");
}
int main() {
//1.建立一个函数初始化界面和使用keypad函数
ncurses1();
//2.动态开辟空间的函数,显示蛇的身体
initsnakes();
//3.绘制地图,
gamemap();
//4.防止程序退出
getch();
//5.防止乱码
endwin();
return 0;
}
运行结果:
贪吃蛇的移动
向右移动,通过删除一个节点然后添加一个节点方式,通过free()函数释放空间
move(0, 0)是ncurses库中的一个函数调用,用于将光标移动到终端屏幕上的指定位置。
代码:
#include<curses.h>
#include<stdlib.h>
typedef struct node {
int hang;
int lie;
struct node*next;
} snakes; //snake node
snakes*head = NULL; //snakes head;
snakes*tail = NULL; //snakes tail;
void ncurses1() {
initscr();//chu shi hua
keypad(stdscr, 1); // jianpan
}
void addsnakes() {
snakes*new = (snakes*)malloc(sizeof(snakes));
new->hang = tail->hang;
new->lie = tail->lie + 1;
new->next = NULL;
tail->next = new;
tail = new;
}
void initsnakes() {
//head zhi xiang kaipikong jian
head = (snakes*)malloc(sizeof(snakes));
//xianshi2,2,NULL
head->hang = 2;
head->lie = 2;
head->next = NULL;
// weiba=head
tail = head;
//gai han shu zeng jia jie dian
addsnakes();
addsnakes();
addsnakes();
}
int shejie(int hang, int lie) {
snakes*point = head;
while (point != NULL) {
if (point->hang == hang && point->lie == lie) {
return 1;
}
point = point->next;
}
return 0;
}
void gamemap() {
move(0, 0);//使其光标固定
int hang, lie;
for (hang = 0; hang < 20; hang++) {
if (hang == 0) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
if (hang >= 0 && hang <= 19) {
for (lie = 0; lie <= 20; lie++) {
if (lie == 0 || lie == 20) {
printw("|");
} else if (shejie(hang, lie)) {
printw("[]");
} else {
printw(" ");
}
}
printw("\n");
}
if (hang == 19) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
}
printw("by xxxxxx\n");
}
void deleatehead() {
snakes*p = head;//保留头原来的节点
head = head->next;//改变头的位置
free(p);//释放多余头节点的位置
}
void snakesright() {
addsnakes();//尾巴添加一个新的节点
deleatehead();//删除头部的一个节点
}
int main() {
int con;
ncurses1();//初始化界面
initsnakes();// 开辟空间,形成链表
gamemap();// 贪吃蛇的地图
//循环,使其蛇的身体向右方向移动
while (1) {
con = getch();
switch (con) {
case KEY_RIGHT:
snakesright();//该函数使其向右移动,通过添加新节点,然后删除一个节点的方式
gamemap();//刷新地图
break;
}
}
getch();
endwin();
return 0;
}
运行结果:按下方向键“->”,使其进行移动
贪吃蛇移动-撞墙后重新回到原来的位置
1.判定是4个边界,触碰到边界然后释放空间,然后开辟一条新的蛇的身体
代码:
#include<curses.h>
#include<stdlib.h>
typedef struct node {
int hang;
int lie;
struct node*next;
} snakes;
snakes*head = NULL; //蛇头
snakes*tail = NULL; //蛇尾
void ncurses1() {
initscr();//初始化界面
keypad(stdscr, 1); //使用键盘
}
void addsnakes() {
//申请空间
snakes*new = (snakes*)malloc(sizeof(snakes));
//新节点的右边加节点,行的坐标不用变化,列的坐标+1
new->hang = tail->hang;
new->lie = tail->lie + 1;
new->next = NULL;
//尾巴的指针指向新的节点,
tail->next = new;
//始终让尾巴的位置在新的节点
tail = new;
}
void initsnakes() {
snakes*p;
while (head != NULL) {
p = head;
head = head->next;
free(p);
}
//给头节点申请空间
head = (snakes*)malloc(sizeof(snakes));
//蛇头节点行坐标和列坐标赋值,指针为空
head->hang = 2;
head->lie = 2;
head->next = NULL;
//尾部节点的指针赋值
tail = head;
//建立函数,在尾巴后面添加节点
addsnakes();
addsnakes();
addsnakes();//三次调用,添加三个节点
}
int shejie(int hang, int lie) {
snakes*point = head; //保留头节点的位置
while (point != NULL) {
//根据每个节点的行和列判断是否满足条件
if (point->hang == hang && point->lie == lie) {
return 1;//满足条件返回1,打印节点
}
point = point->next; //访问下一个节点
}
return 0;//没有相等的节点,返回0不打印
}
void gamemap() {
move(0, 0); //固定光标
//打印出一个正方形,20x20
int hang, lie; //定义两个变量分别代表行和列
for (hang = 0; hang < 20; hang++) { //20行的地图循环20次
//第一行地图的绘制
if (hang == 0) {
for (lie = 0; lie < 20; lie++) {
//打印20个--组成的横线
printw("--");
}
printw("\n");//换行打印
}
//中间部分0-19行显示| |;
if (hang >= 0 && hang <= 19) {
//|的长度不够,列的长度改为20
for (lie = 0; lie <= 20; lie++) {
if (lie == 0 || lie == 20) {
//第0列和第20列打印|
printw("|");
} else if (shejie(hang, lie)) {
//判断是否显示蛇的节点
//根据节点行和列坐标是否相等
printw("[]");
} else {
printw(" ");
}
}
printw("\n");
}
//第19行也打印一个20个--
if (hang == 19) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
}
printw("xxxxx\n");
}
void deleatenode() {
snakes*p = head; //保留一个头节点的位置
head = head->next; //头节点的位置变化
free(p);//删除头节点的位置
}
void rightsnakes() {
//1.先添加一个节点
addsnakes();
//删除一个节点
deleatenode();
//判断是否撞墙,通过尾部节点是否和边界重合判断
if (tail->hang == 0 || tail->lie == 0 || tail->hang == 20 || tail->lie == 20) {
//位置重合,重新显示蛇的节点
initsnakes();
}
}
int main() {
int con;//控制蛇移动的变量,往右
//1.初始化界面和使用特殊键盘的函数
ncurses1();
//2.绘制蛇的身体形成链表
initsnakes();
//绘制地图20x20
gamemap();
//使其向右移动
while (1) {
con = getch(); //获取con的值
switch (con) {
case KEY_RIGHT:
rightsnakes();//向右移动蛇
gamemap();//刷新地图
break;
}
}
getch();//防止退出
endwin();//防止乱码
return 0;
}
运行结果:往右撞到边线后会重新刷新
贪吃蛇自己向右移动
自己移动通过不停的刷新界面的函数refresh();和sleep()函数
refresh()
是一个函数调用,用于刷新ncurses库创建的游戏界面。
在使用ncurses库创建游戏界面时,我们可以使用各种函数来绘制游戏界面的各个元素,比如蛇的身体、食物等。但是这些绘制的元素并不会立即显示在屏幕上,而是在调用
refresh()
函数之后才会显示出来。
refresh()
函数的作用是将之前绘制的元素刷新到屏幕上,使得玩家可以看到最新的游戏界面。
通常,在绘制完游戏界面的所有元素之后,我们会调用
refresh()
函数来更新屏幕显示。这样,玩家就可以看到最新的游戏状态,并且可以根据最新的界面进行操作。
总结起来,
refresh()
函数的作用是刷新游戏界面,使得之前绘制的元素能够显示在屏幕上。
sleep()
是一个函数调用,用于在程序执行过程中暂停一段时间。
在编程中,我们有时需要在程序执行过程中添加一些延迟,以便控制程序的执行速度或者等待一些操作完成。
sleep()
函数就是用来实现这个目的的。
sleep()
函数接受一个整数参数,表示要暂停的时间长度,单位是秒。调用sleep()
函数后,程序会暂停执行指定的时间,然后再继续执行后面的代码。
例如,如果我们调用
sleep(2)
,那么程序会暂停执行2秒钟,然后再继续执行后面的代码。
sleep()
函数在很多编程语言中都有相应的实现,用法也基本相同。它可以用于各种场景,比如在游戏中添加延迟效果、在多线程编程中控制线程的执行速度等。
需要注意的是,
sleep()
函数会阻塞当前线程的执行,也就是说,在调用sleep()
函数期间,当前线程无法执行其他任务。如果需要在后台执行一些其他操作,可以考虑使用异步编程的方式,或者使用定时器等机制来实现延迟效果。
代码:
#include<curses.h>
#include<stdlib.h>
typedef struct node{
int hang;
int lie;
struct node*next;
}snakes;//贪吃蛇每个节点的模板
//定义两个指针,头节点的指针和尾巴节点的指针
snakes*head=NULL;//头
snakes*tail=NULL;//尾巴
void ncurses1()
{
initscr();//初始化界面
keypad(stdscr,1);//使用键盘
}
void addsnakes()
{
//新节点开辟空间,赋值
snakes*new=(snakes*)malloc(sizeof(snakes));
new->hang=tail->hang;
new->lie=tail->lie+1;//列数+1是为了在右边添加行数还是在同一行
new->next=NULL;
tail->next=new;//尾巴节点指向新的节点
tail=new;//尾巴永远在新节点
}
void initsnakes()
{
//撞墙后清空节点
snakes*p;
while(head!=NULL)
{
p=head;
head=head->next;
free(p);
}
//给头节点申请空间赋值
head=(snakes*)malloc(sizeof(snakes));
head->hang=2;
head->lie=2;
head->next=NULL;
//头节点的地址给到尾巴
tail=head;
//添加新节点的函数
addsnakes();
addsnakes();
addsnakes();//添加三个节点
}
int snakesnode(int hang,int lie)
{
snakes*point=head;
while(point!=NULL)
{
if(point->hang==hang&&point->lie==lie)
{
return 1;
}
point=point->next;
}
return 0;
}
void snakesmap()
{
move(0,0);//光标固定
int hang,lie;//行和列
for(hang=0;hang<20;hang++)//20x20的地图
{
//第一行绘制20个--
if(hang==0)
{
for(lie=0;lie<20;lie++)
{
printw("--");
}
printw("\n");
}
//中间部分绘制
if(hang>=0&&hang<=19)
{
for(lie=0;lie<=20;lie++)
{
if(lie==0||lie==20)
{
printw("|");
}else if(snakesnode(hang,lie)){
printw("[]");
}else{
printw(" ");
}
}
printw("\n");
}
if(hang==19)
{
for(lie=0;lie<20;lie++)
{
printw("--");
}
printw("\n");
}
}
printw("by xxxxxx\n");
}
void deleatenode()
{
snakes*p=head;
head=head->next;
free(p);
}
void snakesright()
{
//1.添加一个节点,然后删除一个节点
addsnakes();
deleatenode();
//判定撞墙
if(tail->hang==0||tail->lie==0||tail->hang==20;tail->lie==20)
{
initsnakes();//重新刷新
}
}
int main()
{
//1.初始化界面和使用特殊键盘
ncurses1();
//2.开辟空间使其成为蛇的身体
initsnakes();
//3.绘制地图
snakesmap();
//4.通过循环自己向右移动
while(1)
{
snakesright();//蛇向右移动
snakesmap();
refresh();//刷新界面
usleep(100000);//暂停
}
getch();
endwin();
return 0;
}
linux线程概念的引入及编程实现
线程的概念:
Linux线程是在Linux操作系统上创建和管理的执行单元。线程是进程的一部分,它与其他线程共享同一进程的资源,包括内存空间、文件描述符和其他系统资源。
Linux操作系统使用POSIX线程库(pthread)来支持多线程编程。通过使用pthread库,开发人员可以创建和管理多个线程,并在这些线程之间共享数据和执行任务。
在Linux中,线程的创建和管理是通过调用pthread库中的函数来实现的。一些常用的pthread函数包括:
pthread_create()
:用于创建一个新的线程。pthread_join()
:用于等待一个线程的结束,并获取线程的返回值。pthread_exit()
:用于线程的退出。pthread_mutex_lock()
和pthread_mutex_unlock()
:用于线程之间的互斥访问共享资源。pthread_cond_wait()
和pthread_cond_signal()
:用于线程之间的条件变量同步。
使用多线程编程可以提高程序的并发性和响应性。通过将任务分配给不同的线程并行执行,可以加快程序的执行速度。同时,多线程编程也需要注意线程之间的同步和互斥,以避免数据竞争和死锁等问题。
在Linux中,线程是一种轻量级的执行单元,相对于进程来说,线程的创建和切换开销较小。因此,多线程编程在Linux系统中得到了广泛的应用,包括服务器编程、并行计算、图形界面等领域。
代码:同时运行两个while(1)的循环
#include<stdio.h>
#include<pthread.h>//线程需要包含这个文件夹
void func()
{
while(1)
{
printf("this is func 1\n");
sleep(1);
}
}
void func2()
{
while(1)
{
printf("this is func 2\n");
sleep(1);
}
}
int main()
{
pthread_t t1;//线程的标识符
pthread_t t2;//线程的标识符
//建立两个线程
pthread_create(&t1,NULL,func,NULL);
pthread_create(&t2,NULL,func2,NULL);
while(1);
return 0;
}
运行结果:两个函数while会同时进行
通过多线程的方式实现两个循环同时进行(界面刷新)(键盘检测)
代码:
#include<curses.h>
#include<stdlib.h>
#include<pthread.h>//多线程的需要包含的头文件
typedef struct node {
int hang;
int lie;
struct node*next;
} snakes; //蛇每个节点的结构体
snakes*head = NULL; //蛇头的地址
snakes*tail = NULL; //蛇尾巴的结构体
int con;//键盘输入
void ncurses1() {
initscr();//界面初始化
keypad(stdscr, 1); //使用特殊键盘
}
//增加蛇节点的函数
void addsnakes() {
//定义新节点的指针和开辟空间
snakes*new = (snakes*)malloc(sizeof(snakes));
//头节点的右边增加节点,行不变,列+1
new->hang = tail->hang;
new->lie = tail->lie+1;
new->next = NULL;
//尾巴的指针指向新节点的位置
tail->next = new;
//始终让新节点的位置为尾巴
tail = new;
}
void initsnakes() {
//蛇碰到边界重新刷新
snakes*p = NULL;
while (head != NULL) {
p = head;
head = head->next;
free(p);
}
//蛇头的指针指向开辟的空间
head = (snakes*)malloc(sizeof(snakes));
//蛇在第2行第2列的位置开始打印
head->hang = 2;
head->lie = 2;
head->next = NULL;
//尾巴的位置赋值
tail = head;
//增加节点的函数
addsnakes();
addsnakes();
addsnakes();//增加三个节点
}
int snakesx(int hang,int lie) {
snakes*point = head;
while (point != NULL) {
if (point->hang == hang && point->lie == lie) {
return 1;
}
point = point->next;
}
return 0;
}
//地图打印函数
void snakesmap() {
move(0, 0); //固定光标的位置
int hang, lie; //行和列
for (hang = 0; hang < 20; hang++) { //20行地图的打印
//第一行打印
if (hang == 0) {
//每一列打印20个--
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");//换行
}
//中间部分进行打印
if (hang >= 0 && hang <= 20) {
for (lie = 0; lie <= 20; lie++) {
if (lie == 0 || lie == 20) {
printw("|");
} else if (snakesx(hang, lie)) {
printw("[]");
} else {
printw(" ");
}
}
printw("\n");
}
//最后一行的部分进行打印
if (hang == 19) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
}
printw("by xxxxxx\n");
}
void deleatenode() { //删除头节点
snakes*p = head;
head = head->next;
free(p);//释放节点
}
void rightsnakes() { //向右移动蛇
addsnakes();
deleatenode();
//移动过程碰到边界重新刷新蛇的位置
if (tail->hang == 0 || tail->hang == 20 || tail->lie == 0 || tail->lie == 20) {
//重新调用生成蛇的函数
initsnakes();
}
}
void* initmap() { //界面刷新的函数
while (1) {
rightsnakes();//蛇自己向右移动
snakesmap();//调用地图
refresh();//界面刷新
usleep(100000);//暂停
}
}
void* keyscanf() { //键盘输入
while (1) {
con = getch(); //
switch (con) {
case KEY_UP:
printw("UP\n");
break;
case KEY_DOWN:
printw("DOWN\n");
break;
case KEY_LEFT:
printw("LEFT\n");
break;
case KEY_RIGHT:
printw("RIGHT\n");
break;
}
}
}
int main() {
pthread_t t1;
pthread_t t2;//两个线程的标识符
//界面初始化的函数
ncurses1();
//蛇的节点形成链表
initsnakes();
//绘制地图,打印蛇的身体
snakesmap();
//通过线程实现两个循环,
pthread_create(&t1, NULL, initmap, NULL);
pthread_create(&t2, NULL, keyscanf, NULL);
while (1);
getch();
endwin();
return 0;
}
贪吃蛇改变方向自己移动
代码:
#include<stdio.h>
#include<stdlib.h>
#include<curses.h>
#include<pthread.h>
#define UP 1
#define DOWN 2
#define LEFT 3
#define RIGHT 4//按键设置蛇的四个方向
typedef struct node {
int hang;
int lie;
struct node*next;
} snakes; //蛇的每个节点的结构体
snakes*head = NULL;
snakes*tail = NULL;
int con;//检测按键
int dir;//改变方向
void ncurses1() { //初始化界面,调用键盘
initscr();
keypad(stdscr, 1);
}
void addsnakes() {
//增加节点要开辟新的空间
snakes*new = (snakes*)malloc(sizeof(snakes));
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 = new->lie - 1;
break;
case RIGHT:
new->hang = tail->hang;
new -> lie = tail->lie + 1;
break;
}
tail->next = new; //尾巴指向新的节点
tail = new; //新节点的位置始终在尾巴
}
void initsnakes() {
dir = RIGHT; //现在右边增加三个节点
//触碰到边界释放节点
snakes*p = NULL;
while (head != NULL) {
p = head;
head = head->next;
free(p);
}
//给蛇的头开辟空间赋值
head = (snakes*)malloc(sizeof(snakes));
head->hang = 2;
head->lie = 2;
head->next = NULL;
//蛇头的空间给到尾巴
tail = head;
//在尾巴后面增加三个节点
addsnakes();//增加节点的函数
addsnakes();
addsnakes();
}
int snakesx(int hang, int lie) {
//通过每个节点行坐标和列坐标来判断是否返回1
snakes*point = head;
while (point != NULL) {
if (point->hang == hang && point->lie == lie) {
return 1;
}
point = point->next;
}
return 0;
}
//绘制地图的函数
void gamemap() {
move(0, 0); //固定光标
int hang, lie; //行和列
for (hang = 0; hang < 20; hang++) {
//第一行地图
if (hang == 0) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
//中间部分绘制
if (hang >= 0 && hang <= 19) {
for (lie = 0; lie <= 20; lie++) {
if (lie == 0 || lie == 20) {
printw("|");
} else if (snakesx(hang, lie)) {
printw("[]");
} else {
printw(" ");
}
}
printw("\n");
}
if (hang == 19) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
}
printw("by xxxxxx\n");
}
void deleatenode() {
snakes*p = head;
head = head->next;
free(p);
}
void movesnakes() {
//增加节点
addsnakes();
//删除一个节点
deleatenode();
if (tail->hang == 0 || tail->lie == 0 || tail->hang == 20 || tail->lie == 20) {
initsnakes();
}
}
void* initmap() {
while (1) {
movesnakes();//蛇自己移动
gamemap();//地图
refresh();//刷新
usleep(100000);
}
}
void* keyscanf() {
while (1) {
con = getch();
switch (con) {
case KEY_UP:
dir = UP;
break;
case KEY_DOWN:
dir = DOWN;
break;
case KEY_LEFT:
dir = LEFT;
break;
case KEY_RIGHT:
dir = RIGHT;
break;
}
}
}
int main() {
pthread_t t1;
pthread_t t2;//两个线程的标识
ncurses1();//初始化界面的函数
initsnakes();//绘制蛇的节点
gamemap();//绘制地图
//建立两个线程,一个刷新界面,一个不停使用键盘
pthread_create(&t1, NULL, initmap, NULL); //界面
pthread_create(&t2, NULL, keyscanf, NULL); //键盘
while (1);
getch();
endwin();
return 0;
}
绝对值方式解决走位的问题
通过函数ads();查看绝对值
代码:
#include<curses.h>
#include<stdlib.h>
#include<pthread.h>
#define UP 1
#define DOWN -1
#define LEFT 2
#define RIGHT -2
typedef struct node {
int hang;
int lie;
struct node*next;
} snakes;
snakes*head = NULL;
snakes*tail = NULL;
int con;
int dir;
void ncurses1() {
initscr();
keypad(stdscr, 1);
noecho();
}
void addsnakes() {
snakes*new = (snakes*)malloc(sizeof(snakes));
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 initsnakes() {
snakes*p = NULL;
while (head != NULL) {
p = head;
head = head->next;
free(p);
}
dir = RIGHT;
head = (snakes*)malloc(sizeof(snakes));
head->hang = 2;
head->lie = 2;
head->next = NULL;
tail = head;
addsnakes();
addsnakes();
addsnakes();
}
int snakesx(int hang, int lie) {
snakes*point = head;
while (point != NULL) {
if (point->hang == hang && point->lie == lie) {
return 1;
}
point = point->next;
}
return 0;
}
void gamemap() {
move(0, 0);
int hang, lie;
for (hang = 0; hang < 20; hang++) {
if (hang == 0) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
if (hang >= 0 && hang <= 19) {
for (lie = 0; lie <= 20; lie++) {
if (lie == 0 || lie == 20) {
printw("|");
} else if (snakesx(hang, lie)) {
printw("[]");
} else {
printw(" ");
}
}
printw("\n");
}
if (hang == 19) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
}
printw("by xxxxx\n");
}
void deleatenode() {
snakes*p = head;
head = head->next;
free(p);
}
void movesnakes() {
addsnakes();
deleatenode();
if (tail->hang == 0 || tail->lie == 0 || tail->hang == 20 || tail->lie == 20) {
initsnakes();
}
}
void* func() {
while (1) {
movesnakes();
gamemap();
refresh();
usleep(100000);
}
}
void turn(int dirch) {
if (abs(dir) != abs(dirch)) {
dir = dirch;
}
}
void* func2() {
while (1) {
con = getch();
switch (con) {
case KEY_UP:
turn(UP);
break;
case KEY_DOWN:
turn(DOWN);
break;
case KEY_LEFT:
turn(LEFT);
break;
case KEY_RIGHT:
turn(RIGHT);
break;
}
}
}
int main() {
pthread_t t1;
pthread_t t2;
ncurses1();
initsnakes();
gamemap();
pthread_create(&t1, NULL, func, NULL);
pthread_create(&t2, NULL, func2, NULL);
while (1);
getch();
endwin();
return 0;
}
贪吃蛇吃食物和咬到自己
代码:
#include<curses.h>
#include<stdlib.h>
#include<pthread.h>
#define UP 1
#define DOWN -1
#define LEFT 2
#define RIGHT -2
typedef struct node {
int hang;
int lie;
struct node*next;
} snakes; //蛇的节点结构体
snakes*head = NULL; //蛇头的位置
snakes*tail = NULL; //蛇尾巴的位置
int dir;//改变方向
int con;//键盘输入
snakes food;//食物的结构体
void initfood() { //初始化食物坐标的函数
int x = rand() % 20;
int y = rand() % 20;
food.hang = x;
food.lie = y;
}
void ncurses1() {
initscr();//初始化界面
keypad(stdscr, 1); //键盘调用
noecho();//防止乱码
}
void addsnakes() {
//开辟新的空间
snakes*new = (snakes*)malloc(sizeof(snakes));
new->next = NULL;
//增加节点,根据方向
switch (dir) {
case UP://往上hang-1,列不会变化
new->hang = tail->hang - 1;
new->lie = tail->lie;
break;
case DOWN://往下hang+1,列不变
new->hang = tail->hang + 1;
new->lie = tail->lie;
break;
case LEFT://往左lie-1,行不变
new->hang = tail->hang;
new->lie = tail->lie - 1;
break;
case RIGHT://往右lie+1,行不变
new->hang = tail->hang;
new->lie = tail->lie + 1;
break;
}
tail->next = new;
tail = new;
}
void initsnakes() {
snakes*p=NULL;
while(head!=NULL)
{
p=head;
head=head->next;
free(p);
}
initfood();//调用函数显示食物的位置
dir = RIGHT; //刚进来蛇往右移动
//给蛇头的节点开辟空间并给行和列坐标赋值
head = (snakes*)malloc(sizeof(snakes));
head->hang = 2;
head->lie = 2;
head->next = NULL;
//蛇尾的位置赋值
tail = head; //要在蛇的尾巴后面添加节点
//添加节点的函数
addsnakes();
addsnakes();
addsnakes();//添加三个节点
}
int snakesx(int hang, int lie) {
snakes*point = head; //局部变量保存头节点的地址
while (point != NULL) {
if (point->hang == hang && point->lie == lie) {
return 1;
}
point = point->next;
}
return 0;
}
int havefood(int hang, int lie) { //根据该函数返回值是否显示食物
if (food.hang == hang && food.lie == lie) {
return 1;
}
return 0;
}
void gamemap() {
move(0, 0); //光标固定
int hang, lie; //行和列
for (hang = 0; hang < 20; hang++) {
//第一行地图绘制
if (hang == 0) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
//中间20行地图绘制
if (hang >= 0 && hang <= 19) {
for (lie = 0; lie <= 20; lie++) {
if (lie == 0 || lie == 20) {
printw("|");
} else if (snakesx(hang, lie)) { //根据该函数返回值来判断是否显示蛇的节点
printw("[]");
} else if (havefood(hang, lie)) {
printw("##");
} else {
printw(" ");
}
}
printw("\n");
}
if (hang == 19) {
for (lie = 0; lie < 20; lie++) {
printw("--");
}
printw("\n");
}
}
printw("by xxxx");
}
void deleatenode() {
snakes*p = head;
head = head->next;
free(p);//释放空间
}
int ifdese() {
snakes*p = head;
//移动时候新增节是否和边界重合
if (tail->hang < 0 || tail->hang == 20 || tail->lie == 0 || tail->lie == 20) {
return 1;
}
while (p->next != NULL) {
//头节点是一直变化的,如果变化的过程中和尾巴重合返回1
if (p->hang == tail->hang && p->lie == tail->lie) {
return 1;
}
p=p->next;
}
return 0;
}
void movesnakes() {
//蛇移动要增加节点和删除节点,
addsnakes();//增加节点
if (havefood(tail->hang, tail->lie)) {
initfood();
} else {
deleatenode();//删除节点
}
if (ifdese()) { //判断是否撞墙和咬到自己
initsnakes();
}
}
void* func() {
while (1) {
movesnakes();//蛇的移动
gamemap();//再次调用地图
refresh();//地图刷新
usleep(100000);//暂停
}
}
void turn(int dirses) {
//根据绝对值判断dir
if (abs(dir) != abs(dirses)) {
dir = dirses;
}
}
void* func2() {
while (1) {
con = getch();
switch (con) {
case KEY_UP:
turn(UP);
break;
case KEY_DOWN:
turn(DOWN);
break;
case KEY_LEFT:
turn(LEFT);
break;
case KEY_RIGHT:
turn(RIGHT);
break;
}
}
}
int main() {
pthread_t t1;//界面刷新的线程标识符
pthread_t t2;//键盘输入的线程标识符
//1.初始化界面和使用键盘的函数
ncurses1();
//2.初始化蛇的身体
initsnakes();
//3.地图
gamemap();
//4.建立两个线程刷新地图和键盘输入
pthread_create(&t1, NULL, func, NULL);
pthread_create(&t2, NULL, func2, NULL);
while (1); //主函数循环
getch();//防止退出
endwin();//防止出现乱码
return 0;
}