简易说明:简化了之前的代码,优化了效率,更改了游戏的显示模式(相比之前的每一次清空之后再写入,此次取消了清空,直接对snake的部分进行逻辑处理),其它请在代码中查找。
显示如下:
/*蛇吃字母的游戏*/
/*画面产生A-Z字母,蛇头为@,蛇尾为oo,吃掉的字母在其蛇身顺序显示,如:@ABCoo */
/*2018.9.27*/
/*(c/c++)centos*/
#include <stdio.h>
#include <time.h>
#include <malloc.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/select.h>
#define high 15
#define wide 20
#define up 'w'
#define down 's'
#define left 'a'
#define right 'd'
int score = 0;
int Level = 1;
int FoodNumber=0;
char direction = 'w';
char EatenFood;
int IsEat;
int FoodH=5,FoodW=10;
char Picture[high][wide]; //显示数组
typedef struct snake{
int x;
int y;
struct snake* next;
}Node,*PSnake;
void setIO(int flag)
{
if(flag)
system("stty cbreak -echo");
else
system("stty cooked echo");
}
PSnake Init() //生成一条蛇 坐标为中心点向下2个格,蛇头向上
{
printf("SnakeMake start!\n");
int len=5;
PSnake head=(PSnake)malloc(sizeof(Node));
if(head == NULL)
printf("Snake head make failed!\n");
head->x=wide/2;
head->y=high/2+5;
head->next=NULL;
int i=0;
for(;i<2;i++)
{
PSnake P=(PSnake)malloc(sizeof(Node));
if(P==NULL)
{
printf("Frog king is dead!\n");
break;
}
P->x=wide/2;
P->y=high/2-i+4;
P->next=head;
head=P;
}
printf("Snake is alive!\n");
return head;
}
/*吃食物*/
PSnake Eat(int x,int y,PSnake snake) //把食物与头调换位置完成“吃”的动作
{
EatenFood=Picture[snake->y][snake->x]=Picture[y][x];
PSnake p=(PSnake)malloc(sizeof(Node));
if(p==NULL)
{
printf("New head make failed!");
}
p->x = x;
p->y = y;
Picture[y][x]='@';
p->next=snake;
score += Picture[snake->y][snake->x];
FoodNumber--;
IsEat=1;
return p;
}
/*行进一步*/
void Walk(int x,int y,PSnake snake) //优化,把蛇身前移
{
PSnake p=snake;
int a,b;
while(p!=NULL)
{
a=p->x;
b=p->y;
p->x = x;
p->y = y;
Picture[p->y][p->x] = Picture[b][a];
if(p->next == NULL)
{
Picture[b][a]=' ';
}
x=a;
y=b;
p=p->next;
}
}
/*检验是否会吃掉自己*/
int Serch(int x,int y,PSnake snake)
{
PSnake q=snake->next;
while(q!= NULL)
{
if( ( (q->x) == x ) && ( (q->y) == y ) )
return 1;
q=q->next;
}
return 0;
}
/*初始化蛇的图像*/
void WriteSnake(PSnake snake) //把蛇写入打印数组
{
PSnake p=snake;
while(p != NULL)
{
if( p==snake )
{
Picture[p->y][p->x] = '@';
}
else
{
Picture[p->y][p->x] = 'o';
}
p=p->next;
}
}
/*初始化游戏数组*/
void InitArray(void)
{
int y=high,x=wide,i,j;
for(i=0; i<y; i++)
for(j=0; j<x; j++)
Picture[i][j]=' ';
}
/*显示游戏画面*/
void Print(char* p,int score,int Lev) //打印框架,生成画面
{
int i=0,j;
static int cnt=1;
printf("\033c");
printf(" The Snake Game is On!! The Write times is %d !\n",cnt);
cnt++;
printf("Player:%s Score:%d Level:%d \n",p,score,Lev);
while( i < wide*2+2 )
{
printf("-");
i++;
}
printf("\n");
for (i=0; i < high; i++)
{
printf("|");
for(j=0; j<wide; j++)
{
printf("%c ",Picture[i][j]);
}
printf("|");
printf("\n");
}
for(i=0;i<=wide*2+1;i++)
{
printf("-");
}
printf("\nGameShow:");
if( IsEat != 0)
{
printf("Your snake eat a \"%c\"!Score:+%d !\n",EatenFood,EatenFood);
IsEat=0;
}
else
{
printf("Your snake take a step!\n");
}
printf("-----------------------------------------------------\n");
printf("----Wish you have fun!-------------------------------\n");
printf("===========++++++++This is bottom!!!!++++++++++++++++\n");
}
/*食物产生*/
int MakeFood(void) //创造食物并写入框图
{
static int MC=0; //MC = FoodMake Count
int timeLimit;
struct timeval start,end;
gettimeofday(&start,NULL);
while(1)
{
if(MC > ((high * wide)*2/3 ) )
return 0;
gettimeofday(&end,NULL);
timeLimit = (end.tv_sec - start.tv_sec)*1000000 + end.tv_usec - start.tv_usec;
if(timeLimit > 10000) //控制食物生成时间,提升显示流畅度
return 0;
srand((int)time(0));
FoodH=rand()%high;
FoodW=rand()%wide;
if(Picture[FoodH][FoodW] == ' ')
{
break;
}
}
Picture[FoodH][FoodW]=rand()%26+65;
MC++;
FoodNumber++;
return 1;
}
/*蛇的运动*/
PSnake MakeMove(PSnake s) //蛇的动作
{
int x,y;
PSnake p=s;
x=s->x,y=s->y;
/*产生运动方向下的下一个坐标x,y,以此判断下列情况*/
if(direction == up)
y = y - 1;
if(direction == down)
y = y + 1;
if(direction == right)
x = x + 1;
if(direction == left)
x = x - 1;
//check if the snake crash the wall
if( (y>(high-1)) || ((y<0)) || ((x)<0) || (x>(wide-1)) )
{
//printf("x=%d y=%d s.x=%d s.y=%d \n",x,y,s->x,s->y);
printf("The snake break the wall!\n");
return NULL;
}
//check if the snake eat itself
if(Serch(x,y,s))
{
printf("Your snake eat itsself!\n");
return NULL;
}
//if there is a food
if(Picture[y][x] != ' ')
{
s=Eat(x,y,s);
}
//if there is no food
else
{
Walk(x,y,s);
}
return s;
}
/*检查是否有键按下*/
int kbhit(void)
{
struct timeval tv;
fd_set rdfs;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&rdfs);
FD_SET(STDIN_FILENO,&rdfs);
select(STDIN_FILENO+1,&rdfs,NULL,NULL,&tv);
return FD_ISSET(STDIN_FILENO,&rdfs);
}
/*控制输入*/
void InputCTL(int level)
{
char Dir=direction;
int timeUse;
struct timeval start,end;
gettimeofday(&start,NULL);
setIO(1);
while(1)
{
gettimeofday(&end,NULL);
timeUse = 1000000*(end.tv_sec - start.tv_sec) +
end.tv_usec - start.tv_usec;
if(timeUse > 1000000 - level*100000)
break;
if(kbhit())
Dir=getchar();
}
setIO(0);
/*如果按键方向与蛇原来的行进方向相反,则忽略*/
if( ((Dir == 'w') && (direction == down) ) || ((Dir == 's') && (direction == up))
|| ((Dir == 'a') && (direction == right)) || ((Dir == 'd') && (direction == left) ) )
{
printf("Dir = %d \n",Dir);
}
/*如果按键是有效的,则使用新的direction*/
else if((Dir == 'a') || (Dir=='s') || (Dir=='w') || (Dir=='d'))
{
direction = Dir;
}
else
{
printf("Input direction Wrong!");
}
}
/*游戏等级控制及输出*/
int CheckLevel(int score)
{
static int change=0;
if(((score - change) >= 1000) && (Level < 9) )
{
Level ++;
change += 1000;
}
return Level;
}
/*游戏运行*/
void GameRun(void)
{
int GameState=1;
score=0;
Level=1;
char Name[10];
printf("Please input your name,push the 'Enter' to end:");
scanf("%s",&Name);
PSnake jack=Init();
InitArray();
WriteSnake(jack);
while(GameState)
{
if(FoodNumber<5) 如果存在的食物少于5,则产生新的食物
{
MakeFood();
}
Print(Name,score,CheckLevel(score)); //打印游戏画面
InputCTL(Level); //控制输入
jack = MakeMove(jack);
if( jack == NULL ) //游戏结束判断
{
GameState=0;
printf("Game Over!\n");
printf("Your final score:%d.\n",score);
}
}
}
int main(void)
{
GameRun();
return 0;
}