贪吃蛇小游戏

头文件:

游戏界面:

#ifndef __UI_H__
#define __UI_H__


struct UI {
	// 边缘宽度(字符宽度)
	int marginTop;
	int marginLeft;

	// 游戏区域的字符个数
	int gameWidth;
	int gameHeight;

	// 整个窗口大小字符宽度/高度
	int windowWidth;
	int windowHeight;

	char *snakeBlock;	// 蛇的显示块
	char *wallBlock;	// 墙的显示块
	char *foodBlock;	// 食物的显示块
	int blockWidth;		// 每个块的宽度,注意,上面几个块的宽度要相等,否则就对不齐了
};

// UI 初始化
struct UI * UIInitialize(int width, int height);

// 显示游戏向导
void UIDisplayWizard(const struct UI *pUI);

// 显示游戏整体,包括墙、右边的信息,不包括蛇和食物的显示
void UIDisplayGameWindow(const struct UI *pUI, int score, int scorePerFood);

// 在x,y处显示食物,x,y都是字符个数
void UIDisplayFoodAtXY(const struct UI *pUI, int x, int y);

// 在x,y处显示蛇的一个结点,x,y都是字符个数
void UIDisplaySnakeBlockAtXY(const struct UI *pUI, int x, int y);

// 清空x,y处的显示块,x,y都是字符个数
void UICleanBlockAtXY(const struct UI *pUI, int x, int y);

// 显示分数信息
void UIDisplayScore(const struct UI *pUI, int score, int scorePerFood);

// 在游戏区域居中显示游戏退出消息
void UIShowMessage(const struct UI *pUI, const char *message);

// 销毁 UI 资源
void UIDeinitialize(struct UI *pUI);

#endif

贪吃蛇本蛇游走:

#ifndef __SNAKE_H__
#define __SNAKE_H__

// 游戏区域坐标(对应到 UI 显示的时候就是字符个数)
struct Position {
	int x;
	int y;
};

// 链表结点
struct Node {
	struct Position position;
	struct Node *pNext;
};

// 蛇朝向
enum Direction {
	UP,
	DOWN,
	LEFT,
	RIGHT
};

// 蛇结构体
struct Snake {
	enum Direction direction;
	struct Node *pBody;
};

// 游戏结构体
struct Game {
	int width;	// 游戏区域宽度(不包括墙,对应到 UI 部分就是字符个数)
	int height;	// 游戏区域高度(不包括墙,对应到 UI 部分就是字符个数)
	int score;	// 当前得分
	int scorePerFood;	// 每个食物得分

	struct Snake snake;	// 蛇
	struct Position foodPosition;	// 当前食物坐标
};

#endif

创建游戏:

#ifndef __GAME_H__
#define __GAME_H__

#include "Snake.h"

// 创建并初始化游戏
struct Game * CreateGame();
// 开始游戏
void StartGame(struct Game *pGame);
// 销毁游戏资源
void DestroyGame(struct Game *pGame);

#endif

.C文件:

游戏界面:

#define _CRT_SECURE_NO_WARNINGS

#include "UI.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

// 移动光标到x,y处,注意,这里是相对整个屏幕的,而不是游戏区域的
static void _SetPos(int x, int y);

// 显示墙
static void _DisplayWall(const struct UI *pUI);

// 显示右侧信息
static void _DisplayDesc(const struct UI *pUI);

// 将游戏盘的x,y坐标转换为相对整个屏幕的x,y,也就是把字符个数转成最后的字符宽度
static void _CoordinatePosAtXY(const struct UI *pUI, int x, int y);

// 重置光标到屏幕下方,主要是为了显示的美观
static void _ResetCursorPosition(const struct UI *pUI);


struct UI * UIInitialize(int width, int height)
{
	const int left = 2;
	const int top = 2;
	const int descWidth = 50;

	struct UI *pUI = (struct UI *)malloc(sizeof(struct UI));
	pUI->gameWidth = width;
	pUI->gameHeight = height;
	pUI->marginLeft = left;
	pUI->marginTop = top;
	pUI->windowHeight = top + height + 2 + 3;
	pUI->foodBlock = "█";
	pUI->snakeBlock = "█";
	pUI->wallBlock = "█";
	pUI->blockWidth = strlen(pUI->wallBlock);
	pUI->windowWidth = left + (width + 2) * pUI->blockWidth + descWidth;

	char modeCommand[1024];
	sprintf(modeCommand, "mode con cols=%d lines=%d", pUI->windowWidth, pUI->windowHeight);
	system(modeCommand);

	return pUI;
}

void UIDisplayWizard(const struct UI *pUI)
{
	int i;
	const char *messages[3] = {
		"欢迎来到贪吃蛇小游戏",
		"用↑.↓.←.→分别控制蛇的移动, F1为加速,F2为减速。",
		"加速将能得到更高的分数。"
	};

	i = 0;
	_SetPos(pUI->windowWidth / 2 - strlen(messages[i]) / 2, pUI->windowHeight / 2);
	printf("%s\n", messages[i]);
	_SetPos(pUI->windowWidth / 2 - strlen(messages[i]) / 2, pUI->windowHeight / 2 + 2);
	system("pause");
	system("cls");

	i = 1;
	_SetPos(pUI->windowWidth / 2 - strlen(messages[i]) / 2, pUI->windowHeight / 2);
	printf("%s\n", messages[i]);

	i = 2;
	_SetPos(pUI->windowWidth / 2 - strlen(messages[i]) / 2, pUI->windowHeight / 2 + 2);
	printf("%s\n", messages[i]);
	_SetPos(pUI->windowWidth / 2 - strlen(messages[i]) / 2, pUI->windowHeight / 2 + 4);
	system("pause");
	system("cls");
}

void UIDisplayGameWindow(const struct UI *pUI, int score, int scorePerFood)
{
	_DisplayWall(pUI);
	UIDisplayScore(pUI, score, scorePerFood);
	_DisplayDesc(pUI);

	_ResetCursorPosition(pUI);
}

void UIDisplayFoodAtXY(const struct UI *pUI, int x, int y)
{
	_CoordinatePosAtXY(pUI, x, y);
	printf(pUI->foodBlock);

	_ResetCursorPosition(pUI);
}

void UIDisplaySnakeBlockAtXY(const struct UI *pUI, int x, int y)
{
	_CoordinatePosAtXY(pUI, x, y);
	printf(pUI->snakeBlock);

	_ResetCursorPosition(pUI);
}

void UICleanBlockAtXY(const struct UI *pUI, int x, int y)
{
	_CoordinatePosAtXY(pUI, x, y);
	int i;

	for (i = 0; i < pUI->blockWidth; i++) {
		printf(" ");
	}

	_ResetCursorPosition(pUI);
}

void UIDisplayScore(const struct UI *pUI, int score, int scorePerFood)
{
	int blockWidth = strlen(pUI->wallBlock);
	int left = pUI->marginLeft + (pUI->gameWidth + 2) * blockWidth + 2;
	_SetPos(left, pUI->marginTop + 8);
	printf("得分: %3d,每个食物得分: %3d", score, scorePerFood);

	_ResetCursorPosition(pUI);
}

void UIShowMessage(const struct UI *pUI, const char *message)
{
	// 左填充宽度 + (1(左边界个数)+游戏区域的个数/2) * 每个字符的宽度
	// - 字符串的宽度 / 2
	_SetPos(
		pUI->marginLeft + (
		(1 + pUI->gameWidth / 2) * pUI->blockWidth)
		- strlen(message) / 2,
		pUI->marginTop + 1 + pUI->gameHeight / 2);
	printf("%s\n", message);

	_ResetCursorPosition(pUI);
}

void UIDeinitialize(struct UI *pUI)
{
	free(pUI);
}

static void _DisplayWall(const struct UI *pUI)
{
	int left = pUI->marginLeft;
	int top = pUI->marginTop;
	int width = pUI->gameWidth;
	int height = pUI->gameHeight;
	int blockWidth = pUI->blockWidth;
	int i;

	// 上
	_SetPos(left, top);
	for (i = 0; i < width + 2; i++) {
		printf("%s", pUI->wallBlock);
	}

	// 下
	_SetPos(left, top + 1 + height);
	for (i = 0; i < width + 2; i++) {
		printf("%s", pUI->wallBlock);
	}

	// 左
	for (i = 0; i < height + 2; i++) {
		_SetPos(left, top + i);
		printf("%s", pUI->wallBlock);
	}

	// 右
	for (i = 0; i < height + 2; i++) {
		_SetPos(left + (1 + width) * blockWidth, top + i);
		printf("%s", pUI->wallBlock);
	}
}

static void _DisplayDesc(const struct UI *pUI)
{
	int left = pUI->marginLeft + (pUI->gameWidth + 2) * pUI->blockWidth + 2;
	const char *messages[] = {
		"不能穿墙,不能咬到自己。",
		"用 ↑ ↓ ← → 分别控制蛇的移动。",
		"F1 为加速,F2 为减速。",
		"ESC 退出游戏。 SPACE 暂停游戏。",
		"版权 @比特科技"
	};
	int i;

	for (i = 0; i < sizeof(messages) / sizeof(char *); i++) {
		_SetPos(left, pUI->marginTop + 10 + i);
		printf("%s\n", messages[i]);
	}
}

static void _SetPos(int x, int y)
{
	COORD position = { x, y };
	HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOutput, position);
}

static void _CoordinatePosAtXY(const struct UI *pUI, int x, int y)
{
	_SetPos(pUI->marginLeft + (1 + x) * pUI->blockWidth,
		pUI->marginTop + 1 + y);
}

static void _ResetCursorPosition(const struct UI *pUI)
{
	_SetPos(0, pUI->windowHeight - 1);
}

游戏设计:

#include "Game.h"
#include "UI.h"
#include <stdlib.h>
#include <stdbool.h>
#include <Windows.h>



static void _Pause();

static void _InitializeSnake(struct Snake *pSnake)
{
}

static int _IsOverlapSnake(const struct Snake *pSnake, int x, int y)
{
}

static void _GenerateNewFood(struct Game *pGame)
{
}


struct Game * CreateGame()
{
	struct Game *pGame = (struct Game *)malloc(sizeof(struct Game));
	// TODO: 异常处理
	pGame->width = 28;
	pGame->height = 27;
	pGame->score = 0;
	pGame->scorePerFood = 10;

	// 关于蛇的初始化和放置食物部分,感兴趣的同学可以做扩展练习
	_InitializeSnake(&pGame->snake);
	_GenerateNewFood(pGame);

	return pGame;
}

static void _DisplaySnake(const struct UI *pUI, const struct Snake *pSnake)
{
}

static struct Position _GetNextPosition(const struct Snake *pSnake)
{
	struct Position nextPosition = { 0 };
	
	return nextPosition;
}

static int _IsWillEatFood(struct Position foodPosition, struct Position nextPosition)
{
}

static void _GrowAndMoveAndDisplay(const struct UI *pUI, 
			struct Snake *pSnake, 
			struct Position nextPosition)
{
}

static void _UpdateScoreAndDisplay(const struct UI *pUI, struct Game *pGame)
{
}


static void _AddHeadAndDisplay(const struct UI *pUI, struct Snake *pSnake,
struct Position nextPosition)
{
}

static void _RemoveTailAndDisplay(const struct UI *pUI, struct Snake *pSnake)
{
}

static void _MoveAndDisplay(const struct UI *pUI, struct Snake *pSnake, 
			struct Position nextPosition)
{
}

static int _IsKilledByWall(const struct Snake *pSnake, int width, int height)
{
}

static int _IsKilledBySelf(const struct Snake *pSnake)
{
}

static void _HandleDirection(struct Snake *pSnake)
{
	if (GetAsyncKeyState(VK_UP)) {
		if (pSnake->direction != DOWN) {
			pSnake->direction = UP;
		}
	}
	else if (GetAsyncKeyState(VK_DOWN)) {
		if (pSnake->direction != UP) {
			pSnake->direction = DOWN;
		}
	}
	else if (GetAsyncKeyState(VK_LEFT)) {
		if (pSnake->direction != RIGHT) {
			pSnake->direction = LEFT;
		}
	}
	else if (GetAsyncKeyState(VK_RIGHT)) {
		if (pSnake->direction != LEFT) {
			pSnake->direction = RIGHT;
		}
	}
}

void StartGame(struct Game *pGame)
{
	struct UI *pUI = UIInitialize(pGame->width, pGame->height);

	UIDisplayWizard(pUI);
	UIDisplayGameWindow(pUI, pGame->score, pGame->scorePerFood);
	UIDisplayFoodAtXY(pUI, pGame->foodPosition.x, pGame->foodPosition.y);
	_DisplaySnake(pUI, &pGame->snake);

	while (1) {
		// 方向
		_HandleDirection(&pGame->snake);

		if (GetAsyncKeyState(VK_ESCAPE)) {
			break;
		}

		if (GetAsyncKeyState(VK_SPACE)) {
			_Pause();
		}

		struct Position nextPosition = _GetNextPosition(&pGame->snake);
		if (_IsWillEatFood(pGame->foodPosition, nextPosition)) {
			_GrowAndMoveAndDisplay(pUI, &pGame->snake, nextPosition);
			_UpdateScoreAndDisplay(pUI, pGame);
			_GenerateNewFood(pGame);
			UIDisplayFoodAtXY(pUI, pGame->foodPosition.x, pGame->foodPosition.y);
		} else {
			_MoveAndDisplay(pUI, &pGame->snake, nextPosition);
		}

		if (_IsKilledByWall(&pGame->snake, pGame->width, pGame->height)) {
			break;
		}
		else if (_IsKilledBySelf(&pGame->snake)) {
			break;
		}

		Sleep(300);
	}

	UIShowMessage(pUI, "游戏结束");

	UIDeinitialize(pUI);
}

static void _DestroySnake(struct Snake *pSnake)
{
}

void DestroyGame(struct Game *pGame)
{
	struct Node *pNode, *pNext;
	
	_DestroySnake(&pGame->snake);

	free(pGame);
}

static void _Pause()
{
	while (1)
	{
		Sleep(300);
		if (GetAsyncKeyState(VK_SPACE))
		{
			break;
		}
	}
}

主函数:

#include <stdlib.h>
#include <time.h>
#include "Game.h"
#include "UI.h"

int main(int argc, const char *argv[])
{
	// 设置根据当前时间戳设置随机种子
	srand((unsigned int)time(NULL));

	struct Game *pGame = CreateGame();

	StartGame(pGame);

	DestroyGame(pGame);

	system("pause");

	return 0;
}



  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
水资源是人类社会的宝贵财富,在生活、工农业生产中是不可缺少的。随着世界人口的增长及工农业生产的发展,需水量也在日益增长,水已经变得比以往任何时候都要珍贵。但是,由于人类的生产和生活,导致水体的污染,水质恶化,使有限的水资源更加紧张。长期以来,油类物质(石油类物质和动植物油)一直是水和土壤中的重要污染源。它不仅对人的身体健康带来极大危害,而且使水质恶化,严重破坏水体生态平衡。因此各国都加强了油类物质对水体和土壤的污染的治理。对于水中油含量的检测,我国处于落后阶段,与国际先进水平存在差距,所以难以满足当今技术水平的要求。为了取得具有代表性的正确数据,使分析数据具有与现代测试技术水平相应的准确性和先进性,不断提高分析成果的可比性和应用效果,检测的方法和仪器是非常重要的。只有保证了这两方面才能保证快速和准确地测量出水中油类污染物含量,以达到保护和治理水污染的目的。开展水中油污染检测方法、技术和检测设备的研究,是提高水污染检测的一条重要措施。通过本课题的研究,探索出一套适合我国国情的水质污染现场检测技术和检测设备,具有广泛的应用前景和科学研究价值。 本课题针对我国水体的油污染,探索一套检测油污染的可行方案和方法,利用非分散红外光度法技术,开发研制具有自主知识产权的适合国情的适于野外便携式的测油仪。利用此仪器,可以检测出被测水样中亚甲基、甲基物质和动植物油脂的污染物含量,为我国众多的环境检测站点监测水体的油污染状况提供依据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值