Python 数独小游戏进阶:实现自动填数与错误检测功能
·
Python 数独小游戏进阶实现
下面我将实现一个具有自动填数和错误检测功能的数独游戏。该程序包含以下核心功能:
- 自动填入唯一可能数字
- 实时错误检测
- 可视化界面
import pygame
import sys
import numpy as np
# 初始化pygame
pygame.init()
# 游戏常量
WIDTH, HEIGHT = 540, 600
GRID_SIZE = 9
CELL_SIZE = WIDTH // GRID_SIZE
FONT_SIZE = 36
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (200, 200, 200)
RED = (255, 0, 0)
BLUE = (0, 120, 255)
class SudokuGame:
def __init__(self):
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("数独游戏")
self.font = pygame.font.SysFont(None, FONT_SIZE)
self.small_font = pygame.font.SysFont(None, FONT_SIZE - 10)
self.board = np.zeros((GRID_SIZE, GRID_SIZE), dtype=int)
self.original = None
self.selected = None
self.errors = set()
# 初始化数独板
self.initialize_board()
def initialize_board(self):
"""初始化数独板"""
# 示例数独(0表示空格)
self.board = np.array([
[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]
])
self.original = self.board.copy()
self.errors = set()
def is_valid(self, row, col, num):
"""检查在(row, col)位置填入num是否合法"""
# 检查行
if num in self.board[row]:
return False
# 检查列
if num in self.board[:, col]:
return False
# 检查3x3宫格
box_row, box_col = row // 3 * 3, col // 3 * 3
if num in self.board[box_row:box_row+3, box_col:box_col+3]:
return False
return True
def find_empty(self):
"""找到下一个空格位置"""
for i in range(GRID_SIZE):
for j in range(GRID_SIZE):
if self.board[i][j] == 0:
return (i, j)
return None
def auto_fill_single(self):
"""自动填入唯一可能数字"""
filled = False
for i in range(GRID_SIZE):
for j in range(GRID_SIZE):
if self.board[i][j] == 0:
possible = []
for num in range(1, 10):
if self.is_valid(i, j, num):
possible.append(num)
# 如果只有一个可能数字
if len(possible) == 1:
self.board[i][j] = possible[0]
filled = True
return filled
def detect_errors(self):
"""检测所有错误位置"""
self.errors = set()
# 检查行
for i in range(GRID_SIZE):
seen = set()
for j in range(GRID_SIZE):
num = self.board[i][j]
if num != 0:
if num in seen:
for k in range(GRID_SIZE):
if self.board[i][k] == num:
self.errors.add((i, k))
else:
seen.add(num)
# 检查列
for j in range(GRID_SIZE):
seen = set()
for i in range(GRID_SIZE):
num = self.board[i][j]
if num != 0:
if num in seen:
for k in range(GRID_SIZE):
if self.board[k][j] == num:
self.errors.add((k, j))
else:
seen.add(num)
# 检查3x3宫格
for box_i in range(0, 9, 3):
for box_j in range(0, 9, 3):
seen = set()
positions = []
for i in range(box_i, box_i+3):
for j in range(box_j, box_j+3):
num = self.board[i][j]
positions.append((i, j))
if num != 0:
if num in seen:
for pos in positions:
if self.board[pos[0]][pos[1]] == num:
self.errors.add(pos)
else:
seen.add(num)
def draw(self):
"""绘制游戏界面"""
self.screen.fill(WHITE)
# 绘制网格线
for i in range(GRID_SIZE + 1):
line_width = 4 if i % 3 == 0 else 1
pygame.draw.line(self.screen, BLACK, (0, i * CELL_SIZE), (WIDTH, i * CELL_SIZE), line_width)
pygame.draw.line(self.screen, BLACK, (i * CELL_SIZE, 0), (i * CELL_SIZE, WIDTH), line_width)
# 绘制数字
for i in range(GRID_SIZE):
for j in range(GRID_SIZE):
num = self.board[i][j]
if num != 0:
color = BLUE if self.original[i][j] == 0 else BLACK
text = self.font.render(str(num), True, color)
text_rect = text.get_rect(center=(j * CELL_SIZE + CELL_SIZE // 2,
i * CELL_SIZE + CELL_SIZE // 2))
self.screen.blit(text, text_rect)
# 绘制错误标记
for (i, j) in self.errors:
pygame.draw.rect(self.screen, RED,
(j * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE), 3)
# 绘制选中单元格
if self.selected:
i, j = self.selected
pygame.draw.rect(self.screen, BLUE,
(j * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE), 3)
# 绘制按钮
pygame.draw.rect(self.screen, GRAY, (180, HEIGHT - 50, 180, 40))
text = self.small_font.render("自动填数", True, BLACK)
self.screen.blit(text, (250, HEIGHT - 40))
pygame.display.flip()
def run(self):
"""运行游戏主循环"""
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
x, y = pygame.mouse.get_pos()
# 点击网格
if y < WIDTH:
col = x // CELL_SIZE
row = y // CELL_SIZE
self.selected = (row, col)
# 点击按钮
elif 180 <= x <= 360 and HEIGHT-50 <= y <= HEIGHT-10:
self.auto_fill_single()
if event.type == pygame.KEYDOWN and self.selected:
row, col = self.selected
# 只能修改原始为0的位置
if self.original[row][col] == 0:
if event.key == pygame.K_1: self.board[row][col] = 1
if event.key == pygame.K_2: self.board[row][col] = 2
if event.key == pygame.K_3: self.board[row][col] = 3
if event.key == pygame.K_4: self.board[row][col] = 4
if event.key == pygame.K_5: self.board[row][col] = 5
if event.key == pygame.K_6: self.board[row][col] = 6
if event.key == pygame.K_7: self.board[row][col] = 7
if event.key == pygame.K_8: self.board[row][col] = 8
if event.key == pygame.K_9: self.board[row][col] = 9
if event.key == pygame.K_DELETE or event.key == pygame.K_BACKSPACE:
self.board[row][col] = 0
# 实时错误检测
self.detect_errors()
# 绘制界面
self.draw()
pygame.quit()
sys.exit()
if __name__ == "__main__":
game = SudokuGame()
game.run()
功能说明
-
自动填数功能:
- 点击"自动填数"按钮,程序会扫描所有空格
- 当某个空格只有一个可能数字时,自动填入该数字
- 使用
auto_fill_single()方法实现
-
错误检测系统:
- 实时检查行、列和3×3宫格内的数字冲突
- 冲突数字会用红色方框标记
- 使用
detect_errors()方法实现
-
游戏操作:
- 点击选择单元格
- 按数字键1-9填入数字
- 按Delete键清除数字
- 蓝色数字表示玩家填入的数字
- 黑色数字表示初始题目数字
-
数独规则验证:
- 使用
is_valid()方法检查填入数字的合法性 - 验证行、列和宫格内的唯一性
- 使用
使用说明
- 运行程序后,会显示初始数独棋盘
- 点击单元格后按数字键填入数字
- 点击"自动填数"按钮可自动填入唯一可能的数字
- 冲突的数字会被红色方框标记
- 按ESC键或关闭窗口退出游戏
这个实现包含了完整的数独游戏功能,特别适合用于学习Python游戏开发和算法设计。自动填数功能使用了简单推理算法,错误检测系统则确保玩家遵循数独规则。
更多推荐
所有评论(0)