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

Python战舰游戏generate_nship函数保存状态恢复失效问题

战舰游戏generate_*ship函数问题修复

核心问题分析

  • 部分放置后才回滚:当前代码逐个位置检查并放置舰船,遇到冲突时已修改棋盘部分位置,且savestate = board.copy()是浅拷贝(仅复制外层列表,内部列表仍为引用),回滚操作无效,递归重启函数时原棋盘已被部分修改。
  • sum获取单个元素的错误:用sum(pos[1])获取列表单个元素完全逻辑错误,仅因pos[1]是单元素列表巧合运行,正确做法是直接通过索引取元素,如pos[1][0]。
  • 棋盘初始化重复添加:print_board和print_pboard每次调用都会向棋盘添加新行,导致棋盘尺寸异常增大。

修复步骤及代码修改

1. 分离棋盘初始化与打印逻辑

单独写初始化函数,避免打印时修改棋盘:

def init_board():
    return [["O"] * 10 for _ in range(10)]

board = init_board()
pboard = init_board()

2. 抽象通用舰船生成函数

消除重复代码,先校验所有放置坐标是否可用,再批量放置,避免部分修改棋盘:

def generate_ship(board, length):
    while True:
        orientation = random.choice(["horizontal", "vertical"])
        coords = []
        if orientation == "horizontal":
            # 水平放置时,x起始位置需保证能放下整艘船
            x_start = random.randint(length - 1, 9)
            y = random.randint(0, 9)
            for i in range(length):
                coords.append((x_start - i, y))
        else:
            # 垂直放置时,y起始位置需保证能放下整艘船
            x = random.randint(0, 9)
            y_start = random.randint(length - 1, 9)
            for i in range(length):
                coords.append((x, y_start - i))
        
        # 检查所有坐标是否为空白
        if all(board[x][y] == "O" for x, y in coords):
            # 批量放置舰船
            for x, y in coords:
                board[x][y] = str(length)
            break

3. 简化fill_board函数

调用通用生成函数替代多个重复的generate_nship:

def fill_board():
    generate_ship(board, 5)
    generate_ship(board, 4)
    generate_ship(board, 4)
    generate_ship(board, 3)
    generate_ship(board, 3)
    generate_ship(board, 3)
    generate_ship(board, 2)
    generate_ship(board, 2)
    generate_ship(board, 2)
    generate_ship(board, 2)

4. 修复打印函数

让打印函数仅负责输出棋盘,不修改数据:

def print_board(board):
    print("Enemy Board:")
    print("  " + "  ".join(col))
    for idx, row_data in enumerate(board):
        print(f"{row[idx]} " + "  ".join(row_data))

def print_pboard(board):
    print("Your Board:")
    print("  " + "  ".join(col))
    for idx, row_data in enumerate(board):
        print(f"{row[idx]} " + "  ".join(row_data))

5. 修正命中判断逻辑

原代码命中判断条件错误,修复后正确识别舰船并标记:

def is_hit(x, y):
    if board[x][y] != "O" and board[x][y] != "X":
        print("Hit!")
        pboard[x][y] = "X"
        board[x][y] = "X"
    elif pboard[x][y] == "X":
        print("Already hit!")
    else:
        print("Miss!")
        pboard[x][y] = "M"

修复后的完整代码

import random

row = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
col = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]

def init_board():
    return [["O"] * 10 for _ in range(10)]

board = init_board()
pboard = init_board()

def print_board(board):
    print("Enemy Board:")
    print("  " + "  ".join(col))
    for idx, row_data in enumerate(board):
        print(f"{row[idx]} " + "  ".join(row_data))

def print_pboard(board):
    print("Your Board:")
    print("  " + "  ".join(col))
    for idx, row_data in enumerate(board):
        print(f"{row[idx]} " + "  ".join(row_data))

print("Welcome to Battleship!")

def get_coords():
    coord = str(input("Enter coordinates (e.g., A1): ").upper())
    if len(coord) == 3:
        if coord[2] == "0":
            return row.index(coord[0]), 9
    if len(coord) != 2:
        print("Invalid input. Please enter a letter followed by a number (e.g., A1).")
        return get_coords()
    if coord[0] not in row or not coord[1].isdigit() or int(coord[1]) < 1 or int(coord[1]) > 10:
        print("Invalid coordinates. Please try again.")
        return get_coords()
    return row.index(coord[0]), int(coord[1]) - 1

def generate_ship(board, length):
    while True:
        orientation = random.choice(["horizontal", "vertical"])
        coords = []
        if orientation == "horizontal":
            x_start = random.randint(length - 1, 9)
            y = random.randint(0, 9)
            for i in range(length):
                coords.append((x_start - i, y))
        else:
            x = random.randint(0, 9)
            y_start = random.randint(length - 1, 9)
            for i in range(length):
                coords.append((x, y_start - i))
        
        if all(board[x][y] == "O" for x, y in coords):
            for x, y in coords:
                board[x][y] = str(length)
            break

def fill_board():
    generate_ship(board, 5)
    generate_ship(board, 4)
    generate_ship(board, 4)
    generate_ship(board, 3)
    generate_ship(board, 3)
    generate_ship(board, 3)
    generate_ship(board, 2)
    generate_ship(board, 2)
    generate_ship(board, 2)
    generate_ship(board, 2)

def is_hit(x, y):
    if board[x][y] != "O" and board[x][y] != "X":
        print("Hit!")
        pboard[x][y] = "X"
        board[x][y] = "X"
    elif pboard[x][y] == "X":
        print("Already hit!")
    else:
        print("Miss!")
        pboard[x][y] = "M"

def get_win_condition():
    for i in range(10):
        for j in range(10):
            if board[i][j] not in ["O", "X"]:
                return False
    return True

def get_misses():
    misses = 0
    for i in range(10):
        for j in range(10):
            if pboard[i][j] == "M":
                misses += 1
    return misses

def get_hits_left():
    hits_left = 0
    for i in range(10):
        for j in range(10):
            if board[i][j] not in ["O", "X"]:
                hits_left += 1
    return hits_left

fill_board()

while True:
    print_board(board)
    x, y = get_coords()
    is_hit(x, y)
    print_pboard(pboard)
    hits_left = get_hits_left()
    print(f"Hits left: {hits_left}")
    if get_win_condition():
        print("You win!")
        print(f"You missed {get_misses()} times!")
        break
print("Game Over!")

关键修改说明

  • 通用生成函数彻底解决了部分放置后回滚的问题,先校验所有坐标再批量放置。
  • 移除了错误的sum用法,直接生成坐标元组,逻辑更清晰。
  • 分离初始化与打印逻辑,避免棋盘尺寸异常。
  • 修正了命中判断的逻辑错误,确保正确识别舰船命中状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 12:32:01