C语言小项目-贪吃蛇
1 项目演示
(1)将c语言基础,数据结构链表基础,c变量,流程控制,函数,指针,结构体等串在一块,为后续linux系统编程,文件编程,进程,线程,通信,第三方包等打基础。
2 基础要求
(1)c语言基础,linux基本操作
3 为什么需要ncurse
(1)贪吃蛇界面用简单的printf绘制即可;
(2)输入指令getchar,gets,scanf都需要enter键才有效,故引入ncurse
4 ncurse上下左右键获取
(1)ncurse输入输出,及启动和使用curse界面;gcc curse.c -lcurses(编译时需手动链接-lcurses),含案例curse.c
#include <curses.h>
int main(){
char c;
initscr();
c=getch();
printw("your input :%c\n",c);
printw("this is a curses window.\n");
getch();
endwin();
return 0;
}
(2)ncurse上下左右键获取,目录/usr/include/curses.h,含案例curse2.c
#include <curses.h>
int main(){
int key;
initscr();
keypad(stdscr,1);
while(1){
key=getch();
switch(key){
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;
}
}
endwin();
return 0;
}
5 地图规划
(1)第0行打"–“,其中第0列跟20列打”|“;第1行到19行,头尾打|;第19行打”–";
6 地图实现一
(1)第0行打"–“,其中第0列跟20列打”|"的实现
7 贪吃蛇地图实现结束
(1)第1行到19行,头尾打|;第19行打"–“,其中第0列跟19列打”|"的实现
8 贪吃蛇地图优化及算法说明
(1)第0行从0列到19列打"–“;第0行到第19行,第0列跟第20列打”|“,其他列打” “; 第19行从0列到19列打”–";
含案例tcs_map.c
#include <curses.h>
void initNcurse(){
initscr();
keypad(stdscr,1);
}
void gamePic(){
int hang;
int lie;
for(hang=0;hang<20;hang++){
if(hang==0){
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{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz\n");
}
}
}
int main(){
initNcurse();
gamePic();
getch();
endwin();
return 0;
}
9 显示贪吃蛇身子的一个节点
(1)行坐标,列坐标,下个节点位置(地址/指针)=》
定义结构体struct Snake{int hang;int lie;struct Snake *next;},案例snake.c
#include <curses.h>
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake node1={2,2,NULL};
void initNcurse(){
initscr();
keypad(stdscr,1);
}
void gamePic(){
int hang;
int lie;
for(hang=0;hang<20;hang++){
if(hang==0){
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(hang==node1.hang && lie==node1.lie){
printw("[]");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz\n");
}
}
}
int main(){
initNcurse();
gamePic();
getch();
endwin();
return 0;
}
10 显示贪吃蛇完整身子
(1)定义节点函数,遍历链表,案例snake2.c
#include<curses.h>
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake node1={2,2,NULL};
struct Snake node2={2,3,NULL};
struct Snake node3={2,4,NULL};
struct Snake node4={2,5,NULL};
void initNcurse(){
initscr();
keypad(stdscr,1);
}
int hasSnakeNode(int i,int j){
struct Snake *p;
p=&node1;
while(p!=NULL){
if(p->hang==i && p->lie==j){
return 1;
}
p=p->next;
}
return 0;
}
void gamePic(){
int hang;
int lie;
for(hang=0;hang<20;hang++){
if(hang==0){
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(hasSnakeNode(hang,lie)){
printw("[]");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz\n");
}
}
}
int main(){
initNcurse();
node1.next=&node2;
node2.next=&node3;
node3.next=&node4;
gamePic();
getch();
endwin();
return 0;
}
11 显示贪吃蛇完整身子改进
(1)定义头尾节点,往尾节点后增加节点,利用链表新增节点;
注:用尾部节点可以连续+1延长蛇身;案例snake3.c
#include<curses.h>
#include<stdlib.h>
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head;
struct Snake *tail;
void initNcurse(){
initscr();
keypad(stdscr,1);
}
int hasSnakeNode(int i,int j){
struct Snake *p;
p=head;
while(p!=NULL){
if(p->hang==i && p->lie==j){
return 1;
}
p=p->next;
}
return 0;
}
void gamePic(){
int hang;
int lie;
for(hang=0;hang<20;hang++){
if(hang==0){
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(hasSnakeNode(hang,lie)){
printw("[]");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz\n");
}
}
}
void addNode(){
struct Snake *new=(struct Snake *)malloc(sizeof(struct Snake));
new->hang=tail->hang;
new->lie=tail->lie+1;
new->next=NULL;
tail->next=new;
tail=new;
}
void initSnake(){
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=2;
head->lie=2;
head->next=NULL;
tail=head;
addNode();
addNode();
addNode();
addNode();
}
int main(){
initNcurse();
initSnake();
gamePic();
getch();
endwin();
return 0;
}
12 贪吃蛇向右移动
(1) 蛇移动,新增一个节点后删除一个节点;后刷新地图;案例snake4.c
#include<curses.h>
#include<stdlib.h>
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head;
struct Snake *tail;
void initNcurse(){
initscr();
keypad(stdscr,1);
}
int hasSnakeNode(int i,int j){
struct Snake *p;
p=head;
while(p!=NULL){
if(p->hang==i && p->lie==j){
return 1;
}
p=p->next;
}
return 0;
}
void gamePic(){
int hang;
int lie;
move(0,0);//Cursor reset in ncurses
for(hang=0;hang<20;hang++){
if(hang==0){
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(hasSnakeNode(hang,lie)){
printw("[]");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz\n");
}
}
}
void addNode(){
struct Snake *new=(struct Snake *)malloc(sizeof(struct Snake));
new->hang=tail->hang;
new->lie=tail->lie+1;
new->next=NULL;
tail->next=new;
tail=new;
}
void initSnake(){
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=2;
head->lie=2;
head->next=NULL;
tail=head;
addNode();
addNode();
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head=head->next;
free(p);// The purpose of p is to release the deleted node
}
void moveSnake(){
addNode();
deleNode();
}
int main(){
int con;
initNcurse();
initSnake();
gamePic();
while(1){
con=getch();
if(con==KEY_RIGHT){
moveSnake();
gamePic();//After the snake moves, need Rescan map
}
}
getch();
endwin();
return 0;
}
13 贪吃蛇不想活着撞墙找死
(1) 尾部的行等于0或20,或列等于0或20即为撞墙,撞墙后重新初始化蛇,链表初始化需要释放内存后再开辟内存;案例snake5.c
#include<curses.h>
#include<stdlib.h>
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head=NULL;
struct Snake *tail=NULL;
void initNcurse(){
initscr();
keypad(stdscr,1);
}
int hasSnakeNode(int i,int j){
struct Snake *p;
p=head;
while(p!=NULL){
if(p->hang==i && p->lie==j){
return 1;
}
p=p->next;
}
return 0;
}
void gamePic(){
int hang;
int lie;
move(0,0);//Cursor reset in ncurses
for(hang=0;hang<20;hang++){
if(hang==0){
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(hasSnakeNode(hang,lie)){
printw("[]");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz\n");
}
}
}
void addNode(){
struct Snake *new=(struct Snake *)malloc(sizeof(struct Snake));
new->hang=tail->hang;
new->lie=tail->lie+1;
new->next=NULL;
tail->next=new;
tail=new;
}
void initSnake(){
struct Snake *p;
while(head !=NULL){
p=head;
head=head->next;//All nodes in the head list need to be released
free(p);//To free up the previous memory space
}
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=2;
head->lie=2;
head->next=NULL;
tail=head;
addNode();
addNode();
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head=head->next;
free(p);// The purpose of p is to release the deleted node
}
void moveSnake(){
addNode();
deleNode();
if(tail->hang==0 || tail->lie==0 || tail->hang==20 || tail->lie==20){
initSnake();
}
}
int main(){
int con;
initNcurse();
initSnake();
gamePic();
while(1){
con=getch();
if(con==KEY_RIGHT){
moveSnake();
gamePic();//After the snake moves, need Rescan map
}
}
getch();
endwin();
return 0;
}
14 贪吃蛇脱缰向右自由游走
(1)去掉按键控制,usleep(100000)每隔100毫秒,调用refresh()函数刷新界面;案例snake6.c
#include<curses.h>
#include<stdlib.h>
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head=NULL;
struct Snake *tail=NULL;
void initNcurse(){
initscr();
keypad(stdscr,1);
}
int hasSnakeNode(int i,int j){
struct Snake *p;
p=head;
while(p!=NULL){
if(p->hang==i && p->lie==j){
return 1;
}
p=p->next;
}
return 0;
}
void gamePic(){
int hang;
int lie;
move(0,0);//Cursor reset in ncurses
for(hang=0;hang<20;hang++){
if(hang==0){
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(hasSnakeNode(hang,lie)){
printw("[]");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz\n");
}
}
}
void addNode(){
struct Snake *new=(struct Snake *)malloc(sizeof(struct Snake));
new->hang=tail->hang;
new->lie=tail->lie+1;
new->next=NULL;
tail->next=new;
tail=new;
}
void initSnake(){
struct Snake *p;
while(head !=NULL){
p=head;
head=head->next;//All nodes in the head list need to be released
free(p);//To free up the previous memory space
}
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=2;
head->lie=2;
head->next=NULL;
tail=head;
addNode();
addNode();
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head=head->next;
free(p);// The purpose of p is to release the deleted node
}
void moveSnake(){
addNode();
deleNode();
if(tail->hang==0 || tail->lie==0 || tail->hang==20 || tail->lie==20){
initSnake();
}
}
int main(){
int con;
initNcurse();
initSnake();
gamePic();
while(1){
moveSnake();
gamePic();//After the snake moves, need Rescan map
refresh();//Refresh the interface in ncurses
usleep(1000000);//stay 100ms
}
getch();
endwin();
return 0;
}
15 贪吃蛇方向移动和刷新界面一起实现面临的问题
(1)while(1)的方向移动,跟while(1)刷新界面要同时进行的问题引入;
16 linux线程概念引入编程实现
(1)线程的创建引入:pthread__create(&th1,NULL,fun,NULL);gcc ***.c -lpthread;案例pthread_test.c
#include<stdio.h>
#include<pthread.h>
void* func1(){
while(1){
printf("this is func1\n");
sleep(1);
}
}
void* func2(){
while(1){
printf("this is func2\n");
sleep(1);
}
}
int main(){
pthread_t th1;
pthread_t th2;
pthread_create(&th1,NULL,func1,NULL);
pthread_create(&th2,NULL,func2,NULL);
while(1);
return 0;
}
17 使用线程解决16节中提到的问题
(1)定义2个函数,一个刷新界面,一个改变方向;分别给这2个函数创建线程;案例snake7.c
#include<curses.h>
#include<stdlib.h>
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head=NULL;
struct Snake *tail=NULL;
int key;
void initNcurse(){
initscr();
keypad(stdscr,1);
}
int hasSnakeNode(int i,int j){
struct Snake *p;
p=head;
while(p!=NULL){
if(p->hang==i && p->lie==j){
return 1;
}
p=p->next;
}
return 0;
}
void gamePic(){
int hang;
int lie;
move(0,0);//Cursor reset in ncurses
for(hang=0;hang<20;hang++){
if(hang==0){
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(hasSnakeNode(hang,lie)){
printw("[]");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz,key=%d\n",key);
}
}
}
void addNode(){
struct Snake *new=(struct Snake *)malloc(sizeof(struct Snake));
new->hang=tail->hang;
new->lie=tail->lie+1;
new->next=NULL;
tail->next=new;
tail=new;
}
void initSnake(){
struct Snake *p;
while(head !=NULL){
p=head;
head=head->next;//All nodes in the head list need to be released
free(p);//To free up the previous memory space
}
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=2;
head->lie=2;
head->next=NULL;
tail=head;
addNode();
addNode();
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head=head->next;
free(p);// The purpose of p is to release the deleted node
}
void moveSnake(){
addNode();
deleNode();
if(tail->hang==0 || tail->lie==0 || tail->hang==20 || tail->lie==20){
initSnake();
}
}
void refreshJieMian(){
while(1){
moveSnake();
gamePic();//After the snake moves, need Rescan map
refresh();//Refresh the interface in ncurses
usleep(100000);//stay 100ms
}
}
void changeDir(){
while(1){
key=getch();
switch(key){
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;
}
}
}
int main(){
pthread_t t1;
pthread_t t2;
initNcurse();
initSnake();
gamePic();
pthread_create(&t1,NULL,refreshJieMian,NULL);
pthread_create(&t2,NULL,changeDir,NULL);
while(1);
getch();
endwin();
return 0;
}
18 实现贪吃蛇四方向的疯烧走位
(1)四个方向走位,也是四个方向节点添加,链表中行列+1的区别;
(方向改变跟刷新界面2个线程同时进行,方向改变->界面刷新->蛇移动->添加节点->链表4个方向添加操作);案例snake8.c
#include<curses.h>
#include<stdlib.h>
#define UP 1
#define DOWN 2
#define LEFT 3
#define RIGHT 4
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head=NULL;
struct Snake *tail=NULL;
int key;
int dir;
void initNcurse(){
initscr();
keypad(stdscr,1);
}
int hasSnakeNode(int i,int j){
struct Snake *p;
p=head;
while(p!=NULL){
if(p->hang==i && p->lie==j){
return 1;
}
p=p->next;
}
return 0;
}
void gamePic(){
int hang;
int lie;
move(0,0);//Cursor reset in ncurses
for(hang=0;hang<20;hang++){
if(hang==0){
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(hasSnakeNode(hang,lie)){
printw("[]");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz,key=%d\n",key);
}
}
}
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 initSnake(){
struct Snake *p;
dir =RIGHT;
while(head !=NULL){
p=head;
head=head->next;//All nodes in the head list need to be released
free(p);//To free up the previous memory space
}
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=2;
head->lie=2;
head->next=NULL;
tail=head;
addNode();
addNode();
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head=head->next;
free(p);// The purpose of p is to release the deleted node
}
void moveSnake(){
addNode();
deleNode();
if(tail->hang==0 || tail->lie==0 || tail->hang==20 || tail->lie==20){
initSnake();
}
}
void refreshJieMian(){
while(1){
moveSnake();
gamePic();//After the snake moves, need Rescan map
refresh();//Refresh the interface in ncurses
usleep(100000);//stay 100ms
}
}
void changeDir(){
while(1){
key=getch();
switch(key){
case KEY_DOWN:
dir=DOWN;
break;
case KEY_UP:
dir=UP;
break;
case KEY_LEFT:
dir=LEFT;
break;
case KEY_RIGHT:
dir=RIGHT;
break;
}
}
}
int main(){
pthread_t t1;
pthread_t t2;
initNcurse();
initSnake();
gamePic();
pthread_create(&t1,NULL,refreshJieMian,NULL);
pthread_create(&t2,NULL,changeDir,NULL);
while(1);
getch();
endwin();
return 0;
}
19 绝对值方式解决不合理走位一
(1)旧方向的绝对值不等于新方向的绝对值才改变方向,否则不改方向;案例snake9.c
#include<curses.h>
#include<stdlib.h>
#define UP 1
#define DOWN -1
#define LEFT 2
#define RIGHT -2
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head=NULL;
struct Snake *tail=NULL;
int key;
int dir;
struct Snake food;
void initFood(){
int x = 4;
int y = 5;
food.hang = x;
food.lie = y;
x+=2;
y+=2;
}
void initNcurse(){
initscr();
keypad(stdscr,1);
}
int hasSnakeNode(int i,int j){
struct Snake *p;
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 && foood->lie == j){
return 1;
}
return 0;
}
void gamePic(){
int hang;
int lie;
move(0,0);//Cursor reset in ncurses
for(hang=0;hang<20;hang++){
if(hang==0){
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(hasSnakeNode(hang,lie)){
printw("[]");
}else if(hasFood(hang,lie)){
printw("##");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz,key=%d\n",key);
}
}
}
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 initSnake(){
struct Snake *p;
dir =RIGHT;
while(head !=NULL){
p=head;
head=head->next;//All nodes in the head list need to be released
free(p);//To free up the previous memory space
}
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=2;
head->lie=2;
head->next=NULL;
tail=head;
addNode();
addNode();
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head=head->next;
free(p);// The purpose of p is to release the deleted node
}
void moveSnake(){
addNode();
if(hasFood(tail->hang,tail->lie)){
initFood();
}else{
deleNode();
}
if(tail->hang==0 || tail->lie==0 || tail->hang==20 || tail->lie==20){
initSnake();
}
}
void refreshJieMian(){
while(1){
moveSnake();
gamePic();//After the snake moves, need Rescan map
refresh();//Refresh the interface in ncurses
usleep(100000);//stay 100ms
}
}
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();
gamePic();
pthread_create(&t1,NULL,refreshJieMian,NULL);
pthread_create(&t2,NULL,changeDir,NULL);
while(1);
getch();
endwin();
return 0;
}
20 绝对值方式解决不合理走位二
(1)功能信息显示导致界面乱码,仅需初始化ncurse时调用nocho()函数即可;案例snake10.c
#include<curses.h>
#include<stdlib.h>
#define UP 1
#define DOWN -1
#define LEFT 2
#define RIGHT -2
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head=NULL;
struct Snake *tail=NULL;
int key;
int dir;
void initNcurse(){
initscr();
keypad(stdscr,1);
noecho();//Function key information is not displayed
}
int hasSnakeNode(int i,int j){
struct Snake *p;
p=head;
while(p!=NULL){
if(p->hang==i && p->lie==j){
return 1;
}
p=p->next;
}
return 0;
}
void gamePic(){
int hang;
int lie;
move(0,0);//Cursor reset in ncurses
for(hang=0;hang<20;hang++){
if(hang==0){
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(hasSnakeNode(hang,lie)){
printw("[]");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz,key=%d\n",key);
}
}
}
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 initSnake(){
struct Snake *p;
dir =RIGHT;
while(head !=NULL){
p=head;
head=head->next;//All nodes in the head list need to be released
free(p);//To free up the previous memory space
}
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=2;
head->lie=2;
head->next=NULL;
tail=head;
addNode();
addNode();
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head=head->next;
free(p);// The purpose of p is to release the deleted node
}
void moveSnake(){
addNode();
deleNode();
if(tail->hang==0 || tail->lie==0 || tail->hang==20 || tail->lie==20){
initSnake();
}
}
void refreshJieMian(){
while(1){
moveSnake();
gamePic();//After the snake moves, need Rescan map
refresh();//Refresh the interface in ncurses
usleep(100000);//stay 100ms
}
}
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();
gamePic();
pthread_create(&t1,NULL,refreshJieMian,NULL);
pthread_create(&t2,NULL,changeDir,NULL);
while(1);
getch();
endwin();
return 0;
}
21 贪吃蛇吃饭
(1)定义初始化食物函数及判定是否有食物函数;吃到食物增加节点;案例snake11.c
#include<curses.h>
#include<stdlib.h>
#define UP 1
#define DOWN -1
#define LEFT 2
#define RIGHT -2
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head=NULL;
struct Snake *tail=NULL;
int key;
int dir;
struct Snake food;
void initFood(){
static int x = 4;
static int y = 5;
food.hang = x;
food.lie = y;
x+=2;
y+=2;
}
void initNcurse(){
initscr();
keypad(stdscr,1);
noecho();//Function key information is not displayed
}
int hasSnakeNode(int i,int j){
struct Snake *p;
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 gamePic(){
int hang;
int lie;
move(0,0);//Cursor reset in ncurses
for(hang=0;hang<20;hang++){
if(hang==0){
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(hasSnakeNode(hang,lie)){
printw("[]");
}else if(hasFood(hang,lie)){
printw("##");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz,key=%d,food.hang=%d,food.lie=%d\n",key,food.hang,food.lie);
}
}
}
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 initSnake(){
struct Snake *p;
dir =RIGHT;
while(head !=NULL){
p=head;
head=head->next;//All nodes in the head list need to be released
free(p);//To free up the previous memory space
}
initFood();
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=2;
head->lie=2;
head->next=NULL;
tail=head;
addNode();
addNode();
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head=head->next;
free(p);// The purpose of p is to release the deleted node
}
void moveSnake(){
addNode();
if(hasFood(tail->hang,tail->lie)){
initFood();
}else{
deleNode();
}
if(tail->hang==0 || tail->lie==0 || tail->hang==20 || tail->lie==20){
initSnake();
}
}
void refreshJieMian(){
while(1){
moveSnake();
gamePic();//After the snake moves, need Rescan map
refresh();//Refresh the interface in ncurses
usleep(100000);//stay 100ms
}
}
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();
gamePic();
pthread_create(&t1,NULL,refreshJieMian,NULL);
pthread_create(&t2,NULL,changeDir,NULL);
while(1);
getch();
endwin();
return 0;
}
22 贪吃蛇食物位置随机
(1)调用rand()函数与边界20进行取余可得到随机在20内的坐标。rand()%20;案例snake12.c
#include<curses.h>
#include<stdlib.h>
#define UP 1
#define DOWN -1
#define LEFT 2
#define RIGHT -2
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head=NULL;
struct Snake *tail=NULL;
int key;
int dir;
struct Snake food;
void initFood(){
int x = rand()%20;
int y = rand()%20;
food.hang = x;
food.lie = y;
}
void initNcurse(){
initscr();
keypad(stdscr,1);
noecho();//Function key information is not displayed
}
int hasSnakeNode(int i,int j){
struct Snake *p;
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 gamePic(){
int hang;
int lie;
move(0,0);//Cursor reset in ncurses
for(hang=0;hang<20;hang++){
if(hang==0){
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(hasSnakeNode(hang,lie)){
printw("[]");
}else if(hasFood(hang,lie)){
printw("##");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz,key=%d,food.hang=%d,food.lie=%d\n",key,food.hang,food.lie);
}
}
}
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 initSnake(){
struct Snake *p;
dir =RIGHT;
while(head !=NULL){
p=head;
head=head->next;//All nodes in the head list need to be released
free(p);//To free up the previous memory space
}
initFood();
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=2;
head->lie=2;
head->next=NULL;
tail=head;
addNode();
addNode();
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head=head->next;
free(p);// The purpose of p is to release the deleted node
}
void moveSnake(){
addNode();
if(hasFood(tail->hang,tail->lie)){
initFood();
}else{
deleNode();
}
if(tail->hang==0 || tail->lie==0 || tail->hang==20 || tail->lie==20){
initSnake();
}
}
void refreshJieMian(){
while(1){
moveSnake();
gamePic();//After the snake moves, need Rescan map
refresh();//Refresh the interface in ncurses
usleep(100000);//stay 100ms
}
}
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();
gamePic();
pthread_create(&t1,NULL,refreshJieMian,NULL);
pthread_create(&t2,NULL,changeDir,NULL);
while(1);
getch();
endwin();
return 0;
}
23 贪吃蛇撞墙找死和想不开要死自己结束游戏的代码优化
(1)定义是否死亡函数,内部有2中死亡情况,第一种为撞墙,第二种为咬到自己(尾的行列与头的行列相等了);案例snake13.c;编译运行gcc snake13.c -lcurses -lpthread
#include<curses.h>
#include<stdlib.h>
#define UP 1
#define DOWN -1
#define LEFT 2
#define RIGHT -2
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head=NULL;
struct Snake *tail=NULL;
int key;
int dir;
struct Snake food;
void initFood(){
int x = rand()%20;
int y = rand()%20;
food.hang = x;
food.lie = y;
}
void initNcurse(){
initscr();
keypad(stdscr,1);
noecho();//Function key information is not displayed
}
int hasSnakeNode(int i,int j){
struct Snake *p;
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 gamePic(){
int hang;
int lie;
move(0,0);//Cursor reset in ncurses
for(hang=0;hang<20;hang++){
if(hang==0){
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(hasSnakeNode(hang,lie)){
printw("[]");
}else if(hasFood(hang,lie)){
printw("##");
}
else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By qiuz,key=%d,food.hang=%d,food.lie=%d\n",key,food.hang,food.lie);
}
}
}
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 initSnake(){
struct Snake *p;
dir =RIGHT;
while(head !=NULL){
p=head;
head=head->next;//All nodes in the head list need to be released
free(p);//To free up the previous memory space
}
initFood();
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=2;
head->lie=2;
head->next=NULL;
tail=head;
addNode();
addNode();
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head=head->next;
free(p);// The purpose of p is to release the deleted node
}
int isSnakeDie(){
struct Snake *p;
p=head;
if(tail->hang<0 || tail->lie==0 ||tail->hang==20 || tail->lie==20){
return 1;
}
while(p->next!=NULL){
if(p->hang == tail->hang && p->lie == tail->lie){
return 1;
}
p=p->next;
}
return 0;
}
void moveSnake(){
addNode();
if(hasFood(tail->hang,tail->lie)){
initFood();
}else{
deleNode();
}
if(isSnakeDie()){
initSnake();
}
}
void refreshJieMian(){
while(1){
moveSnake();
gamePic();//After the snake moves, need Rescan map
refresh();//Refresh the interface in ncurses
usleep(100000);//stay 100ms
}
}
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();
gamePic();
pthread_create(&t1,NULL,refreshJieMian,NULL);
pthread_create(&t2,NULL,changeDir,NULL);
while(1);
getch();
endwin();
return 0;
}
24 贪吃蛇小游戏总结
(1)地图-》蛇走位-》蛇吃食物;
编译运行:gcc snake13.c -lcurses -lpthread,即可显示最终结果