private IEnumerable <Point> GetBreakingWalls(ClosedArea ca) { Fill(ca.Pt.X, ca.Pt.Y, 2); //OutputToImageFile(); // 途中経過 for (int x = 1; x < Map_W - 1; x++) { for (int y = 1; y < Map_H - 1; y++) { if ( Map[x - 1, y] == 0 || Map[x + 1, y] == 0 || Map[x, y + 1] == 0 || Map[x, y - 1] == 0 ) { if ( Map[x - 1, y] == 2 || Map[x + 1, y] == 2 || Map[x, y + 1] == 2 || Map[x, y - 1] == 2 ) { yield return(new Point(x, y)); } } } } Fill(ca.Pt.X, ca.Pt.Y, 0); // 復元 }
/// <summary> /// ダンジョンマップを作る。 /// </summary> /// <param name="w">マップの幅</param> /// <param name="h">マップの高さ</param> public DungeonMap MakeDungeonMap(int w, int h, int seed) { if (seed == 0) { seed = (int)(DateTimeToSec.Now.GetSec() % IntTools.IMAX); } Rand = new Random(seed); Map_W = w; Map_H = h; Map_Seed = seed; Map = MakeLikeADungeonMap(24); // pattern == 24 //OutputToImageFile(); // 初期状態 for (; ;) // 全ての通路を繋げる。 { Point[] cps = AllClosedAreaPoints().ToArray(); if (cps.Length == 1) // ? 全ての通路が繋がった。 { break; } ClosedArea[] cas = AllClosedAreas(cps).ToArray(); Array.Sort(cas, (a, b) => a.Size - b.Size); // 狭い順 ClosedArea ca = cas[0]; // 最も狭い空間を選択 Point[] breakingWalls = GetBreakingWalls(ca).ToArray(); // 選択された空間の破壊可能な(厚さ1枚の)壁を列挙 if (breakingWalls.Length == 0) // ? 破壊可能な壁が無い。⇒ この空間は壁で埋める。 { Fill(ca.Pt.X, ca.Pt.Y, 1); //OutputToImageFile(); // 途中経過 continue; } Point breakingWall = breakingWalls[Rand.Next(breakingWalls.Length)]; // ランダムに選択 Map[breakingWall.X, breakingWall.Y] = 0; // 壁を破壊 //OutputToImageFile(); // 途中経過 //Fill(breakingWall.X, breakingWall.Y, 2); // 途中経過用に塗りつぶし //OutputToImageFile(); // 途中経過 //Fill(breakingWall.X, breakingWall.Y, 0); // 復元 //OutputToImageFile(); // 途中経過 } // スタート地点とゴール地点を設置 { Point[] pts = AllPoints().Where(p => Map[p.X, p.Y] == 0).ToArray(); Point startPt = default(Point); Point goalPt = pts[Rand.Next(pts.Length)]; // 適当な通路から開始 for (int c = 0; c < 10; c++) // スタート地点から最も遠い場所、そこから最も遠い場所、そこから最も遠い場所 ... と何回か繰り返す。 { startPt = goalPt; pts = Farthest(startPt); goalPt = pts[Rand.Next(pts.Length)]; } Map[startPt.X, startPt.Y] = 2; // スタート地点を設置 Map[goalPt.X, goalPt.Y] = 2; // ゴール地点を設置 } //OutputToImageFile(); // 結果 return(ToDungeonMap()); }