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

Python战舰游戏开发求助:对战循环与胜负判断问题

战舰(Battleship)游戏改进方案

当前代码存在的核心问题

  • 没有实现对战循环:船只放置完成后游戏直接终止,玩家和电脑无法互相攻击
  • 电脑攻击逻辑错误:check_comp_hit函数要求玩家输入坐标,完全不符合电脑自动攻击的逻辑
  • 代码冗余严重:玩家放置5艘船的逻辑重复了5次,维护成本高
  • 缺少胜负判定机制:没有检测双方战舰是否全部被击沉的逻辑
  • 无重复攻击防护:玩家或电脑可能重复攻击同一坐标,导致无效操作

具体改进步骤

1. 实现对战循环

在主函数中添加循环,交替执行玩家攻击和电脑攻击,直到某一方所有战舰被击沉。

2. 修复电脑攻击逻辑

让电脑随机生成攻击坐标,并且记录已攻击过的位置,避免重复攻击。

3. 重构重复代码

将玩家放置单艘船的逻辑封装成通用函数,通过遍历ship_initial和ship_names批量处理所有船只放置,减少冗余。

4. 添加游戏结束检测函数

编写函数统计战场中剩余的战舰数量,当某一方战舰数量为0时判定游戏结束,宣布胜负。

5. 优化战场显示逻辑

  • 玩家自己的战场:显示所有船只位置、被击中的船只和电脑的攻击 miss
  • 玩家看到的电脑战场:只显示自己击中的船只和miss,隐藏电脑未被攻击的船只位置

6. 添加重复攻击检测

记录双方已攻击的坐标,当攻击重复坐标时提示用户并重新输入。

修改后的完整代码

from random import randrange

ship_initial = ["B", "C", "F", "A", "S"]
ship_names = ["Battleship", "Cruiser", "Frigate", "Aircraft Carrier", "Submarine"]
map_size = 10

def get_username():
    while True:
        user_name = input("Enter your name: ")
        if user_name:
            print(f"Welcome to the Battleship game {user_name}!")
            return user_name
        print("Please enter a valid name.")

def create_battlefield(map_size):
    return [["_"] * map_size for _ in range(map_size)]

def display_battlefield(board, show_ships=True):
    # 打印列号
    print("  " + " ".join(str(i) for i in range(map_size)))
    for idx, row in enumerate(board):
        # 打印行号和每行内容
        display_row = []
        for cell in row:
            if not show_ships and cell in ship_initial:
                display_row.append("_")
            else:
                display_row.append(cell)
        print(f"{idx} " + " ".join(display_row))

def place_single_ship(board, ship_char, ship_name, occupied):
    while True:
        try:
            row = int(input(f"Enter the row for {ship_name}: "))
            col = int(input(f"Enter the column for {ship_name}: "))
            if 0 <= row < map_size and 0 <= col < map_size and (row, col) not in occupied:
                board[row][col] = ship_char
                occupied.add((row, col))
                break
            print("Invalid coordinates. Please enter values between 0-9 and not already occupied.")
        except ValueError:
            print("Invalid input. Please enter a valid integer.")

def player_ship_coordinate(player_board):
    occupied = set()
    for char, name in zip(ship_initial, ship_names):
        place_single_ship(player_board, char, name, occupied)
    return player_board

def comp_ship_coordinate(comp_board):
    occupied = set()
    for ship in ship_initial:
        while True:
            row = randrange(0, map_size)
            col = randrange(0, map_size)
            if (row, col) not in occupied:
                comp_board[row][col] = ship
                occupied.add((row, col))
                break
    return comp_board

def player_attack(comp_board, player_view, player_attacked):
    while True:
        try:
            row = int(input("\nEnter attack row (0-9): "))
            col = int(input("Enter attack column (0-9): "))
            if not (0 <= row < map_size and 0 <= col < map_size):
                print("Coordinates out of range! Enter 0-9.")
                continue
            if (row, col) in player_attacked:
                print("You already attacked this spot! Choose another.")
                continue
            
            player_attacked.add((row, col))
            if comp_board[row][col] in ship_initial:
                ship_idx = ship_initial.index(comp_board[row][col])
                print(f"Hit! You sunk the computer's {ship_names[ship_idx]}!")
                player_view[row][col] = comp_board[row][col]
                # 标记被击沉的战舰
                comp_board[row][col] = "X"
            else:
                print("Miss!")
                player_view[row][col] = "M"
            break
        except ValueError:
            print("Invalid input. Enter integers only.")

def comp_attack(player_board, comp_view, comp_attacked):
    while True:
        row = randrange(0, map_size)
        col = randrange(0, map_size)
        if (row, col) not in comp_attacked:
            comp_attacked.add((row, col))
            print(f"\nComputer attacks row {row}, column {col}!")
            if player_board[row][col] in ship_initial:
                ship_idx = ship_initial.index(player_board[row][col])
                print(f"Oh no! The computer hit your {ship_names[ship_idx]}!")
                comp_view[row][col] = player_board[row][col]
                # 标记被击沉的战舰
                player_board[row][col] = "X"
            else:
                print("Computer missed!")
                comp_view[row][col] = "M"
            break

def check_game_over(board):
    # 检查战场中是否还有剩余战舰
    for row in board:
        for cell in row:
            if cell in ship_initial:
                return False
    return True

if __name__ == "__main__":
    username = get_username()

    # 创建战场
    player_board = create_battlefield(map_size)
    comp_board = create_battlefield(map_size)
    # 玩家看到的电脑战场(隐藏未攻击的船只)
    player_view = create_battlefield(map_size)
    # 记录电脑攻击结果的战场
    comp_view = create_battlefield(map_size)

    # 放置船只
    print("\n=== Place Your Ships ===")
    player_ship_coordinate(player_board)
    print("\nYour Battlefield:")
    display_battlefield(player_board)

    print("\n=== Computer is Placing Ships ===")
    comp_ship_coordinate(comp_board)
    print("Computer's Battlefield (hidden):")
    display_battlefield(player_view, show_ships=False)

    # 记录已攻击的坐标
    player_attacked = set()
    comp_attacked = set()

    # 对战循环
    while True:
        # 玩家回合
        print("\n=== Your Turn to Attack ===")
        display_battlefield(player_view, show_ships=False)
        player_attack(comp_board, player_view, player_attacked)
        if check_game_over(comp_board):
            print(f"\nCongratulations {username}! You won!")
            break

        # 电脑回合
        print("\n=== Computer's Turn to Attack ===")
        display_battlefield(player_board)
        comp_attack(player_board, comp_view, comp_attacked)
        if check_game_over(player_board):
            print("\nGame Over! The computer won.")
            break

改进说明

  • 重构了船只放置逻辑,用循环替代重复代码,更易维护
  • 修复了电脑攻击逻辑,实现自动随机攻击并避免重复
  • 添加了游戏结束检测,能正确判定胜负
  • 优化了战场显示,玩家只能看到自己攻击过的电脑战场区域,符合真实游戏逻辑
  • 增加了重复攻击检测,避免无效操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 06:00:03