Created
March 13, 2014 15:19
-
-
Save moehuster/9530447 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <time.h> | |
#include <conio.h> | |
#include <windows.h> | |
struct node { | |
int x; | |
int y; | |
}; | |
typedef struct node Node; | |
int delay = 600; /* 延时(蛇爬行速度) */ | |
int state = 1; /* 判断蛇存活的标记 */ | |
int eatFlag = 0; /* 吃了的目标点标记1 */ | |
int maxScore = 0; /* 最高分 */ | |
int length = 1; /* 蛇的长度 */ | |
Node snake[100]; /* 一行存放蛇每个点的X和Y坐标 */ | |
Node head = {40,12}; /* 蛇头 */ | |
Node tail = {40,12}; /* 存放蛇尾的坐标 */ | |
Node target; /* 存放目标点的坐标 */ | |
int xMin=1,xMax=62,yMin=1,yMax=24; /* 窗口坐标范围 */ | |
char directionPre = 's'; /* 蛇移动方向 */ | |
char direction = 's'; /* 修改蛇移动方向 */ | |
void createWindow(); /* 创建一个窗口 */ | |
void init(); /* 初始化 */ | |
void createTarget(); /* 创建随即目标 */ | |
void getDirection(); /* 获取方向 */ | |
void eat(); /* 吃动作 */ | |
void updateSnake(); /* 更新保存蛇的数组 */ | |
void liveState(); /* 蛇存活状态判定 */ | |
void showSnake(); /* 显示蛇 */ | |
void setXy(int,int); /* 获取窗口坐标 */ | |
void updateScore(); /* 更新分数 */ | |
int main(void) { | |
createWindow(); | |
init(); | |
createTarget(); | |
while (1) { | |
getDirection(); | |
eat(); | |
updateSnake(); | |
liveState(); | |
if (state) showSnake(); | |
else break; | |
Sleep(delay); | |
} | |
return 0; | |
} | |
void createWindow() { | |
int i; | |
char str[64]; | |
memset(str,'=',60); str[60]='\0'; | |
setXy(0,0); | |
printf( "|%s|\n",str ); | |
printf( "|%30c%30c|\n",'|',' ' ); | |
printf( "|%s|\n",str ); | |
for (i=3; i<23; i++) | |
printf ( "|%60c|\n",' ' ); | |
printf( "|%s|\n",str ); | |
} | |
void setXy(int x,int y) { | |
COORD position = {x,y}; | |
HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE); | |
SetConsoleCursorPosition(hout,position); | |
} | |
void init() { | |
FILE *fp; | |
setXy(head.x, head.y); /* 将最开始的蛇头显示出来 */ | |
printf("*"); | |
snake[0] = head; /* 将蛇头保存在数组的第一个位置 */ | |
if ((fp = fopen("score.txt","r"))==NULL) {/* 读取存档文件,里面有分数 */ | |
fp = fopen("score.txt","w"); | |
fprintf(fp,"%d",0); /* 第一次玩这个游戏,最高分设置为零 */ | |
maxScore = 0; | |
fclose(fp); | |
} | |
else {/* 表示非第一次玩,将源文件里面存放的最高分读出来放在max变量里面 */ | |
fscanf(fp,"%d",&maxScore); | |
fclose(fp); | |
} | |
updateScore();/* 取出maxScore后将这个结果显示在窗口上 */ | |
} | |
void updateScore() { | |
setXy(5,1); | |
printf( "蛇长:%d",length ); | |
setXy(36,1); | |
printf( "最高分:%d\n",maxScore ); | |
} | |
void createTarget() { | |
int i,flag=1; | |
srand(time(NULL)); | |
while(flag) { | |
target.x = rand()%(xMax-1); | |
target.y = rand()%(yMax-1); | |
while (target.x%2 || target.x<xMin || target.y<yMin+1){ | |
target.x = rand()%(xMax-1); | |
target.y = rand()%(yMax-1); | |
} | |
for (i=0; i<length; i++) /* 蛇身不能和目标点重合 */ | |
if (target.x!=snake[i].x && target.y!=snake[i].y) { | |
flag = 0; | |
break; | |
} | |
} | |
setXy(target.x,target.y); | |
printf ( "o" ); | |
} | |
char reDirection(char direct) { /* 获取蛇移动的相反方向 */ | |
switch (direct) { | |
case 'a': return 'd'; | |
case 'd': return 'a'; | |
case 'w': return 's'; | |
case 's': return 'w'; | |
default: break; | |
} | |
return 0; | |
} | |
void getDirection() { | |
char direct; | |
directionPre = direction;/* 将上次蛇移动的方向赋值给预方向 */ | |
while (kbhit() != 0) { /* 当键盘有输入的时候那么就去缓冲区接受输入 */ | |
direction = getch(); | |
} | |
direct = reDirection(direction); | |
if (!direct || directionPre==direct) | |
direction = directionPre;/*如果按键按下的方向和上次移动的方向相反, | |
那么将上次移动的方向赋值给本次移动的方向 */ | |
switch (direction) { | |
case 'a': head.x -= 2; /* 按下a的时候,让代表蛇头的坐标的X轴位置减2 */ | |
break; | |
case 'd': head.x += 2; | |
break; | |
case 'w': head.y -= 1; | |
break; | |
case 's': head.y += 1; | |
break; | |
default: break; | |
} | |
} | |
void eat() { | |
if (target.x==head.x && target.y==head.y) { | |
length++; | |
snake[length-1] = head;/* 将蛇头存放在snake数组最后,并将snake长度加1 */ | |
eatFlag = 1; | |
createTarget(); | |
if (length>maxScore) maxScore = length; | |
updateScore(); /* 更新蛇长度 */ | |
if (delay>100) /* 最初是600,只要>100延迟就减少50ms */ | |
delay -= 50; /* 延迟至少是100,否则蛇无法控制 */ | |
} | |
} | |
void updateSnake(){ | |
int i; | |
if (!eatFlag) { | |
tail = snake[0];/* 将蛇尾存放在tail,如果一次按键没有吃到目标,数组整体左移, | |
仍然要将蛇头head保存在snake数组,因为snake数组保存的蛇的最新状态 */ | |
for (i=0; i<length-1; i++) | |
snake[i] = snake[i+1]; | |
snake[length-1] = head; | |
} | |
} | |
void liveState() { | |
FILE *fp; | |
int i,flag; | |
for (i=0,flag=0; i<length-1; i++) { | |
if (head.x==snake[i].x && head.y==snake[i].y) { | |
flag = 1; /* 蛇头和蛇身重合--表示要退出了 */ | |
break; | |
} | |
} | |
/* 下面的判断表示蛇头碰壁了或者蛇头和蛇身重合了就结束 */ | |
if (head.x<=xMin || head.x>=xMax || head.y<=yMin || head.y>=yMax || flag==1) { | |
setXy(26,12); | |
printf ( "Game Over!\n" ); | |
state = 0; | |
fp = fopen("score.txt","w"); | |
fprintf(fp,"%d",maxScore); | |
fclose(fp); | |
} | |
} | |
void showSnake() { | |
setXy(head.x,head.y); | |
printf ( "*" ); | |
if (!eatFlag) { | |
setXy(tail.x,tail.y); | |
printf ( " " ); /* 将蛇以前的尾巴覆盖 */ | |
} | |
else eatFlag=0;/* 要是吃了就要将这个吃的标记还原,以便下次吃的时候容易判断 */ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment