游戏入门-推箱子(初级版)

上代码

#include <iostream>
using namespace std;

const char gStateData[] = "\
########\n\
# .. p #\n\
# oo   #\n\
#      #\n\
########";

const int gStateWidth = 8;
const int gStateHeight = 5;

enum Object
{
	OBJ_SPACE,
	OBJ_WALL,
	OBJ_GOAL,
	OBJ_BLOCK,
	OBJ_BLOCK_ON_GOAL,
	OBJ_MAN,
	OBJ_MAN_ON_GOAL,

	OBJ_UNKNOWN,
};

void initialize(Object* state, int width, int height, const char* stageData);
void draw(const Object* state, int width, int height);
void update(Object* state, char input, int width, int height);
bool checkClear(const Object* state, int width, int height);

int main()
{
	// 使用一维数组存放状态数据
	Object* state = new Object[gStateWidth * gStateHeight];

	// 初始化
	initialize(state, gStateWidth, gStateHeight, gStateData);

	// 主循环
	while (true)
	{
		// 首先绘制
		draw(state, gStateWidth, gStateHeight);

		// 通关检测
		if (checkClear(state, gStateWidth, gStateHeight))
			break;

		// 提示如何操作
		cout << "a:left s:right w:up z:down. command?" << endl;

		char input;
		cin >> input;

		// 更新
		update(state, input ,gStateWidth, gStateHeight);
	}

	// 通关祝贺信息
	cout << "Contratulation's ! you won." << endl;

	// 析构
	delete[] state;
	state = NULL;

	// 阻止窗口闪退
	system("pause");

	return 0;
}

// 初始化函数,根据stateData填充
void initialize(Object* state, int width, int height, const char* stageData)
{
	const char* d = stageData;
	int x = 0, y = 0;
	while ((*d) != '\0')
	{
		Object t;
		switch(*d)
		{
		case '#': t = OBJ_WALL; break;
		case ' ': t = OBJ_SPACE; break;
		case 'o': t = OBJ_BLOCK; break;
		case 'O': t = OBJ_BLOCK_ON_GOAL; break;
		case '.': t = OBJ_GOAL; break;
		case 'p': t = OBJ_MAN; break;
		case 'P': t = OBJ_MAN_ON_GOAL; break;
		case '\n': x = 0; ++y; t = OBJ_UNKNOWN; break;
		default: t = OBJ_UNKNOWN; break;
		}
		++d;
		if (t != OBJ_UNKNOWN)
		{
			state[y * width + x] = t;	// 写入
			++x;
		}

	}


}

// 绘制
void draw(const Object* state, int width, int height)
{
	// Object的可能值
	const char font[] = {' ', '#', '.', 'o', 'O', 'p', 'P'};
	for (int i = 0; i < height; i++) 
	{
		for (int j = 0; j < width; j++)
			cout << font[state[i * width + j]];
		cout << endl;
	}
}

// 根据输入的方向键更新数据
void update(Object* state, char input, int width, int height)
{
	int dx = 0, dy = 0;
	switch (input)
	{
	case 'a': dx = -1; break;
	case 's': dx = 1; break;
	case 'w': dy = -1; break;
	case 'z': dy = 1; break;
	default:
		break;
	}

	// 查询人物坐标
	int sub = 0;
	for (; sub < width * height; ++sub)
		if (state[sub] == OBJ_MAN || state[sub] == OBJ_MAN_ON_GOAL)
			break;

	int xPos = sub % width;
	int yPos = sub / width;

	int xMov = xPos + dx;
	int yMov = yPos + dy;

	// 检测坐标的合理性
	if (xMov < 0 || xMov >= width || yMov < 0 || yMov >= height)
		return ;

	// 该方向上是空白或者终点,人物则移动
	int pPosSub = yPos * width + xPos;
	int pMovSub = yMov * width + xMov;
	if (state[pMovSub] == OBJ_SPACE || state[pMovSub == OBJ_GOAL])
	{
		state[pMovSub] = (state[pMovSub] == OBJ_GOAL) ? OBJ_MAN_ON_GOAL : OBJ_MAN;
		state[pPosSub] = (state[pPosSub] == OBJ_MAN_ON_GOAL) ? OBJ_GOAL : OBJ_SPACE;
	}

	// 如果该方向上是箱子,并且该方向的下下个格子似乎空白或终点,则可以移动
	else if (state[pMovSub] == OBJ_BLOCK || state[pMovSub] == OBJ_BLOCK_ON_GOAL)
	{
		// 下下个点坐标
		int xMovNext = xMov + dx;
		int yMovNext = yMov + dy;

		if (xMovNext < 0 || xMovNext >= width || yMovNext < 0 || yMovNext >= height)
			return ;

		// 计算下下个点的下标
		int pMovNext = yMovNext * width + xMovNext;

		if (state[pMovNext] == OBJ_SPACE || state[pMovNext] == OBJ_GOAL)
		{
			state[pMovNext] = (state[pMovNext] == OBJ_GOAL) ? OBJ_BLOCK_ON_GOAL : OBJ_GOAL;
			state[pMovSub] = (state[pMovSub] == OBJ_BLOCK_ON_GOAL) ? OBJ_MAN_ON_GOAL : OBJ_MAN;
			state[pPosSub] = (state[pPosSub] == OBJ_MAN_ON_GOAL) ? OBJ_GOAL : OBJ_SPACE;
		}
	}
}

// 如果没有方块了则判定为通关
bool checkClear(const Object* state, int width, int height)
{
	for (int i = 0; i < width * height; ++i)
		if (state[i] == OBJ_BLOCK)
			return false;

	return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值