如何在Pygame中随机放置船只?现有代码仅生成右侧坐标
Pygame船只随机放置问题修复
我希望在Pygame中实现如图所示的船只随机放置效果,但当前运行代码后,仅能生成#right分支下的船只坐标。请帮忙分析并给出修复方案:

现有代码
for i in range(1,6): while True: x,y = random.randrange(14,24,1),random.randrange(1,11,1) angle = ship_angle[random.randrange(0,4,1)] X,Y = x+i*math.cos(angle),y+i*math.sin(angle) if (14 <= X <= 24) and (1 <= Y <= 11) and (not((X,Y) in ai_ships)): #down if (x == X) and (y < Y): for d in range(i): ai_ships.add((x*TILE,(y+d)*TILE)) break #up if (x == X) and (y > Y): for d in range(i): ai_ships.add((x*TILE,(y-d)*TILE)) break #right if (y == Y) and (x < X): for d in range(i): ai_ships.add(((x+d)*TILE,y*TILE)) break #left if (y == Y) and (x > X): for d in range(i): ai_ships.add(((x-d)*TILE,y*TILE)) break else: continue
问题分析
- 浮点数精度误差:
math.cos和math.sin返回浮点数,哪怕是标准角度(如90度)的计算结果也可能出现微小偏差,导致x == X或y == Y的精确判断失效,上下左分支的条件无法触发。 - 边界检查不完整:仅验证船只终点
(X,Y)的合法性,未检查船只路径上的所有格子,可能导致部分船身超出边界或与其他船只重叠。 - 角度对应关系模糊:若
ship_angle数组中的角度值未严格对应上下左右的标准弧度,会直接导致方向判断逻辑失效。
修复方案
方案1:用方向偏移量替代三角函数(推荐)
直接通过方向枚举定义偏移量,彻底避免浮点数计算误差,逻辑更清晰:
import random # 定义四个正交方向:右、左、下、上(x偏移量,y偏移量) directions = [(1, 0), (-1, 0), (0, 1), (0, -1)] for ship_length in range(1, 6): while True: # 随机生成起始坐标 x = random.randrange(14, 24) y = random.randrange(1, 11) # 随机选择方向 dx, dy = random.choice(directions) # 预生成船只所有格子并验证合法性 ship_tiles = [] valid = True for d in range(ship_length): curr_x = x + d * dx curr_y = y + d * dy # 检查当前格子是否在边界内且未被占用 if not (14 <= curr_x <= 24 and 1 <= curr_y <= 11) or (curr_x, curr_y) in ai_ships: valid = False break ship_tiles.append((curr_x * TILE, curr_y * TILE)) if valid: ai_ships.update(ship_tiles) break
方案2:修复原代码的浮点数判断问题
若要保留原角度逻辑,需修改相等判断方式并补全路径检查:
import math import random # 确保ship_angle为标准正交弧度:右(0)、左(π)、下(π/2)、上(-π/2) ship_angle = [0, math.pi, math.pi/2, -math.pi/2] for i in range(1, 6): while True: x, y = random.randrange(14, 24, 1), random.randrange(1, 11, 1) angle = ship_angle[random.randrange(0, 4, 1)] # 对计算结果取整,消除浮点数误差 X = round(x + i * math.cos(angle)) Y = round(y + i * math.sin(angle)) if not (14 <= X <= 24 and 1 <= Y <= 11): continue # 验证船只所有路径格子 valid = True ship_tiles = [] if abs(x - X) < 1e-6: # 上下方向(x坐标近似相等) step = 1 if Y > y else -1 for d in range(i): curr_y = y + d * step if (x, curr_y) in ai_ships or not (1 <= curr_y <= 11): valid = False break ship_tiles.append((x * TILE, curr_y * TILE)) elif abs(y - Y) < 1e-6: # 左右方向(y坐标近似相等) step = 1 if X > x else -1 for d in range(i): curr_x = x + d * step if (curr_x, y) in ai_ships or not (14 <= curr_x <= 24): valid = False break ship_tiles.append((curr_x * TILE, y * TILE)) else: valid = False if valid: ai_ships.update(ship_tiles) break
核心修复点
- 替换精确相等判断:用
abs(a - b) < 1e-6或取整操作,避免浮点数精度误差导致的条件失效。 - 全路径合法性检查:遍历船只长度内的每一个格子,确保所有船身都在边界内且未被占用。
- 明确方向逻辑:要么用直观的方向偏移量,要么严格对应标准弧度,避免方向判断歧义。
内容的提问来源于stack exchange,提问作者Igor Bond
相关产品推荐
相关产品推荐

