ダンジョン自動生成アルゴリズムのコーディング

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アルツハイマー

ダンジョン自動生成アルゴリズムのコーディング

#1

投稿記事 by アルツハイマー » 13年前

こんばんは、夜遅くにごめんなさい。

「ダンジョン自動生成アルゴリズム」の文献は読み漁ったのですが、
コーディングできません。

どなたか、教えていただけませんでしょうか。

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: ダンジョン自動生成アルゴリズムのコーディング

#2

投稿記事 by beatle » 13年前

まず,アルゴリズムをここに書いて下さい.
書かないと,アルツハイマーさんが読んだアルゴリズムが何かなんて誰にも分かりません.

アルツハイマー

Re: ダンジョン自動生成アルゴリズムのコーディング

#3

投稿記事 by アルツハイマー » 13年前

beatle さんが書きました:まず,アルゴリズムをここに書いて下さい.
書かないと,アルツハイマーさんが読んだアルゴリズムが何かなんて誰にも分かりません.
↓最近は、ここのサイトです。↓
http://racanhack.sourceforge.jp/rhdoc/index.html

ただ、↑のサイトのコードをいじってみたのですが、

正常に動きません。
※スペースがないのに部屋を作ったり

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ダンジョン自動生成アルゴリズムのコーディング

#4

投稿記事 by softya(ソフト屋) » 13年前

今のコード見ないとなんとも言えないのでcodeタグを使って今のコードをここに貼りつけて下さい。投稿前にプレビューで動作を確認した上でお願いします。
http://dixq.net/board/board.html#k10 ← 詳しくはここに。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アルツハイマー

Re: ダンジョン自動生成アルゴリズムのコーディング

#5

投稿記事 by アルツハイマー » 13年前

softya(ソフト屋) さんが書きました:今のコード見ないとなんとも言えないのでcodeタグを使って今のコードをここに貼りつけて下さい。投稿前にプレビューで動作を確認した上でお願いします。
http://dixq.net/board/board.html#k10 ← 詳しくはここに。

コード:

#include "DxLib.h"		//Dxライブラリ ヘッダー
#include "main.h"			//main			ヘッダー
#include "keyboard.h"		//keyboard		ヘッダー
#include "graphics.h"		//graphics		ヘッダー
#include <stdlib.h>		//メモリー操作	ヘッダー

#define Rand( min, max ) GetRand( max ) + min		///乱数の範囲取得(int型)
#define WHITE GetColor( 255, 255, 255 )			///白色の取得

#define MAX_RECT_COUNT 4		///区間の最大数
#define MIN_RECT_SIZE 8			///区間の最小サイズ
#define MIN_ROOM_SIZE 4			///部屋の最小サイズ

#define MAP_WIDTH 50			///マップの幅
#define MAP_HEIGHT 50			///マップの高

int map[ MAP_WIDTH ][ MAP_HEIGHT ];		///マップ配列


typedef struct{
	int x, y, w, h;
} s_room;			///部屋の構造体 定義
typedef struct {
	int x, y, w, h;
	s_room room;
} s_rect;			///区間の構造体 定義

int roomCount = 0;			///部屋リスト数
s_room *room_list = NULL;	///部屋リスト
int rectCount = 0;			///区間リスト数
s_rect *rect_list = NULL;	///区間リスト

//部屋リストに追加
void roomList_append(s_room room)
{
	roomCount++;
	room_list = (s_room *)realloc( room_list, sizeof( s_room ) * roomCount );
	room_list[ roomCount - 1 ].x = room.x;
	room_list[ roomCount - 1 ].y = room.y;
	room_list[ roomCount - 1 ].w = room.w;
	room_list[ roomCount - 1 ].h = room.h;
}
//部屋の追加
s_room room_add( int x, int y, int w, int h )
{
	s_room room;
	room.x = x;
	room.y = y;
	room.w = w;
	room.h = h;
	roomList_append(room);
	return room;
}
//部屋の生成
void room_make( )
{
	s_rect rect;		///参照用
	int x, y, w, h;	///結果用
	for( int i = 0; i < rectCount; i++ )
	{
		rect = rect_list[ i ];
		w = Rand( MIN_ROOM_SIZE, rect.w - 3 );
		h = Rand( MIN_ROOM_SIZE, rect.h - 3 );
		x = Rand( rect.x + 2, rect.x + rect.w - w - 1 );
		y = Rand( rect.y + 2, rect.y + rect.h - h - 1 );
		rect_list[ i ].room = room_add( x, y, w, h );
	}
}
//区間リストに追加
void rectList_append(s_rect rect)
{
	rectCount++;
	rect_list = (s_rect *)realloc( rect_list, sizeof( s_rect ) * rectCount );
	rect_list[ rectCount - 1 ].x = rect.x;
	rect_list[ rectCount - 1 ].y = rect.y;
	rect_list[ rectCount - 1 ].w = rect.w;
	rect_list[ rectCount - 1 ].h = rect.h;
}
//区間の追加
s_rect rect_add( int x, int y, int w, int h )
{
	s_rect rect;
	rect.x = x;
	rect.y = y;
	rect.w = w;
	rect.h = h;
	rectList_append(rect);
	return rect;
}
//区間の生成
void rect_split( s_rect rect_parent )
{
	s_rect rect_child;
	
	if( ( rect_parent.h <= MIN_RECT_SIZE * 2 ) ||
		( rect_parent.w <= MIN_RECT_SIZE * 2 ) ||
		rectCount > MAX_RECT_COUNT)
		return;

	rect_child = rect_add( rect_parent.x, rect_parent.y, rect_parent.w, rect_parent.h );
	int split_coord;

	if( Rand( 0, 2 ) == 0 ){
		split_coord = Rand( rect_parent.y + MIN_RECT_SIZE, rect_parent.y + rect_parent.h - MIN_RECT_SIZE );
		rect_parent.h = split_coord - rect_parent.y;
		rect_child.y = split_coord;
		rect_split( rect_parent );
		rect_split( rect_child );
		return;
	} else{
		split_coord = Rand( rect_parent.x + MIN_RECT_SIZE, rect_parent.x + rect_parent.w - MIN_RECT_SIZE );
		rect_parent.w = split_coord - rect_parent.x;
		rect_child.x = split_coord;
		rect_split( rect_parent );
		rect_split( rect_child );
		return;
	}
}
//マップの生成
void mapCreate( void )
{
	int i, j, k;
	for ( j = 0; j < MAP_HEIGHT; j++)
		for ( i = 0; i < MAP_WIDTH; i++)
			map[ i ][ j ] = -1;

	rect_list = NULL;
	room_list = NULL;

	rect_split( rect_add( 0, 0, MAP_WIDTH - 1, MAP_HEIGHT - 1 ) );
//	rect_add( 0, 0, MAP_WIDTH - 1, MAP_HEIGHT - 1 );
//	room_make( );

	s_rect rect;
	s_room room;


	for( k = 0; k < rectCount; k++ ) {
		rect = rect_list[ k ];
		for ( i = rect.x, j = rect.y; i <= rect.x + rect.w; i++ ) map[ i ][ j ] = -2;
		for ( i = rect.x, j = rect.y + rect.h; i <= rect.x + rect.w; i++) map[ i ][ j ] = -2;
		for ( i = rect.x, j = rect.y; j <= rect.y + rect.h; j++) map[ i ][ j ] = -2;
		for ( i = rect.x + rect.w, j = rect.y; j <= rect.y + rect.h; j++) map[ i ][ j ] = -2;
		room = rect.room;
		for ( i = room.x; i <= room.x + room.w; i++ )
			for ( j = room.y; j <= room.y + room.h; j++ )
				map[ i ][ j ] = 0;
	}
//	for( k = 0; k < roomCount; k++ ) {
//		room = room_list[ k ];
//		for ( i = room.x; i <= room.x + room.w; i++ )
//			for ( j = room.y; j <= room.y + room.h; j++ )
//				map[ i ][ j ] = 0;
//	}

}



int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ){

	//ゲームの初期化
	MainInit( );			///メインゲームの初期化

	GraphicsInit( );		///グラフィックの初期化

	int l_fontHandle = CreateFontToHandle( "MS ゴシック", 15, -1 );

	mapCreate( );

	//ゲームの初期化

	//メインループ
	while( MainLoopCheck( ) ){		///メインループチェック
		for ( int j = 0; j < MAP_HEIGHT; j++)
			for ( int i = 0; i < MAP_WIDTH; i++){
				if ( map[ i ][ j ] == -1 )
					DrawStringToHandle( 15 * i, 15 * j, "■", WHITE,l_fontHandle );
				else if ( map[ i ][ j ] == -2 )
					DrawStringToHandle( 15 * i, 15 * j, "区", WHITE,l_fontHandle );
				else if ( map[ i ][ j ] == 0 )
					DrawStringToHandle( 15 * i, 15 * j, "床", WHITE,l_fontHandle );
			}
	}
	//メインループ

	//ゲームの終了処理
	GraphicsEnd( );			///グラフィックの終了処理

	MainEnd( );				///メインゲームの終了処理
	//ゲームの終了処理

	return 0;
}


アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ダンジョン自動生成アルゴリズムのコーディング

#6

投稿記事 by softya(ソフト屋) » 13年前

すいません。他の部分もないと動かないので他の部分もお願いします。
出来ればダンジョン生成部分にはコメントをお願いします。追いかけるのが結構辛いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アルツハイマー

Re: ダンジョン自動生成アルゴリズムのコーディング

#7

投稿記事 by アルツハイマー » 13年前

コード:

#include "DxLib.h"      //Dxライブラリ ヘッダー
#include <stdlib.h>     //メモリー操作    ヘッダー
 
#define Rand( min, max ) GetRand( max ) + min       ///乱数の範囲取得(int型)
#define WHITE GetColor( 255, 255, 255 )         ///白色の取得
 
#define MAX_RECT_COUNT 4        ///区間の最大数
#define MIN_RECT_SIZE 8         ///区間の最小サイズ
#define MIN_ROOM_SIZE 4         ///部屋の最小サイズ
 
#define MAP_WIDTH 50            ///マップの幅
#define MAP_HEIGHT 50           ///マップの高
 
int map[ MAP_WIDTH ][ MAP_HEIGHT ];     ///マップ配列
 
 
typedef struct{
    int x, y, w, h;
} s_room;           ///部屋の構造体 定義
typedef struct {
    int x, y, w, h;
    s_room room;
} s_rect;           ///区間の構造体 定義
 
int roomCount = 0;          ///部屋リスト数
s_room *room_list = NULL;   ///部屋リスト
int rectCount = 0;          ///区間リスト数
s_rect *rect_list = NULL;   ///区間リスト

//関数 メインループ継続のチェック
bool MainLoopCheck( void ){
	//裏画面を表画面に反映, メッセージ処理, 画面クリア
	return ScreenFlip( ) == 0 && ProcessMessage( ) == 0 && ClearDrawScreen( ) == 0;
} 
//部屋リストに追加
void roomList_append(s_room room)
{
    roomCount++;
    room_list = (s_room *)realloc( room_list, sizeof( s_room ) * roomCount );
    room_list[ roomCount - 1 ].x = room.x;
    room_list[ roomCount - 1 ].y = room.y;
    room_list[ roomCount - 1 ].w = room.w;
    room_list[ roomCount - 1 ].h = room.h;
}
//部屋の追加
s_room room_add( int x, int y, int w, int h )
{
    s_room room;
    room.x = x;
    room.y = y;
    room.w = w;
    room.h = h;
    roomList_append(room);
    return room;
}
//部屋の生成
void room_make( )
{
    s_rect rect;        ///参照用
    int x, y, w, h; ///結果用
    for( int i = 0; i < rectCount; i++ )
    {
        rect = rect_list[ i ];
        w = Rand( MIN_ROOM_SIZE, rect.w - 3 );
        h = Rand( MIN_ROOM_SIZE, rect.h - 3 );
        x = Rand( rect.x + 2, rect.x + rect.w - w - 1 );
        y = Rand( rect.y + 2, rect.y + rect.h - h - 1 );
        rect_list[ i ].room = room_add( x, y, w, h );
    }
}
//区間リストに追加
void rectList_append(s_rect rect)
{
    rectCount++;
    rect_list = (s_rect *)realloc( rect_list, sizeof( s_rect ) * rectCount );
    rect_list[ rectCount - 1 ].x = rect.x;
    rect_list[ rectCount - 1 ].y = rect.y;
    rect_list[ rectCount - 1 ].w = rect.w;
    rect_list[ rectCount - 1 ].h = rect.h;
}
//区間の追加
s_rect rect_add( int x, int y, int w, int h )
{
    s_rect rect;
    rect.x = x;
    rect.y = y;
    rect.w = w;
    rect.h = h;
    rectList_append(rect);
    return rect;
}
//区間の生成
void rect_split( s_rect rect_parent )
{
    s_rect rect_child;
    
    //生成中止条件
    if( ( rect_parent.h <= MIN_RECT_SIZE * 2 ) ||    //y軸方向のサイズが最小区間サイズの2倍以下
        ( rect_parent.w <= MIN_RECT_SIZE * 2 ) ||    //x軸方向のサイズが最小区間サイズの2倍以下
        rectCount > MAX_RECT_COUNT)                   //区間データ数が最大数よりおおきい
        return;

    //区間(子)の生成 
    rect_child = rect_add( rect_parent.x, rect_parent.y, rect_parent.w, rect_parent.h );

    //分割点
    int split_coord;
 
    if( Rand( 0, 2 ) == 0 ){
       //縦の分割
        split_coord = Rand( rect_parent.y + MIN_RECT_SIZE, rect_parent.y + rect_parent.h - MIN_RECT_SIZE );
        rect_parent.h = split_coord - rect_parent.y;
        rect_child.y = split_coord;
        rect_split( rect_parent );
        rect_split( rect_child );
        return;
    } else{
      //横の分割
        split_coord = Rand( rect_parent.x + MIN_RECT_SIZE, rect_parent.x + rect_parent.w - MIN_RECT_SIZE );
        rect_parent.w = split_coord - rect_parent.x;
        rect_child.x = split_coord;
        rect_split( rect_parent );
        rect_split( rect_child );
        return;
    }
}
//マップの生成
void mapCreate( void )
{
    int i, j, k;
     //マップの初期化
    for ( j = 0; j < MAP_HEIGHT; j++)
        for ( i = 0; i < MAP_WIDTH; i++)
            map[ i ][ j ] = -1;
 
    rect_list = NULL;
    room_list = NULL;
 
 //区間の生成
    rect_split( rect_add( 0, 0, MAP_WIDTH - 1, MAP_HEIGHT - 1 ) );
//  rect_add( 0, 0, MAP_WIDTH - 1, MAP_HEIGHT - 1 );
    //部屋の生成
    room_make( );
 
    s_rect rect;
    s_room room;
 
    //描画のための処理
    for( k = 0; k < rectCount; k++ ) {
        rect = rect_list[ k ];
      //「区」の処理
        for ( i = rect.x, j = rect.y; i <= rect.x + rect.w; i++ ) map[ i ][ j ] = -2;
        for ( i = rect.x, j = rect.y + rect.h; i <= rect.x + rect.w; i++) map[ i ][ j ] = -2;
        for ( i = rect.x, j = rect.y; j <= rect.y + rect.h; j++) map[ i ][ j ] = -2;
        for ( i = rect.x + rect.w, j = rect.y; j <= rect.y + rect.h; j++) map[ i ][ j ] = -2;
        room = rect.room;
      //「床」の処理
        for ( i = room.x; i <= room.x + room.w; i++ )
            for ( j = room.y; j <= room.y + room.h; j++ )
                map[ i ][ j ] = 0;
    }

}
 
 
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ){
 
    //ゲームの初期化
 	ChangeWindowMode( TRUE );			//TRUE・・・ウィンドウモード	FALSE・・・フルスクリーン

	SetGraphMode( 1024 , 768, 16 );			//1024×768のサイズで解像度16bitに設定

	DxLib_Init( );					//DXライブラリ初期化

	SetDrawScreen( DX_SCREEN_BACK );		//描画先を裏画面に設定

    int l_fontHandle = CreateFontToHandle( "MS ゴシック", 15, -1 );
 
    mapCreate( );
 
    //ゲームの初期化
 
    //メインループ
    while( MainLoopCheck( ) ){      ///メインループチェック
        for ( int j = 0; j < MAP_HEIGHT; j++)
            for ( int i = 0; i < MAP_WIDTH; i++){
                if ( map[ i ][ j ] == -1 )
                    DrawStringToHandle( 15 * i, 15 * j, "■", WHITE,l_fontHandle );
                else if ( map[ i ][ j ] == -2 )
                    DrawStringToHandle( 15 * i, 15 * j, "区", WHITE,l_fontHandle );
                else if ( map[ i ][ j ] == 0 )
                    DrawStringToHandle( 15 * i, 15 * j, "床", WHITE,l_fontHandle );
            }
    }
    //メインループ
 
    //ゲームの終了処理
	DxLib_End( );						//DXライブラリ終了
    //ゲームの終了処理
 
    return 0;
}

non
記事: 1097
登録日時: 14年前

Re: ダンジョン自動生成アルゴリズムのコーディング

#8

投稿記事 by non » 13年前

添付されたプログラムを実行してみました。
わかりやすいように色をつけましたが。
うまくいかないのはどの部分ですか?
床は、わかるけど、■と区はどういう意味ですか?
添付ファイル
map.jpg
non

non
記事: 1097
登録日時: 14年前

Re: ダンジョン自動生成アルゴリズムのコーディング

#9

投稿記事 by non » 13年前

返事がいただけないので、自分でプログラムを読みました。
特に、w,hの考え方がオリジナルと違っており、その考え方ではマズイのではないだろうかと思います。
non

アルツハイマー

Re: ダンジョン自動生成アルゴリズムのコーディング

#10

投稿記事 by アルツハイマー » 13年前

non さんが書きました:返事がいただけないので、自分でプログラムを読みました。
特に、w,hの考え方がオリジナルと違っており、その考え方ではマズイのではないだろうかと思います。
では、オリジナルに沿って作ってみようと思います。

non
記事: 1097
登録日時: 14年前

Re: ダンジョン自動生成アルゴリズムのコーディング

#11

投稿記事 by non » 13年前

再帰呼び出しにおける構造体の引数も、ポインタ渡しでないとマズイです。

#define Rand( min, max ) GetRand( max ) + min
これもマズイです。
non

閉鎖

“C言語何でも質問掲示板” へ戻る