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

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

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

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

Q&A

0回答

615閲覧

配列のステージマップを分割してその一つを個別に認識する方法

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

0グッド

0クリップ

投稿2022/05/07 04:43

編集2022/05/07 05:00

提示画像ですがこれはダンジョンRPGのダンジョンマップ生成アルゴリズムのステージ分割した時のスクショなのですがステージを適当に分割した後に次はその分割した矩形の中にランダムな大きさの矩形を配置する必要があるのですがこれをするにはどういった思考を用いて実装するのでしょうか?
現状のように縦、横に直線を引いてステージを分割しているのですがその後の分割した矩形の中にランダムな大きさの矩形を配置するということをコード上で実装したいのですが実装方法が思い付きません。ステージの各エリアをどうやって認識したらいいでしょうか?

提示コードsetGenerate()関数部

現状

縦、横に線を引いてステージを分割

参考サイト:https://kt2525family.com/rogue-development-5/
イメージ説明

Dungeon_Generate.cpp

cpp

1#include "../header/Generate_Dungeon.hpp" 2#include "../../FrameWork/header/FrameWork.hpp" 3#include <glm/glm.hpp> 4#include <algorithm> 5 6 7// ##################################### コンストラクタ ##################################### 8Generate_Dungeon::Generate_Dungeon(glm::ivec2 s,int div) 9{ 10 divNum = div; //分割数 11 allSize = s; //全体サイズ 12 13 minSize = glm::ivec2(3,3); //最小区画サイズ 14 maxSize = glm::ivec2(s.x / minSize.x,s.y / minSize.y); //最大区画サイズ 15 16 17 18 19 stage.resize(s.x * s.y); 20 area.resize(0); 21 area.push_back(Area { s.x * s.y,glm::ivec2(0,0),s }); 22} 23 24// ##################################### ステージ再設定 ##################################### 25void Generate_Dungeon::setReSetStage(glm::ivec2 s,int div) 26{ 27 28 divNum = div; 29 allSize = s; 30 stage.resize(s.x * s.y); 31 32 area.resize(0); 33 area.push_back(Area { s.x * s.y,glm::ivec2(0,0),s }); 34} 35 36// ##################################### 一番大きいエリアを削除 ##################################### 37void Generate_Dungeon::DeleteMaxArea() 38{ 39 Area map = Area{0,glm::ivec2(0,0),glm::ivec2(allSize.x,allSize.y)}; 40 int i = 0; 41 int num = -1; 42 for(std::vector<Area>::iterator itr = area.begin(); itr != area.end(); itr++) 43 { 44 if(map.size < itr->size) 45 { 46 47 map = *itr; 48 num = i; 49 50// std::cout<<map.size<<std::endl; 51 } 52 i++; 53 } 54 55 if(num != -1) 56 { 57 area.erase(area.begin() + num); 58 } 59 else 60 { 61 std::cout<< "Error: 削除するエリアがありません。"<<std::endl; 62 } 63} 64 65// ##################################### 一番大きいエリアを取得 ##################################### 66Generate_Dungeon::Area Generate_Dungeon::GetMaxArea() 67{ 68 Area map = Area{0,glm::ivec2(0,0),glm::ivec2(0,0)}; 69 for(std::vector<Area>::iterator itr = area.begin(); itr != area.end(); itr++) 70 { 71 if(map.size < itr->size) 72 { 73 map = *itr; 74 75 76 std::cout<<" map.start.y: " << map.start.y<<std::endl; 77// std::cout<<map.size<<std::endl; 78 79 } 80 81 82 } 83// std::cout<<" map.start.y: " << map.start.y<<std::endl; 84 85 std::cout<<"return map.start.y: " << map.start.y<<std::endl; 86// std::cout<<std::endl; 87// std::cout<<std::endl; 88// std::cout<<std::endl; 89 90 91 92 93 return map; 94} 95 96// ##################################### エリアに値を設定 ##################################### 97void Generate_Dungeon::SetArea(glm::ivec2 start,glm::ivec2 size,byte b) 98{ 99 for(int y = start.y; y < start.y + size.y; y++) 100 { 101 for(int x = start.x; x < start.x + size.x; x++) 102 { 103 stage.at((y * allSize.x) + x) = b; 104 } 105 } 106} 107 108// ##################################### X軸からYの長さを取得 ##################################### 109int Generate_Dungeon::GetCheckLineDown(glm::ivec2 start) 110{ 111 byte b = stage.at( (allSize.x * start.y) + start.x); 112 int y = 0; 113 for(int i = start.y; i < allSize.y; i++) 114 { 115 if(stage.at( (allSize.x * i + start.x)) != b) 116 { 117 return y; 118 } 119 120 y++; 121 } 122 123 return y; 124} 125 126// ##################################### X軸からYの長さを取得 ##################################### 127int Generate_Dungeon::GetCheckLineUp(glm::ivec2 start) 128{ 129 byte b = stage.at( (allSize.x * start.y) + start.x); 130 int y = 0; 131 for(int i = start.y; i > 0; i--) 132 { 133 if(stage.at( (allSize.x * i + start.x)) != b) 134 { 135 return y; 136 } 137 138 y++; 139 } 140 141 return y; 142} 143 144// ##################################### Y軸からXの長さを取得 ##################################### 145int Generate_Dungeon::GetCheckLineRight(glm::ivec2 start) 146{ 147 byte b = stage.at( (allSize.x * (start.y) ) + start.x); 148 int x = 0; 149 for(int i = start.x; i < allSize.x; i++) 150 { 151 if(stage.at( (allSize.x * start.y) + i) != b) 152 { 153 return x; 154 } 155 156 x++; 157 } 158 159 return x; 160} 161 162// ##################################### Y軸からXの長さを取得 ##################################### 163int Generate_Dungeon::GetCheckLineLeft(glm::ivec2 start) 164{ 165 byte b = stage.at( (allSize.x * (start.y) ) + start.x); 166 int x = 0; 167 for(int i = start.x; i > 0; i--) 168 { 169 if(stage.at( (allSize.x * start.y) + i) != b) 170 { 171 return x; 172 } 173 174 x++; 175 } 176 177 return x; 178} 179 180 181 182// ##################################### ステージに値を設定 ##################################### 183void Generate_Dungeon::SetStage(glm::ivec2 pos,byte b) 184{ 185 stage.at((allSize.x * pos.y) + pos.x) = b; 186} 187 188// ##################################### ステージに値を取得 ##################################### 189byte Generate_Dungeon::GetStage(glm::ivec2 pos) 190{ 191 return stage.at((allSize.x * pos.y) + pos.x); 192} 193 194// ##################################### X軸に分割ラインを引く ##################################### 195void Generate_Dungeon::SetLine_Width(int posY) 196{ 197 byte b = GetStage(glm::ivec2(0,posY)); 198 for(int x = 0; x < allSize.x; x++) 199 { 200 if(b == GetStage(glm::ivec2(x,posY))) 201 { 202 SetStage(glm::ivec2(x,posY),flag); 203 } 204 else 205 { 206 break; 207 } 208 209 } 210} 211 212// ##################################### Y軸に分割ラインを引く ##################################### 213void Generate_Dungeon::SetLine_Height(int posX) 214{ 215 byte b = GetStage(glm::ivec2(posX,0)); 216 for(int y = 0; y < allSize.y; y++) 217 { 218 if(b == GetStage(glm::ivec2(posX,y))) 219 { 220 SetStage(glm::ivec2(posX,y),flag); 221 } 222 else 223 { 224 break; 225 } 226 } 227} 228 229// ##################################### エリアを作成 ##################################### 230void Generate_Dungeon::SetCreateArea() 231{ 232 233 234} 235 236// ##################################### エリアを取得 ##################################### 237glm::ivec2 Generate_Dungeon::GetAreaSize(glm::ivec2 start) 238{ 239 glm::ivec2 size = glm::ivec2(0,0); 240 byte b = GetStage(start); 241 for(int x = 0; x < allSize.x; x++) 242 { 243 if(GetStage(start + glm::ivec2(x,0)) != b) 244 { 245 break; 246 } 247 else 248 { 249 size.x += 1; 250 } 251 } 252 253 254 for(int y = 0; y < allSize.y; y++) 255 { 256 if(GetStage(start + glm::ivec2(0,y)) != b) 257 { 258 break; 259 } 260 else 261 { 262 size.y += 1; 263 } 264 } 265 266 return size; 267} 268 269// ##################################### min以上の間隔で0~maxまでの位置を取得 ##################################### 270int Generate_Dungeon::GetRandom_Width(int min,int max) 271{ 272 while(true) 273 { 274 int rand = FrameWork::GetRandom(0,max); 275 if((min < GetCheckLineUp(glm::ivec2(0,rand))) && (min < GetCheckLineDown(glm::ivec2(0,rand)))) 276 { 277 return rand; 278 } 279 } 280} 281 282// ##################################### min以上の間隔で0~maxまでの位置を取得 ##################################### 283int Generate_Dungeon::GetRandom_Height(int min,int max) 284{ 285 while(true) 286 { 287 int rand = FrameWork::GetRandom(0,max); 288 if((min < GetCheckLineLeft(glm::ivec2(rand,0))) && (min < GetCheckLineRight(glm::ivec2(rand,0)))) 289 { 290 return rand; 291 } 292 } 293} 294 295// ##################################### ステージを生成 ##################################### 296void Generate_Dungeon::setGenerate() 297{ 298 for(int i = 0; i < divNum; i++) 299 { 300 SetLine_Height(GetRandom_Height(minSize.x,allSize.x - minSize.x)); 301 SetLine_Width(GetRandom_Width(minSize.y,allSize.y - minSize.y)); 302 } 303} 304 305// ##################################### ステージを取得 ##################################### 306std::vector<byte> Generate_Dungeon::getStage() 307{ 308 return stage; 309} 310 311// ##################################### デストラクタ ##################################### 312Generate_Dungeon::~Generate_Dungeon() 313{ 314 315} 316

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

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

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

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

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

fana

2022/05/07 10:17 編集

逆に問うけど,一体何のために線を引いたのか? 「線を引いたならば,その次の処理ではその結果をこういうふうに用いることであれができるから…」だとかいうような 計画/見通し もなく,単に「線を引いてみた」のですか? 次の処理で「エリアを認識する必要がある」のならば,認識できるようなデータ構造を考えて,「分割」なる処理ではそのデータ構造を適切に取り扱うべきなのではないのか? 線を引いた後に「で,エリアをどう認識すればよいのか?」とか言ってる時点で,何というか,言葉は悪いけども【どうかしてる】と思う.
退会済みユーザー

退会済みユーザー

2022/05/07 10:39

なるほど。ではどうやればいいのでしょうか?
fana

2022/05/08 01:41

いや,知らんけどさ. 仮に「エリア」とかいう物の形状が常に矩形だという話なのであれば,全く「分割」してない状態ってのは「でかい矩形が1個だけある」っていう状態として表現できるよね. で,それを2つに「分割」する処理ってのは,結果として2つの矩形データを得る処理になるんじゃないの? (1個だったのが2個になるわけだ.これこそ「分割」と呼ぶに相応しいと思えるな) そういうデータ(この例では矩形群)を保有しているのであれば,エリアの座標とは完全に自明なわけ. あなたが今現在扱っているデータってのが実際どういう物になってるのかは知らんけども,【やりたいことがやりやすいデータ を扱えばよい】だけなんじゃないの? #「参考サイト」とやらのいたるところに "Rect" ってワードが書いてるんだから,「参考」にしたら良いのでは?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問