Python战舰游戏开发教程:构建核心游戏循环与智能命中检测(战舰.命中.游戏开发.构建.循环...)

wufei123 发布于 2025-08-29 阅读(5)

Python战舰游戏开发教程:构建核心游戏循环与智能命中检测

本教程详细指导如何在Python中构建一个功能完善的战舰游戏。我们将从基础的游戏板创建和船只放置开始,逐步深入探讨如何实现回合制游戏循环、玩家与电脑的交互、智能的命中检测逻辑,以及如何利用“虚拟”敌方战场提升用户体验,最终实现完整的游戏胜利判断。1. 游戏基础结构与初始化

构建战舰游戏首先需要定义游戏的基本元素和初始化流程。这包括欢迎玩家、创建游戏地图、以及玩家和电脑船只的初始部署。

1.1 用户欢迎与地图创建

游戏开始时,首先获取玩家昵称并显示欢迎信息。游戏地图通过二维列表表示,初始状态下所有格子均为空(_)。

from random import randrange

# 船只类型定义
ship_initial = ["B", "C", "F", "A", "S"]
ship_names = ["Battleship", "Cruiser", "Frigate", "Aircraft Carrier", "Sub"]
map_size = 10 # 地图大小

def get_username():
    """获取玩家昵称"""
    while True:
        user_name = input("请输入您的名字: ")
        if user_name:
            print(f"欢迎来到战舰游戏, {user_name}!")
            return user_name
        else:
            print("请勿输入空值。")

def create_battlefield(size):
    """根据指定大小创建游戏地图"""
    return [["_"] * size for _ in range(size)]

def display_battlefield(board):
    """显示当前地图状态"""
    for row in board:
        print(" ".join(row))
1.2 玩家与电脑船只部署

玩家手动输入坐标放置船只,电脑则随机放置。为避免船只重叠,玩家放置时需检查坐标是否已被占用;电脑放置时则需确保目标格子为空。

def player_ship_coordinate(player_board, occupied_coords):
    """
    玩家手动放置船只。
    参数:
        player_board: 玩家自己的地图。
        occupied_coords: 一个集合,存储已被占用的坐标,防止船只重叠。
    """
    print("请放置您的船只:")
    for i, ship_name in enumerate(ship_names):
        while True:
            try:
                row = int(input(f"请输入 {ship_name} 的行坐标 (0-9): "))
                col = int(input(f"请输入 {ship_name} 的列坐标 (0-9): "))
                if 0 <= row < map_size and 0 <= col < map_size and (row, col) not in occupied_coords:
                    player_board[row][col] = ship_initial[i]
                    occupied_coords.add((row, col))
                    break
                else:
                    print("无效坐标或该位置已被占用。请重新输入。")
            except ValueError:
                print("输入无效。请输入一个整数。")
    return player_board, occupied_coords

def comp_ship_coordinate(comp_board):
    """
    电脑随机放置船只。
    参数:
        comp_board: 电脑的地图。
    """
    for ship_char in ship_initial:
        while True:
            row = randrange(0, map_size)
            col = randrange(0, map_size)
            if comp_board[row][col] == "_":
                comp_board[row][col] = ship_char
                break
    return comp_board
2. 实现回合制游戏循环

游戏的核心是回合制循环,玩家和电脑轮流攻击,直到一方所有船只被击沉。

2.1 游戏主循环结构

在 if __name__ == "__main__": 块中,我们初始化游戏并进入一个无限循环,直到有玩家获胜。player_hits 和 comp_hits 变量用于跟踪双方击沉的船只数量。

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

    player_board = create_battlefield(map_size)
    comp_board = create_battlefield(map_size)
    dummy_board = create_battlefield(map_size) # 玩家视角的电脑地图,初始为空

    occupied_coords = set()

    print("\n玩家部署船只:")
    player_ship_coordinate(player_board, occupied_coords)
    print("\n您的战场:")
    display_battlefield(player_board)

    print("\n电脑部署船只:")
    comp_ship_coordinate(comp_board)
    # display_battlefield(comp_board) # 测试时可以显示电脑地图,实际游戏中应隐藏
    print("\n电脑的战场 (您的攻击目标):")
    display_battlefield(dummy_board) # 玩家只能看到虚拟地图

    player_hits = 0 # 玩家击中电脑船只的数量
    comp_hits = 0   # 电脑击中玩家船只的数量

    while True:
        print(f"\n--- {user} 的回合 ---")
        # 玩家攻击
        hit_status = check_player_hit(comp_board, dummy_board, user)
        player_hits += hit_status
        print("\n电脑的战场 (您的攻击结果):")
        display_battlefield(dummy_board)

        if player_hits == len(ship_initial): # 如果玩家击沉所有船只
            print(f"\n恭喜 {user},您击沉了所有敌舰,赢得游戏!")
            break

        print("\n--- 电脑的回合 ---")
        # 电脑攻击
        hit_status = check_comp_hit(player_board)
        comp_hits += hit_status
        print("\n您的战场 (电脑的攻击结果):")
        display_battlefield(player_board)

        if comp_hits == len(ship_initial): # 如果电脑击沉所有船只
            print("\n很遗憾,电脑击沉了您的所有船只,电脑赢得游戏!")
            break
3. 玩家射击与“虚拟”敌方战场

为了提供更好的游戏体验,玩家不应直接看到电脑的船只部署。我们引入一个“虚拟战场”(dummy_board),它只显示玩家的攻击结果(命中或未命中)。

3.1 check_player_hit 函数

这个函数负责处理玩家的攻击。它接收电脑的真实地图 (comp_board) 和玩家视角的虚拟地图 (dummy_board)。

  • 玩家输入攻击坐标。
  • 根据 comp_board 判断是否命中。
  • 如果命中,dummy_board 对应位置标记为 'X',comp_board 上的船只标记为小写字母(表示已击中)。
  • 如果未命中,dummy_board 对应位置标记为 '*'。
  • 函数返回 1 表示命中,0 表示未命中。
def check_player_hit(comp_board, dummy_board, user_name):
    """
    玩家攻击敌方船只。
    参数:
        comp_board: 电脑的真实地图。
        dummy_board: 玩家可见的虚拟地图。
        user_name: 玩家昵称,用于提示信息。
    返回: 1 表示命中,0 表示未命中。
    """
    while True:
        try:
            print(f"{user_name},请选择您的攻击坐标。")
            row = int(input("请输入攻击的行坐标 (0-9): "))
            col = int(input("请输入攻击的列坐标 (0-9): "))
            if 0 <= row < map_size and 0 <= col < map_size:
                # 检查是否重复攻击同一位置
                if dummy_board[row][col] != '_' :
                    print("您已经攻击过这个位置了。请选择其他坐标。")
                    continue
                break
            else:
                print("无效坐标。请重新输入 (0-9)。")
        except ValueError:
            print("输入无效。请输入一个整数。")

    hit = 0 # 默认未命中

    target_char = comp_board[row][col]
    if target_char in ship_initial: # 命中船只
        comp_board[row][col] = target_char.lower() # 标记为已击中(小写)
        dummy_board[row][col] = "X" # 虚拟地图显示命中
        print(f"命中!电脑的 {ship_names[ship_initial.index(target_char)]} 被击中了!")
        hit = 1
    else: # 未命中
        dummy_board[row][col] = "*" # 虚拟地图显示未命中
        print("未命中!")
    return hit
4. 电脑AI射击逻辑

电脑的攻击需要一定的智能性,至少要避免重复攻击已命中或已尝试过的位置。

4.1 check_comp_hit 函数

这个函数处理电脑的攻击。

  • 电脑随机选择一个坐标,但会确保该坐标之前未被攻击过(即不是 '*' 或已击中的小写船只字符)。
  • 根据 player_board 判断是否命中。
  • 如果命中,player_board 上的船只标记为小写字母。
  • 如果未命中,player_board 对应位置标记为 '*'。
  • 函数返回 1 表示命中,0 表示未命中。
def check_comp_hit(player_board):
    """
    电脑攻击玩家船只。
    参数:
        player_board: 玩家的真实地图。
    返回: 1 表示命中,0 表示未命中。
    """
    hit = 0 # 默认未命中

    while True: # 随机选择一个未曾攻击过的位置
        row = randrange(0, map_size)
        col = randrange(0, map_size)
        # 确保电脑不会重复攻击已经命中或尝试过的位置
        if player_board[row][col] not in ["*", "a", "b", "c", "f", "s"]:
            break

    print(f"电脑选择了坐标 ({row}, {col}) 进行攻击。")

    target_char = player_board[row][col]
    if target_char in ship_initial: # 命中船只
        player_board[row][col] = target_char.lower() # 标记为已击中(小写)
        print(f"您的 {ship_names[ship_initial.index(target_char)]} 被击中了!")
        hit = 1
    else: # 未命中
        player_board[row][col] = "*" # 标记为未命中
        print("电脑未命中!")
    return hit
5. 游戏胜利条件判断

游戏胜利的条件是当一方击沉了对方所有船只。在本教程中,我们假设每艘船只占据一个格子,共有5艘船。因此,当 player_hits 或 comp_hits 达到5时,游戏结束。

在主游戏循环中,每次攻击后都会检查胜利条件:

        # ... (玩家攻击代码) ...
        player_hits += hit_status
        # ... (显示玩家视角电脑地图) ...

        if player_hits == len(ship_initial): # 如果玩家击沉所有船只
            print(f"\n恭喜 {user},您击沉了所有敌舰,赢得游戏!")
            break

        # ... (电脑攻击代码) ...
        comp_hits += hit_status
        # ... (显示玩家地图) ...

        if comp_hits == len(ship_initial): # 如果电脑击沉所有船只
            print("\n很遗憾,电脑击沉了您的所有船只,电脑赢得游戏!")
            break
6. 注意事项与代码优化建议
  • 错误处理增强: 当前代码已包含基本的 try-except 进行输入验证,但可以进一步细化,例如对玩家输入坐标的范围进行更严格的检查,并提供更友好的提示。
  • 船只大小与方向: 现有实现中所有船只都只占据一个格子。要实现更真实的战舰游戏,需要扩展船只类,使其具有长度和方向(水平或垂直),并在放置船只时进行碰撞检测和边界检查。
  • 游戏状态管理: 可以引入一个更复杂的船只对象来管理每艘船的状态(如生命值、是否被击沉),而不是仅仅通过地图上的字符变化来判断。
  • 更智能的电脑AI: 当前电脑AI只是随机攻击未曾攻击过的位置。更高级的AI可以在击中船只后,优先攻击相邻的格子,以“追踪”并击沉船只。
  • 用户界面: 对于命令行游戏,可以考虑使用ANSI转义序列来为输出添加颜色,提升可读性。如果希望更复杂的界面,可以考虑使用Pygame等图形库。
  • 模块化: 随着游戏复杂度的增加,可以将不同的功能(如船只管理、玩家操作、电脑AI)拆分到不同的模块或类中,提高代码的可维护性。例如,可以创建 Ship 类、Player 类和 Computer 类。
  • 代码可读性: 确保变量命名清晰,函数功能单一,并添加足够的注释。
总结

通过本教程,我们构建了一个Python战舰游戏的基础框架,涵盖了从游戏初始化、船只部署到回合制战斗循环和胜利条件判断的核心逻辑。关键改进包括引入“虚拟战场”以隐藏电脑船只位置,以及优化电脑AI使其避免重复攻击。这个基础版本为进一步扩展和提升游戏体验奠定了坚实的基础,例如实现多格船、更复杂的AI策略以及图形用户界面等。

以上就是Python战舰游戏开发教程:构建核心游戏循环与智能命中检测的详细内容,更多请关注知识资源分享宝库其它相关文章!

标签:  战舰 命中 游戏开发 

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。