关键点:
1:地图界面的刷新 用22x22的方格,作为地图空间,第一和最后一行(列),作为边界;
边界:*
蛇身:【】
食物:##
2:蛇身的制作及移动规则,方向控制(按键响应)
3:食物刷新
4:按键响应、
为了实现上下左右的按键响应控制和界面显示,调用了ncurses库,因为简单易用。
initscr():设定并初始化ncurses要用到的一些值;
endwin():恢复终端机到使用前的状态,和initscr作用呼应;
getch():等待获取用户输入;
printw:打印,ncurses库封装好的printf
keypad(stdscr,1):功能按键设定
refersh():刷新界面,有时候界面不会马上刷新出来
要用到的功能按键:
#define KEY_DOWN 0402 /* down-arrow key */
#define KEY_UP 0403 /* up-arrow key */
#define KEY_LEFT 0404 /* left-arrow key */
#define KEY_RIGHT 0405 /* right-arrow key */
ncurses 按键响应代码模板:
#include<curses.h>
int main()
{
initscr();
keypad(stdscr,1);
int key;
while(1){
key = getch();
printw("key = %d\n",key);
}
endwin();
return 0;
}
完整代码如下:
#include<stdio.h>
#include<curses.h>
#include <stdlib.h>
#include <unistd.h>
#include<pthread.h>
#include<string.h>
struct snake{ //小蛇结构体
int hang;
int lie;
struct snake *next;
};
struct snake *head = NULL; //蛇头节点
struct snake *tail = NULL; //蛇尾节点
struct snake food; //食物
int dir ; //键盘输入方向
char *Dir ; //当前方向
int score; //游戏得分
void initncurses(){ //初始化ncurses库
initscr();
keypad(stdscr,1); //按键响应
}
void gamepic(){
int hang;
int lie;
struct snake *p;
p = head;
int k = 0;
move(0,0);
for(hang = 0;hang < 22;hang++){
if(hang == 0){
printw("\n\nSNAKE score:%d\n",score);
for(lie = 0;lie < 22;lie++){
if(lie > 0 && lie < 21){
printw("**");
}else if(lie == 0 || lie == 21){
printw("*");
}
}
printw("\n");
}else if(hang > 0 && hang < 21){
for(lie = 0;lie < 22;lie++){
if(lie == 0 || lie == 21){
printw("*");
}else {
while(p != NULL){
if(p->hang == hang && p->lie == lie){
printw("[]");
k = 1;
}
p = p->next;
}
if(k != 1){
if(hang == food.hang && lie == food.lie){
printw("##");
}else{
printw(" ");
}
}
k = 0;
p = head;
}
}
printw("\n");
}else if(hang == 21){
for(lie = 0;lie < 22;lie++){
if(lie > 0 && lie < 21){
printw("**");
}else if(lie == 0 || lie == 21){
printw("*");
}
}
printw("\n\n");
printw("make by zengtiejiang Direction: %s ",Dir);
}
}
}
void initfood(){
struct snake *p;
p = head;
int hang = rand()%21; //随机一个0到20的数
int lie = rand()%21;
while(p != NULL){
if((hang == p->hang && lie == p->lie) || hang == 0 || lie == 0){
hang = rand()%21;
lie = rand()%21;
p = head;
}
p = p->next;
}
food.hang = hang;
food.lie = lie;
}
void initDir(){
Dir = (char *)malloc(16);
memset(Dir,'\0',16);
Dir ="RIGHT";
dir =KEY_RIGHT ;
}
void addnode(){
struct snake *new;
new = (struct snake *)malloc(sizeof(struct snake));
switch(dir){
case KEY_DOWN:
if(Dir != "UP "){ //防止小蛇反向走位,将方向改正,并向前加一个节点
new->hang = head->hang+1;
new->lie = head->lie ;
Dir = "DOWN ";
}else{
dir = KEY_UP;
Dir != "UP ";
new->hang = head->hang-1;
new->lie = head->lie ;
}
break;
case KEY_UP:
if(Dir != "DOWN "){
new->hang = head->hang-1;
new->lie = head->lie ;
Dir = "UP ";
}else{
dir = KEY_DOWN;
Dir != "DOWN ";
new->hang = head->hang+1;
new->lie = head->lie ;
}
break;
case KEY_LEFT:
if(Dir != "RIGHT"){
new->hang = head->hang;
new->lie = head->lie - 1;
Dir = "LEFT ";
}else{
dir = KEY_RIGHT ;
Dir != "RIGHT";
new->hang = head->hang;
new->lie = head->lie + 1;
}
break;
case KEY_RIGHT:
if(Dir != "LEFT "){
new->hang = head->hang;
new->lie = head->lie + 1;
Dir = "RIGHT";
}else{
dir = KEY_LEFT;
Dir != "LEFT ";
new->hang = head->hang;
new->lie = head->lie - 1;
}
break;
}
new->next = head;
head = new;
}
void deletenode(){
struct snake *p;
p = head;
while(p != NULL){
if(p->next->next == NULL){
tail = p;
tail->next = NULL;
p = p->next;
free(p);
}else {
p = p->next;
}
}
}
void initsnake(){
struct snake *p;
initDir();
while(head != NULL){ //清除所有节点
p = head;
head = head->next;
free(p);
}
head = (struct snake *)malloc(sizeof(struct snake));
head->hang = 2;
head->lie = 2;
head->next = NULL;
tail = head;
addnode(); //给蛇身增加一个链表节点
addnode();
score = 0;
}
int eatitself(){
struct snake *p;
struct snake *q;
p = head->next;
while( p != NULL){
if(p->hang == head->hang && p->lie == head->lie){ //蛇撞到自己
return 1;
}
p = p->next;
}
return 0;
}
void movesnake(){
if(head->hang == 0 || head->hang == 21 || head->lie == 0 || head->lie == 21){ //撞墙
initsnake();
initfood();
}else if(head->hang == food.hang && head->lie == food.lie){ //吃到食物
initfood();
score = score+1;
addnode();
}else if(eatitself() == 1){ //吃到自己
initsnake();
initfood();
}else{ //正常移动
addnode();
deletenode();
}
}
void *changedir(){
while(1){
dir = getch();
}
}
void *refreshface(){
while(1){
movesnake();
if(head->hang != 0 && head->hang != 21 && head->lie != 0 && head->lie != 21 ){ //撞墙时不刷新地图
if(eatitself() == 0){
gamepic();
}
}
refresh();
usleep(200000);
}
}
int main(){
pthread_t t1;
pthread_t t2; //定义线程名字
initncurses(); //初始化ncurses
initDir(); //初始化方向
initsnake(); //创建蛇身链表
initfood(); //随即刷新食物
gamepic(); //初始化地图
pthread_create(&t1,NULL,refreshface,NULL);//刷新界面线程
pthread_create(&t2,NULL,changedir,NULL);//按键响应线程
while(1); //防止主进程退出
getch();
endwin();
return 0;
}