|
@@ -1,6 +1,9 @@
|
|
|
# Sudoku: 9x9 Spielfeld. Auf jedem Feld ist eine Liste mit möglichen Werten.
|
|
|
# Enthält diese Liste nur einen Wert, ist das der gesuchte Wert für das Feld.
|
|
|
|
|
|
+import logging
|
|
|
+logging.basicConfig(level=logging.DEBUG)
|
|
|
+
|
|
|
gamefield = [
|
|
|
[[],[7],[],[5],[8],[3],[],[2],[]],
|
|
|
[[],[5],[9],[2],[],[],[3],[],[]],
|
|
@@ -14,6 +17,7 @@ gamefield = [
|
|
|
];
|
|
|
|
|
|
def fill_empty_fields_with_possible_values():
|
|
|
+ logging.debug("fill_empty_fields_with_possible_values")
|
|
|
y = 0
|
|
|
for row in gamefield:
|
|
|
x = 0
|
|
@@ -47,16 +51,19 @@ def print_sudoku():
|
|
|
print('')
|
|
|
|
|
|
def solve_by_cell_check():
|
|
|
+ logging.debug("solve_by_cell_check")
|
|
|
while True:
|
|
|
if solve_by_cell_check_inner():
|
|
|
# break when algorithm runs through without any findings
|
|
|
break
|
|
|
|
|
|
def solve_by_cell_check_inner():
|
|
|
+ logging.debug("solve_by_cell_check_inner")
|
|
|
# for each cell
|
|
|
y = 0
|
|
|
for row in gamefield:
|
|
|
x = 0
|
|
|
+ logging.debug(f"check at {x}/{y}")
|
|
|
for field in row:
|
|
|
# if value is already defined, check next value
|
|
|
if(len(field) == 1):
|
|
@@ -65,6 +72,7 @@ def solve_by_cell_check_inner():
|
|
|
# for each possible value
|
|
|
field_changed = False
|
|
|
for possible_value in field[:]:
|
|
|
+ logging.debug(f"check value {possible_value} in {field}")
|
|
|
# check if the value already exists in row/column/3x3 field
|
|
|
if(check_row_for_value(y, possible_value) or
|
|
|
check_column_for_value(x, possible_value) or
|
|
@@ -74,17 +82,21 @@ def solve_by_cell_check_inner():
|
|
|
field_changed = True
|
|
|
# return False because algorithm found something
|
|
|
if field_changed:
|
|
|
+ logging.debug(f"solve_by_cell_check_inner found something and changed field -> restart")
|
|
|
return False
|
|
|
x += 1
|
|
|
y += 1
|
|
|
# return True when algorithm runs through without any findings
|
|
|
+ logging.debug(f"solve_by_cell_check_inner runs through without any findings")
|
|
|
return True
|
|
|
|
|
|
def remove_from_possible_values(x, y, value):
|
|
|
+ logging.debug(f"remove {value} from possible values at {x}/{y}")
|
|
|
gamefield[y][x].remove(value)
|
|
|
|
|
|
# i do not explicitely skip the field itself because it is skipped by len check
|
|
|
def check_row_for_value(rowIndex, value):
|
|
|
+ logging.debug(f"check row {rowIndex} for {value}")
|
|
|
for field in gamefield[rowIndex]:
|
|
|
if len(field) == 1:
|
|
|
if field[0] == value:
|
|
@@ -92,6 +104,7 @@ def check_row_for_value(rowIndex, value):
|
|
|
return False
|
|
|
|
|
|
def check_column_for_value(columnIndex, value):
|
|
|
+ logging.debug(f"check row {columnIndex} for {value}")
|
|
|
rowIndex = 0
|
|
|
while rowIndex < len(gamefield):
|
|
|
field = get_field_by_coord(columnIndex, rowIndex)
|
|
@@ -102,6 +115,7 @@ def check_column_for_value(columnIndex, value):
|
|
|
return False
|
|
|
|
|
|
def check_3x3_for_value(x, y, value):
|
|
|
+ logging.debug(f"check 3x3 at {x}/{y} for {value}")
|
|
|
(block_x, block_y) = get_3x3_start_coords(x, y)
|
|
|
block_x_end = block_x + 2
|
|
|
block_y_end = block_y + 2
|