protected override void Generate()
        {
            Stack <IMazeCell> back_tracker = new Stack <IMazeCell>();

            //把起点塞进去
            back_tracker.Push(cells[0]);

            //如果栈空了,表示迷宫完成了。
            while (back_tracker.Count > 0)
            {
                //寻找栈顶元素
                IMazeCell start_node = back_tracker.Peek();

                //直接选择出,没访问过,且不连通的点。注意,不连通,但是有可能是已经访问过的,没访问过,一定不连通!
                EMazeDirection move_dir = start_node.GenRandomNeighbourDirection(ESelectCondition.NoVisited);

                //如果这个点的周围都已经访问过来,开始回溯,每次遍历回溯一格。直到找到下一个,周围有没访问过的点的节点。
                if (move_dir == EMazeDirection.Invalid)
                {
                    back_tracker.Pop();
                    continue;
                }

                //点周围有没访问过,也没联通的点
                start_node.ConnectionTo(move_dir);
                back_tracker.Push(start_node.GetNeighbour(move_dir));
            }
        }
Exemple #2
0
        public override void PostProcess(MazeAlgorithm maze_algorithm)
        {
            int size_x = maze_algorithm.size_x;
            int size_y = maze_algorithm.size_y;

            for (int iy = 0; iy < size_y; iy++)
            {
                for (int ix = 0; ix < size_x; ix++)
                {
                    IMazeCell cell = maze_algorithm.GetAt(ix, iy);
                    if (cell != null && cell.ConnectionCount == 1 && Random.Range(0.0f, 1.0f) < braidingrate)
                    {
                        for (int i = 0; i < (int)EMazeDirection.DirectionCount; i++)
                        {
                            EMazeDirection dir = (EMazeDirection)i;

                            //尚未联通的点
                            if (cell.IsConnectedTo(dir) == true)
                            {
                                //只做反向联通,确保不会出现孤点
                                EMazeDirection inverse_dir = MazeAlgorithm.InvertDirection(dir);
                                IMazeCell      invert_cell = cell.GetNeighbour(inverse_dir);
                                if (invert_cell != null)
                                {
                                    cell.ConnectionTo(inverse_dir);
                                }
                            } //END OF IF Connected to
                        }     //END OF FOR Neighbours
                    }         //END OF IF Test Cell
                }
            }
        }
        /// <summary>
        /// From given maze and cell, whose coordinates correlate to a cell in maze,
        /// its adjacent cells of type wall extracted an returned.
        /// </summary>
        /// <param name="maze">Maze as two dimensional array of IMazeCell objects.</param>
        /// <param name="cell">IMazeCell object.</param>
        /// <returns>A collection of IMazeCell objects.</returns>
        private List <IMazeCell> GetAdjacentWallCells(IMazeCell[,] maze, IMazeCell cell)
        {
            var neighbours = new List <IMazeCell>();

            if (cell.Position.Row - 1 >= 0 && maze[cell.Position.Row - 1, cell.Position.Col].IsWall)
            {
                neighbours.Add(maze[cell.Position.Row - 1, cell.Position.Col]);
            }

            if (cell.Position.Row + 1 < maze.GetLength(0) && maze[cell.Position.Row + 1, cell.Position.Col].IsWall)
            {
                neighbours.Add(maze[cell.Position.Row + 1, cell.Position.Col]);
            }

            if (cell.Position.Col - 1 >= 0 && maze[cell.Position.Row, cell.Position.Col - 1].IsWall)
            {
                neighbours.Add(maze[cell.Position.Row, cell.Position.Col - 1]);
            }

            if (cell.Position.Col + 1 < maze.GetLength(1) && maze[cell.Position.Row, cell.Position.Col + 1].IsWall)
            {
                neighbours.Add(maze[cell.Position.Row, cell.Position.Col + 1]);
            }

            return(neighbours);
        }
Exemple #4
0
        /// <summary>
        /// Checks if a cell borders with exactly one path cell, having respectively the rest of its neighbors as walls.
        /// </summary>
        /// <param name="maze">Maze as two dimensional array of IMazeCell objects.</param>
        /// <param name="cell">IMazeCell object.</param>
        /// <returns>A boolean value, depending on whether the condition is fulfilled.</returns>
        private bool HasOnlyOneAdjacentPathCell(IMazeCell[,] maze, IMazeCell cell)
        {
            int adjacentPathCells = 0;

            if (cell.Position.Row - 1 >= 0 && !maze[cell.Position.Row - 1, cell.Position.Col].IsWall)
            {
                adjacentPathCells++;
            }

            if (cell.Position.Row + 1 < maze.GetLength(0) && !maze[cell.Position.Row + 1, cell.Position.Col].IsWall)
            {
                adjacentPathCells++;
            }

            if (cell.Position.Col - 1 >= 0 && !maze[cell.Position.Row, cell.Position.Col - 1].IsWall)
            {
                adjacentPathCells++;
            }

            if (cell.Position.Col + 1 < maze.GetLength(1) && !maze[cell.Position.Row, cell.Position.Col + 1].IsWall)
            {
                adjacentPathCells++;
            }

            return(adjacentPathCells == 1);
        }
Exemple #5
0
        void Kill(int visited, IMazeCell start_point)
        {
            if (visited <= cells.Count)
            {
                do
                {
                    EMazeDirection move_dir = start_point.GenRandomNeighbourDirection(ESelectCondition.NoVisited);

                    if (move_dir == EMazeDirection.Invalid)
                    {
                        break;
                    }
                    IMazeCell next = start_point.GetNeighbour(move_dir);

                    start_point.ConnectionTo(move_dir);
                    start_point = next;
                    visited++;
                }while(true);

                //finish kill begin hunt.
                if (visited < cells.Count)
                {
                    Hunt(visited);
                }
            }
        }
Exemple #6
0
        void Hunt(int visited)
        {
            IMazeCell hunt_result = null;

            for (int iy = size_y - 1; iy >= 0; iy--)
            //for (int iy = 0; iy < size_y;iy++ )
            {
                for (int ix = 0; ix < size_x; ix++)
                //for (int ix = size_x-1; ix >=0; ix--)
                {
                    hunt_result = GetAt(ix, iy);

                    //hunt result 必须是一个未访问过的点,并且他要链接一个已经访问过的点(隐含一定不会连接)
                    if (hunt_result.ConnectionCount == 0)
                    {
                        EMazeDirection dir = hunt_result.GenRandomNeighbourDirection(ESelectCondition.Visited);

                        if (dir != EMazeDirection.Invalid)
                        {
                            hunt_result.ConnectionTo(dir);
                            visited++;
                            Kill(visited, hunt_result);
                            break;
                        }
                    }
                }
            }
        }
Exemple #7
0
        public IMazeCell[,] InitializeMaze(int HorizontalSize, int VerticalSize)
        {
            IMazeCell[,] generatedMaze = new IMazeCell[HorizontalSize, VerticalSize];
            for (int i = 0; i < HorizontalSize; i++)
            {
                for (int j = 0; j < VerticalSize; j++)
                {
                    generatedMaze[i, j]           = new MazeCell();
                    generatedMaze[i, j].Value     = (int)MazeCellValueEnum.Wall;
                    generatedMaze[i, j].PositionX = i;
                    generatedMaze[i, j].PositionY = j;

                    if (i == 0)
                    {
                        generatedMaze[i, j].Value = (int)MazeCellValueEnum.WallBorder;
                    }

                    if (j == 0)
                    {
                        generatedMaze[i, j].Value = (int)MazeCellValueEnum.WallBorder;
                    }

                    if (i == HorizontalSize - 1)
                    {
                        generatedMaze[i, j].Value = (int)MazeCellValueEnum.WallBorder;
                    }

                    if (j == VerticalSize - 1)
                    {
                        generatedMaze[i, j].Value = (int)MazeCellValueEnum.WallBorder;
                    }
                }
            }
            return(generatedMaze);
        }
        /// <summary>
        /// 注意:该算法对不规则图形非常不友好,如果一定要应用到不规则图形
        /// 需要做很多修改,因此建议直接禁止本算法应用到不规则图形上去。
        /// </summary>
        protected override void Generate()
        {
            List <IMazeCell>      temp_cell_collection = new List <IMazeCell>();
            List <EMazeDirection> filter_dir           = new List <EMazeDirection>();

            filter_dir.Add(EMazeDirection.North);
            filter_dir.Add(EMazeDirection.East);

            for (int iy = 0; iy < size_y; iy++)
            {
                for (int ix = 0; ix < size_x; ix++)
                {
                    IMazeCell cell = GetAt(ix, iy);
                    //尽管如此,还是可以利用fiter做一波优化,去掉重复代码!
                    EMazeDirection move_dir = cell.GenRandomNeighbourDirection(ESelectCondition.None, filter_dir);
                    if (move_dir == EMazeDirection.North)
                    {
                        temp_cell_collection.Add(cell);
                        IMazeCell dig_cell = temp_cell_collection[Random.Range(0, temp_cell_collection.Count)];
                        dig_cell.ConnectionTo(EMazeDirection.North);
                        temp_cell_collection.Clear();
                    }
                    else if (move_dir == EMazeDirection.East)
                    {
                        temp_cell_collection.Add(cell);
                        cell.ConnectionTo(EMazeDirection.East);
                    }
                }
            }
        }
Exemple #9
0
        /// <summary>
        /// 返回值可以为Null,null表示邻居为迷宫边界,或是邻居没有被初始化
        /// </summary>
        /// <param name="direction"></param>
        /// <returns>null means no neighbour or not successefully inited.</returns>
        public IMazeCell GetNeighbour(EMazeDirection direction)
        {
            IMazeCell output = null;

            neighbours.TryGetValue(direction, out output);
            return(output);
        }
Exemple #10
0
        protected void Infect(int new_group_id, IMazeCell to)
        {
            int old_group_id = to.GroupID;
            Stack <IMazeCell> infect_stack = new Stack <IMazeCell>();

            to.GroupID = new_group_id;
            infect_stack.Push(to);

            //if stack is not null.
            while (infect_stack.Count > 0)
            {
                //find stack top
                IMazeCell        top        = infect_stack.Pop();
                List <IMazeCell> neighbours = top.Neighbours;

                //for all top`s neighbours.
                for (int i = 0; i < neighbours.Count; i++)
                {
                    //if belong to old group.
                    if (neighbours[i].GroupID == old_group_id)
                    {
                        //merge to new group go on to find with it`s neighbours untill no new neighbour is added.
                        neighbours[i].GroupID = new_group_id;
                        infect_stack.Push(neighbours[i]);
                    }
                }
            }
        }
        protected override void Generate()
        {
            IMazeCell random_start = GetRandomCell();
            int       visited      = 1;

            while (visited < cells.Count)
            {
                EMazeDirection valid        = random_start.GenRandomNeighbourDirection();
                IMazeCell      pending_next = random_start.GetNeighbour(valid);

                if (pending_next != null)
                {
                    //言外之意,没被访问过
                    //means, not visited.
                    if (pending_next.ConnectionCount == 0)
                    {
                        random_start.ConnectionTo(valid);
                        random_start = pending_next;
                        visited++;
                    }
                    else
                    {
                        random_start = pending_next;
                        continue;
                    }
                }
            }
        }
Exemple #12
0
        public void BuildMaze <T>(int x_size, int y_size) where T : IMazeCell
        {
            this.size_x = x_size;
            this.size_y = y_size;

            cells.Capacity = size_x * size_y;

            int group_id = 0;

            //FIRST PASS
            for (int iy = 0; iy < size_y; iy++)
            {
                for (int ix = 0; ix < size_x; ix++)
                {
                    if (maze_mask_cells != null && maze_mask_cells.Contains(SharedUtil.PointHash(ix, iy)))
                    {
                        cells.Add(null);
                    }
                    else
                    {
                        T cell = System.Activator.CreateInstance <T>();
                        cell.X       = ix;
                        cell.Y       = iy;
                        cell.GroupID = group_id++;
                        cells.Add(cell);
                    }
                }
            }

            //SECOND PASS
            for (int iy = 0; iy < size_y; iy++)
            {
                for (int ix = 0; ix < size_x; ix++)
                {
                    IMazeCell cell = GetAt(ix, iy);
                    if (cell != null)
                    {
                        IMazeCell[] neighbours = new IMazeCell[4];
                        neighbours[(int)EMazeDirection.North] = GetAt(ix, iy + 1);
                        neighbours[(int)EMazeDirection.South] = GetAt(ix, iy - 1);
                        neighbours[(int)EMazeDirection.West]  = GetAt(ix - 1, iy);
                        neighbours[(int)EMazeDirection.East]  = GetAt(ix + 1, iy);
                        cell.SetNeighbours(neighbours);
                    }
                }
            }

            Generate();

            for (int i = 0; i < post_processer.Count; i++)
            {
                if (post_processer[i] != null)
                {
                    post_processer[i].PostProcess(this);
                }
            }
        }
Exemple #13
0
        //1-寻找任意点A,作为目标点,标记为Visited。
        //2-寻找任意点B,作为起始点。
        //3-从B寻找A,找到非闭合路径,将路径挖通,并且标记为Visited
        //4-遇到闭合路径,从新挖。
        //5-随机找B2,重复过程
        //6-直到所有的点都被访问过
        protected override void Generate()
        {
            //注意,一个格子,要么在Unvisited 里面,要么在Visited里面
            //所以这里不需要两个数组,实际上,Visited的记录是毫无意义的。
            //更重要的是Unvisited里面还剩什么。
            //而判断 visited.Contain( x ) 的等价命题是 unvisited.Contain( x ) == false
            //这样起码可以节省一半的内存空间
            List <IMazeCell> unvisited = new List <IMazeCell>(cells);
            List <IMazeCell> temp_path = new List <IMazeCell>();

            IMazeCell first = unvisited[Random.Range(0, unvisited.Count)];

            unvisited.Remove(first);

            IMazeCell random_start = unvisited[Random.Range(0, unvisited.Count)];

            while (unvisited.Count > 0)
            {
                temp_path.Clear();
                temp_path.Add(random_start);

                while (true)
                {
                    //如果有强烈需求,可以考虑增加接口,暂时先这样做。
                    EMazeDirection dir  = temp_path[temp_path.Count - 1].GenRandomNeighbourDirection();
                    IMazeCell      next = temp_path[temp_path.Count - 1].GetNeighbour(dir);

                    //没有形成环路
                    if (unvisited.Contains(next) == false)
                    {
                        //开始联通了
                        temp_path.Add(next);

                        for (int i = 0; i < temp_path.Count - 1; i++)
                        {
                            unvisited.Remove(temp_path[i]);
                            temp_path[i].ConnectionTo(temp_path[i].LastRandomNeibourDirection);
                        }

                        if (unvisited.Count > 0)
                        {
                            random_start = unvisited[Random.Range(0, unvisited.Count)];
                        }
                        break;
                    }
                    //形成了环路
                    else if (temp_path.Contains(next) == true)
                    {
                        break;
                    }

                    temp_path.Add(next);
                }
            }
        }
Exemple #14
0
        protected override void Generate()
        {
            //Use GroupID as COST !!!!
            List <IMazeCell> actived = new List <IMazeCell>(cells);

            //Make sure each cell has different priority.
            while (actived.Count > 1)
            {
                IMazeCell random = actived[Random.Range(0, actived.Count)];
                random.GroupID = actived.Count + 1;
                actived.Remove(random);
            }

            List <IMazeCell>      candidate = new List <IMazeCell>(actived[0].Neighbours);
            List <EMazeDirection> candidate_connect_direction = new List <EMazeDirection>((int)EMazeDirection.DirectionCount);

            //actived now has only one element in it, active[0]. it do not need to have a priority
            while (actived.Count < cells.Count)
            {
                IMazeCell min = candidate[0];
                for (int i = 0; i < candidate.Count; i++)
                {
                    if (min.GroupID > candidate[i].GroupID)
                    {
                        min = candidate[i];
                    }
                }

                candidate.Remove(min);

                candidate_connect_direction.Clear();
                for (int i = 0; i < (int)EMazeDirection.DirectionCount; i++)
                {
                    EMazeDirection dir       = (EMazeDirection)i;
                    IMazeCell      neighbour = min.GetNeighbour(dir);
                    if (neighbour != null)
                    {
                        if (actived.Contains(neighbour) == true)
                        {
                            candidate_connect_direction.Add(dir);
                        }
                        else
                        {
                            if (candidate.Contains(neighbour) == false)
                            {
                                candidate.Add(neighbour);
                            }
                        }
                    }
                }

                min.ConnectionTo(candidate_connect_direction[Random.Range(0, candidate_connect_direction.Count)]);
                actived.Add(min);
            }
        }
Exemple #15
0
        protected override void Generate()
        {
            List <IMazeCell> actived = new List <IMazeCell>();

            actived.Add(GetRandomCell());

            List <EMazeDirection> candidate_connect_direction = new List <EMazeDirection>((int)EMazeDirection.DirectionCount);

            while (actived.Count > 0)
            {
                IMazeCell random = null;

                switch (shample_type)
                {
                case EGrowingTreeShampleType.Rand:
                    random = actived[Random.Range(0, actived.Count)];
                    break;

                case EGrowingTreeShampleType.Last:
                    random = actived[actived.Count - 1];
                    break;

                case EGrowingTreeShampleType.Rand_Last:
                    random = Random.Range(0, 2) == 0?  actived[Random.Range(0, actived.Count)]: actived[actived.Count - 1];
                    break;
                }

                candidate_connect_direction.Clear();
                for (int i = 0; i < (int)EMazeDirection.DirectionCount; i++)
                {
                    EMazeDirection dir       = (EMazeDirection)i;
                    IMazeCell      neighbour = random.GetNeighbour(dir);
                    if (neighbour != null && neighbour.ConnectionCount == 0)
                    {
                        candidate_connect_direction.Add(dir);
                    }
                }

                if (candidate_connect_direction.Count > 0)
                {
                    EMazeDirection select_dir = candidate_connect_direction[Random.Range(0, candidate_connect_direction.Count)];
                    actived.Add(random.GetNeighbour(select_dir));
                    random.ConnectionTo(select_dir);
                }
                else
                {
                    actived.Remove(random);
                }
            }
        }
Exemple #16
0
        /// <summary>
        /// 研究这个算法的时候,遇到了一些坑
        /// 主要是我想偷懒,一开始,没用到记录使用过的 连接点的策略
        /// 而是试图,用算法算出来
        /// 但是,不论通过:A - 统计连接,B-统计GroupID是否一致,都无法正确的算出一个点,是否被用过。
        /// 如果
        ///
        /// 1|1
        /// 1 1
        ///
        /// 用GroupID来判断。很有可能一个没用过的点,被当成用过的了。错误
        /// 用Connection来判断。一个已经用过的点,会反复被当成没用过的来多次计算。
        /// 于是,最终还是回到了相对浪费空间的一种算法。那就是
        ///
        /// 用两个Int型数组,记录所有使用过的连接点的 Hash结果。然后下次寻找的时候,发现已经用过的,直接跨过。
        /// 事实上我们必须这么做,否则就算你记录每个Group为一个List,也不能保证不犯上面的错误。除非,你记录两套GroupLists
        /// 一套为水平扫描准备。
        /// 一套为垂直扫描准备。
        /// 但是这两套,空间消耗都太大,并且反复创建List,GC开销也是蛮大的。所以最终结果,还是用现在的方式。
        ///
        /// 分析一下,这种算法不是使用随机连接某个点的方式计算迷宫的,所以不适合任意形状的迷宫
        /// 但是,他特别适合生成 Waving Maze
        /// </summary>
        protected override void Generate()
        {
            int horizon_merge  = size_x - 1;
            int vertical_merge = size_y - 1;

            List <int> used_horizon  = new List <int>();
            List <int> used_vertical = new List <int>();

            //先横向融合,再纵向融合,为一个Loop,知道所有的格子都被合在一起。
            while (horizon_merge > 0 || vertical_merge > 0)
            {
                if (horizon_merge > 0)
                {
                    //horizon merge,loop every row
                    for (int i = 0; i < size_y; i++)
                    {
                        int       rand_num    = Random.Range(0, horizon_merge);
                        IMazeCell start_merge = FindRandomMergeStartCell(rand_num, true, i, used_horizon);
                        used_horizon.Add(SharedUtil.PointHash(start_merge.X, start_merge.Y));

                        if (start_merge.GroupID != start_merge.GetNeighbour(EMazeDirection.East).GroupID)
                        {
                            Infect(start_merge.GroupID, start_merge.GetNeighbour(EMazeDirection.East));
                            start_merge.ConnectionTo(EMazeDirection.East);
                        }
                    }
                    horizon_merge--;
                }

                if (vertical_merge > 0)
                {
                    for (int i = 0; i < size_x; i++)
                    {
                        int       rand_num    = Random.Range(0, vertical_merge);
                        IMazeCell start_merge = FindRandomMergeStartCell(rand_num, false, i, used_vertical);
                        used_vertical.Add(SharedUtil.PointHash(start_merge.X, start_merge.Y));

                        if (start_merge.GroupID != start_merge.GetNeighbour(EMazeDirection.North).GroupID)
                        {
                            Infect(start_merge.GroupID, start_merge.GetNeighbour(EMazeDirection.North));
                            start_merge.ConnectionTo(EMazeDirection.North);
                        }
                    }
                    vertical_merge--;
                }
            }
        }
        public override void PostProcess(MazeAlgorithm maze_algorithm)
        {
            int size_x = maze_algorithm.size_x;
            int size_y = maze_algorithm.size_y;

            for (int iy = 0; iy < size_y; iy++)
            {
                for (int ix = 0; ix < size_x; ix++)
                {
                    IMazeCell cell = maze_algorithm.GetAt(ix, iy);

                    //Dead Ends
                    if (cell != null && cell.ConnectionCount == 1 && Random.Range(0.0f, 1.0f) < braidingrate)
                    {
                        bool processed = false;
                        for (int i = 0; i < (int)EMazeDirection.Invalid; i++)
                        {
                            EMazeDirection dir = (EMazeDirection)i;

                            //尚未联通的点
                            if (cell.IsConnectedTo(dir) == true)
                            {
                                //只做反向联通,确保不会出现孤点
                                EMazeDirection inverse_dir = MazeAlgorithm.InvertDirection(dir);
                                IMazeCell      invert_cell = cell.GetNeighbour(inverse_dir);
                                if (invert_cell != null)
                                {
                                    cell.ConnectionTo(inverse_dir);
                                    processed = true;
                                }
                            } //END OF IF Connected to
                        }     //END OF FOR Neighbours

                        if (processed == false)
                        {
                            EMazeDirection connect_dir = cell.GenRandomNeighbourDirection(ESelectCondition.NoConnected);

                            if (connect_dir != EMazeDirection.Invalid)
                            {
                                cell.ConnectionTo(connect_dir);
                            }
                        }
                    }
                }
            }
        }
        GameObject CreateMazeCellObject(IMazeCell cell_def)
        {
            List <EMazeDirection> connections = new List <EMazeDirection>();

            for (int i = 0; i < (int)EMazeDirection.DirectionCount; i++)
            {
                if (cell_def.IsConnectedTo((EMazeDirection)i))
                {
                    connections.Add((EMazeDirection)i);
                }
            }

            MazePrefab match = null;

            foreach (var candidate in config.cell_list)
            {
                if (candidate.match_direction.Count == connections.Count)
                {
                    bool full_match = true;
                    foreach (var test_dir in connections)
                    {
                        if (candidate.match_direction.Contains(test_dir) == false)
                        {
                            full_match = false;
                            break;
                        }
                    }

                    if (full_match)
                    {
                        //match
                        match = candidate;
                        break;
                    }
                }
            }

            GameObject result = Object.Instantiate(match.prefab);

            result.transform.SetParent(map_root);
            result.transform.localPosition = new Vector3(cell_def.X * config.grid_size, 0, cell_def.Y * config.grid_size);

            return(result);
        }
        protected override void Generate()
        {
            List <IMazeCell> actived = new List <IMazeCell>(cells.Count);
            IMazeCell        first   = GetRandomCell();

            actived.Add(first);

            //加入First 的有效Neighbour作为第一波的Candidate
            List <IMazeCell>      candidate = new List <IMazeCell>(first.Neighbours);
            List <EMazeDirection> candidate_connect_direction = new List <EMazeDirection>((int)EMazeDirection.DirectionCount);

            //只要所有的格子没有被全部访问。
            while (actived.Count < cells.Count)
            {
                IMazeCell random = candidate[Random.Range(0, candidate.Count)];
                candidate.Remove(random);

                candidate_connect_direction.Clear();
                for (int i = 0; i < (int)EMazeDirection.DirectionCount; i++)
                {
                    EMazeDirection dir       = (EMazeDirection)i;
                    IMazeCell      neighbour = random.GetNeighbour(dir);
                    if (neighbour != null)
                    {
                        if (actived.Contains(neighbour) == true)
                        {
                            candidate_connect_direction.Add(dir);
                        }
                        else
                        {
                            if (candidate.Contains(neighbour) == false)
                            {
                                candidate.Add(neighbour);
                            }
                        }
                    }
                }

                random.ConnectionTo(candidate_connect_direction[Random.Range(0, candidate_connect_direction.Count)]);
                actived.Add(random);
            }
        }
Exemple #20
0
        /// <summary>
        /// 寻找一个随机的,还没用过的,连接点
        /// </summary>
        /// <param name="rand_num">随机数,随机数越来越小,因为可选择的随机起始点,会随着融合越来越少</param>
        /// <param name="is_row">true:水平。false:垂直</param>
        /// <param name="index">is_row:true 传入行索引(y),否则传入列索引(x)</param>
        /// <param name="used"> is_row:true 传入用过的水平连接点。否则传入用过的垂直连接点。</param>
        /// <returns>随机的,没用过的连接点</returns>
        IMazeCell FindRandomMergeStartCell(int rand_num, bool is_row, int index, List <int> used)
        {
            IMazeCell      start_cell = is_row ? GetAt(0, index) : GetAt(index, 0);
            EMazeDirection dir        = is_row ? EMazeDirection.East : EMazeDirection.North;

            do
            {
                while (used.Contains(SharedUtil.PointHash(start_cell.X, start_cell.Y)))
                {
                    start_cell = start_cell.GetNeighbour(dir);
                }

                if (rand_num == 0)
                {
                    return(start_cell);
                }

                start_cell = start_cell.GetNeighbour(dir);
                rand_num--;
            }while (rand_num >= 0);

            Debug.LogError("Error this should not happen!!");
            return(null);
        }
        /// <summary>
        /// 这个算法同样不能胜任,不规则格子的迷宫。
        /// 因为他会产生孤立点。
        /// </summary>
        protected override void Generate()
        {
            List <EMazeDirection> dir_filter = new List <EMazeDirection>();

            dir_filter.Add(EMazeDirection.North);
            dir_filter.Add(EMazeDirection.East);

            for (int iy = 0; iy < size_y; iy++)
            {
                for (int ix = 0; ix < size_x; ix++)
                {
                    IMazeCell cell = GetAt(ix, iy);

                    //算法优化,不能每次都判断是不是在墙角,那种判断对于不规则迷宫是无效的,且麻烦的。
                    //如果只希望沿着某两个方向扩展,更科学的方式是使用DirectionFilter 这样可以方便的产生更多的选择组合。
                    EMazeDirection move_to_dir = cell.GenRandomNeighbourDirection(ESelectCondition.None, dir_filter);

                    if (move_to_dir != EMazeDirection.DirectionCount)
                    {
                        cell.ConnectionTo(move_to_dir);
                    }
                }
            }
        }
        protected override void Generate()
        {
            IMazeCell        random_start = GetRandomCell();
            List <IMazeCell> unvisited    = new List <IMazeCell>(cells);

            unvisited.Remove(random_start);

            //前半段,用AldourBroder
            while (unvisited.Count > cells.Count / 2)
            {
                EMazeDirection valid        = random_start.GenRandomNeighbourDirection();
                IMazeCell      pending_next = random_start.GetNeighbour(valid);

                if (pending_next != null)
                {
                    //言外之意,没被访问过
                    //means, not visited.
                    if (pending_next.ConnectionCount == 0)
                    {
                        random_start.ConnectionTo(valid);
                        random_start = pending_next;
                        unvisited.Remove(random_start);
                    }
                    else
                    {
                        random_start = pending_next;
                        continue;
                    }
                }
            }

            //后半段,用Wilson
            List <IMazeCell> temp_path = new List <IMazeCell>();

            random_start = unvisited[Random.Range(0, unvisited.Count)];

            while (unvisited.Count > 0)
            {
                temp_path.Clear();
                temp_path.Add(random_start);

                while (true)
                {
                    //如果有强烈需求,可以考虑增加接口,暂时先这样做。
                    EMazeDirection dir  = temp_path[temp_path.Count - 1].GenRandomNeighbourDirection();
                    IMazeCell      next = temp_path[temp_path.Count - 1].GetNeighbour(dir);

                    //没有形成环路
                    if (unvisited.Contains(next) == false)
                    {
                        //开始联通了
                        temp_path.Add(next);

                        for (int i = 0; i < temp_path.Count - 1; i++)
                        {
                            unvisited.Remove(temp_path[i]);
                            temp_path[i].ConnectionTo(temp_path[i].LastRandomNeibourDirection);
                        }

                        if (unvisited.Count > 0)
                        {
                            random_start = unvisited[Random.Range(0, unvisited.Count)];
                        }
                        break;
                    }
                    //形成了环路
                    else if (temp_path.Contains(next) == true)
                    {
                        break;
                    }

                    temp_path.Add(next);
                }
            }
        }
Exemple #23
0
        /// <summary>
        /// 不是特别完美,和map_data产生了耦合,不过只把他当成内部类,也无妨,只不过,其他类调用的时候,返回的是这个类的成员变量而不是临时变量!
        /// </summary>
        /// <returns></returns>
        public TileMapData GenerateTileMapData()
        {
            //重置
            TileMapData temp_data = new TileMapData();

            config.theme_config.RebuildTileThemeConfig();
            int tile_size_x     = config.tile_size_x;
            int tile_size_y     = config.tile_size_y;
            int total_thickness = config.wall_thickness + config.road_thickness;

            //初始化地图
            for (int iy = 0; iy < tile_size_y; iy++)
            {
                for (int ix = 0; ix < tile_size_x; ix++)
                {
                    int key = SharedUtil.PointHash(ix, iy);
                    temp_data[key] = config.theme_config.GetTilePrefabConfigIndex(config.road_name);
                }
            }

            MazeAlgorithm algorithm =
                (MazeAlgorithm)System.Activator.CreateInstance(System.Type.GetType("TileMazeMaker.Algorithm.Maze." + config.maze_algorithm.ToString()));

            //处理Mask
            algorithm.SetMazeMaskCells(config.maze_mask);

            //设置后期处理
            for (int i = 0; i < config.post_process.Count; i++)
            {
                if (config.post_process[i] != EMazePostProcess.None)
                {
                    algorithm.AddPostProcesser(config.post_process[i].ToString());
                }
            }

            algorithm.BuildMaze <MazeCell>(config.width, config.height);

            dig_list.Add(DigNorth);
            dig_list.Add(DigWest);
            dig_list.Add(DigSouth);
            dig_list.Add(DigEast);

            for (int iy = 0; iy < config.height; iy++)
            {
                for (int ix = 0; ix < config.width; ix++)
                {
                    IMazeCell cell = algorithm.GetAt(ix, iy);
                    if (cell != null)
                    {
                        TileRect out_rect = new TileRect(
                            ix * total_thickness,
                            iy * total_thickness,
                            config.road_thickness + 2 * config.wall_thickness,
                            config.road_thickness + 2 * config.wall_thickness);

                        out_rect.SetMapTileType(temp_data, config.theme_config, config.wall_name);

                        TileRect rect = new TileRect(
                            ix * total_thickness + config.wall_thickness,
                            iy * total_thickness + config.wall_thickness,
                            config.road_thickness,
                            config.road_thickness);

                        rect.SetMapTileType(temp_data, config.theme_config, config.road_name);

                        for (int i = 0; i < (int)EMazeDirection.DirectionCount; i++)
                        {
                            if (cell.IsConnectedTo((EMazeDirection)i))
                            {
                                dig_list[i](temp_data, rect);
                            }
                        }
                    }
                }
            }

            return(temp_data);
        }
Exemple #24
0
        public EMazeDirection GenRandomNeighbourDirection(ESelectCondition condition = ESelectCondition.None, List <EMazeDirection> direction_filter = null)
        {
            List <EMazeDirection> candidate = new List <EMazeDirection>();

            foreach (var key in neighbours.Keys)
            {
                //Debug:注意要判断target是不是visited,而不是自己!
                IMazeCell target = neighbours[key];
                switch (condition)
                {
                case ESelectCondition.None:
                    candidate.Add(key);
                    break;

                case ESelectCondition.NoConnected:
                    if (IsConnectedTo(key) == false)
                    {
                        candidate.Add(key);
                    }
                    break;

                case ESelectCondition.NoVisited:

                    if (target.ConnectionCount == 0)
                    {
                        candidate.Add(key);
                    }
                    break;

                case ESelectCondition.Connected:
                    if (IsConnectedTo(key) == true)
                    {
                        candidate.Add(key);
                    }
                    break;

                case ESelectCondition.Visited:
                    if (target.ConnectionCount > 0)
                    {
                        candidate.Add(key);
                    }
                    break;

                case ESelectCondition.VisitedConnected:
                    if (IsConnectedTo(key) == true && target.ConnectionCount > 0)
                    {
                        candidate.Add(key);
                    }
                    break;
                }
            }

            //追加Filter 使得 随机筛选只能从指定方向中筛选。
            if (direction_filter != null && candidate.Count > 0)
            {
                for (int i = candidate.Count - 1; i >= 0; i--)
                {
                    if (direction_filter.Contains(candidate[i]) == false)
                    {
                        candidate.Remove(candidate[i]);
                    }
                }
            }

            //albour-broder算法需要,因此,得,保存这个值
            random_select_direction = candidate.Count == 0 ? EMazeDirection.Invalid : candidate[Random.Range(0, candidate.Count)];
            return(random_select_direction);
        }
        protected override void Generate()
        {
            foreach (var cell in cells)
            {
                cell.GroupID = 0;
            }

            int global_group_id = 1;

            for (int row_id = size_y - 1; row_id >= 0; row_id--)
            {
                //init_group_id
                for (int ix = 0; ix < size_x; ix++)
                {
                    IMazeCell cell = GetAt(ix, row_id);
                    if (cell.GroupID == 0)
                    {
                        cell.GroupID = global_group_id++;
                    }
                }

                if (row_id > 0)
                {
                    //try merge randomly
                    int pointer = 0;
                    while (pointer < size_x - 1)
                    {
                        if (Random.Range(0, 2) == 0)
                        {
                            IMazeCell from = GetAt(pointer, row_id);
                            IMazeCell to   = GetAt(pointer + 1, row_id);
                            if (from.GroupID != to.GroupID)
                            {
                                Infect(from.GroupID, to);
                                from.ConnectionTo(EMazeDirection.East);
                            }
                        }
                        pointer++;
                    }

                    //try grouth to north
                    List <IMazeCell> temp_list = new List <IMazeCell>();
                    for (int ix = 0; ix < size_x; ix++)
                    {
                        temp_list.Add(GetAt(ix, row_id));

                        if (ix + 1 == size_x || (ix + 1 < size_x && GetAt(ix, row_id).GroupID != GetAt(ix + 1, row_id).GroupID))
                        {
                            int rand_times = Random.Range(0, temp_list.Count);
                            if (rand_times == 0)
                            {
                                rand_times = 1;
                            }

                            while (rand_times > 0)
                            {
                                IMazeCell rand = temp_list[Random.Range(0, temp_list.Count)];
                                rand.ConnectionTo(EMazeDirection.South);
                                rand.GetNeighbour(EMazeDirection.South).GroupID = rand.GroupID;
                                temp_list.Remove(rand);
                                rand_times--;
                            }

                            temp_list.Clear();
                        }
                    }
                }
                else //编筐编篓,全在收口.
                {
                    //seal all cells

                    for (int ix = 0; ix < size_x - 1; ix++)
                    {
                        IMazeCell from = GetAt(ix, row_id);
                        IMazeCell to   = GetAt(ix + 1, row_id);
                        if (from.GroupID != to.GroupID)
                        {
                            from.ConnectionTo(EMazeDirection.East);
                            Infect(from.GroupID, to);
                        }
                    }
                }
            }

            DebugMazeGroupID();
        }
Exemple #26
0
        /// <summary>
        /// From given maze and coordinates correlating to a cell in maze,
        /// its adjacent cells, which are not backtracked yet, are extracted an returned as a collection.
        /// </summary>
        /// <param name="maze">Maze as two dimensional array of IMazeCell objects.</param>
        /// <param name="cell">IMazeCell object.</param>
        /// <returns>A collection of IMazeCell objects.</returns>
        private IList <BacktrackerCell> GetUnvisitedNeighbours(BacktrackerCell[,] maze, IMazeCell cell)
        {
            var unvisitedNeighbours = new List <BacktrackerCell>();
            var row = cell.Position.Row;
            var col = cell.Position.Col;

            if (row - 1 >= 1 && !maze[row - 1, col].IsBacktracked)
            {
                unvisitedNeighbours.Add(maze[row - 1, col]);
            }

            if (row + 1 < maze.GetLength(0) - 1 && !maze[row + 1, col].IsBacktracked)
            {
                unvisitedNeighbours.Add(maze[row + 1, col]);
            }

            if (col - 1 >= 1 && !maze[row, col - 1].IsBacktracked)
            {
                unvisitedNeighbours.Add(maze[row, col - 1]);
            }

            if (col + 1 < maze.GetLength(1) - 1 && !maze[row, col + 1].IsBacktracked)
            {
                unvisitedNeighbours.Add(maze[row, col + 1]);
            }

            return(unvisitedNeighbours);
        }