Rogue游戏(二)——房间与走廊的创建

上次我们已经实现了游戏基本的框架,现在我们来创建地图。随机地图是Rogue游戏的生命力所在。我们采取的算法是随机创建房间,然后用走廊将它们连起来。

Makefile:

objects = main.o makemap.o
rogue:$(objects)
    g++ $(objects) -o rogue -lncurses

makemap.o:makemap.cpp
    g++ -c makemap.cpp

main.o:main.cpp
    g++ -c main.cpp 

clean:
    rm -rf *.o rogue

main.cpp:

#include <curses.h>
#define EMPTY 0
#define ME 1
#define WALL 2
#include <stdlib.h>
static char symbol[] = {'.', '@', '#'};
static const int m_w = 90;
static const int m_h = 22;
static const int offset_x = 5;
static const int offset_y = 2;
static int **map;
void MakeMap(int _w, int _h, int **_map);
void drawMap()
{
	for (int i = 0;i < m_w;++i)
		for (int j = 0;j < m_h;++j)
			mvaddch(j + offset_y, i + offset_x, symbol[map[j][i]]);
}
class human
{
	int x;
	int y;
	int kind;
public:
	human(int _kind);
	void Move(int _dir);
	void ShowMove(int fx, int fy, int tx, int ty);
};
human::human(int _kind)
{
	kind = _kind;
	do
	{
		x = rand() % m_w;
		y = rand() % m_h;
	}while(map[y][x] != 0);
	mvaddch(y + offset_y, x + offset_x, symbol[kind]);
	refresh();
}
void human::Move(int _dir)
{
	int dir_x[4] = {-1, 0, 1, 0};
	int dir_y[4] = {0, 1, 0, -1};
	int old_x = x;
	int old_y = y;
	x += dir_x[_dir];
	y += dir_y[_dir];
	if (map[y][x] == WALL)
	{
		x = old_x;
		y = old_y;
		return;
	}
	ShowMove(old_x, old_y, x, y);
	move(0, 0);
	refresh();
}
void human::ShowMove(int fx, int fy, int tx, int ty)
{
	mvaddch(fy + offset_y, fx + offset_x, symbol[EMPTY]); //EMPTY
	mvaddch(ty + offset_y, tx + offset_x, symbol[this->kind]);
}
int main()
{
	initscr();
	clear();
	noecho();
	curs_set(0);
	mvprintw(0, 0, "My Rogue\na/left w/up s/down d/right q/Exit");
	
	map = new int*[m_h];
	for (int i = 0;i < m_h;++i)
		map[i] = new int[m_w];
	MakeMap(m_w, m_h, map);
	drawMap();
	human me(ME);
	while(1)
	{
		char order = getch();
		if (order == 'q') break;
		switch(order)
		{
			case 'a': me.Move(0);break;
			case 's': me.Move(1);break;
			case 'd': me.Move(2);break;
			case 'w': me.Move(3);break;
		}
	}
	for (int i = 0;i < m_h;++i)
		delete []map[i];
	delete []map;
		endwin();
	return 0;
}

makemap.cpp

#include <stdlib.h>
#include <time.h>
#define ROOM_MIN_W 5
#define ROOM_MIN_H 4
#define ROOM_MAX_W 10
#define ROOM_MAX_H 7
#define ROOM_NUM 10
#define MAX_TRY 300
class room
{
public:
	int x;
	int y;
	int w;
	int h;
	bool TryCreateRoom(int _w, int _h, int **map)
	{
		do
			w = rand() % (ROOM_MAX_W + 1);
		while(w < ROOM_MIN_W);
		do
			h = rand() % (ROOM_MAX_H + 1);
		while(h < ROOM_MIN_H);
		x = rand() % (_w + 1);
		y = rand() % (_h + 1);
		if (x + w > _w || y + h > _h)
			return false;
		for (int i = x;i < x + w;++i)
			for (int j = y;j < y + h;++j)
			{
				if (map[j][i] != 2 || i == 0 || i == _w-1 || j == 0 || j == _h-1)
					return false;
			}
		return true;
	}
	bool CreateRoom(int _w, int _h, int **map)
	{
		for (int i = 0;i < MAX_TRY;++i)
			if (TryCreateRoom(_w, _h, map))
			{
				for (int ii = x;ii < x + w;++ii)
					for (int jj = y;jj < y + h;++jj)
						map[jj][ii] = 0;
				return true;
			}
		return false;
	}
};
void MakePassageWay(int fx, int fy, int tx, int ty, int **map)
{
	for (int i = 0;i <= tx || i <= fx;++i)
		if (map[fy][i] == 2 
			&& ((i <= tx && i >= fx)||(i >= tx && i <= fx)))
			map[fy][i] = 0;
	for (int i = 0;i <= ty || i <= fy;++i)
		if (map[i][tx] == 2 
			&& ((i <= ty && i >= fy)||(i >= ty && i <= fy)))
			map[i][tx] = 0;
}
void LinkRoom(room *_r1, room *_r2, int **map)
{
	MakePassageWay(_r1->x, _r1->y, _r2->x, _r2->y, map);
}
void MakeMap(int _w, int _h, int **map)
{
	srand((unsigned)time(NULL));
	for (int i = 0;i < _w;++i)
		for (int j = 0;j < _h;++j)
			map[j][i] = 2;
	room r[ROOM_NUM];
	r[0].CreateRoom(_w, _h, map);
	for (int i = 1;i < ROOM_NUM;++i)
		if (r[i].CreateRoom(_w, _h, map))
			LinkRoom(&r[i-1], &r[i], map);
	//LinkRoom(&r1, &r2, map);
	return;
}

运行结果:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值