minesweeper.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import random
  2. import os
  3. class Minesweeper:
  4. def __init__(self, width=10, height=10, mines=10):
  5. self.width = width
  6. self.height = height
  7. self.mines = mines
  8. self.board = [[0 for _ in range(width)] for _ in range(height)]
  9. self.revealed = [[False for _ in range(width)] for _ in range(height)]
  10. self.marked = [[False for _ in range(width)] for _ in range(height)]
  11. self.game_over = False
  12. self.win = False
  13. self.first_click = True
  14. def place_mines(self, exclude_x, exclude_y):
  15. """在除了第一次点击位置之外的地方放置地雷"""
  16. positions = [(x, y) for x in range(self.width) for y in range(self.height)]
  17. positions.remove((exclude_x, exclude_y)) # 确保第一次点击的位置没有地雷
  18. mine_positions = random.sample(positions, self.mines)
  19. for x, y in mine_positions:
  20. self.board[y][x] = -1 # -1 表示地雷
  21. # 计算每个非地雷格子周围的地雷数
  22. for y in range(self.height):
  23. for x in range(self.width):
  24. if self.board[y][x] == -1:
  25. continue
  26. count = 0
  27. for dy in [-1, 0, 1]:
  28. for dx in [-1, 0, 1]:
  29. if dx == 0 and dy == 0:
  30. continue
  31. nx, ny = x + dx, y + dy
  32. if 0 <= nx < self.width and 0 <= ny < self.height:
  33. if self.board[ny][nx] == -1:
  34. count += 1
  35. self.board[y][x] = count
  36. def reveal(self, x, y):
  37. """揭示一个格子"""
  38. if not (0 <= x < self.width and 0 <= y < self.height):
  39. return
  40. if self.revealed[y][x] or self.marked[y][x]:
  41. return
  42. if self.first_click:
  43. self.place_mines(x, y)
  44. self.first_click = False
  45. self.revealed[y][x] = True
  46. # 如果点击到地雷,游戏结束
  47. if self.board[y][x] == -1:
  48. self.game_over = True
  49. return
  50. # 如果周围没有地雷,自动揭示周围的格子
  51. if self.board[y][x] == 0:
  52. for dy in [-1, 0, 1]:
  53. for dx in [-1, 0, 1]:
  54. if dx == 0 and dy == 0:
  55. continue
  56. self.reveal(x + dx, y + dy)
  57. # 检查是否获胜
  58. self.check_win()
  59. def toggle_mark(self, x, y):
  60. """标记或取消标记一个格子"""
  61. if not (0 <= x < self.width and 0 <= y < self.height):
  62. return
  63. if self.revealed[y][x]:
  64. return
  65. self.marked[y][x] = not self.marked[y][x]
  66. self.check_win()
  67. def check_win(self):
  68. """检查是否获胜"""
  69. for y in range(self.height):
  70. for x in range(self.width):
  71. # 如果所有非地雷格子都被揭示,则获胜
  72. if self.board[y][x] != -1 and not self.revealed[y][x]:
  73. return
  74. self.win = True
  75. self.game_over = True
  76. def display(self):
  77. """显示游戏板"""
  78. # 清屏
  79. os.system('cls' if os.name == 'nt' else 'clear')
  80. # 打印列号
  81. print(" ", end="")
  82. for x in range(self.width):
  83. print(f"{x % 10} ", end="")
  84. print()
  85. # 打印分隔线
  86. print(" ", end="")
  87. for x in range(self.width):
  88. print("- ", end="")
  89. print()
  90. # 打印行
  91. for y in range(self.height):
  92. print(f"{y % 10}|", end="") # 行号
  93. for x in range(self.width):
  94. if self.marked[y][x]:
  95. print("F ", end="") # 标记
  96. elif not self.revealed[y][x]:
  97. print(". ", end="") # 未揭示
  98. elif self.board[y][x] == -1:
  99. print("* ", end="") # 地雷
  100. elif self.board[y][x] == 0:
  101. print(" ", end="") # 空白
  102. else:
  103. print(f"{self.board[y][x]} ", end="") # 数字
  104. print()
  105. def play(self):
  106. """开始游戏"""
  107. while not self.game_over:
  108. self.display()
  109. print("\n命令:")
  110. print(" r x y - 揭示格子 (例如: r 3 5)")
  111. print(" m x y - 标记/取消标记格子 (例如: m 3 5)")
  112. print(" q - 退出游戏")
  113. try:
  114. command = input("\n请输入命令: ").strip().split()
  115. if not command:
  116. continue
  117. if command[0].lower() == 'q':
  118. return
  119. if len(command) != 3:
  120. print("无效命令!请按照格式输入。")
  121. continue
  122. action = command[0].lower()
  123. x = int(command[1])
  124. y = int(command[2])
  125. if action == 'r':
  126. self.reveal(x, y)
  127. elif action == 'm':
  128. self.toggle_mark(x, y)
  129. else:
  130. print("无效命令!使用 'r' 揭示或 'm' 标记。")
  131. except (ValueError, IndexError):
  132. print("无效输入!请确保输入正确的坐标。")
  133. # 游戏结束,显示最终结果
  134. self.display()
  135. if self.win:
  136. print("\n恭喜你!你赢了!")
  137. else:
  138. print("\n游戏结束!你踩到地雷了。")
  139. def main():
  140. print("欢迎来到扫雷游戏!")
  141. print("游戏规则:")
  142. print("1. 输入 'r x y' 来揭示坐标 (x,y) 的格子")
  143. print("2. 输入 'm x y' 来标记/取消标记可能有地雷的格子")
  144. print("3. 数字表示周围8个格子中有多少个地雷")
  145. print("4. 标记所有地雷并揭示所有安全格子即可获胜")
  146. print("\n按回车键开始游戏...")
  147. input()
  148. # 创建游戏实例(10x10的棋盘,10个地雷)
  149. game = Minesweeper(10, 10, 10)
  150. game.play()
  151. if __name__ == "__main__":
  152. main()