数独是各种应用程序中流行的益智类拼图游戏。数独板是一个9×9的网格,玩家必须在每行、每列和3×3的子网格中放置一次数字1到9,并且只能放置一次。游戏开始时,有几个空格已经用数字填充,称为givens。一个好的数独谜题应该只有一个可能的有效解决方案。
它的工作原理
数独网格类的对象是表示数独网格的数据结构。您可以调用它们的方法来修改网格或检索有关网格的信息。例如,makeMove()方法在网格上放置一个数字,resetGrid()方法将网格恢复到其原始状态,如果解决方案的所有数字都已放置在网格上,则isSolved()返回True。
该程序的主要部分从第141行开始,为该游戏使用了一个数独网格对象及其方法,但您也可以将此类复制并粘贴到您创建的其他数独程序中,以重用其功能。
先直接上代码:
import copy, random, sys
EMPTY_SPACE = '.'
GRID_LENGTH = 9
BOX_LENGTH = 3
FULL_GRID_SIZE = GRID_LENGTH * GRID_LENGTH
class SudokuGrid:
def __init__(self, originalSetup):
self.originalSetup = originalSetup
self.grid = {}
self.resetGrid()
self.moves = []
def resetGrid(self):
"""Reset the state of the grid, tracked by self.grid, to the
state in self.originalSetup."""
for x in range(1, GRID_LENGTH + 1):
for y in range(1, GRID_LENGTH + 1):
self.grid[(x, y)] = EMPTY_SPACE
assert len(self.originalSetup) == FULL_GRID_SIZE
i = 0
y = 0
while i < FULL_GRID_SIZE:
for x in range(GRID_LENGTH):
self.grid[(x, y)] = self.originalSetup[i]
i += 1
y += 1
def makeMove(self, column, row, number):
"""Place the number at the column (a letter from A to I) and row
(an integer from 1 to 9) on the grid."""
x = 'ABCDEFGHI'.find(column)
y = int(row) - 1
if self.originalSetup[y * GRID_LENGTH + x] != EMPTY_SPACE:
return False
self.grid[(x, y)] = number
self.moves.append(copy.copy(self.grid))
return True
def undo(self):
"""Set the current grid state to the previous state in the
self.moves list."""
if self.moves == []:
return
self.moves.pop()
if self.moves == []:
self.resetGrid()
else:
self.grid = copy.copy(self.moves[-1])
def display(self):
"""Display the current state of the grid on the screen."""
print(' A B C D E F G H I')
for y in range(GRID_LENGTH):
for x in range(GRID_LENGTH):
if x == 0:
print(str(y + 1) + ' ', end='')
print(self.grid[(x, y)] + ' ', end='')
if x == 2 or x == 5:
print('| ', end='')
print()
if y == 2 or y == 5:
print(' ------+-------+------')
def _isCompleteSetOfNumbers(self, numbers):
"""Return True if numbers contains the digits 1 through 9."""
return sorted(numbers) == list('123456789')
def isSolved(self):
"""Returns True if the current grid is in a solved state."""
for row in range(GRID_LENGTH):
rowNumbers = []
for x in range(GRID_LENGTH):
number = self.grid[(x, row)]
rowNumbers.append(number)
if not self._isCompleteSetOfNumbers(rowNumbers):
return False
for column in range(GRID_LENGTH):
columnNumbers = []
for y in range(GRID_LENGTH):
number = self.grid[(column, y)]
columnNumbers.append(number)
if not self._isCompleteSetOfNumbers(columnNumbers):
return False
for boxx in (0, 3, 6):
for boxy in (0, 3, 6):
boxNumbers = []
for x in range(BOX_LENGTH):
for y in range(BOX_LENGTH):
number = self.grid[(boxx + x, boxy + y)]
boxNumbers.append(number)
if not self._isCompleteSetOfNumbers(boxNumbers):
return False
return True
print('''Sudoku Puzzle
Sudoku is a number placement logic puzzle game. A Sudoku grid is a 9x9
grid of numbers. Try to place numbers in the grid such that every row,
column, and 3x3 box has the numbers 1 through 9 once and only once.
For example, here is a starting Sudoku grid and its solved form:
5 3 . | . 7 . | . . . 5 3 4 | 6 7 8 | 9 1 2
6 . . | 1 9 5 | . . . 6 7 2 | 1 9 5 | 3 4 8
. 9 8 | . . . | . 6 . 1 9 8 | 3 4 2 | 5 6 7
------+-------+------ ------+-------+------
8 . . | . 6 . | . . 3 8 5 9 | 7 6 1 | 4 2 3
4 . . | 8 . 3 | . . 1 --> 4 2 6 | 8 5 3 | 7 9 1
7 . . | . 2 . | . . 6 7 1 3 | 9 2 4 | 8 5 6
------+-------+------ ------+-------+------
. 6 . | . . . | 2 8 . 9 6 1 | 5 3 7 | 2 8 4
. . . | 4 1 9 | . . 5 2 8 7 | 4 1 9 | 6 3 5
. . . | . 8 . | . 7 9 3 4 5 | 2 8 6 | 1 7 9
''')
input('Press Enter to begin...')
with open('data.txt') as puzzleFile:
puzzles = puzzleFile.readlines()
for i, puzzle in enumerate(puzzles):
puzzles[i] = puzzle.strip()
grid = SudokuGrid(random.choice(puzzles))
while True:
grid.display()
if grid.isSolved():
print('Congratulations! You solved the puzzle!')
print('Thanks for playing!')
sys.exit()
while True:
print()
print('Enter a move, or RESET, NEW, UNDO, ORIGINAL, or QUIT:')
print('(For example, a move looks like "B4 9".)')
action = input('> ').upper().strip()
if len(action) > 0 and action[0] in ('R', 'N', 'U', 'O', 'Q'):
break
if len(action.split()) == 2:
space, number = action.split()
if len(space) != 2:
continue
column, row = space
if column not in list('ABCDEFGHI'):
print('There is no column', column)
continue
if not row.isdecimal() or not (1 <= int(row) <= 9):
print('There is no row', row)
continue
if not (1 <= int(number) <= 9):
print('Select a number from 1 to 9, not ', number)
continue
break
print()
if action.startswith('R'):
grid.resetGrid()
continue
if action.startswith('N'):
grid = SudokuGrid(random.choice(puzzles))
continue
if action.startswith('U'):
grid.undo()
continue
if action.startswith('O'):
originalGrid = SudokuGrid(grid.originalSetup)
print('The original grid looked like this:')
originalGrid.display()
input('Press Enter to continue...')
if action.startswith('Q'):
print('Thanks for playing!')
sys.exit()
if grid.makeMove(column, row, number) == False:
print('You cannot overwrite the original grid\'s numbers.')
print('Enter ORIGINAL to view the original grid.')
input('Press Enter to continue...')
运行sudoku.py时,输出将如下所示:
代码的工作原理:
SudokuGrid类的对象是表示数独网格的数据结构。您可以调用它们的方法来修改网格或检索有关网格的信息。例如,makeMove()方法在网格上放置一个数字,resetGrid()方法将网格恢复到其原始状态,如果解决方案的所有数字都已放置在网格上,则isSolved()返回True。
该程序的主要部分从第111行开始,为该游戏使用了一个数独网格对象及其方法,但您也可以将此类复制并粘贴到您创建的其他数独程序中,以重用其功能。
date.txt文件包含的是谜题,以下是此文件中的内容示例:
..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..
2...8.3...6..7..84.3.5..2.9...1.54.8.........4.27.6...3.1..7.4.72..4..6...4.1...3
......9.7...42.18....7.5.261..9.4....5.....4....5.7..992.1.8....34.59...5.7......
.3..5..4...8.1.5..46.....12.7.5.2.8....6.3....4.1.9.3.25.....98..1.2.6...8..6..2.
提示:粘贴代码时注意格式的缩进。