<think>我们将创建一个3x3的熄灯游戏(LightsOut)。游戏规则:每个灯有开(1)和关(0)两种状态。每次点击一个灯,它会翻转(开变关,关变开)并且相邻(上下左右)的灯也会翻转。目标是将所有灯都关闭。我们将使用Python的Tkinter库来构建图形界面。步骤:1.创建一个3x3的网格,每个网格是一个按钮。2.每次点击按钮,翻转该按钮及其上下左右相邻按钮的状态。3.按钮状态用颜色表示(比如黄色表示开,灰色表示关)。4.提供重置按钮,将游戏重置为初始状态(可以随机生成一个初始状态,或者固定初始状态)。注意:由于是3x3,相邻关系需要考虑边界。代码结构:-创建主窗口-创建3x3的按钮网格-每个按钮点击事件处理函数-重置按钮由于熄灯游戏有数学解,我们还可以提供求解功能(可选),但本题需求中没有明确要求,我们暂不实现求解。我们先实现基本功能:翻转和重置。初始状态我们可以随机生成,但为了简单,我们先固定一个初始状态。但是注意,不是所有的初始状态都是可解的,所以我们确保生成一个可解的状态(比如从全关开始,随机点击若干次生成初始状态)。不过,为了简单起见,我们可以先不随机,使用固定的初始状态。然后增加一个“随机生成”按钮。具体实现:1.初始化一个3x3的状态矩阵(0表示关,1表示开)。2.创建一个3x3的按钮网格,每个按钮的背景色根据状态设置。3.每个按钮的点击事件:修改状态矩阵,并更新相邻按钮的状态和颜色。4.重置功能:重置状态矩阵为初始状态(可以是固定的,也可以是随机生成的可解状态)。随机生成初始状态:为了确保有解,我们可以从全0状态开始,随机点击若干次(比如10次),然后将这个状态作为初始状态。注意:随机点击时,每次点击的位置是随机的。我们使用一个类来封装整个游戏状态和UI。代码实现如下:</think>
以下是一个基于 Python 的 3x3 熄灯游戏实现,使用 Pygame 库创建图形界面:
```python
import pygame
import sys
import random
# 初始化 Pygame
pygame.init()
# 游戏常量
GRID_SIZE = 3
CELL_SIZE = 100
MARGIN = 5
WIDTH = GRID_SIZE * CELL_SIZE + (GRID_SIZE + 1) * MARGIN
HEIGHT = WIDTH + 50 # 额外空间给按钮
BUTTON_HEIGHT = 40
BUTTON_MARGIN = 20
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (200, 200, 200)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
YELLOW = (255, 255, 0)
BLUE = (100, 100, 255)
class LightsOut:
def __init__(self):
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("3x3 熄灯游戏")
self.clock = pygame.time.Clock()
self.font = pygame.font.SysFont(None, 36)
self.reset_game()
def reset_game(self):
"""重置游戏到初始状态"""
self.board = [[False for _ in range(GRID_SIZE)] for _ in range(GRID_SIZE)]
self.moves = 0
# 随机生成一个可解的谜题
for _ in range(10):
row = random.randint(0, GRID_SIZE - 1)
col = random.randint(0, GRID_SIZE - 1)
self.toggle_lights(row, col)
def toggle_lights(self, row, col):
"""切换指定位置及其相邻灯的状态"""
# 切换指定位置的灯
self.board[row][col] = not self.board[row][col]
self.moves += 1
# 切换上方灯
if row > 0:
self.board[row - 1][col] = not self.board[row - 1][col]
# 切换下方灯
if row < GRID_SIZE - 1:
self.board[row + 1][col] = not self.board[row + 1][col]
# 切换左侧灯
if col > 0:
self.board[row][col - 1] = not self.board[row][col - 1]
# 切换右侧灯
if col < GRID_SIZE - 1:
self.board[row][col + 1] = not self.board[row][col + 1]
def is_solved(self):
"""检查游戏是否已解决(所有灯都熄灭)"""
for row in range(GRID_SIZE):
for col in range(GRID_SIZE):
if self.board[row][col]:
return False
return True
def draw_board(self):
"""绘制游戏面板"""
for row in range(GRID_SIZE):
for col in range(GRID_SIZE):
color = YELLOW if self.board[row][col] else BLUE
rect_x = MARGIN + col * (CELL_SIZE + MARGIN)
rect_y = MARGIN + row * (CELL_SIZE + MARGIN)
pygame.draw.rect(self.screen, color,
[rect_x, rect_y, CELL_SIZE, CELL_SIZE])
# 添加边缘高光
pygame.draw.rect(self.screen, WHITE,
[rect_x, rect_y, CELL_SIZE, CELL_SIZE], 2)
def draw_buttons(self):
"""绘制游戏按钮"""
# 重置按钮
reset_rect = pygame.Rect(BUTTON_MARGIN, HEIGHT - BUTTON_HEIGHT - BUTTON_MARGIN,
(WIDTH - 3 * BUTTON_MARGIN) // 2, BUTTON_HEIGHT)
pygame.draw.rect(self.screen, GREEN, reset_rect)
pygame.draw.rect(self.screen, BLACK, reset_rect, 2)
reset_text = self.font.render("重置", True, BLACK)
reset_text_rect = reset_text.get_rect(center=reset_rect.center)
self.screen.blit(reset_text, reset_text_rect)
# 退出按钮
quit_rect = pygame.Rect(WIDTH // 2 + BUTTON_MARGIN, HEIGHT - BUTTON_HEIGHT - BUTTON_MARGIN,
(WIDTH - 3 * BUTTON_MARGIN) // 2, BUTTON_HEIGHT)
pygame.draw.rect(self.screen, RED, quit_rect)
pygame.draw.rect(self.screen, BLACK, quit_rect, 2)
quit_text = self.font.render("退出", True, BLACK)
quit_text_rect = quit_text.get_rect(center=quit_rect.center)
self.screen.blit(quit_text, quit_text_rect)
# 显示移动次数
moves_text = self.font.render(f"移动次数: {self.moves}", True, BLACK)
self.screen.blit(moves_text, (BUTTON_MARGIN, HEIGHT - BUTTON_HEIGHT - BUTTON_MARGIN - 40))
return reset_rect, quit_rect
def draw(self):
"""绘制整个游戏界面"""
self.screen.fill(GRAY)
self.draw_board()
return self.draw_buttons()
def run(self):
"""运行游戏主循环"""
while True:
reset_rect, quit_rect = self.draw()
if self.is_solved():
solved_text = self.font.render("恭喜你解决谜题!", True, GREEN)
self.screen.blit(solved_text, (WIDTH // 2 - solved_text.get_width() // 2,
HEIGHT - BUTTON_HEIGHT - BUTTON_MARGIN - 80))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = pygame.mouse.get_pos()
# 检查是否点击了按钮
if reset_rect.collidepoint(mouse_pos):
self.reset_game()
elif quit_rect.collidepoint(mouse_pos):
pygame.quit()
sys.exit()
else:
# 确定点击的单元格
for row in range(GRID_SIZE):
for col in range(GRID_SIZE):
cell_x = MARGIN + col * (CELL_SIZE + MARGIN)
cell_y = MARGIN + row * (CELL_SIZE + MARGIN)
if (cell_x <= mouse_pos[0] <= cell_x + CELL_SIZE and
cell_y <= mouse_pos[1] <= cell_y + CELL_SIZE):
self.toggle_lights(row, col)
pygame.display.flip()
self.clock.tick(60)
if __name__ == "__main__":
game = LightsOut()
game.run()
```
### 代码解释
这个熄灯游戏实现包含以下核心组件:
1. **游戏逻辑类 `LightsOut`**:
- `__init__()`: 初始化游戏界面和状态
- `reset_game()`: 重置游戏,生成新的谜题
- `toggle_lights(row, col)`: 切换指定位置及其相邻灯的状态
- `is_solved()`: 检查所有灯是否都已熄灭
2. **界面绘制方法**:
- `draw_board()`: 绘制3×3的游戏网格
- `draw_buttons()`: 绘制重置和退出按钮
- `draw()`: 组合所有绘制元素
3. **游戏循环 `run()`**:
- 处理鼠标事件
- 更新游戏状态
- 渲染游戏界面
4. **游戏核心机制**:
- 每次点击一个灯,会切换该灯及其上下左右相邻灯的状态
- 目标是使所有灯都熄灭(False状态)
- 重置按钮会生成新的随机可解谜题
### 游戏功能说明
1. **交互功能**:
- 点击灯按钮:切换该灯及其相邻灯的状态
- 重置按钮:生成新的随机谜题
- 退出按钮:关闭游戏
2. **视觉反馈**:
- 亮灯:黄色
- 灭灯:蓝色
- 按钮:绿色(重置)和红色(退出)
- 移动计数:显示玩家已进行的操作次数
3. **成功状态**:
- 当所有灯熄灭时,显示"恭喜你解决谜题!"的消息
### 运行要求
要运行此游戏,需要安装 Pygame 库:
```
pip install pygame
```
游戏会创建一个3×3的网格界面,玩家需要通过多次点击熄灭所有灯。
---
###