Skip to content

Instantly share code, notes, and snippets.

@moehuster
Created March 13, 2014 15:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moehuster/9530447 to your computer and use it in GitHub Desktop.
Save moehuster/9530447 to your computer and use it in GitHub Desktop.
#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