You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

扫雷棋盘生成器Bug:大尺寸棋盘周边地雷计数错误

扫雷游戏棋盘生成计数错误排查

问题描述

编写的扫雷棋盘生成Python代码,在生成10×10、含10个地雷的棋盘时输出正确,但生成10×15、含30个地雷的棋盘时,部分格子的周边地雷计数出现错误(例如标注的4应为3,5应为4)。

原代码

import random

objects = []

class Minesweeper_gameboard():
    def __init__(self, width, height, num_mines):
        self.width = width
        self.height = height
        self.num_mines = num_mines
        objects.append(self)
    def game_board(self):
        
        board = [[0 for i in range(self.height)] for j in range(self.width)]
        number_of_mines = 0
        
        while number_of_mines < self.num_mines:
            x = random.randint(0, self.width - 1)
            y = random.randint(0, self.height - 1)
            
            #Create conditions, when test is true, adopt range: a_True; when test is false, adopt range: a_False
            a_test = (x - 1) >= 0
            b_test = (x + 1) < self.width
            c_test = (y - 1) >= 0
            d_test = (y + 1) < self.height
            #when (x-1) is more or equal to 0, use (x-1) as the starting point of the range, vice versa
            a_True = x-1 
            b_True = x+2
            c_True = y-1
            d_True = y+2
            #when (x-1) is less than 0, x locate at the corner, use x as the starting point of the range, vice versa
            a_False = x 
            b_False = x+1
            c_False = y
            d_False = y+1
            
            condition_list = [[a_test, a_True, a_False], [b_test, b_True, b_False],
                                [c_test, c_True, c_False], [d_test, d_True, d_False]]
            #Delete the condition that is not satisfied
            for i in condition_list:
                if i[0] == True:
                    del i[0]
                    del i[1]
                else:
                    del i[0]
                    del i[0]
            #Flatten the list with a nested loop
            condition_list = [a for b in condition_list for a in b]
            #Create Rules to illustrate mine locations            
            if board[x][y] != 'X':
                board[x][y] = 'X'
                number_of_mines += 1
            try:
            #call out the flatten condition_list as the range to illustrate the number of mines nearby
                for i in range(condition_list[0], condition_list[1]):
                    for j in range(condition_list[2], condition_list[3]):
                        if board[i][j] != 'X':
                            board[i][j] += 1
            except:
                continue
            else:
                x = random.randint(0, self.width-1)
                y = random.randint(0, self.height-1)
        return board
    
    def player_board(self):
        player_board = [['-' for i in range(self.height)] for j in range(self.width)]
    
    def display_board(self, board):
        for row in board:
            print(" ".join(str(cell) for cell in row))
            print("")
            
#testing function
mine = Minesweeper_gameboard(10,10,10)
for object in objects:
    object.game_board()
    object.display_board(object.game_board())

测试情况

正确输出(10×10、10个地雷)

X 2 0 0 1 1 1 0 0 0

X 2 0 0 1 X 2 1 0 0

1 1 0 0 1 2 X 1 0 0

0 1 2 2 1 1 1 1 0 0

1 2 X X 1 0 0 1 2 2

X 2 2 2 1 0 0 1 X X

1 1 0 0 0 0 0 1 2 2

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 1 1 1 0 0

0 0 0 0 0 1 X 1 0 0

错误输出(10×15、30个地雷)

0 0 0 0 1 X 2 X X X 3 1 X 1 0

0 1 1 2 2 2 3 4 7 X 3 1 1 1 0

2 **4** X 3 X 1 1 X X 3 2 0 1 1 1

X **5** X 4 2 2 2 2 2 1 0 0 1 X 1

3 5 X 3 2 X 1 0 1 1 2 1 2 1 1

X 2 1 2 X 2 2 2 4 X 3 X 1 0 0

1 2 1 2 1 1 1 X X X 4 1 2 1 1

0 1 X 2 1 0 1 3 X X 2 0 1 X 1

0 1 2 X 3 2 2 2 3 3 1 0 2 2 2

0 0 1 1 3 X 2 1 X 1 0 0 1 X 1

错误说明:标注的4应为3,5应为4。

问题原因分析

  1. 重复累加计数:当随机数重复选中已存在地雷的位置时,代码不会新增地雷,但仍会执行周边格子的计数累加操作,导致这些格子的计数被多算一次。这是核心错误,当地雷数量占比越高(如10×15棋盘放30个地雷,占比20%),重复选中的概率就越高,计数错误就越明显。
  2. 棋盘重复生成:测试代码中连续调用两次game_board(),第一次生成的棋盘未被使用,第二次生成新棋盘进行展示,虽然不直接导致计数错误,但属于冗余逻辑。
  3. 多余的else分支:try-except后的else分支会重新生成随机坐标,但此时循环会继续迭代,导致逻辑混乱,可能引发不必要的重复处理。

修复方案

修复后的代码

import random

objects = []

class Minesweeper_gameboard():
    def __init__(self, width, height, num_mines):
        self.width = width
        self.height = height
        self.num_mines = num_mines
        objects.append(self)
    
    def game_board(self):
        board = [[0 for _ in range(self.height)] for _ in range(self.width)]
        number_of_mines = 0
        
        while number_of_mines < self.num_mines:
            x = random.randint(0, self.width - 1)
            y = random.randint(0, self.height - 1)
            
            # 跳过已存在地雷的位置
            if board[x][y] == 'X':
                continue
            
            # 设置当前位置为地雷
            board[x][y] = 'X'
            number_of_mines += 1
            
            # 计算周边格子的范围,避免越界
            x_start = max(x - 1, 0)
            x_end = min(x + 2, self.width)
            y_start = max(y - 1, 0)
            y_end = min(y + 2, self.height)
            
            # 遍历周边格子并累加计数
            for i in range(x_start, x_end):
                for j in range(y_start, y_end):
                    if board[i][j] != 'X':
                        board[i][j] += 1
        
        return board
    
    def player_board(self):
        return [['-' for _ in range(self.height)] for _ in range(self.width)]
    
    def display_board(self, board):
        for row in board:
            print(" ".join(str(cell) for cell in row))
            print("")
            
# 测试函数
mine = Minesweeper_gameboard(10,15,30)
for obj in objects:
    generated_board = obj.game_board()
    obj.display_board(generated_board)

修复要点

  • 跳过重复地雷位置:新增判断,若选中的坐标已经是地雷则直接跳过,不执行后续计数累加。
  • 简化范围计算:用max()和min()直接计算合法的边界范围,替代原有的复杂列表处理逻辑,更简洁且不易出错。
  • 避免重复生成棋盘:将生成的棋盘保存到变量中,再传入display_board展示。
  • 移除冗余逻辑:删除不必要的try-except和else分支,简化代码流程。

内容的提问来源于stack exchange,提问作者Becky1122

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 15:45:05