예제 #1
0
 public void ConnectWith(Cell other)
 {
     var segment = new Line2D(new Point2D(x, y), new Point2D(other.X, other.Y));
      var connector = new CellConnector(this, other, segment, ConnectorState.Unlinked);
      connectors.Add(connector);
      other.connectors.Add(connector);
 }
예제 #2
0
        public void PlaceLocksAndKeys(Cell entrance, List<Cell> cells, Color[] keyColors)
        {
            if (keyColors.Length > cells.Count - 2) {
            throw new InvalidOperationException("The operation would require placing more than one key per cell or placing a key on the entrance.");
             }

             var lockedCells = cells.Where(x => x != entrance).Shuffle(random).Take(keyColors.Length).ToArray();
             for (var i = 0 ; i < keyColors.Length; i++) {
            lockedCells[i].LockColor = keyColors[i];
             }

             // Handle case where all entrance neighbors have a lock: Redistribute one lock elsewhere.
             var entranceNeighborCells = entrance.Connectors.Where(x => x.State == ConnectorState.Linked).Select(x => x.Other(entrance));
             if (entranceNeighborCells.All(x => x.LockColor != Color.Empty)) {
            // Remove lock from random entrance neighbor and place in any other cell.
            var recipientCell = cells.Where(x => x.LockColor == Color.Empty).Shuffle().First();
            var entranceNeighborCell = entranceNeighborCells.Shuffle().First();
            recipientCell.LockColor = entranceNeighborCell.LockColor;
            entranceNeighborCell.LockColor = Color.Empty;
             }

             var visited = new HashSet<Cell>();
             var frontline = new List<Cell>();
             var keyable = new List<Cell>();

             visited.Add(entrance);
             entrance.Connectors.Where(x => x.State == ConnectorState.Linked).Select(x => x.Other(entrance)).ForEach(frontline.Add);

             int keysRemaining = keyColors.Length;

             while (frontline.Any()) {
            var frontlineCellIndex = (int)(random.NextDouble() * frontline.Count);
            var frontlineCell = frontline[frontlineCellIndex];
            frontline.RemoveAt(frontlineCellIndex);

            Console.WriteLine("!" + frontlineCell);

            if (frontlineCell.LockColor != Color.Empty) {
               var keyableCellIndex = (int)(random.NextDouble() * keyable.Count);
               var keyableCell = keyable[keyableCellIndex];
               keyable.RemoveAt(keyableCellIndex);
               keyableCell.KeyColor = frontlineCell.LockColor;
               keysRemaining--;
            }

            keyable.Add(frontlineCell);
            if (keyable.Count > keysRemaining + keyColors.Length / 5) {
               keyable.RemoveAt(0);
            }
            visited.Add(frontlineCell);
            foreach (var neighbor in frontlineCell.Connectors.Where(x => x.State == ConnectorState.Linked).Select(x => x.Other(frontlineCell))) {
               if (!visited.Contains(neighbor)) {
                  frontline.Add(neighbor);
               }
            }
             }
        }
예제 #3
0
        public List<Cell> FillRegion(Cell initialSeed, Renderer renderer = null)
        {
            var seeds = new List<Cell>();
             seeds.Add(initialSeed);

             var cells = new List<Cell>(); // includes all seeds - any room which has a clearly defined entrance
             cells.Add(initialSeed);

             while (seeds.Any()) {
            var index = (int)(seeds.Count * Math.Pow(random.NextDouble(), 0.25));
            var seed = seeds.ElementAt(index); //GetRandomIntegerWeightedTowardEnd(seeds.Count, random));
            var candidates = seed.Connectors.Where((c) => c.State == ConnectorState.Unlinked && !cells.Contains(c.Other(seed))).ToArray();

            if (!candidates.Any()) {
               seeds.Remove(seed);
               continue;
            }

            CellConnector connector;
            if (candidates.Count() == 1) {
               seeds.Remove(seed);
               connector = candidates.First();
            } else {
               connector = candidates.SelectRandom();
            }

            connector.Connect();
            var cell = connector.Other(seed);
            seeds.Add(cell);
            cells.Add(cell);
            renderer?.RenderGrid(grid);
             }

             return cells;
        }
예제 #4
0
 public Grid(Cell[] cells, int width, int height)
 {
     this.cells = cells;
      this.width = width;
      this.height = height;
 }
예제 #5
0
 public Cell Other(Cell cell)
 {
     if (cell == first) {
     return second;
      } else if (cell == second) {
     return first;
      } else {
     throw new InvalidOperationException();
      }
 }
예제 #6
0
 public CellConnector(Cell first, Cell second, Line2D segment,  ConnectorState connectorState = ConnectorState.Unlinked)
 {
     this.first = first;
      this.second = second;
      this.segment = segment;
      this.connectorState = connectorState;
 }