質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

812閲覧

ダンジョンマップ生成アルゴリズムで乱数を微調整する方法が知りたい

退会済みユーザー

退会済みユーザー

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2022/05/05 03:50

編集2022/05/05 03:54

提示コードはダンジョンマップ生成アルゴリズムなのですが参考サイトよりステージを縦横に分割する処理を実装しているのですが乱数のばらまきをもう少し調整したいのですがこの場合どうやって調整するべきなのでしょうか?現状だと提示画像のように6回分割を行っており5以上でエリアの最大値より5小さいという制限をかけて乱数を取得していますが提示画像のように乱数の値がバラバラすぎて区画が大きいのと小さいのとで不揃いになってしまいます。どう調整すればまんべんなく区画を生成できるのでしょうか?
Generate_Dungeon.cppソースファイルのvoid Generate_Dungeon::SetLine_X(int posY)関数部ですがvoid Generate_Dungeon::setGenerate()関数で乱数を設定しています。

参考サイト:http://rainbowvortex.blog.fc2.com/blog-entry-127.html

イメージ説明

Generate_Dungeon.cpp

cpp

1#include "../header/Generate_Dungeon.hpp" 2#include "../../FrameWork/header/FrameWork.hpp" 3#include <glm/glm.hpp> 4 5// ##################################### コンストラクタ ##################################### 6Generate_Dungeon::Generate_Dungeon(glm::ivec2 s,glm::ivec2 div = glm::ivec2(0,0)) 7{ 8 setDivisionNum_X(div.x); 9 setDivisionNum_Y(div.y); 10 11 //printf("%d\n",s.y); 12 13 allSize = s; 14 stage.resize(s.x * s.y); 15 area.resize(0); 16 area.push_back(Area { s.x * s.y,glm::ivec2(0,0),s }); 17} 18 19 20// ##################################### ステージ再設定 ##################################### 21void Generate_Dungeon::setReSetStage(glm::ivec2 s,glm::ivec2 div) 22{ 23 setDivisionNum_X(div.x); 24 setDivisionNum_Y(div.y); 25 26 allSize = s; 27 stage.resize(s.x * s.y); 28 29 area.resize(0); 30 area.push_back(Area { s.x * s.y,glm::ivec2(0,0),s }); 31} 32 33// ##################################### 一番大きいエリアを削除 ##################################### 34void Generate_Dungeon::DeleteMaxArea() 35{ 36 Area map = Area{0,glm::ivec2(0,0),glm::ivec2(allSize.x,allSize.y)}; 37 int i = 0; 38 int num = -1; 39 for(std::vector<Area>::iterator itr = area.begin(); itr != area.end(); itr++) 40 { 41 if(map.size < itr->size) 42 { 43 44 map = *itr; 45 num = i; 46 47// std::cout<<map.size<<std::endl; 48 } 49 i++; 50 } 51 52 if(num != -1) 53 { 54 area.erase(area.begin() + num); 55 } 56 else 57 { 58 std::cout<< "Error: 削除するエリアがありません。"<<std::endl; 59 } 60} 61 62// ##################################### 一番大きいエリアを取得 ##################################### 63Generate_Dungeon::Area Generate_Dungeon::GetMaxArea() 64{ 65 Area map = Area{0,glm::ivec2(0,0),glm::ivec2(0,0)}; 66 for(std::vector<Area>::iterator itr = area.begin(); itr != area.end(); itr++) 67 { 68 if(map.size < itr->size) 69 { 70 map = *itr; 71 72 73 std::cout<<" map.start.y: " << map.start.y<<std::endl; 74// std::cout<<map.size<<std::endl; 75 76 } 77 78// std::cout<<" map.start.y: " << map.start.y<<std::endl; 79 80 } 81 82 std::cout<<"return map.start.y: " << map.start.y<<std::endl; 83// std::cout<<std::endl; 84// std::cout<<std::endl; 85// std::cout<<std::endl; 86 87 88 89 90 return map; 91} 92 93// ##################################### エリアに値を設定 ##################################### 94void Generate_Dungeon::SetArea(glm::ivec2 start,glm::ivec2 size,byte b) 95{ 96 for(int y = start.y; y < start.y + size.y; y++) 97 { 98 for(int x = start.x; x < start.x + size.x; x++) 99 { 100 // std::cout<<((y * allSize.x) + x)<<std::endl; 101 stage.at((y * allSize.x) + x) = b; 102 } 103 } 104 105} 106 107// ##################################### X軸からYの長さを取得 ##################################### 108/* 109 説明 110 マス目の数を返す 111*/ 112int Generate_Dungeon::GetCheckLine_Y(glm::ivec2 start,int posX) 113{ 114 //std::cout<<( (allSize.x * start.y) + start.x + posX - 1)<<std::endl; 115 116 byte b = stage.at( (allSize.x * start.y) + start.x + posX); 117 int y = 0; 118 for(int i = start.y; i < allSize.y; i++) 119 { 120 //std::cout<<( (allSize.x * i + start.x) + posX)<<std::endl; 121 if(stage.at( (allSize.x * i + start.x) + posX) != b) 122 { 123 return y; 124 } 125 126 y++; 127 } 128 129 return y; 130} 131 132// ##################################### Y軸からXの長さを取得 ##################################### 133int Generate_Dungeon::GetCheckLine_X(glm::ivec2 start,int posY) 134{ 135 //std::cout<<"aaaaaaa "<< (allSize.x * (start.y + posY) ) + start.x -1 <<std::endl; 136 byte b = stage.at( (allSize.x * (start.y + posY) ) + start.x - 1); 137 int x = 0; 138 for(int i = start.x; i < allSize.x; i++) 139 { 140 141// std::cout<<(allSize.x * posY) + i<<std::endl; 142 if(stage.at( (allSize.x * posY) + i) != b) 143 { 144 return x; 145 } 146 147 x++; 148 } 149 150 return x; 151} 152 153// ##################################### ステージに値を設定 ##################################### 154void Generate_Dungeon::SetStage(glm::ivec2 start,glm::ivec2 pos,byte b) 155{ 156 stage.at((allSize.x * (pos.y + start.y)) + pos.x + start.x) = b; 157} 158 159// ##################################### ステージに値を取得 ##################################### 160byte Generate_Dungeon::GetStage(glm::ivec2 start,glm::ivec2 pos) 161{ 162 return stage.at((allSize.x * (pos.y + start.y)) + pos.x + start.x); 163} 164// ##################################### X軸に分割ラインを引く ##################################### 165void Generate_Dungeon::SetLine_X(int posY) 166{ 167// std::cout<<"posY: " << posY<<std::endl; 168 169 Area map = GetMaxArea(); //一番大きいエリアを取得 170 DeleteMaxArea(); //一番大きいエリアを削除 171 172 173// printf("allSize.y: %d\n",posY); 174 175 int rangeX = GetCheckLine_X(map.start,posY); //X軸のマス目の個数を取得 176 SetArea(map.start,glm::ivec2(rangeX,posY),flag); //範囲に値を設定 177 glm::ivec2 s = glm::ivec2(map.end.y - map.start.y,map.end.x - map.start.x); 178 179 180 181 area.push_back(Area{ rangeX * posY,map.start,glm::ivec2(map.start.x + rangeX,map.start.y + posY) }); //エリアを追加 182 183 184 flag++; 185 186// std::cout<<"posY: " << posY<<std::endl; 187 188 189 190 191 int y = GetCheckLine_Y(map.start + glm::ivec2(0,posY),0); //乱数のY軸から範囲の下までの個数を得る 192 193 std::cout<<"posY: " << posY<<std::endl; 194 std::cout<<"y: " << y<<std::endl; 195 196 197 198// std::cout<< (map.start + glm::ivec2(rangeX,posY)).x<<std::endl; 199// std::cout<< (map.start + glm::ivec2(rangeX,posY)).y<<std::endl; 200 201 SetArea(map.start + glm::ivec2(0,posY),glm::ivec2(rangeX,y),flag); //範囲に値を設定 202 203 204 area.push_back(Area{ s.x * s.y,map.start + glm::ivec2(0,posY),glm::ivec2(map.start.x + rangeX,map.start.y + posY + y - 1) }); //エリアを追加 205 206 std::cout<<"map.start.y + posY + y - 1: " << map.start.y + posY + y - 1<<std::endl; 207 //std::cout<<allSize.y<<std::endl; 208 //std::cout<<GetMaxArea().end.y <<std::endl; 209 //std::cout<<GetMaxArea().start.x <<std::endl; 210 211 flag++; 212 213 214} 215 216// ##################################### Y軸に分割ラインを引く ##################################### 217void Generate_Dungeon::SetLine_Y(int pos) 218{ 219 220} 221 222// ##################################### ステージを生成 ##################################### 223void Generate_Dungeon::setGenerate() 224{ 225 //std::cout<<divsion_X<<std::endl; 226 for(int i = 0; i< 6; i++) 227 { 228 Area map = GetMaxArea(); 229 //std::cout<<"map.end.y: " <<map.end.y<<std::endl; 230 //std::cout<<"map.end.X: " <<map.end.x<<std::endl; 231 232// std::cout<<map.end.y - map.start.y<<std::endl; 233 234 //printf("random : %d\n",map.end.y - map.start.y); 235 236 std::cout<<map.end.y - map.start.y - 5 - 1<<std::endl; 237 238 if(map.end.y - map.start.y - 5 - 1 < 5) 239 { 240 break; 241 } 242 243 //std::cout<<map.end.y - map.start.y - 5<<std::endl; 244 245 246 //std::cout<<"random: "<< FrameWork::GetRandom(5,map.end.y - map.start.y - 5)<<std::endl; 247 int rand = FrameWork::GetRandom(5,map.end.y - map.start.y - 5 - 1); 248 std::cout<<"Random: "<<rand<<std::endl; 249 SetLine_X(rand); 250 //SetLine_X(29 - 1); 251 //printf("aaaaa\n"); 252// flag++; 253/* 254 for(int i = 0; i< divsion_Y; i++) 255 { 256 257 } 258*/ 259 //SetLine_Y(FrameWork::GetRandom(10,allSize.X)); 260 } 261}

#####Stage.cpp

cpp

1// ##################################### コンストラクタ ##################################### 2Stage::Stage() 3{ 4 stage.resize( (int)(FrameWork::GetCurrentWindow()->getSize().x / 24) * (int)(FrameWork::GetCurrentWindow()->getSize().y / 24) ); 5 std::fill(stage.begin(),stage.end(),(byte)0x00); 6 7 sprite = FrameWork::LoadTexture("asset/texture/brickChip.png"); 8 9 10 dungeon = std::make_shared<Generate_Dungeon>(glm::ivec2((FrameWork::GetCurrentWindow()->getSize().x / 24),(FrameWork::GetCurrentWindow()->getSize().y / 24)),glm::ivec2(3,3)); 11 dungeon->setGenerate(); 12 //printf("aaaa\n"); 13 stage = dungeon->getStage(); 14 15 int xNum = (int)(FrameWork::GetCurrentWindow()->getSize().x / 24); 16 int yNum = (int)(FrameWork::GetCurrentWindow()->getSize().y / 24); 17 18 //std::cout<<"X: " << xNum<<std::endl; 19 //std::cout<<"Y: " << yNum<<std::endl; 20 //std::cout<<"Y * X: " << yNum * xNum<<std::endl; 21 22 23 for(int i = 0; i< yNum; i++) 24 { 25 for(int j = 0; j < xNum; j++) 26 { 27 switch(stage.at(xNum * i + j)) 28 { 29 case 0x00: 30 { 31 printf("*"); 32 } 33 break; 34 35 case 0x01: 36 { 37 printf("A"); 38 } 39 break; 40 41 case 0x02: 42 { 43 printf("B"); 44 } 45 break; 46// 文字数の関係で省略 47 } 48 49 } 50 51 printf("\n"); 52 } 53 54 55} 56
FrameWork::GetRandom

cpp

1 2// ##################################### 乱数 取得 ##################################### 3int FrameWork::GetRandom(int start, int end) 4{ 5 std::random_device rnd; // 非決定的な乱数生成器を生成 6 std::mt19937 mt(rnd()); // メルセンヌ・ツイスタの32ビット版、引数は初期シード値 7 std::uniform_int_distribution<> Rand(start, end); // [start, end] 範囲の一様乱数 8 9 return Rand(mt); 10} 11 12`` 13

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2022/05/05 03:52

同じ質問。 前の質問は削除された。
Zuishin

2022/05/05 03:54

提示画像と言いつつ画像がないところを見ると、おそらくマルチポスト。
guest

回答1

0

ベストアンサー

乱数の値がバラバラすぎて区画が大きいのと小さいのとで不揃いになってしまいます

乱数の振れ幅を小さくすればいんじゃなくて?
たとえば平均(start+end)/2の正規分布とか。

投稿2022/05/05 05:59

編集2022/05/05 06:07
episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問