private void save_Click(object sender, RoutedEventArgs e) { if (gr.Validate()) { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { gr.boxes[i, j].Focusable = false; } } } }
public DancingLinks(SudokuGrid s) { rowLookUp = new Dictionary <Triple <int>, SudokuRowHeader>(); if (s.Validate()) { columns = new List <DancingLinksColumnHeader>(); rows = new List <SudokuRowHeader>(); //Initialise blank Sudoku Grid. for (int i = 1; i <= 9; i++) { for (int j = 1; j <= 9; j++) { columns.Add(new DancingLinksColumnHeader(new Tuple <int, int>(i, j), DancingLinksColumnHeader.ColumnType.Cell)); columns.Add(new DancingLinksColumnHeader(new Tuple <int, int>(i, j), DancingLinksColumnHeader.ColumnType.Row)); columns.Add(new DancingLinksColumnHeader(new Tuple <int, int>(i, j), DancingLinksColumnHeader.ColumnType.Square)); columns.Add(new DancingLinksColumnHeader(new Tuple <int, int>(i, j), DancingLinksColumnHeader.ColumnType.Column)); for (int k = 1; k <= 9; k++) { SudokuRowHeader r = new SudokuRowHeader(new Triple <int>(i, j, k)); rows.Add(r); rowLookUp.Add(new Triple <int>(i, j, k), r); } } } //Convention: for cell numbers, x is the row and y is the column. This is reversed for square numbering. This is an artefact of how I am visualising the objects. //Column Linking foreach (DancingLinksColumnHeader column in columns) { column.columnMemberCount = 9; if (column.type == DancingLinksColumnHeader.ColumnType.Cell) { int content; if (int.TryParse(s.boxes[column.constraintNum.Item1 - 1, column.constraintNum.Item2 - 1].Text, out content)) { column.columnMemberCount = 1; column.firstEntry = new DancingLinksNode(column, column.constraintNum.Item1, column.constraintNum.Item2, content); column.firstEntry.up = column.firstEntry; column.firstEntry.down = column.firstEntry; if (rowLookUp.ContainsKey(new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, content))) { rowLookUp[new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, content)].firstNode.left.right = column.firstEntry; rowLookUp[new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, content)].firstNode.left = column.firstEntry; } else { SudokuRowHeader r = new SudokuRowHeader(new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, content)); rows.Add(r); rowLookUp.Add(new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, content), r); r.firstNode = column.firstEntry; } } else { column.firstEntry = new DancingLinksNode(column, column.constraintNum.Item1, column.constraintNum.Item2, 1); DancingLinksNode curNode = column.firstEntry; if (rowLookUp.ContainsKey(new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, 1))) { rowLookUp[new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, 1)].firstNode.left.right = curNode; rowLookUp[new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, 1)].firstNode.left = curNode; } else { SudokuRowHeader r = new SudokuRowHeader(new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, 1)); rows.Add(r); rowLookUp.Add(new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, 1), r); r.firstNode = curNode; } for (int i = 2; i <= 9; i++) { curNode.down = new DancingLinksNode(column, column.constraintNum.Item1, column.constraintNum.Item2, i); curNode.down.up = curNode; curNode = curNode.down; if (i == 9) { column.firstEntry.up = curNode; curNode.down = column.firstEntry; } if (rowLookUp.ContainsKey(new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, i))) { rowLookUp[new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, i)].firstNode.left.right = curNode; rowLookUp[new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, i)].firstNode.left = curNode; } else { SudokuRowHeader r = new SudokuRowHeader(new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, i)); rows.Add(r); rowLookUp.Add(new Triple <int>(column.constraintNum.Item1, column.constraintNum.Item2, i), r); r.firstNode = curNode; } } } } if (column.type == DancingLinksColumnHeader.ColumnType.Column) { int content; int rowNum = 0; bool isInColumn = false; for (int i = 1; i <= 9 && !isInColumn; i++) { if (int.TryParse(s.boxes[i - 1, column.constraintNum.Item1 - 1].Text, out content)) { if (content == column.constraintNum.Item2) { isInColumn = true; } rowNum = i; } } if (isInColumn) { column.columnMemberCount = 1; column.firstEntry = new DancingLinksNode(column, rowNum, column.constraintNum.Item1, column.constraintNum.Item2); column.firstEntry.up = column.firstEntry; column.firstEntry.down = column.firstEntry; } else { column.firstEntry = new DancingLinksNode(column, 1, column.constraintNum.Item1, column.constraintNum.Item2); DancingLinksNode curNode = column.firstEntry; for (int i = 2; i <= 9; i++) { curNode.down = new DancingLinksNode(column, i, column.constraintNum.Item1, column.constraintNum.Item2); curNode.down.up = curNode; curNode = curNode.down; if (i == 9) { column.firstEntry.up = curNode; curNode.down = column.firstEntry; } } } } if (column.type == DancingLinksColumnHeader.ColumnType.Row) { int content; int colNum = 0; bool isInColumn = false; for (int i = 1; i <= 9 && !isInColumn; i++) { if (int.TryParse(s.boxes[column.constraintNum.Item1 - 1, i - 1].Text, out content)) { if (content == column.constraintNum.Item2) { isInColumn = true; } colNum = i; } } if (isInColumn) { column.columnMemberCount = 1; column.firstEntry = new DancingLinksNode(column, column.constraintNum.Item1, colNum, column.constraintNum.Item2); column.firstEntry.up = column.firstEntry; column.firstEntry.down = column.firstEntry; } else { column.firstEntry = new DancingLinksNode(column, column.constraintNum.Item1, 1, column.constraintNum.Item2); DancingLinksNode curNode = column.firstEntry; for (int i = 2; i <= 9; i++) { curNode.down = new DancingLinksNode(column, column.constraintNum.Item1, i, column.constraintNum.Item2); curNode.down.up = curNode; curNode = curNode.down; if (i == 9) { column.firstEntry.up = curNode; curNode.down = column.firstEntry; } } } } if (column.type == DancingLinksColumnHeader.ColumnType.Square) { int squareX = column.constraintNum.Item1 % 3 - 1; if (squareX < 0) { squareX += 3; } int squareY = (column.constraintNum.Item1 - (squareX + 1)) / 3; int rowNum = 0; int colNum = 0; bool isInSquare = false; for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 3; j++) { int content; if (int.TryParse(s.boxes[squareY * 3 + i - 1, squareX * 3 + j - 1].Text, out content)) { if (content == column.constraintNum.Item2) { isInSquare = true; rowNum = squareY * 3 + i; colNum = squareX * 3 + j; } } } } if (isInSquare) { column.columnMemberCount = 1; column.firstEntry = new DancingLinksNode(column, rowNum, colNum, column.constraintNum.Item2); column.firstEntry.up = column.firstEntry; column.firstEntry.down = column.firstEntry; } else { column.firstEntry = new DancingLinksNode(column, squareY * 3 + 1, squareX * 3 + 1, column.constraintNum.Item2); DancingLinksNode curNode = column.firstEntry; for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 3; j++) { if (i != 1 || j != 1) { curNode.down = new DancingLinksNode(column, squareY * 3 + i, squareX * 3 + j, column.constraintNum.Item2); curNode.down.up = curNode; curNode = curNode.down; } if (i == 3 && j == 3) { column.firstEntry.up = curNode; curNode.down = column.firstEntry; } } } } } } } }