Example #1
0
        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);             // 復元
        }
Example #2
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());
        }