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

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

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

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

受付中

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

samidare_chan
samidare_chan

総合スコア142

C++

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

0回答

-4評価

0クリップ

364閲覧

投稿2022/05/07 04:43

編集2022/05/08 10:41

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

提示コードsetGenerate()関数部

現状

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

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

Dungeon_Generate.cpp

cpp

#include "../header/Generate_Dungeon.hpp" #include "../../FrameWork/header/FrameWork.hpp" #include <glm/glm.hpp> #include <algorithm> // ##################################### コンストラクタ ##################################### Generate_Dungeon::Generate_Dungeon(glm::ivec2 s,int div) { divNum = div; //分割数 allSize = s; //全体サイズ minSize = glm::ivec2(3,3); //最小区画サイズ maxSize = glm::ivec2(s.x / minSize.x,s.y / minSize.y); //最大区画サイズ stage.resize(s.x * s.y); area.resize(0); area.push_back(Area { s.x * s.y,glm::ivec2(0,0),s }); } // ##################################### ステージ再設定 ##################################### void Generate_Dungeon::setReSetStage(glm::ivec2 s,int div) { divNum = div; allSize = s; stage.resize(s.x * s.y); area.resize(0); area.push_back(Area { s.x * s.y,glm::ivec2(0,0),s }); } // ##################################### 一番大きいエリアを削除 ##################################### void Generate_Dungeon::DeleteMaxArea() { Area map = Area{0,glm::ivec2(0,0),glm::ivec2(allSize.x,allSize.y)}; int i = 0; int num = -1; for(std::vector<Area>::iterator itr = area.begin(); itr != area.end(); itr++) { if(map.size < itr->size) { map = *itr; num = i; // std::cout<<map.size<<std::endl; } i++; } if(num != -1) { area.erase(area.begin() + num); } else { std::cout<< "Error: 削除するエリアがありません。"<<std::endl; } } // ##################################### 一番大きいエリアを取得 ##################################### Generate_Dungeon::Area Generate_Dungeon::GetMaxArea() { Area map = Area{0,glm::ivec2(0,0),glm::ivec2(0,0)}; for(std::vector<Area>::iterator itr = area.begin(); itr != area.end(); itr++) { if(map.size < itr->size) { map = *itr; std::cout<<" map.start.y: " << map.start.y<<std::endl; // std::cout<<map.size<<std::endl; } } // std::cout<<" map.start.y: " << map.start.y<<std::endl; std::cout<<"return map.start.y: " << map.start.y<<std::endl; // std::cout<<std::endl; // std::cout<<std::endl; // std::cout<<std::endl; return map; } // ##################################### エリアに値を設定 ##################################### void Generate_Dungeon::SetArea(glm::ivec2 start,glm::ivec2 size,byte b) { for(int y = start.y; y < start.y + size.y; y++) { for(int x = start.x; x < start.x + size.x; x++) { stage.at((y * allSize.x) + x) = b; } } } // ##################################### X軸からYの長さを取得 ##################################### int Generate_Dungeon::GetCheckLineDown(glm::ivec2 start) { byte b = stage.at( (allSize.x * start.y) + start.x); int y = 0; for(int i = start.y; i < allSize.y; i++) { if(stage.at( (allSize.x * i + start.x)) != b) { return y; } y++; } return y; } // ##################################### X軸からYの長さを取得 ##################################### int Generate_Dungeon::GetCheckLineUp(glm::ivec2 start) { byte b = stage.at( (allSize.x * start.y) + start.x); int y = 0; for(int i = start.y; i > 0; i--) { if(stage.at( (allSize.x * i + start.x)) != b) { return y; } y++; } return y; } // ##################################### Y軸からXの長さを取得 ##################################### int Generate_Dungeon::GetCheckLineRight(glm::ivec2 start) { byte b = stage.at( (allSize.x * (start.y) ) + start.x); int x = 0; for(int i = start.x; i < allSize.x; i++) { if(stage.at( (allSize.x * start.y) + i) != b) { return x; } x++; } return x; } // ##################################### Y軸からXの長さを取得 ##################################### int Generate_Dungeon::GetCheckLineLeft(glm::ivec2 start) { byte b = stage.at( (allSize.x * (start.y) ) + start.x); int x = 0; for(int i = start.x; i > 0; i--) { if(stage.at( (allSize.x * start.y) + i) != b) { return x; } x++; } return x; } // ##################################### ステージに値を設定 ##################################### void Generate_Dungeon::SetStage(glm::ivec2 pos,byte b) { stage.at((allSize.x * pos.y) + pos.x) = b; } // ##################################### ステージに値を取得 ##################################### byte Generate_Dungeon::GetStage(glm::ivec2 pos) { return stage.at((allSize.x * pos.y) + pos.x); } // ##################################### X軸に分割ラインを引く ##################################### void Generate_Dungeon::SetLine_Width(int posY) { byte b = GetStage(glm::ivec2(0,posY)); for(int x = 0; x < allSize.x; x++) { if(b == GetStage(glm::ivec2(x,posY))) { SetStage(glm::ivec2(x,posY),flag); } else { break; } } } // ##################################### Y軸に分割ラインを引く ##################################### void Generate_Dungeon::SetLine_Height(int posX) { byte b = GetStage(glm::ivec2(posX,0)); for(int y = 0; y < allSize.y; y++) { if(b == GetStage(glm::ivec2(posX,y))) { SetStage(glm::ivec2(posX,y),flag); } else { break; } } } // ##################################### エリアを作成 ##################################### void Generate_Dungeon::SetCreateArea() { } // ##################################### エリアを取得 ##################################### glm::ivec2 Generate_Dungeon::GetAreaSize(glm::ivec2 start) { glm::ivec2 size = glm::ivec2(0,0); byte b = GetStage(start); for(int x = 0; x < allSize.x; x++) { if(GetStage(start + glm::ivec2(x,0)) != b) { break; } else { size.x += 1; } } for(int y = 0; y < allSize.y; y++) { if(GetStage(start + glm::ivec2(0,y)) != b) { break; } else { size.y += 1; } } return size; } // ##################################### min以上の間隔で0~maxまでの位置を取得 ##################################### int Generate_Dungeon::GetRandom_Width(int min,int max) { while(true) { int rand = FrameWork::GetRandom(0,max); if((min < GetCheckLineUp(glm::ivec2(0,rand))) && (min < GetCheckLineDown(glm::ivec2(0,rand)))) { return rand; } } } // ##################################### min以上の間隔で0~maxまでの位置を取得 ##################################### int Generate_Dungeon::GetRandom_Height(int min,int max) { while(true) { int rand = FrameWork::GetRandom(0,max); if((min < GetCheckLineLeft(glm::ivec2(rand,0))) && (min < GetCheckLineRight(glm::ivec2(rand,0)))) { return rand; } } } // ##################################### ステージを生成 ##################################### void Generate_Dungeon::setGenerate() { for(int i = 0; i < divNum; i++) { SetLine_Height(GetRandom_Height(minSize.x,allSize.x - minSize.x)); SetLine_Width(GetRandom_Width(minSize.y,allSize.y - minSize.y)); } } // ##################################### ステージを取得 ##################################### std::vector<byte> Generate_Dungeon::getStage() { return stage; } // ##################################### デストラクタ ##################################### Generate_Dungeon::~Generate_Dungeon() { }

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

fana

2022/05/07 10:17 編集

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

2022/05/07 10:39

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

2022/05/08 01:41

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

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

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

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

C++

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