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

Python战舰游戏AI棋盘生成问题:舰船重叠与函数返回异常

控制台战舰游戏AI棋盘生成问题解决方法

我正在用Python开发一款控制台战舰游戏,AI方拥有3艘长度为3格的舰船,舰船格用O表示,水域格用*表示,棋盘是7x7的二维列表。多数情况下create_board函数能正常生成3艘3格舰船,但偶尔会出现舰船重叠,导致2艘3格舰船和1艘2格舰船,总舰船格数不足9。我尝试通过检查总舰船格数,若不足则重新调用函数生成棋盘,但此时函数未返回结果,出现列表为空的错误。请问如何确保舰船永不重叠,且始终生成3艘长度为3格的舰船?

附原始代码:

import random

ai_board = [['*' for _ in range(7)] for _ in range(7)]

def create_board(starting_board):
    for i in range(3):
        anchor_x = random.randint(0, 6)
        anchor_y = random.randint(0, 6)

        starting_board[anchor_y][anchor_x] = 'O'
        orientation = random.choice(['h', 'v'])

        if orientation == 'h':
            if anchor_x > 4:
                starting_board[anchor_y][anchor_x-1] = 'O'
                starting_board[anchor_y][anchor_x-2] = 'O'
            else:
                starting_board[anchor_y][anchor_x+1] = 'O'
                starting_board[anchor_y][anchor_x+2] = 'O'
        else:
            if anchor_y > 4:
                starting_board[anchor_y-1][anchor_x] = 'O'
                starting_board[anchor_y-2][anchor_x] = 'O'
            else:
                starting_board[anchor_y+1][anchor_x] = 'O'
                starting_board[anchor_y+2][anchor_x] = 'O'

    ship_count = 0

    for row in starting_board:
        for column in row:
            if column == 'O':
                ship_count += 1

    if ship_count == 9:
        return starting_board

    if ship_count < 9:
        new_board = [['*' for _ in range(7)] for _ in range(7)]
        create_board(new_board)

ai_board = create_board(ai_board)

for row in ai_board:
    print(" ".join(row))

我原本期望通过递归调用函数修正棋盘,但实际出现了函数未返回内容的错误。


问题根源

  • 递归未返回结果:当ship_count < 9时,递归调用create_board(new_board)但未将递归的返回值向上传递,导致上层函数接收到None,最终ai_board为空。
  • 无重叠检查逻辑:直接随机放置舰船,未提前验证目标位置是否已被占用,导致重叠后总舰船格数不足9。

修正方案

方案一:修复递归返回问题(治标)

在递归调用时添加return语句,确保有效棋盘能逐层返回:

if ship_count < 9:
    new_board = [['*' for _ in range(7)] for _ in range(7)]
    return create_board(new_board)  # 添加return传递递归结果

但此方法仅解决返回问题,本质靠重试避免重叠,效率较低,极端情况可能陷入递归循环。

方案二:预检查放置位置(治本)

修改舰船放置逻辑,每艘船放置前先验证所有目标格子是否为水域,只有全部可用时才放置,从根源避免重叠。

完整修正代码:

import random

def create_board():
    # 初始化空棋盘
    board = [['*' for _ in range(7)] for _ in range(7)]
    ships_placed = 0

    while ships_placed < 3:
        # 随机生成锚点和方向
        anchor_x = random.randint(0, 6)
        anchor_y = random.randint(0, 6)
        orientation = random.choice(['h', 'v'])
        positions = []

        # 计算当前舰船的所有格子位置
        if orientation == 'h':
            if anchor_x <= 4:
                positions = [(anchor_y, anchor_x + offset) for offset in range(3)]
            else:
                positions = [(anchor_y, anchor_x - offset) for offset in range(3)]
        else:
            if anchor_y <= 4:
                positions = [(anchor_y + offset, anchor_x) for offset in range(3)]
            else:
                positions = [(anchor_y - offset, anchor_x) for offset in range(3)]
        
        # 检查所有位置是否未被占用
        valid = True
        for y, x in positions:
            if board[y][x] != '*':
                valid = False
                break
        
        # 位置有效则放置舰船
        if valid:
            for y, x in positions:
                board[y][x] = 'O'
            ships_placed += 1
    
    return board

ai_board = create_board()

for row in ai_board:
    print(" ".join(row))

代码说明

  • 移除原始函数的starting_board参数,改为内部初始化空棋盘,逻辑更简洁。
  • 使用while循环确保3艘舰船全部成功放置,每艘船放置前先验证所有目标位置的可用性。
  • 预计算舰船的所有格子位置,通过遍历检查是否存在已占用的O,只有全部有效才执行放置操作,彻底避免重叠。
  • 无需再通过统计总格子数重试,效率更高且逻辑更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 20:05:03