private static void AddMapNeighbors(MapNode[,] lookup)
 {
     //Add neighbors
     for (int y = 0; y < lookup.Height(); y++)
     {
         for (int x = 0; x < lookup.Width(); x++)
         {
             bool isLeftNotSame = lookup.CanGetLeft(x) && lookup.GetAt(x, y).Color != lookup.GetLeftOf(x, y).Color;
             bool isAboveNotSame = lookup.CanGetAbove(y) && lookup.GetAt(x, y).Color != lookup.GetAboveOf(x, y).Color;
             bool isRightNotSame = lookup.CanGetRight(x) && lookup.GetAt(x, y).Color != lookup.GetRightOf(x, y).Color;
             bool isBelowNotSame = lookup.CanGetBelow(y) && lookup.GetAt(x, y).Color != lookup.GetBelowOf(x, y).Color;
             MapNode currentNode = lookup.GetAt(x, y);
             if (isAboveNotSame)
             {
                 currentNode.AddNeighbor(lookup.GetAboveOf(x, y));
             }
             if (isLeftNotSame)
             {
                 currentNode.AddNeighbor(lookup.GetLeftOf(x, y));
             }
             if (isRightNotSame)
             {
                 currentNode.AddNeighbor(lookup.GetRightOf(x, y));
             }
             if (isBelowNotSame)
             {
                 currentNode.AddNeighbor(lookup.GetBelowOf(x, y));
             }
         }
     }
 }
 public void Merge(MapNode mergingNode)
 {
     this._neighbors = new HashSet<MapNode>(this._neighbors.Union(mergingNode._neighbors)); //take all of mergingNode's neighbors
     //update other nodes of mergingNode's deletion
     foreach (MapNode mergingNodesNeighbors in mergingNode._neighbors)
     {
         mergingNodesNeighbors._neighbors.Remove(mergingNode);
         mergingNodesNeighbors._neighbors.Add(this);
     }
     this._neighbors.Remove(this); //can't have reference to yourself
     this.Color = mergingNode.Color;
     mergingNode._neighbors.Clear(); //@OPTIMIZE We don't have to remove them, it should be understood that the node is invalid
 }
        //private static TreeNode[,] ToTreeNode(MapNode[,] lookup)
        //{
        //    TreeNode[,] treeLookup = new TreeNode[lookup.Height(), lookup.Width()];
        //    for (int y = 0; y < lookup.Height(); y++)
        //    {
        //        for (int x = 0; x < lookup.Width(); x++)
        //        {
        //            TreeNode treeNode = new TreeNode(lookup.GetAt(x, y).Color);
        //            treeLookup.SetAt(x, y, treeNode);
        //            throw new NotImplementedException("Doesn't keep the same reference for touching colors");
        //        }
        //    }
        //    return treeLookup;
        //}
        private static MapNode[,] BuildLookupGrid(Color[,] board)
        {
            MapNode[,] lookup = new MapNode[board.Height(), board.Width()];

            //build lookup
            for (int y = 0; y < board.Height(); y++)
            {
                for (int x = 0; x < board.Width(); x++)
                {
                    //Create MapNode
                    bool isLeftSame = board.CanGetLeft(x) && board.GetAt(x, y) == board.GetLeftOf(x, y);
                    bool isAboveSame = board.CanGetAbove(y) && board.GetAt(x, y) == board.GetAboveOf(x, y);

                    if (isLeftSame && isAboveSame) //check above & to the left
                    {
                        MapNode left = lookup.GetLeftOf(x, y);
                        MapNode above = lookup.GetAboveOf(x, y);
                        lookup.SetAt(x, y, left);
                        if (left != above)
                        {
                            left.Merge(above);
                            //update "above's" references to left
                            for (int updateY = y; updateY >= 0; updateY--)
                            {
                                for (int updateX = x; updateX >= 0; updateX--)
                                {
                                    if (lookup.GetAt(updateX, updateY) == above)
                                        lookup.SetAt(updateX, updateY, left);
                                }
                            }
                        }
                    }
                    else if (isLeftSame) // check to the left
                    {
                        lookup.SetAt(x, y, lookup.GetLeftOf(x, y));
                    }
                    else if (isAboveSame) // check above
                    {
                        lookup.SetAt(x, y, lookup.GetAboveOf(x, y));
                    }
                    else
                    {
                        lookup.SetAt(x, y, new MapNode(board.GetAt(x, y)));
                    }
                }
            }
            return lookup;
        }
        private void Clone(Dictionary<MapNode, MapNode> originalToClone)
        {
            //Add yourself to lookup
            MapNode thisClone;
            if (!originalToClone.TryGetValue(this, out thisClone)) //Determines if this MapNode has been visited yet
            {
                thisClone = new MapNode(this.Color);
                originalToClone.Add(this, thisClone);
                //Add neighbors to lookup
                foreach (MapNode neighbor in _neighbors)
                {
                    neighbor.Clone(originalToClone); //guarentees the neighbor will be in the lookup
                    MapNode neighborClone = originalToClone[neighbor];
                    if (!thisClone._neighbors.Contains(neighborClone))
                        thisClone._neighbors.Add(neighborClone);
                }

            }
        }
 public void AddNeighbor(MapNode node)
 {
     _neighbors.Add(node);
 }