1. 程式人生 > >資訊學奧林匹克競賽-C語言貪吃蛇

資訊學奧林匹克競賽-C語言貪吃蛇

來源:http://www.clang.cc/news/project/2015/0611/93.html

#include<stdio.h>
#include<time.h>
#include<windows.h>
#include<stdlib.h>

#define U 1
#define D 2
#define L 3
#define R 4       //蛇的狀態,U:上 ;D:下;L:左 R:右

typedef struct SNAKE { //蛇身的一個節點
	int x;
	int y;
	struct SNAKE *next;
} snake;

//全域性變數//
int score=0,add=10;//總得分與每次吃食物得分。
int status,sleeptime=200;//每次執行的時間間隔
snake *head, *food;//蛇頭指標,食物指標
snake *q;//遍歷蛇的時候用到的指標
int endgamestatus=0; //遊戲結束的情況,1:撞到牆;2:咬到自己;3:主動退出遊戲。

//宣告全部函式//
void Pos();
void creatMap();
void initsnake();
int biteself();
void createfood();
void cantcrosswall();
void snakemove();
void pause();
void gamecircle();
void welcometogame();
void endgame();
void gamestart();

void Pos(int x,int y) { //設定游標位置
	COORD pos;
	HANDLE hOutput;
	pos.X=x;
	pos.Y=y;
	hOutput=GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOutput,pos);
}

void creatMap() { //建立地圖
	int i;
	for(i=0; i<58; i+=2) { //列印上下邊框
		Pos(i,0);
		printf("■");
		Pos(i,26);
		printf("■");
	}
	for(i=1; i<26; i++) { //列印左右邊框
		Pos(0,i);
		printf("■");
		Pos(56,i);
		printf("■");
	}
}

void initsnake() { //初始化蛇身
	snake *tail;
	int i;
	tail=(snake*)malloc(sizeof(snake));//從蛇尾開始,頭插法,以x,y設定開始的位置//
	tail->x=24;
	tail->y=5;
	tail->next=NULL;
	for(i=1; i<=4; i++) {
		head=(snake*)malloc(sizeof(snake));
		head->next=tail;
		head->x=24+2*i;
		head->y=5;
		tail=head;
	}
	while(tail!=NULL) { //從頭到為,輸出蛇身
		Pos(tail->x,tail->y);
		printf("■");
		tail=tail->next;
	}
}

int biteself() { //判斷是否咬到了自己
	snake *self;
	self=head->next;
	while(self!=NULL) {
		if(self->x==head->x && self->y==head->y) {
			return 1;
		}
		self=self->next;
	}
	return 0;
}

void createfood() { //隨機出現食物
	snake *food_1;
	srand((unsigned)time(NULL));
	food_1=(snake*)malloc(sizeof(snake));
	while((food_1->x%2)!=0) {  //保證其為偶數,使得食物能與蛇頭對其
		food_1->x=rand()%52+2;
	}
	food_1->y=rand()%24+1;
	q=head;
	while(q->next==NULL) {
		if(q->x==food_1->x && q->y==food_1->y) { //判斷蛇身是否與食物重合
			free(food_1);
			createfood();
		}
		q=q->next;
	}
	Pos(food_1->x,food_1->y);
	food=food_1;
	printf("■");
}

void cantcrosswall() { //不能穿牆
	if(head->x==0 || head->x==56 ||head->y==0 || head->y==26) {
		endgamestatus=1;
		endgame();
	}
}

void snakemove() { //蛇前進,上U,下D,左L,右R
	snake * nexthead;
	cantcrosswall();

	nexthead=(snake*)malloc(sizeof(snake));
	if(status==U) {
		nexthead->x=head->x;
		nexthead->y=head->y-1;
		if(nexthead->x==food->x && nexthead->y==food->y) { //如果下一個有食物//
			nexthead->next=head;
			head=nexthead;
			q=head;
			while(q!=NULL) {
				Pos(q->x,q->y);
				printf("■");
				q=q->next;
			}
			score=score+add;
			createfood();
		} else {                                           //如果沒有食物//
			nexthead->next=head;
			head=nexthead;
			q=head;
			while(q->next->next!=NULL) {
				Pos(q->x,q->y);
				printf("■");
				q=q->next;
			}
			Pos(q->next->x,q->next->y);
			printf("  ");
			free(q->next);
			q->next=NULL;
		}
	}
	if(status==D) {
		nexthead->x=head->x;
		nexthead->y=head->y+1;
		if(nexthead->x==food->x && nexthead->y==food->y) { //有食物
			nexthead->next=head;
			head=nexthead;
			q=head;
			while(q!=NULL) {
				Pos(q->x,q->y);
				printf("■");
				q=q->next;
			}
			score=score+add;
			createfood();
		} else {                           //沒有食物
			nexthead->next=head;
			head=nexthead;
			q=head;
			while(q->next->next!=NULL) {
				Pos(q->x,q->y);
				printf("■");
				q=q->next;
			}
			Pos(q->next->x,q->next->y);
			printf("  ");
			free(q->next);
			q->next=NULL;
		}
	}
	if(status==L) {
		nexthead->x=head->x-2;
		nexthead->y=head->y;
		if(nexthead->x==food->x && nexthead->y==food->y) { //有食物
			nexthead->next=head;
			head=nexthead;
			q=head;
			while(q!=NULL) {
				Pos(q->x,q->y);
				printf("■");
				q=q->next;
			}
			score=score+add;
			createfood();
		} else {                            //沒有食物
			nexthead->next=head;
			head=nexthead;
			q=head;
			while(q->next->next!=NULL) {
				Pos(q->x,q->y);
				printf("■");
				q=q->next;
			}
			Pos(q->next->x,q->next->y);
			printf("  ");
			free(q->next);
			q->next=NULL;
		}
	}
	if(status==R) {
		nexthead->x=head->x+2;
		nexthead->y=head->y;
		if(nexthead->x==food->x && nexthead->y==food->y) { //有食物
			nexthead->next=head;
			head=nexthead;
			q=head;
			while(q!=NULL) {
				Pos(q->x,q->y);
				printf("■");
				q=q->next;
			}
			score=score+add;
			createfood();
		} else {                                     //沒有食物
			nexthead->next=head;
			head=nexthead;
			q=head;
			while(q->next->next!=NULL) {
				Pos(q->x,q->y);
				printf("■");
				q=q->next;
			}
			Pos(q->next->x,q->next->y);
			printf("  ");
			free(q->next);
			q->next=NULL;
		}
	}
	if(biteself()==1) {     //判斷是否會咬到自己
		endgamestatus=2;
		endgame();
	}
}

void pause() { //暫停
	while(1) {
		Sleep(300);
		if(GetAsyncKeyState(VK_SPACE)) {
			break;
		}

	}
}

void gamecircle() { //控制遊戲

	Pos(64,15);
	printf("不能穿牆,不能咬到自己\n");
	Pos(64,16);
	printf("用↑.↓.←.→分別控制蛇的移動.");
	Pos(64,17);
	printf("F1 為加速,F2 為減速\n");
	Pos(64,18);
	printf("ESC :退出遊戲.space:暫停遊戲.");
	Pos(64,20);
	printf("C語言研究中心 www.clang.cc");
	status=R;
	while(1) {
		Pos(64,10);
		printf("得分:%d  ",score);
		Pos(64,11);
		printf("每個食物得分:%d分",add);
		if(GetAsyncKeyState(VK_UP) && status!=D) {
			status=U;
		} else if(GetAsyncKeyState(VK_DOWN) && status!=U) {
			status=D;
		} else if(GetAsyncKeyState(VK_LEFT)&& status!=R) {
			status=L;
		} else if(GetAsyncKeyState(VK_RIGHT)&& status!=L) {
			status=R;
		} else if(GetAsyncKeyState(VK_SPACE)) {
			pause();
		} else if(GetAsyncKeyState(VK_ESCAPE)) {
			endgamestatus=3;
			break;
		} else if(GetAsyncKeyState(VK_F1)) {
			if(sleeptime>=50) {
				sleeptime=sleeptime-30;
				add=add+2;
				if(sleeptime==320) {
					add=2;//防止減到1之後再加回來有錯
				}
			}
		} else if(GetAsyncKeyState(VK_F2)) {
			if(sleeptime<350) {
				sleeptime=sleeptime+30;
				add=add-2;
				if(sleeptime==350) {
					add=1;  //保證最低分為1
				}
			}
		}
		Sleep(sleeptime);
		snakemove();
	}
}

void welcometogame() { //開始介面
	Pos(40,12);

	system("title C語言研究中心   www.clang.cc");
	printf("歡迎來到貪食蛇遊戲!");
	Pos(40,25);
	printf("              C語言研究中心  www.clang.cc.\n");
	system("pause");
	system("cls");
	Pos(25,12);
	printf("用↑.↓.←.→分別控制蛇的移動, F1 為加速,2 為減速\n");
	Pos(25,13);
	printf("加速將能得到更高的分數。\n");
	system("pause");
	system("cls");
}

void endgame() { //結束遊戲

	system("cls");
	Pos(24,12);
	if(endgamestatus==1) {
		printf("對不起,您撞到牆了。遊戲結束.");
	} else if(endgamestatus==2) {
		printf("對不起,您咬到自己了。遊戲結束.");
	} else if(endgamestatus==3) {
		printf("您的已經結束了遊戲。");
	}
	Pos(24,13);
	printf("您的得分是%d\n",score);
	exit(0);
}

void gamestart() { //遊戲初始化
	system("mode con cols=100 lines=30");
	welcometogame();
	creatMap();
	initsnake();
	createfood();
}

int main() {
	gamestart();
	gamecircle();
	endgame();
	return 0;
}