C++を使用して不思議のダンジョン系マップを作る

今回から数回に分けてC++を使用してローグライクのマップ生成の方法を記事に残します。普段C言語を使用しているためC++のライブラリは<vector.h>のみ、機能もclass以外はおそらく使用していません。

今回の作成の仕方

今回は上の画像のように一つのマップを分割していくやり方で行います。
今回のコードで作れるマップは下記のようなものです。

完成図

構造体、クラスの解説

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <vector>

using namespace std;

#define MAP_SIZE		(40)	//マップの縦横のサイズ
#define MINIMUM_SIZE	(5)		//ルームの最低サイズ
#define AISLE_WIDTH		(3)		//通路幅

enum DIRECTION {	//方向
	VERTICAL,		//縦
	HORIZON			//横
};

struct Room {
	int leftTop_x;	//左上のx座標
	int leftTop_y;	//左上のy座標
	int width;		//幅
	int haight;		//高さ
	vector<int> aisleNum;	//MapGeneのaisleの何番目を使うか
};

struct Aisle {
	int startPoint;	//分割線の始点 上か左
	int endPoint;	//分割線の終点 下か右
	int line;		//分割線の場所
	int direction;	//方向
};

class MapGene {
private:
	char map[MAP_SIZE][MAP_SIZE];
	int geneRoomNum;	//部屋をいくつ生成するか 
	vector<Room> room;	//部屋
	vector<Aisle> aisle;	//通路
public:
	MapGene();		//コンストラクタ
	~MapGene();		//デストラクタ
	void MakeMap();	//マップを生成する
	int MakeDivideLine(int roomNum,int direction);	//部屋の分割する場所を探す	direction=0 縦 direction=1 横
	void RoomDivide(int roomNum,int line, int direction);	//部屋を分割する
	void RoomDig();		//マップに部屋を書き込む
	void AisleDig();	//マップに通路を書き込む
	void Output();		//表示する
};

Room構造体は部屋の位置を、Aisle構造体は通路の位置をそれぞれ覚えておくためのclassです。
Room構造体は左上のx座標、y座標と幅と高さを持っています。aisleNumは隣接する、roomを分割する線それぞれの番号(vector aisleの配列番号)をvector型で記憶する変数です。
Aisle構造体はdirectionでenum DIRECTIONで定義した縦方向か横方向か向きがわかるようになっており、lineでその方向の何列目にラインがあるかを記憶しています。またその列の中での始点と終点の座標を記憶しています。

MapGeneクラスはマップを生成するクラスです。
char型のmap配列でマップを記録しており、今回は簡単にするために定数を使用した正方形の配列です。
geneRooomNumは部屋を分割する回数。残りはRoomとAisleをそれぞれ可変長で持っておく変数です。

コンストラクタ

MapGene::MapGene() {	//コンストラクタ
	for (int e = 0; e < MAP_SIZE; e++) {	//マップの初期化
		for (int f = 0; f < MAP_SIZE; f++) {
			map[f][e] = '*';
		}
	}
	geneRoomNum = rand()%3+5;  //部屋を生成する数を乱数で生成 
  //最初の大きな部屋を生成
	Room tempRoom;
	tempRoom.leftTop_x = 1;
	tempRoom.leftTop_y = 1;
	tempRoom.width = MAP_SIZE-2;
	tempRoom.haight = MAP_SIZE-2;
	room.push_back(tempRoom);
}

コンストラクタではmapの初期化、生成する部屋数の生成、分割前の部屋のお生成を行っています。
Room tempRoomで変数を作り、数値を入れたのちvector roomに入れています。

メイン関数

int main(void) {
	srand((unsigned)time(NULL));	//時間を用いた乱数生成
	MapGene* mpG = new MapGene();	//インスタンス化
	mpG->MakeMap();					//マップ生成
	mpG->Output();					//描画
	delete mpG;						//ポインタの開放
}

メイン関数では乱数シードの生成→MapGeneのインスタンス化→マップ生成関数の呼び出し→描画→ポインタの開放を行っています。

マップを生成する関数

void MapGene::MakeMap() {	//マップを生成する
	//geneRoomNumまでマップを生成する
	geneRoomNum -= 1;
	//分割できるサイズの部屋がいくつあるか 13以上
	int roomNum = 0;        //規定サイズ以上の部屋の数
	vector<int> passRoom;	//規定サイズ以上の部屋番号を入れる
	for (int e = 0; e < (int)room.size(); e++) {
		if (room[e].width >= MINIMUM_SIZE * 2 + AISLE_WIDTH
			|| room[e].haight >= MINIMUM_SIZE * 2 + AISLE_WIDTH) {
			roomNum++;
			passRoom.push_back(e);
		}
	}
	//分割する部屋を決める
	roomNum = rand() % roomNum;
	//縦か横かを決める
	int direction = 0;	//direction=0 縦 direction=1 横
	if (room[passRoom[roomNum]].width >= (MINIMUM_SIZE * 2 + AISLE_WIDTH)
		&& room[passRoom[roomNum]].haight >= (MINIMUM_SIZE * 2 + AISLE_WIDTH)) {
		direction = rand() % 2;
	}
	else if (room[passRoom[roomNum]].width >= (MINIMUM_SIZE * 2 + AISLE_WIDTH)) {
		direction = VERTICAL;
	}
	else {
		direction = HORIZON;
	}
	//分割するラインを作り、通路を作る
	RoomDivide(passRoom[roomNum],MakeDivideLine(passRoom[roomNum], direction), direction);

	if (geneRoomNum != 0) {	//規定数まで生成したかを判定
		MakeMap();
		return;
	}
	RoomDig();
	AisleDig();
}

MakeMap関数は再起関数で、geneRoomNumが一以上の時自身をもう一度呼び出すように作っています。この際、直後にreturn;をつけないとその後の処理を再起した回数行ってしまうため注意が必要です。
この関数では縦か横が既定の大きさ(定数で作ってある部屋の最小サイズの2倍と通路幅を足した数)以上の部屋を探しその中から、乱数で部屋と分割する向きを決定し、実際に分割する関数に送っています。

分割する場所を決定、分割する関数

int MapGene::MakeDivideLine(int roomNum, int direction) {	//部屋の分割する場所を探す	direction=0 縦 direction=1 横
	int divideLine = 0;
	if (direction == VERTICAL) {
		divideLine = room[roomNum].width;
	}
	else {
		divideLine = room[roomNum].haight;
	}

	divideLine -= (MINIMUM_SIZE * 2 + 2);
	divideLine = rand() % divideLine + MINIMUM_SIZE + 2;	//randの+1 通路の+1

	return divideLine;
}

MakeDivideLineは分割する場所を決定する関数です。引数で受け取った部屋番号、方向からどこを分割するかを作ります。

void MapGene::RoomDivide(int roomNum,int line,int direction) {	//部屋を分割する
	Room room1, room2;
	Aisle tempAisle;
	if (direction == VERTICAL) {	//縦分割
		room1.leftTop_y = room2.leftTop_y = room[roomNum].leftTop_y;
		room1.leftTop_x = room[roomNum].leftTop_x;
		room2.leftTop_x = room1.leftTop_x + line + 1;
		room1.haight = room2.haight = room[roomNum].haight;
		room1.width = line - 2;
		room2.width = room[roomNum].width - line - 1;
		//分割線の情報を入れる場所
		tempAisle.startPoint = room[roomNum].leftTop_y - 1;
		tempAisle.endPoint = room[roomNum].leftTop_y + room[roomNum].haight;
		tempAisle.line = room[roomNum].leftTop_x+line-1;
		tempAisle.direction = VERTICAL;
		//分割前の部屋の持つ分割線をそれぞれに渡す
		for (int e = 0; e < room[roomNum].aisleNum.size(); e++) {
			if (aisle[room[roomNum].aisleNum[e]].direction == VERTICAL) {	//縦の線だった場合
				if (aisle[room[roomNum].aisleNum[e]].line < room[roomNum].leftTop_x) {	//分割線が元の部屋より左にある場合
					room1.aisleNum.insert(room1.aisleNum.end(), room[roomNum].aisleNum[e]);
				}
				else {	//右の場合
					room2.aisleNum.insert(room2.aisleNum.end(), room[roomNum].aisleNum[e]);
				}
			}
			else {	//横の線の場合
				room1.aisleNum.insert(room1.aisleNum.end(), room[roomNum].aisleNum[e]);
				room2.aisleNum.insert(room2.aisleNum.end(), room[roomNum].aisleNum[e]);
			}
		}
	}
	else {	//横分割
		room1.leftTop_x = room2.leftTop_x = room[roomNum].leftTop_x;
		room1.leftTop_y = room[roomNum].leftTop_y;
		room2.leftTop_y = room1.leftTop_y + line + 1;
		room1.width = room2.width = room[roomNum].width;
		room1.haight = line - 2;
		room2.haight = room[roomNum].haight - line - 1;
		//分割線の情報を入れる場所
		tempAisle.startPoint = room[roomNum].leftTop_x - 1;
		tempAisle.endPoint = room[roomNum].leftTop_x + room[roomNum].width;
		tempAisle.line = room[roomNum].leftTop_y+line-1;
		tempAisle.direction = HORIZON;
		//分割前の部屋の持つ分割線をそれぞれに渡す
		for (int e = 0; e < room[roomNum].aisleNum.size(); e++) {
			if (aisle[room[roomNum].aisleNum[e]].direction == HORIZON) {	//横の線だった場合
				if (aisle[room[roomNum].aisleNum[e]].line < room[roomNum].leftTop_y) {	//分割線が元の部屋より上にある場合
					room1.aisleNum.insert(room1.aisleNum.end(), room[roomNum].aisleNum[e]);
				}
				else {	//下の場合
					room2.aisleNum.insert(room2.aisleNum.end(), room[roomNum].aisleNum[e]);
				}
			}
			else {	//縦の線の場合
				room1.aisleNum.insert(room1.aisleNum.end(), room[roomNum].aisleNum[e]);
				room2.aisleNum.insert(room2.aisleNum.end(), room[roomNum].aisleNum[e]);
			}
		}
	}
	//分割線を通路として新たにaisleに追加する
	aisle.push_back(tempAisle);
	room1.aisleNum.push_back(aisle.size()-1);
	room2.aisleNum.push_back(aisle.size()-1);
	//分割した部屋を削除し、新しい部屋をroomに入れる
	room.erase(room.begin() + roomNum);
	room.push_back(room1);
	room.push_back(room2);
}

RoomDivideは実際に分割を行う関数です。非常に長い関数ですが、やっていることは単純です。
Room型のroom1,room2を作ります。分割線が縦向きの場合左が、横向きの場合上がroom1となります。room1,room2それぞれに必要な情報を入れていきます。
次に、Aisle型のtempAisleに必要な情報を入れる。
その後、分割前の部屋が持っている通路の情報をroom1,room2に入れます。その際に隣接しているほうにのみ入れます。
room1,room2にtempAisleに入れます。
最後にroomの元の部屋を消し、room1,room2を入れてこの関数は終わりです。

部屋と通路を作る関数

void MapGene::RoomDig() {		//マップに部屋を書き込む
	for (int e = 0; e < (int)room.size(); e++) {
		for (int f = room[e].leftTop_x; f < room[e].leftTop_x + room[e].width; f++) {
			for (int g = room[e].leftTop_y; g < room[e].leftTop_y + room[e].haight; g++) {
				map[f][g] = ' ';
			}
		}
	}
}

RoomDigはmapに部屋の場所を書き込む関数です。この関数は単純なので次に行きます。

void MapGene::AisleDig() {	//マップに通路を書き込む
	int tempRand = 0;
	for (int e = 0; e < room.size(); e++) {	//部屋の数だけ行う
		for (int f = 0; f < room[e].aisleNum.size(); f++) {	//部屋の持つ通路の数
			if (aisle[room[e].aisleNum[f]].direction == VERTICAL) {	//縦線の時(部屋から横向きに掘る)
				tempRand = rand() % room[e].haight + room[e].leftTop_y;	//通路を作るy座標を決める
				if (aisle[room[e].aisleNum[f]].line < room[e].leftTop_x) {	//左
					for (int g = 0; g < 2; g++) {
						map[room[e].leftTop_x - g - 1][tempRand] = ' ';
					}
				}	
				else {	//右
					for (int g = 0; g < 2; g++) {
						map[room[e].leftTop_x + room[e].width + g][tempRand] = ' ';
					}
				}
			}
			else {	//横線の時(部屋から縦向きに掘る)
				tempRand = rand() % room[e].width + room[e].leftTop_x;	//通路を作るx座標を決める
				if (aisle[room[e].aisleNum[f]].line < room[e].leftTop_y) {	//上
					for (int g = 0; g < 2; g++) {
						map[tempRand][room[e].leftTop_y - g - 1] = ' ';
					}
				}
				else {	//下
					for (int g = 0; g < 2; g++) {
						map[tempRand][room[e].leftTop_y + room[e].haight + g] = ' ';
					}
				}
			}
		}
	}
	for (int e = 0; e < aisle.size(); e++) {
		//通路同士をつなげる
		vector<int>temp;
		//通路が作られかけている場所を探す
		if (aisle[e].direction == VERTICAL) {
			for (int f = aisle[e].startPoint; f < aisle[e].endPoint; f++) {
				if (map[aisle[e].line][f] == ' ') {
					temp.push_back(f);
				}
			}
		}
		else {
			for (int f = aisle[e].startPoint; f < aisle[e].endPoint; f++) {
				if (map[f][aisle[e].line] == ' ') {
					temp.push_back(f);
				}
			}
		}
		//つなぐ
		if (temp.size() % 2 == 0) {	//通路の数が偶数なら
			while (temp.size() > 0) {
				for (int f = temp[0]+1; f < temp[1]; f++) {
					if (aisle[e].direction == VERTICAL)	//縦の時
					{
						map[aisle[e].line][f] = ' ';
					}
					else {
						map[f][aisle[e].line] = ' ';
					}
				}
				temp.erase(temp.begin());
				temp.erase(temp.begin());
			}
		}
		else {	//奇数の時
			if (temp.size() != 1) {	//通路が一つの時はつながっているためとばす
				while (temp.size() > 3) {
					for (int f = temp[0] + 1; f < temp[1]; f++) {
						if (aisle[e].direction == VERTICAL)	//縦の時
						{
							map[aisle[e].line][f] = ' ';
						}
						else {
							map[f][aisle[e].line] = ' ';
						}
					}
					temp.erase(temp.begin());
					temp.erase(temp.begin());
				}
				//残り3つをくっつける
				for (int f = temp[0] + 1; f < temp[2]; f++) {
					if (aisle[e].direction == VERTICAL)	//縦の時
					{
						map[aisle[e].line][f] = ' ';
					}
					else {
						map[f][aisle[e].line] = ' ';
					}
				}
			}
		}
	}
}

AisleDigは通路をつなげる関数です。このコードでは通路の幅が3で固定のため、部屋から通路方向に2マス堀り、それをつなげていきます。通路同士をつなげる際には縦横だけではなく、分割された部屋が分割された場合通路に3つ穴が開くことがあるため、奇数か偶数かでも場合分けをします。

今回参考にしたサイト

今回作成したコード

スタンダードライブラリ以外使用していないため、コピペで簡単にお試しいただけます。

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <vector>

using namespace std;

#define MAP_SIZE		(40)	//マップの縦横のサイズ
#define MINIMUM_SIZE	(5)		//ルームの最低サイズ
#define AISLE_WIDTH		(3)		//通路幅

enum DIRECTION {	//方向
	VERTICAL,		//縦
	HORIZON			//横
};

struct Aisle {
	int startPoint;	//分割線の始点 上か左
	int endPoint;	//分割線の終点 下か右
	int line;		//分割線の場所
	int direction;	//方向
};

struct Room {
	int leftTop_x;	//左上のx座標
	int leftTop_y;	//左上のy座標
	int width;		//幅
	int haight;		//高さ
	vector<int> aisleNum;	//MapGeneのaisleの何番目を使うか
};

class MapGene {
private:
	char map[MAP_SIZE][MAP_SIZE];
	int geneRoomNum;	//部屋をいくつ生成するか 
	vector<Room> room;	//部屋
	vector<Aisle> aisle;	//通路
public:
	MapGene();		//コンストラクタ
	~MapGene();		//デストラクタ
	void MakeMap();	//マップを生成する
	int MakeDivideLine(int roomNum,int direction);	//部屋の分割する場所を探す	direction=0 縦 direction=1 横
	void RoomDivide(int roomNum,int line, int direction);	//部屋を分割する
	void RoomDig();		//マップに部屋を書き込む
	void AisleDig();	//マップに通路を書き込む
	void Output();		//表示する
};

MapGene::MapGene() {	//コンストラクタ
	for (int e = 0; e < MAP_SIZE; e++) {	//マップの初期化
		for (int f = 0; f < MAP_SIZE; f++) {
			map[f][e] = '*';
		}
	}
	geneRoomNum = rand()%3+5;
	Room tempRoom;
	tempRoom.leftTop_x = 1;
	tempRoom.leftTop_y = 1;
	tempRoom.width = MAP_SIZE-2;
	tempRoom.haight = MAP_SIZE-2;
	room.push_back(tempRoom);
}

MapGene::~MapGene() {		//デストラクタ
}

void MapGene::MakeMap() {	//マップを生成する
	//geneRoomNumまでマップを生成する
	geneRoomNum -= 1;
	//分割できるサイズの部屋がいくつあるか 13以上
	int roomNum = 0;
	vector<int> passRoom;	//規定サイズ以上の部屋番号を入れる
	for (int e = 0; e < (int)room.size(); e++) {
		if (room[e].width >= MINIMUM_SIZE * 2 + AISLE_WIDTH
			|| room[e].haight >= MINIMUM_SIZE * 2 + AISLE_WIDTH) {
			roomNum++;
			passRoom.push_back(e);
		}
	}
	//分割する部屋を決める
	roomNum = rand() % roomNum;
	//縦か横かを決める
	int direction = 0;	//direction=0 縦 direction=1 横
	if (room[passRoom[roomNum]].width >= (MINIMUM_SIZE * 2 + AISLE_WIDTH)
		&& room[passRoom[roomNum]].haight >= (MINIMUM_SIZE * 2 + AISLE_WIDTH)) {
		direction = rand() % 2;
	}
	else if (room[passRoom[roomNum]].width >= (MINIMUM_SIZE * 2 + AISLE_WIDTH)) {
		direction = VERTICAL;
	}
	else {
		direction = HORIZON;
	}
	//分割するラインを作り、通路を作る
	RoomDivide(passRoom[roomNum],MakeDivideLine(passRoom[roomNum], direction), direction);

	if (geneRoomNum != 0) {	//規定数まで生成したかを判定
		MakeMap();
		return;
	}
	RoomDig();
	AisleDig();
}

int MapGene::MakeDivideLine(int roomNum, int direction) {	//部屋の分割する場所を探す	direction=0 縦 direction=1 横
	int divideLine = 0;
	if (direction == VERTICAL) {
		divideLine = room[roomNum].width;
	}
	else {
		divideLine = room[roomNum].haight;
	}

	divideLine -= (MINIMUM_SIZE * 2 + 2);
	divideLine = rand() % divideLine + MINIMUM_SIZE + 2;	//randの+1 通路の+1

	return divideLine;
}

void MapGene::RoomDivide(int roomNum,int line,int direction) {	//部屋を分割する
	Room room1, room2;
	Aisle tempAisle;
	if (direction == VERTICAL) {	//縦分割
		room1.leftTop_y = room2.leftTop_y = room[roomNum].leftTop_y;
		room1.leftTop_x = room[roomNum].leftTop_x;
		room2.leftTop_x = room1.leftTop_x + line + 1;
		room1.haight = room2.haight = room[roomNum].haight;
		room1.width = line - 2;
		room2.width = room[roomNum].width - line - 1;
		//分割線の情報を入れる場所
		tempAisle.startPoint = room[roomNum].leftTop_y - 1;
		tempAisle.endPoint = room[roomNum].leftTop_y + room[roomNum].haight;
		tempAisle.line = room[roomNum].leftTop_x+line-1;
		tempAisle.direction = VERTICAL;
		//分割前の部屋の持つ分割線をそれぞれに渡す
		for (int e = 0; e < room[roomNum].aisleNum.size(); e++) {
			if (aisle[room[roomNum].aisleNum[e]].direction == VERTICAL) {	//縦の線だった場合
				if (aisle[room[roomNum].aisleNum[e]].line < room[roomNum].leftTop_x) {	//分割線が元の部屋より左にある場合
					room1.aisleNum.insert(room1.aisleNum.end(), room[roomNum].aisleNum[e]);
				}
				else {	//右の場合
					room2.aisleNum.insert(room2.aisleNum.end(), room[roomNum].aisleNum[e]);
				}
			}
			else {	//横の線の場合
				room1.aisleNum.insert(room1.aisleNum.end(), room[roomNum].aisleNum[e]);
				room2.aisleNum.insert(room2.aisleNum.end(), room[roomNum].aisleNum[e]);
			}
		}
	}
	else {	//横分割
		room1.leftTop_x = room2.leftTop_x = room[roomNum].leftTop_x;
		room1.leftTop_y = room[roomNum].leftTop_y;
		room2.leftTop_y = room1.leftTop_y + line + 1;
		room1.width = room2.width = room[roomNum].width;
		room1.haight = line - 2;
		room2.haight = room[roomNum].haight - line - 1;
		//分割線の情報を入れる場所
		tempAisle.startPoint = room[roomNum].leftTop_x - 1;
		tempAisle.endPoint = room[roomNum].leftTop_x + room[roomNum].width;
		tempAisle.line = room[roomNum].leftTop_y+line-1;
		tempAisle.direction = HORIZON;
		//分割前の部屋の持つ分割線をそれぞれに渡す
		for (int e = 0; e < room[roomNum].aisleNum.size(); e++) {
			if (aisle[room[roomNum].aisleNum[e]].direction == HORIZON) {	//横の線だった場合
				if (aisle[room[roomNum].aisleNum[e]].line < room[roomNum].leftTop_y) {	//分割線が元の部屋より上にある場合
					room1.aisleNum.insert(room1.aisleNum.end(), room[roomNum].aisleNum[e]);
				}
				else {	//下の場合
					room2.aisleNum.insert(room2.aisleNum.end(), room[roomNum].aisleNum[e]);
				}
			}
			else {	//縦の線の場合
				room1.aisleNum.insert(room1.aisleNum.end(), room[roomNum].aisleNum[e]);
				room2.aisleNum.insert(room2.aisleNum.end(), room[roomNum].aisleNum[e]);
			}
		}
	}
	//分割線を通路として新たにaisleに追加する
	aisle.push_back(tempAisle);
	room1.aisleNum.push_back(aisle.size()-1);
	room2.aisleNum.push_back(aisle.size()-1);
	//分割した部屋を削除し、新しい部屋をroomに入れる
	room.erase(room.begin() + roomNum);
	room.push_back(room1);
	room.push_back(room2);
}

void MapGene::RoomDig() {		//マップに部屋を書き込む
	for (int e = 0; e < (int)room.size(); e++) {
		for (int f = room[e].leftTop_x; f < room[e].leftTop_x + room[e].width; f++) {
			for (int g = room[e].leftTop_y; g < room[e].leftTop_y + room[e].haight; g++) {
				map[f][g] = ' ';
			}
		}
	}
}

void MapGene::AisleDig() {	//マップに通路を書き込む
	int tempRand = 0;
	for (int e = 0; e < room.size(); e++) {	//部屋の数だけ行う
		for (int f = 0; f < room[e].aisleNum.size(); f++) {	//部屋の持つ通路の数
			if (aisle[room[e].aisleNum[f]].direction == VERTICAL) {	//縦線の時(部屋から横向きに掘る)
				tempRand = rand() % room[e].haight + room[e].leftTop_y;	//通路を作るy座標を決める
				if (aisle[room[e].aisleNum[f]].line < room[e].leftTop_x) {	//左
					for (int g = 0; g < 2; g++) {
						map[room[e].leftTop_x - g - 1][tempRand] = ' ';
					}
				}	
				else {	//右
					for (int g = 0; g < 2; g++) {
						map[room[e].leftTop_x + room[e].width + g][tempRand] = ' ';
					}
				}
			}
			else {	//横線の時(部屋から縦向きに掘る)
				tempRand = rand() % room[e].width + room[e].leftTop_x;	//通路を作るx座標を決める
				if (aisle[room[e].aisleNum[f]].line < room[e].leftTop_y) {	//上
					for (int g = 0; g < 2; g++) {
						map[tempRand][room[e].leftTop_y - g - 1] = ' ';
					}
				}
				else {	//下
					for (int g = 0; g < 2; g++) {
						map[tempRand][room[e].leftTop_y + room[e].haight + g] = ' ';
					}
				}
			}
		}
	}
	for (int e = 0; e < aisle.size(); e++) {
		//通路同士をつなげる
		vector<int>temp;
		//通路が作られかけている場所を探す
		if (aisle[e].direction == VERTICAL) {
			for (int f = aisle[e].startPoint; f < aisle[e].endPoint; f++) {
				if (map[aisle[e].line][f] == ' ') {
					temp.push_back(f);
				}
			}
		}
		else {
			for (int f = aisle[e].startPoint; f < aisle[e].endPoint; f++) {
				if (map[f][aisle[e].line] == ' ') {
					temp.push_back(f);
				}
			}
		}
		//つなぐ
		if (temp.size() % 2 == 0) {	//通路の数が偶数なら
			while (temp.size() > 0) {
				for (int f = temp[0]+1; f < temp[1]; f++) {
					if (aisle[e].direction == VERTICAL)	//縦の時
					{
						map[aisle[e].line][f] = ' ';
					}
					else {
						map[f][aisle[e].line] = ' ';
					}
				}
				temp.erase(temp.begin());
				temp.erase(temp.begin());
			}
		}
		else {	//奇数の時
			if (temp.size() != 1) {	//通路が一つの時はつながっているためとばす
				while (temp.size() > 3) {
					for (int f = temp[0] + 1; f < temp[1]; f++) {
						if (aisle[e].direction == VERTICAL)	//縦の時
						{
							map[aisle[e].line][f] = ' ';
						}
						else {
							map[f][aisle[e].line] = ' ';
						}
					}
					temp.erase(temp.begin());
					temp.erase(temp.begin());
				}
				//残り3つをくっつける
				for (int f = temp[0] + 1; f < temp[2]; f++) {
					if (aisle[e].direction == VERTICAL)	//縦の時
					{
						map[aisle[e].line][f] = ' ';
					}
					else {
						map[f][aisle[e].line] = ' ';
					}
				}
			}
		}
	}
}

void MapGene::Output() {	//表示する
	for (int e = 0; e < MAP_SIZE; e++) {
		for (int f = 0; f < MAP_SIZE; f++) {
			printf("%c", map[f][e]);
		}
		printf("\n");
	}
}

int main(void) {
	srand((unsigned)time(NULL));	//時間を用いた乱数生成
	MapGene* mpG = new MapGene();	//インスタンス化
	mpG->MakeMap();					//マップ生成
	mpG->Output();					//描画
	delete mpG;						//ポインタの開放
}

この記事が気に入ったらサポートをしてみませんか?