private static int GetRoomIndexForCoords(IReadOnlyList<Room> rooms, Coords coords)
        {
            for (var roomIndex = 0; roomIndex < rooms.Count; roomIndex++)
            {
                var room = rooms[roomIndex];
                if (room.Cells.Contains(coords)) return roomIndex;
            }

            throw new InvalidOperationException($"Failed to find coords {coords} in any room!");
        }
 private static InternalRow BuildInternalRow(IReadOnlyList<Room> rooms, Coords coords, int value, bool isInitialValue)
 {
     var roomIndex = GetRoomIndexForCoords(rooms, coords);
     return new InternalRow(coords, value, roomIndex, isInitialValue);
 }
 public bool HasDigitAt(Coords coords, int value)
 {
     return _placedDigits.ContainsKey(Tuple.Create(coords, value));
 }
 public void AddDigit(Coords coords, int value)
 {
     AddDigit(coords, value, false);
 }
        private void AddDigit(Coords coords, int value, bool isInitialValue)
        {
            // http://stackoverflow.com/questions/17828417/centering-text-vertically-and-horizontally-in-textblock-and-passwordbox-in-windo

            var textBlock = new TextBlock
            {
                Text = Convert.ToString(value),
                FontSize = 48,
                Foreground = new SolidColorBrush(Colors.Black),
                Opacity = isInitialValue ? 0.6 : 1.0,
                TextAlignment = TextAlignment.Center,
                Tag = isInitialValue ? TagType.InitialValue : TagType.Digit
            };

            var border = new Border
            {
                Width = _sw,
                Height = _sh,
                Child = textBlock
            };

            Canvas.SetLeft(border, coords.Col * _sw + GridLineHalfThickness);
            Canvas.SetTop(border, (_numRows - coords.Row - 1) * _sh + GridLineHalfThickness);
            BoardCanvas.Children.Add(border);

            if (!isInitialValue)
                _placedDigits[Tuple.Create(coords, value)] = border;
        }
        private static void FindNextLine(IList<Coords> outsideEdges, Coords currentLineEndCoords, out Coords nextLineStartCoords, out Coords nextLineEndCoords)
        {
            var numLines = outsideEdges.Count / 2;

            for (var i = 0; i < numLines; i++)
            {
                var pt1 = outsideEdges[i * 2];
                var pt2 = outsideEdges[i * 2 + 1];

                if (pt1.Equals(currentLineEndCoords))
                {
                    nextLineStartCoords = pt1;
                    nextLineEndCoords = pt2;
                    return;
                }
            }

            throw new InvalidOperationException("FindNextLine failed to find the next line!");
        }