1.5. 部屋を作ろう

迷路の骨組みができてきたようです。次に、この区画のそれぞれに、部屋をひとつずつ作ります。

まずは、部屋を追加する関数を書きます。


struct _room {
  int lx, ly, hx, hy;
};

GList *room_list;

struct _room *room_add(int lx, int ly, int hx, int hy)
{
  struct _room *room;
  room = g_new(struct _room, 1);
  room->lx = lx;
  room->ly = ly;
  room->hx = hx;
  room->hy = hy;
  room_list = g_list_append(room_list, room);
  return(room);
}

部屋をひとつずつ作る関数room_make()を書きます。


enum {
  MINIMUM_ROOM_SIZE = 4,
  MARGIN_BETWEEN_RECT_ROOM = 2,
  MINIMUM_RECT_SIZE = MINIMUM_ROOM_SIZE + (MARGIN_BETWEEN_RECT_ROOM * 2)
};

struct _rect {
  int lx, ly, hx, hy;
  struct _room *room;
};

static void room_make()
{
  GList *li;
  struct _rect *rect;
  int x, y, w, h;
  for (li = g_list_first(rect_list); li != NULL; li = g_list_next(li)) {
    rect = (struct _rect *)li->data;
    w = g_random_int_range(MINIMUM_ROOM_SIZE, rect->hx - rect->lx - (MARGIN_BETWEEN_RECT_ROOM * 2) + 1);
    h = g_random_int_range(MINIMUM_ROOM_SIZE, rect->hy - rect->ly - (MARGIN_BETWEEN_RECT_ROOM * 2) + 1);
    x = g_random_int_range(rect->lx + MARGIN_BETWEEN_RECT_ROOM, rect->hx - MARGIN_BETWEEN_RECT_ROOM - w + 1);
    y = g_random_int_range(rect->ly + MARGIN_BETWEEN_RECT_ROOM, rect->hy - MARGIN_BETWEEN_RECT_ROOM - h + 1);
    rect->room = room_add(x, y, x + w, y + h);
  };
}

関数map_printに、部屋のところを"#"で塗りつぶすように以下のコードを加えます。


  for (li = g_list_first(room_list); li != NULL; li = g_list_next(li)) {
    room = (struct _room *)li->data;
    for (i = room->lx; i <= room->hx; i++) {
      for (j = room->ly; j <= room->hy; j++) {
      	map[i][j] = TRUE;
      };
    };
  };

最終的にこうなります。


#include <glib.h>

enum {
  MAP_W = 50,
  MAP_H = 40,
  MINIMUM_ROOM_SIZE = 4,
  MARGIN_BETWEEN_RECT_ROOM = 2,
  MINIMUM_RECT_SIZE = MINIMUM_ROOM_SIZE + (MARGIN_BETWEEN_RECT_ROOM * 2)
};

struct _rect {
  int lx, ly, hx, hy;
  struct _room *room;
};

struct _room {
  int lx, ly, hx, hy;
};

GList *rect_list;
GList *room_list;
gboolean map[MAP_W][MAP_H];

void map_print();
void rect_split(struct _rect *rect_parent);
void room_make();
struct _rect *rect_add(int lx, int ly, int hx, int hy);
struct _room *room_add(int lx, int ly, int hx, int hy);

int main(int argc, char *argv[])
{
  int i, j;
  for (j = 0; j < MAP_H; j++) {
    for (i = 0; i < MAP_W; i++) {
      map[i][j] = FALSE;
    };
  };
  rect_list = NULL;
  room_list = NULL;
  rect_split(rect_add(0, 0, MAP_W - 1, MAP_H - 1));
  room_make();
  map_print();
  return 0;
}

void map_print()
{
  int i, j;
  GList *li;
  struct _rect *rect;
  struct _room *room;
  for (li = g_list_first(rect_list); li != NULL; li = g_list_next(li)) {
    rect = (struct _rect *)li->data;
    for (i = rect->lx, j = rect->ly; i <= rect->hx; i++) map[i][j] = TRUE;
    for (i = rect->lx, j = rect->hy; i <= rect->hx; i++) map[i][j] = TRUE;
    for (i = rect->lx, j = rect->ly; j <= rect->hy; j++) map[i][j] = TRUE;
    for (i = rect->hx, j = rect->ly; j <= rect->hy; j++) map[i][j] = TRUE;
  };
  for (li = g_list_first(room_list); li != NULL; li = g_list_next(li)) {
    room = (struct _room *)li->data;
    for (i = room->lx; i <= room->hx; i++) {
      for (j = room->ly; j <= room->hy; j++) {
      	map[i][j] = TRUE;
      };
    };
  };
  for (j = 0; j < MAP_H; j++) { 
    for (i = 0; i < MAP_W; i++) {
      if (map[i][j]) g_print("#"); else g_print(".");
    }; 
    g_print("\n"); 
  }; 

} 

void rect_split(struct _rect *rect_parent)
{
  struct _rect *rect_child;
  if ((rect_parent->hy - rect_parent->ly <= MINIMUM_RECT_SIZE * 2) ||
      (rect_parent->hx - rect_parent->lx <= MINIMUM_RECT_SIZE * 2)) {
    return;
  };
  rect_child = rect_add(rect_parent->lx, rect_parent->ly,
			rect_parent->hx, rect_parent->hy);
  if (g_random_int_range(0, 2) == 0) {
    int split_coord_y;
    split_coord_y = g_random_int_range(rect_parent->ly + MINIMUM_RECT_SIZE, rect_parent->hy - MINIMUM_RECT_SIZE);
    rect_parent->hy = split_coord_y;
    rect_child->ly = split_coord_y;
    rect_split(rect_parent);
    rect_split(rect_child);
    return;
  }  else {
    int split_coord_x;
    split_coord_x = g_random_int_range(rect_parent->lx + MINIMUM_RECT_SIZE, rect_parent->hx - MINIMUM_RECT_SIZE);
    rect_parent->hx = split_coord_x;
    rect_child->lx = split_coord_x;
    rect_split(rect_parent);
    rect_split(rect_child);
    return;
  };
}

void room_make()
{
  GList *li;
  struct _rect *rect;
  int x, y, w, h;
  for (li = g_list_first(rect_list); li != NULL; li = g_list_next(li)) {
    rect = (struct _rect *)li->data;
    w = g_random_int_range(MINIMUM_ROOM_SIZE, rect->hx - rect->lx - (MARGIN_BETWEEN_RECT_ROOM * 2) + 1);
    h = g_random_int_range(MINIMUM_ROOM_SIZE, rect->hy - rect->ly - (MARGIN_BETWEEN_RECT_ROOM * 2) + 1);
    x = g_random_int_range(rect->lx + MARGIN_BETWEEN_RECT_ROOM, rect->hx - MARGIN_BETWEEN_RECT_ROOM - w + 1);
    y = g_random_int_range(rect->ly + MARGIN_BETWEEN_RECT_ROOM, rect->hy - MARGIN_BETWEEN_RECT_ROOM - h + 1);
    rect->room = room_add(x, y, x + w, y + h);
  };
}

struct _rect *rect_add(int lx, int ly, int hx, int hy)
{
  struct _rect *rect;
  rect = g_new(struct _rect, 1);
  rect->lx = lx;
  rect->ly = ly;
  rect->hx = hx;
  rect->hy = hy;
  rect_list = g_list_append(rect_list, rect);
  return(rect);
}

struct _room *room_add(int lx, int ly, int hx, int hy)
{
  struct _room *room;
  room = g_new(struct _room, 1);
  room->lx = lx;
  room->ly = ly;
  room->hx = hx;
  room->hy = hy;
  room_list = g_list_append(room_list, room);
  return(room);
}

出力はこのようになります。

[user@machine ~/dir]$ ./test
##################################################
#...........#....................................#
#...........#....................................#
#...........#....................................#
#...........#....................................#
#...........#....................................#
#...........#.................###############....#
#.######....#.................###############....#
#.######....#.................###############....#
#.######....#.................###############....#
#.######....#.................###############....#
#.######....#.................###############....#
#.######....#.................###############....#
#.######....#....................................#
#.######....#....................................#
#.######....#....................................#
#.######....######################################
#.######....#........................#...........#
#.######....#........................#....######.#
#.######....#........................#....######.#
#.######....#.####################...#....######.#
#.######....#.####################...#....######.#
#.######....#.####################...#....######.#
#.######....#.####################...#....######.#
#.######....#.####################...#....######.#
#.######....#........................#....######.#
#.######....#........................#....######.#
#.######....##########################....######.#
#.######....#........................#....######.#
#.######....#........................#....######.#
#...........#........................#....######.#
#...........#........................#....######.#
#...........#........................#....######.#
#...........#.........######.........#....######.#
#...........#.........######.........#....######.#
#...........#.........######.........#....######.#
#...........#.........######.........#....######.#
#...........#.........######.........#...........#
#...........#........................#...........#
##################################################

上の出力を見ながら、どうやって部屋と部屋を通路でつなぐかを、考えてみてください。