贪吃蛇-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;
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值