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
相关产品推荐
相关产品推荐

