C语言小项目-贪吃蛇

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,即可显示最终结果

  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值