貪喫蛇-C語言版

最近將STL源碼剖析、linux編程擱置了一段時間,簡單做了個C語言版的貪喫蛇
涉及到的知識點如下:
1、隨機數 srand((unsigned)time(NULL))種子、獲取隨機數rand()%100
2、enum枚舉體變量
3、volatile關鍵字

  • 編譯器的優化技術:一般情況下編譯器會將變量的值存儲在寄存器中,以便配合CPU的執行速率,減少對RAM的訪問,提高執行速度
  • volatile關鍵字則提醒編譯器被定義的變量每次只能從內存空間中訪問,而不能從寄存器中讀取。
  • 用處:某一個變量需要作爲多個.c文件的通信中介時,可以用volatile關鍵字修飾,告訴編譯器該變量的隨時可能被更改

4、BOOL關鍵字與C++中的bool關鍵字比較

  • BOOL關鍵字聲明如下 typedef int BOOL;即BOOL只是int類型的一個別名
  • 賦值形式:BOOL與bool變量均可以賦予<0 =0 >0三種形式的值,但是BOOL型變量輸出時輸出的是實際值,而bool變量輸出的只有0 1之分
    • 如 BOOL i=3.3;(編譯器會報warning),則輸出3
  • 類型大小:sizeof(BOOL)==4; sizeof(bool)==1;
  • BOOL關鍵字頭文件 windows.h

5、sprintf(str,"…");str的長度要保證能夠容納後面的字符串,否則報錯如下
出此錯誤後修改char str[len]中的len即可
6、文件操作fopen()、fscanf()
7、單鏈表的頭插法與尾刪除(本程序使用的是不帶頭結點的單鏈表)
8、window下的一下操作

  • system(“cls”);//清屏 windows.h
  • windows下創建線程 process.h

9、多文件編程 #pragma once防止頭文件重複包含

====================================================
模塊分類:食物、蛇、隨機數(食物位置)、地圖加載
使用的全局宏定義如下 global.h

遊戲設計介紹:(速度的快慢通過Sleep()實現)
路徑 “ ” 1 MAP_ROAD
蛇身 □ 2 MAP_BODY
蛇頭 ○ 3 MAP_HEAD
正常食物 ▲ 4 MAP_FOOD_NORMAL(吃了以後蛇長+1)
有毒食物 ★ 7 MAP_FOOD_SHORTEN(吃了以後蛇長-1,速度減慢)
致幻食物 ◆ 6 MAP_FOOD_ACCELERATE(吃了以後蛇長+1,速度加快)
障礙物 ╬ 5 MAP_OBSTACLE

注:由於代碼設計問題,目前只能對寬和長相同的二維數組地圖進行良好測試
補:補一個測試用例的二維數組(30爲寬和高 1爲蛇可以行走的路徑 5代表站愛物)
30 30
1 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 1 1 1 1 1
1 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

用到的全局宏定義 global.h

#pragma once

#define TRUE 1
#define FALSE 0
#define OTHER -1

#define INIT_SNACK_LEN	4			//初始蛇長度
#define VICTORY_SNACK_LEN 10		//過關時要求的長度
#define MAX_LENGTH 40				//路徑字符串數組長度(如果你的路徑過長,把這個數據改大一點)
#define CONSOLE_MAX_WIDTH 80		//控制檯最大寬度
#define DELAY_TIME 500				//延時
#define DELAY_TIME_ACCELERATE 100	//吃了致幻食物的延時
#define DELAY_TIME_SHORTEN 1000		//吃了有毒食物的延時

地圖 map.h

#pragma once
#include "global.h"

//地圖路徑、蛇頭、蛇身、正常食物、障礙物、致幻食物、有毒食物
enum EMap{
	MAP_ROAD=1,
	MAP_BODY,
	MAP_HEAD,
	MAP_FOOD_NORMAL,
	MAP_OBSTACLE,
	MAP_FOOD_ACCELERATE,
	MAP_FOOD_SHORTEN,
};

enum EGameStatus{
	GAME_LOOP,		//循環
	GAME_VICTORY,	//勝利
	GAME_FAILURE	//失敗
};

int width, height;						//地圖長寬
volatile enum EGameStatus status;		//遊戲狀態
int map[MAX_LENGTH][MAX_LENGTH];		
int mapTemp[MAX_LENGTH][MAX_LENGTH];
int selectNum;							//所選關卡

//地圖預處理
void PreviewMap();
//載入地圖
void LoadMap(int scene);
//地圖顯示(多線程)
void DisplayMap();



map.c

#define _CRT_SECURE_NO_WARNINGS
#include "global.h"
#include "snack.h"
#include "food.h"
#include "map.h"
#include <stdio.h>
//#include <stdlib.h>
#include <windows.h>

static FILE* fp = NULL;
volatile enum EGameStatus status = GAME_LOOP;
//加載地圖
void LoadMap(int scene){
	int i, j;
	char str[MAX_LENGTH] = "";
	sprintf(str, "D:\\Code\\project\\2_game1\\Map\\%d.txt", scene);		//TODO...
	//puts(str);
	fp = fopen(str, "r");
	fscanf(fp, "%d%d", &width, &height);				//從文件中讀取地圖的寬和高

	for (i = 0; i < height; ++i){
		for (j = 0; j < width; ++j){
			fscanf(fp, "%d", &map[j][i]);			   //讀取地圖的信息(一列一列的讀取)
			mapTemp[j][i] = map[j][i];				   //存儲
			printf("%d ", map[j][i]);
		}
		printf("\n");
	}
	fclose(fp);
	fp = NULL;
}

//預處理地圖
void PreviewMap(){
	int i, j;
	for (i = 0; i < height; ++i){
		for (j = 0; j < width; ++j){
			map[i][j] = mapTemp[i][j];
		}
	}

	//設置蛇頭位置
	Snack* pSnack = pHeader;
	map[pSnack->x][pSnack->y] = MAP_HEAD;		//3
	pSnack = pSnack->pNext;
	//設置蛇身位置
	while (pSnack){
		map[pSnack->x][pSnack->y] = MAP_BODY;	//2
		pSnack = pSnack->pNext;
	}
	//設置食物(類型)
	map[food.x][food.y] = food.foodKind;
}

//顯示地圖
void DisplayMap(){
	int i, j;
	system("cls");
	printf("	  貪喫蛇項目\n");

	for (i = 0; i < height; ++i){
		for (j = 0; j < width; ++j){
			if (i == 0 || j == 0){	//二維數組
				printf("回");
				continue;
			}

			switch (map[j][i])
			{
			case MAP_ROAD:			 //路			1
				printf("  ");
				break;
			case MAP_BODY:			 //蛇身			2
				printf("□");
				break;
			case MAP_HEAD:			 //蛇頭			3
				printf("○");
				break;
			case MAP_FOOD_NORMAL:	 //正常食物		4
				printf("▲");
				break;
			case MAP_FOOD_ACCELERATE://致幻食物		6
				printf("◆");
				break;
			case MAP_FOOD_SHORTEN:	 //有毒食物		7
				printf("★");
				break;
			case MAP_OBSTACLE:		 //障礙物		5
				printf("╬");
				break;
			}
		}
		printf("回");				//地圖右邊邊界
		switch (i){
		case 3:
			printf("\t您的得分是:%d", snackLength);
			break;
		case 7:
			printf("\t遊戲過關需要得分10");
			break;
		case 8:
			printf("\t目前蛇長:%d", snackLength);
			break;
		case 9:
			printf("\t距過關還需要:%d",10-snackLength);
			break;

		case 13:
			switch (food.foodKind){
			case MAP_FOOD_NORMAL:
				printf("\t出現的食物爲:正常食物!");
				break;
			case MAP_FOOD_ACCELERATE:
				printf("\t出現的食物爲:致幻食物!");
				break;
			case MAP_FOOD_SHORTEN:
				printf("\t出現的食物爲:有毒食物!");
				break;
			default:
				break;
			}
			break;

		case 14:
			switch (food.foodKind){
			case MAP_FOOD_NORMAL:
				printf("\t效果:蛇身+1!");
				break;
			case MAP_FOOD_ACCELERATE:
				printf("\t效果:蛇身+1,且加速!");
				break;
			case MAP_FOOD_SHORTEN:
				printf("\t效果:蛇身-1,且減速!");
				break;
			default:
				break;
			}
			break;
		default:
			break;
		}
		printf("\n");						//一行打印完畢

	}
	for (j = 0; j <= width; ++j)			//地圖下邊邊界
		printf("回");
	printf("\n");
}

蛇 snack.h

#pragma once
enum Edirection{
	SNACK_UP,	//W
	SNACK_LEFT,	//A
	SNACK_DOWN,	//S
	SNACK_RIGHT	//D
};

typedef struct Snack{
	int x;					//對應於二維數組的座標
	int y;
	struct Snack* pNext;
}Snack;

//蛇喫食物後的狀態
enum ESnakeStatus{
	SnakeNormal = 1,	//正常
	SnakeShorten,		//有毒
	SnakeAccelerate		//興奮
};

int snackLength;				//蛇的長度
Snack *pHeader, *pTail;			//蛇頭、蛇尾
enum Edirection direction;		//蛇的移動方向
enum ESnakeStatus SnakeStatus;	//蛇喫食物後的狀態


//初始化蛇
Snack* SnackInit();
//鏈表蛇移動(多線程)
void SnackMove();
//頭插法鏈表增長
Snack* SnackInsert();
//某個關卡遊戲的結束
void SnackDestory();

void SnackNormalFn();		//正常食物
Snack* SnackShorten();		//有毒食物、縮短
void SnackAccelerate();		//致幻食物,加速

snack.c
蛇移動分爲兩種情況:喫到食物與未喫到食物
蛇移動(不喫食物)的處理思想:

  1. 蛇尾放到蛇頭前
  2. 原先的蛇頭變爲蛇身

蛇移動(喫食物)的處理思想

  1. 正常食物:
    • 食物變爲蛇頭,蛇身不動,原來的蛇頭變爲蛇身
  2. 致幻食物(長度+1,加速)
    • 同上,修改延時Sleep即可
  3. 有毒食物(長度-1,減速)
    • 將食物變爲蛇頭,刪掉蛇的最後兩個節點,修改延時(這樣既可以實現蛇前進,又可以實現蛇長度-1)
    • 實際操作時並不是刪除2個節點,而是隻刪除蛇尾,將倒數第二個節點的數據域修改後(即改爲有毒食物的位置)充當蛇頭(這樣可以避免重複malloc空間耗費時間)
#include "global.h"
#include "snack.h"
#include "map.h"
#include "food.h"
#include <malloc.h>
#include <Windows.h>

//蛇的初始化
Snack* SnackInit(){
	direction = SNACK_RIGHT;			//初始時蛇向右移動
	snackLength = INIT_SNACK_LEN;		//初始蛇長4
	int cnt = INIT_SNACK_LEN;			//當前蛇長
	SnakeStatus = SnakeNormal;			//蛇的狀態爲正常

	//蛇頭創建
	pHeader = pTail = (Snack*)malloc(sizeof(Snack));
	pTail->x = cnt;						//蛇頭的初始座標(4,1)
	pTail->y = 1;

	//蛇身創建(尾插法) --長度爲3
	while (cnt-- > 1){
		pTail->pNext = (Snack*)malloc(sizeof(Snack));
		pTail=pTail->pNext;				//pTail始終指向蛇尾(鏈表尾節點)
		pTail->x = cnt;					//蛇身的座標(cnt,1)
		pTail->y = 1;
	}
	pTail->pNext = NULL;
	return pHeader;
}

//蛇頭判定事件--返回TRUE表示蛇頭可以向預定的方向前進,反之不可
static BOOL SnackJudge(int x, int y){
	Snack* pSnack = pHeader;
	if (x >= width || x <= 0 || y >= height || y <= 0)		//蛇頭撞牆
		return FALSE;
	switch (map[x][y]){
	case MAP_ROAD:
		return TRUE;
	case MAP_BODY:											//蛇頭與蛇身是否有碰撞
		//退出while的情況:
		while (pSnack && (pSnack->x != x || pSnack->y != y))
			pSnack = pSnack->pNext;
		if (!pSnack)										//蛇頭的預定位置與現在蛇的全部位置不重合,則可以移動
			return TRUE;
		return FALSE;										//預定位置與蛇目前有重合,不可移動
	case MAP_FOOD_NORMAL:									//蛇頭的預定位置爲正常食物
		SnackNormalFn();
		FoodRelease();										//此處實際新建了食物,等待下次重繪地推
		return OTHER;
		break;
	case MAP_FOOD_ACCELERATE:
		SnackAccelerate();
		FoodRelease();
		return OTHER;
		break;
	case MAP_FOOD_SHORTEN:
		SnackShorten();
		FoodRelease();
		return OTHER;
		break;
	case MAP_OBSTACLE:
	default:
		return FALSE;
	}
}


//蛇移動(多線程)
void SnackMove(){
	BOOL result;
	Snack* pSnack = NULL;

	int x = pHeader->x, y = pHeader->y, newX = x, newY = y;;
	switch (direction){
	case SNACK_UP:
		result = SnackJudge(x, y - 1);
		if (result == TRUE)
			newY = y - 1;
		break;
	case SNACK_LEFT:
		result = SnackJudge(x-1, y);
		if (result == TRUE)
			newX = x - 1;
		break;
	case SNACK_DOWN:
		result = SnackJudge(x, y + 1);
		if (result == TRUE)
			newY = y + 1;
		break;
	case SNACK_RIGHT:
		result = SnackJudge(x+1, y );
		if (result == TRUE)
			newX = x + 1;
		break;
	}

	//蛇不喫食物時的移動,因爲蛇移動時遇到食物,result都等於OTHER
	if (result == TRUE){
		Snack* pTemp = pHeader;
		pTail->pNext = pHeader;						//尾節點前移
		//map[pTail->x][pTail->y] = MAP_ROAD;			//尾節點原來的位置變爲路徑
		while (pTemp->pNext != pTail)				//尋找尾節點的前一個節點
			pTemp = pTemp->pNext;
		pTemp->pNext = NULL;						//pTemp指向尾節點
		pHeader = pTail;							//pHeader重新指向頭節點
		pHeader->x = newX;							//設置蛇頭的位置
		pHeader->y = newY;
		map[pTail->x][pTail->y] = MAP_ROAD;			//尾節點原來的位置變爲路徑
		pTail = pTemp;
	}
	else if (result == FALSE)
		status = GAME_FAILURE;
}


//頭插法鏈表增長
Snack* SnackInsert(){
	Snack* pSnack = (Snack*)malloc(sizeof(Snack));
	pSnack->x = food.x;
	pSnack->y = food.y;
	pSnack->pNext = pHeader;					//
	pHeader = pSnack;							//pHeader始終指向蛇頭
	if (++snackLength == VICTORY_SNACK_LEN)		//判斷是否達到10(過關)
		status = GAME_VICTORY;
	return pHeader;
}

//正常食物作爲新的蛇頭,蛇尾不動,即可蛇增長
void SnackNormalFn(){
	SnackInsert();
	SnakeStatus = SnakeNormal;
}

Snack* SnackShorten(){
	if (snackLength <= 2){										//長度<=2,遊戲失敗
		status = GAME_FAILURE;
		return pHeader;
	}
	Snack* pTempHeader = pHeader;
	Snack* pTempTail = pTail;
	//Snack* pTempBehTail =pTail;

	//刪除蛇的最後兩個節點
	while ((pTempHeader->pNext->pNext != pTempTail))			//尋找蛇尾:尾節點
		pTempHeader = pTempHeader->pNext;
	pTail = pTempHeader;										//新尾節點
	pTempHeader = pTempHeader->pNext;							//新尾節點的後一個節點
	pTail->pNext = NULL;										//實現蛇前進並剪短2個蛇長

	//將食物作爲新的頭結點(利用原鏈表的倒數第二個節點,修改數據即可,避免重複申請開闢空間)
	pTempHeader->x = food.x;
	pTempHeader->y = food.y;
	pTempHeader->pNext = pHeader;								
	pHeader = pTempHeader;

	//釋放掉刪除的節點的空間
	//free(pTempHeader);										
	free(pTempTail);
	--snackLength;

	SnakeStatus = SnakeShorten;									//修改蛇當前的狀態爲變短
	return pHeader;
}

void SnackAccelerate(){
	SnackInsert();
	SnakeStatus = SnakeAccelerate;								//修改蛇當前的狀態
}

//蛇的銷燬
void SnackDestory(){
	Snack* pSnack = pHeader;
	while (pHeader){
		pHeader = pHeader->pNext;
		free(pSnack);
		pSnack = NULL;
	}
	pTail = NULL;
}

食物 food.h

#pragma once
#include "map.h"

typedef struct Food{
	int x;				//(x,y)事務的出現位置
	int y;
	enum EMap foodKind; //食物類型
}Food;

Food food;

//創建食物
Food FoodCreate();
//食物被喫掉
void FoodRelease();


food.c

#include <Windows.h>
#include "global.h"
#include "random.h"
#include "food.h"
#include "map.h"


static BOOL bIsExisted = FALSE;				//地圖中是否存在食物

//確定食物種類
enum EMAP FoodKindFn(){
	int xx = GetRandomNumber(1, 10);
	if (xx > 0 && xx <= 8)
		return MAP_FOOD_NORMAL;
	else if (xx == 9)
		return MAP_FOOD_ACCELERATE;			//致幻食物
	else
		return MAP_FOOD_SHORTEN;			//有毒食物
}

//創建食物
Food FoodCreate(){
	int x, y;
	BOOL result;
	//因爲要不斷的刷屏(system("cls"),所以會可能再次顯現原來的食物(位置以及是否有毒)
	if (bIsExisted)
		return food;						//原來的食物(位置、種類)
	//將食物刷新到路徑之上
	do{
		result = TRUE;
		x = GetRandomNumber(0, width - 1);
		y = GetRandomNumber(0, height - 1);
		if (map[x][y] != MAP_ROAD || x == 0 || y == 0)	//刷新的食物不合規範
			result = FALSE;
	} while (!result);

	bIsExisted = TRUE;						//食物位置已更新
	food.x = x;
	food.y = y;
	food.foodKind = FoodKindFn();			//獲取更新後的食物的種類

	return food;
}

void FoodRelease(){
	if (bIsExisted){
		bIsExisted = FALSE;					//本輪食物銷燬,但屏幕中還未刷新
		FoodCreate();	
	}
}

隨機數 random.h

#pragma once

//初始化隨機數系統
void InitRandomSystem();
//產生(leftVal, int rightVal)之間的隨機整數
int GetRandomNumber(int leftVal, int rightVal);

ramdom.c

#include "global.h"
#include "random.h"
#include <windows.h>
#include<stdio.h>
#include<stdlib.h>
#include <time.h>

static BOOL bIsInit = FALSE;		//本文件內使用

void InitRandomSystem(){
	if (!bIsInit){
		time_t t;
		bIsInit = TRUE;
		srand((unsigned)time(&t));
	}
}
//獲取一個隨機數
int GetRandomNumber(int leftVal, int rightVal){
	return rand() % (rightVal - leftVal + 1) + leftVal;
}

主函數 main.c 此中創建了一個子線程處理用戶輸入

#define _CRT_SECURE_NO_WARNINGS

#include "food.h"
#include "global.h"
#include "map.h"
#include "random.h"
#include "snack.h"

#include <stdio.h>
#include <conio.h>
#include <process.h>		//線程
#include <windows.h>		//鍵盤輸入

void InitGame(int n){
	LoadMap(n);						//加載地圖
	SnackInit();					//蛇初始化
	//PreviewMap();					//預處理地圖
	FoodCreate();					//創建食物
	PreviewMap();					//預處理地圖
	DisplayMap();					//顯示地圖
}

//子線程處理鍵盤的輸入
void MainLoop(void* param){
	char ch;
	while (status == GAME_LOOP){
		ch = _getch();
		switch (ch)
		{
		case 'w':
		case 'W':
			direction = SNACK_UP;			//向上
			break;
		case 'a':
		case 'A':
			direction = SNACK_LEFT;
			break;
		case 's':
		case 'S':
			direction = SNACK_DOWN;
			break;
		case 'd':
		case 'D':
			direction = SNACK_RIGHT;
			break;
		default:
			break;
		}
	}
}

//遊戲失敗,打印遊戲結束界面
void Failure(){
	int i, tmp;
	system("cls");
	printf("\n\n\n");
	for (i = 0; i < CONSOLE_MAX_WIDTH; ++i)
		printf("#");

	tmp = CONSOLE_MAX_WIDTH - 30;
	for (i = 0; i < tmp / 2; ++i)
		printf(" ");
	printf("抱歉,你失敗了!請再次開啓遊戲!\n");

	for (i = 0; i < CONSOLE_MAX_WIDTH; ++i)
		printf("#");
	system("pause");
}

//打印勝利過關界面
void VictoryFn(){
	int i, tmp;
	system("cls");
	printf("\n\n\n");
	for (i = 0; i < CONSOLE_MAX_WIDTH; ++i)
		printf("#");

	tmp = CONSOLE_MAX_WIDTH - 30;
	for (i = 0; i < tmp / 2; ++i)
		printf(" ");
	printf("恭喜你,順利進入下一關!\n");
	for (i = 0; i < CONSOLE_MAX_WIDTH; ++i)
		printf("#");
	Sleep(5000);
}


int main(){
	HANDLE hThread;
	hThread = (HANDLE)_beginthread(MainLoop,0, NULL);//創建一個子線程
	int selectNum = 1;
	InitRandomSystem();					//初始化隨機數系統
	AA:
	InitGame(selectNum);				//根據隨機選擇的關卡初始化遊戲

	while (status == GAME_LOOP){		//遊戲一直執行
		switch (SnakeStatus){
		case SnakeShorten:
			Sleep(DELAY_TIME_SHORTEN);	//顯示完地圖後,停頓DELAY_TIME_SHORTEN時間
			SnackMove();
			break;
		case SnakeNormal:
			Sleep(DELAY_TIME);
			SnackMove();
			break;
		case SnakeAccelerate:
			Sleep(DELAY_TIME_ACCELERATE);
			SnackMove();
			break;
		default:
			SnackMove();
			break;
		}

		PreviewMap();
		DisplayMap();
	}
	if (status == GAME_FAILURE){
		Failure();
		SnackDestory();
	}
	else if (status == GAME_VICTORY){
		VictoryFn();
		status = GAME_LOOP;
		selectNum = selectNum % 3 + 1;
		goto AA;
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章