当前位置:首页 > 文章列表 > 文章 > python教程 > Python战舰游戏开发:核心循环与命中实现

Python战舰游戏开发:核心循环与命中实现

2025-09-12 10:11:14 0浏览 收藏

IT行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰。所以我们需要踏踏实实的不断学习,精进自己的技术,尤其是初学者。今天golang学习网给大家整理了《Python战舰游戏开发:核心循环与命中逻辑实现》,聊聊,我们一起来看看吧!

Python战舰游戏开发:构建核心游戏循环与命中逻辑

本教程旨在指导Python初学者构建一个完整的战舰游戏,重点解决游戏循环、玩家与电脑的交互、命中判定及游戏结束条件。我们将通过引入“虚拟板”来跟踪玩家对电脑船只的攻击,并使用命中计数器来管理游戏状态,最终实现一个功能完善的命令行版战舰游戏。

1. 游戏基础结构回顾

在构建战舰游戏时,首先需要定义一些基本元素,如地图大小、船只类型以及用于显示和操作游戏板的函数。原始代码已经提供了这些基础:

  • ship_initial 和 ship_names: 定义了船只的缩写和全称。
  • get_username(): 获取玩家名称。
  • create_battlefield(map_size): 创建一个指定大小的空地图。
  • display_battlefield(board): 打印地图的当前状态。
  • player_ship_coordinate(player_board, occupied): 引导玩家放置船只。
  • comp_ship_coordinate(comp_board): 随机放置电脑的船只。

这些函数构成了游戏的骨架,但在实现完整的游戏流程(即玩家和电脑轮流攻击直到一方所有船只被击沉)时,还需要进一步完善。

2. 核心挑战:游戏循环与命中判定

原始代码的主要挑战在于缺乏一个持续的游戏循环来管理回合制攻击,以及有效的机制来跟踪船只的命中状态和判断游戏结束。为了解决这些问题,我们需要引入以下概念:

  • 虚拟板 (Dummy Board): 玩家在攻击电脑时,不应看到电脑船只的真实位置。虚拟板作为玩家视角下的电脑地图,只显示玩家攻击的结果(命中或未命中)。
  • 命中计数器 (Hit Counters): 分别为玩家和电脑维护一个计数器,当击中对方一艘船时,计数器增加。达到预设值(例如,所有船只数量)时,游戏结束。
  • 主游戏循环 (Main Game Loop): 一个 while True 循环,用于交替执行玩家和电脑的回合,直到满足游戏结束条件。

3. 改进的命中判定函数

为了支持上述逻辑,我们需要修改 check_player_hit 和 check_comp_hit 函数,并引入一个虚拟板。

3.1 玩家攻击判定 (check_player_hit)

此函数将接收电脑的真实船只板 (comp_board) 和玩家视角的虚拟板 (dummy_board)。

def check_player_hit(comp_board, dummy_board, user):
    """
    函数用于玩家攻击敌方船只的命中或未命中判定。
    同时更新玩家视角的虚拟板。
    """
    print(f"\n{user},请选择攻击坐标:")
    while True:
        try:
            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] != '_' and dummy_board[row][col] != '*':
                    print("你已经攻击过这个位置了,请选择其他位置。")
                    continue
                break
            else:
                print("无效坐标,请重新输入。")
        except ValueError:
            print("输入无效,请输入整数。")

    hit = 0  # 默认未命中

    if comp_board[row][col] in ship_initial: # 如果是船只字母
        # 击中船只,将电脑板上的船只标记为小写表示已击中
        # 虚拟板上标记为'X'表示命中
        original_ship_char = comp_board[row][col]
        comp_board[row][col] = original_ship_char.lower()
        dummy_board[row][col] = "X"
        print(f"电脑:{ship_names[ship_initial.index(original_ship_char)]} 被击中了!")
        hit = 1 # 命中
    else:
        dummy_board[row][col] = "*" # 未命中,虚拟板上标记为'*'
        print("未命中!")

    return hit

关键改进点:

  • 参数增加 dummy_board: 用于更新玩家对电脑板的视图。
  • 命中标记: 电脑板上的船只被击中后,其字符变为小写(例如 'B' -> 'b'),这样可以区分未被击中的船只和已被击中的船只。
  • 虚拟板更新: 命中时 dummy_board[row][col] 变为 'X',未命中时变为 '*'。
  • 返回命中状态: 函数返回 1 表示命中,0 表示未命中,以便更新总命中计数。
  • 输入验证: 增加了对重复攻击同一位置的检查。

3.2 电脑攻击判定 (check_comp_hit)

电脑的攻击需要随机性,并且不能重复攻击已经攻击过的位置。

def check_comp_hit(player_board):
    """
    函数用于电脑攻击玩家船只的命中或未命中判定。
    """
    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}) 进行攻击。")

    if player_board[row][col] in ship_initial: # 如果是船只字母
        original_ship_char = player_board[row][col]
        player_board[row][col] = original_ship_char.lower() # 标记为小写表示已击中
        print(f"玩家:你的 {ship_names[ship_initial.index(original_ship_char)]} 被击中了!")
        hit = 1 # 命中
    else:
        player_board[row][col] = "*" # 未命中
        print("电脑未命中!")

    return hit

关键改进点:

  • 随机不重复攻击: while True 循环确保电脑选择一个尚未被攻击过的有效位置。
  • 命中标记: 玩家板上的船只被击中后,同样将其字符变为小写。
  • 返回命中状态: 函数返回 1 表示命中,0 表示未命中。

4. 构建主游戏循环

现在,我们可以将所有组件整合到 if __name__ == "__main__": 块中,构建游戏的完整流程。

from random import randrange

ship_initial = ["B", "C", "F", "A", "S"]
ship_names = ["Battleship", "Cruiser", "Frigate", "Aircraft Carrier", "Submarine"] # 修正Sub为Submarine
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(map_size):
    """
    根据指定大小创建地图的函数。
    """
    return [["_"] * map_size for _ in range(map_size)]

def display_battlefield(board, title=""):
    """
    显示当前地图状态的函数。
    """
    if title:
        print(f"\n--- {title} ---")
    # 打印列索引
    print("  " + " ".join(str(i) for i in range(map_size)))
    for i, row in enumerate(board):
        print(f"{i} " + " ".join(row))

def player_ship_coordinate(player_board, occupied):
    """
    玩家放置船只的函数。
    """
    print("\n请放置你的船只。")
    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:
                    player_board[row][col] = ship_initial[i]
                    occupied.add((row, col))
                    break
                else:
                    print("无效坐标或该位置已被占用。请输入正确的值。")
            except ValueError:
                print("输入无效。请输入一个有效的整数。")
    return player_board, occupied

def comp_ship_coordinate(comp_board):
    """
    电脑放置船只的函数。
    """
    for ship 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
                break
    return comp_board

def check_player_hit(comp_board, dummy_board, user):
    """
    函数用于玩家攻击敌方船只的命中或未命中判定。
    同时更新玩家视角的虚拟板。
    """
    print(f"\n{user},请选择攻击坐标:")
    while True:
        try:
            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("无效坐标,请重新输入。")
        except ValueError:
            print("输入无效,请输入整数。")

    hit = 0

    if comp_board[row][col] in ship_initial:
        original_ship_char = comp_board[row][col]
        comp_board[row][col] = original_ship_char.lower()
        dummy_board[row][col] = "X"
        print(f"电脑:{ship_names[ship_initial.index(original_ship_char)]} 被击中了!")
        hit = 1
    else:
        dummy_board[row][col] = "*"
        print("未命中!")

    return hit

def check_comp_hit(player_board):
    """
    函数用于电脑攻击玩家船只的命中或未命中判定。
    """
    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"\n电脑选择了坐标 ({row}, {col}) 进行攻击。")

    if player_board[row][col] in ship_initial:
        original_ship_char = player_board[row][col]
        player_board[row][col] = original_ship_char.lower()
        print(f"玩家:你的 {ship_names[ship_initial.index(original_ship_char)]} 被击中了!")
        hit = 1
    else:
        player_board[row][col] = "*"
        print("电脑未命中!")

    return hit

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 = set()

    # 玩家放置船只
    player_ship_coordinate(player_board, occupied)
    display_battlefield(player_board, f"{user} 的船只部署")

    # 电脑放置船只
    comp_ship_coordinate(comp_board)
    # display_battlefield(comp_board, "电脑的船只部署 (仅供测试)") # 实际游戏中不显示
    display_battlefield(dummy_board, f"{user} 的攻击目标板") # 显示玩家的攻击目标板

    player_hits = 0 # 玩家击中电脑船只的数量
    comp_hits = 0   # 电脑击中玩家船只的数量
    total_ships = len(ship_initial) # 总船只数量

    print("\n--- 游戏开始! ---")

    while True:
        # 玩家回合
        print(f"\n--- {user} 的回合 ---")
        display_battlefield(dummy_board, f"{user} 的攻击目标板")
        player_hits += check_player_hit(comp_board, dummy_board, user)
        if player_hits == total_ships:
            print(f"\n恭喜你,{user}!你击沉了电脑所有船只,赢得了游戏!")
            break

        # 电脑回合
        print("\n--- 电脑的回合 ---")
        comp_hits += check_comp_hit(player_board)
        display_battlefield(player_board, f"{user} 的船只板") # 显示玩家自己的板,查看电脑攻击结果
        if comp_hits == total_ships:
            print("\n很遗憾,电脑击沉了你所有船只,电脑赢得了游戏!")
            break

        # 每回合结束显示双方板状态(玩家只看自己的船只板和攻击目标板)
        display_battlefield(player_board, f"{user} 的船只板")
        display_battlefield(dummy_board, f"{user} 的攻击目标板")

5. 运行与测试

运行上述代码,你将体验到一个完整的战舰游戏流程:

  1. 输入你的名字。
  2. 在提示下输入船只的行和列坐标来部署你的船只。
  3. 电脑会自动部署其船只。
  4. 游戏进入循环,你和电脑轮流输入攻击坐标。
  5. 每次攻击后,会显示命中或未命中信息,并更新相应的地图。
  6. 当一方的所有船只都被击沉时,游戏结束,并宣布获胜者。

6. 注意事项与潜在改进

  • 船只大小与方向: 当前实现中,每艘船只占用一个格子。更真实的战舰游戏会包含不同长度的船只,并允许玩家选择水平或垂直放置。这需要更复杂的船只放置逻辑和命中判定。
  • 输入验证: 尽管已添加了基本的坐标和重复攻击验证,但可以进一步增强,例如防止输入非数字字符时程序崩溃。
  • 游戏界面: 这是一个命令行游戏。可以通过使用库(如 pygame 或 curses)来创建更具吸引力的图形用户界面。
  • 电脑AI: 当前电脑只是随机攻击未命中/未被击中的位置。可以实现更复杂的AI策略,例如“搜索-摧毁”模式(当击中一艘船后,在其周围格子进行搜索)。
  • 船只沉没判定: 当前游戏只计数总命中次数。更精细的实现会跟踪每艘船的命中情况,当一艘船的所有部分都被击中时,宣布该船沉没。

通过本教程,你已经掌握了构建一个基本战舰游戏的核心逻辑,包括游戏循环、命中判定和游戏状态管理。在此基础上,你可以继续探索更高级的功能和改进,使你的游戏更加完善和有趣。

到这里,我们也就讲完了《Python战舰游戏开发:核心循环与命中实现》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

Excel边框怎么去掉?简单删除方法Excel边框怎么去掉?简单删除方法
上一篇
Excel边框怎么去掉?简单删除方法
Node.js对象合并内存优化方法
下一篇
Node.js对象合并内存优化方法
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    514次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    499次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • SEO  AI Mermaid 流程图:自然语言生成,文本驱动可视化创作
    AI Mermaid流程图
    SEO AI Mermaid 流程图工具:基于 Mermaid 语法,AI 辅助,自然语言生成流程图,提升可视化创作效率,适用于开发者、产品经理、教育工作者。
    280次使用
  • 搜获客笔记生成器:小红书医美爆款内容AI创作神器
    搜获客【笔记生成器】
    搜获客笔记生成器,国内首个聚焦小红书医美垂类的AI文案工具。1500万爆款文案库,行业专属算法,助您高效创作合规、引流的医美笔记,提升运营效率,引爆小红书流量!
    250次使用
  • iTerms:一站式法律AI工作台,智能合同审查起草与法律问答专家
    iTerms
    iTerms是一款专业的一站式法律AI工作台,提供AI合同审查、AI合同起草及AI法律问答服务。通过智能问答、深度思考与联网检索,助您高效检索法律法规与司法判例,告别传统模板,实现合同一键起草与在线编辑,大幅提升法律事务处理效率。
    284次使用
  • TokenPony:AI大模型API聚合平台,一站式接入,高效稳定高性价比
    TokenPony
    TokenPony是讯盟科技旗下的AI大模型聚合API平台。通过统一接口接入DeepSeek、Kimi、Qwen等主流模型,支持1024K超长上下文,实现零配置、免部署、极速响应与高性价比的AI应用开发,助力专业用户轻松构建智能服务。
    244次使用
  • 迅捷AIPPT:AI智能PPT生成器,高效制作专业演示文稿
    迅捷AIPPT
    迅捷AIPPT是一款高效AI智能PPT生成软件,一键智能生成精美演示文稿。内置海量专业模板、多样风格,支持自定义大纲,助您轻松制作高质量PPT,大幅节省时间。
    271次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码