讲师中心 微信公众号
AI工具推荐 视频效率加速

Java中随机且不重复地放置战舰:20位置数组中部署5艘船只的策略

陌丽君_3230

陌丽君_3230

发布时间:2025-10-26 09:05:39

|

797人浏览过

|

来源于php中文网

原创

Java中随机且不重复地放置战舰:20位置数组中部署5艘船只的策略

本教程详细介绍了如何在java中实现战舰游戏的随机布船逻辑。针对在20个位置的数组中不重复地放置5艘编号为1到5的船只,并用0填充空位的问题,文章提出了一种高效的解决方案。该方案利用一个动态的可用位置列表来确保船只位置的唯一性,并通过随机选择并移除位置的方式,避免了重复和复杂的冲突检测。教程提供了完整的java代码示例,帮助开发者理解并实现这一核心游戏机制。

1. 问题背景与挑战

在开发如“战舰”这类棋盘游戏时,一个常见的需求是在一个固定大小的游戏板上随机且不重复地放置多艘船只。具体而言,我们面临的任务是在一个包含20个位置的数组中,随机放置5艘船只。每艘船只应有一个唯一的标识(例如,从1到5),而未放置船只的位置则用0表示。

直接使用简单的随机数生成器可能会导致以下问题:

  • 位置重复:同一位置可能被多次选中,导致多艘船只放置在同一格,或覆盖已放置的船只。
  • 船只标识重复:如果船只标识也随机生成,可能出现多个位置使用相同的船只标识。
  • 效率低下:为了避免重复,可能需要复杂的冲突检测和重试机制,尤其是在板子逐渐被填满时,效率会显著降低。

2. 核心策略:基于可用位置列表的随机选择

为了解决上述挑战,我们采用一种高效且简洁的策略:维护一个动态的“可用位置”列表。这个列表最初包含所有可能的棋盘位置索引。每次放置一艘船时,我们从这个列表中随机选择一个位置,然后将其从列表中移除。这样可以确保每个选定的位置都是唯一的,从而避免了重复放置的问题。

该策略的关键步骤如下:

立即学习“Java免费学习笔记(深入)”;

  1. 初始化游戏板:创建一个大小为20的整型数组,所有元素默认初始化为0,表示空位。
  2. 创建可用位置列表:创建一个 List,并用0到19的整数填充它,代表所有可用的棋盘索引。
  3. 循环放置船只:对于要放置的每艘船(共5艘):
    • 生成随机索引:从0到 可用位置列表.size() - 1 之间生成一个随机整数作为索引。
    • 获取实际位置:使用这个随机索引从 可用位置列表 中获取一个实际的棋盘位置(例如,如果列表当前有10个元素,随机索引可能是3,获取到的值可能是原始棋盘的第7个位置)。
    • 放置船只:将当前船只的标识(例如,第1艘船为1,第2艘船为2,依此类推)放置到游戏板数组中对应的实际位置上。
    • 移除已用位置:从 可用位置列表 中移除刚才使用的随机索引处的元素。这样,该位置就不会被再次选中。

3. 实现步骤与代码示例

下面是使用Java语言实现上述策略的详细步骤和完整代码。

Java Api Extractor
Java Api Extractor

从 Java 项目中提取 Controller 层接口定义为 JSON 数据。

下载

3.1 定义常量与主函数

首先,我们定义游戏板的大小和船只数量为常量,并在 main 方法中初始化游戏板并调用船只放置函数。

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class BattleshipPlacement {

    // 定义游戏板的大小
    private static final int BOARD_SIZE = 20;
    // 定义要放置的船只数量
    private static final int NUM_SHIPS = 5;

    public static void main(String[] args) {
        // 初始化游戏板数组,Java中int数组默认元素值为0
        int[] gameBoard = new int[BOARD_SIZE]; 

        // 调用函数随机放置船只
        placeShipsRandomly(gameBoard, NUM_SHIPS);

        // 打印最终的游戏板布局
        printBoard(gameBoard);
    }

    // ... (后续方法将在下面定义)
}

3.2 随机放置船只的逻辑

placeShipsRandomly 方法是核心,它实现了我们前面讨论的策略。

    /**
     * 随机放置指定数量的船只到游戏板上。
     * 船只编号从1到NUM_SHIPS,空位为0。
     *
     * @param board 游戏板数组,用于存储船只位置
     * @param numShips 要放置的船只数量
     */
    public static void placeShipsRandomly(int[] board, int numShips) {
        // 检查船只数量是否超过板子大小,防止越界或逻辑错误
        if (numShips > board.length) {
            System.err.println("错误:船只数量不能超过板子大小。");
            return;
        }

        // 1. 初始化所有可用位置的列表
        // 这个列表最初包含所有棋盘位置的索引 (0 到 BOARD_SIZE-1)
        List<Integer> availablePositions = new ArrayList<>();
        for (int i = 0; i < board.length; i++) {
            availablePositions.add(i);
        }

        // 创建一个随机数生成器实例
        Random random = new Random();

        // 2. 循环放置每艘船只
        // shipId 从1开始,代表第一艘船到第五艘船
        for (int shipId = 1; shipId <= numShips; shipId++) {
            // 生成一个随机索引,范围是 0 到 availablePositions.size() - 1
            // 随着位置的移除,availablePositions.size() 会逐渐减小
            int randomIndex = random.nextInt(availablePositions.size());

            // 从可用位置列表中获取选定的实际棋盘位置
            int actualPosition = availablePositions.get(randomIndex);

            // 将当前船只的标识(shipId)放置到游戏板的对应位置上
            board[actualPosition] = shipId; 

            // 从可用位置列表中移除该位置,确保该位置不会被再次选中
            availablePositions.remove(randomIndex);
        }
    }

3.3 打印游戏板的方法

为了验证结果,我们需要一个辅助方法来打印游戏板的当前布局。

    /**
     * 打印游戏板内容。
     *
     * @param board 游戏板数组
     */
    public static void printBoard(int[] board) {
        System.out.println("最终游戏板布局:");
        for (int i = 0; i < board.length; i++) {
            System.out.print(board[i] + "\t"); // 使用制表符分隔,使输出更整齐
        }
        System.out.println(); // 换行
    }

4. 运行结果示例

运行上述 BattleshipPlacement 类,你将得到类似以下输出的结果(具体位置因随机性而异):

最终游戏板布局:
0       0       0       0       3       0       0       0       0       0       1       0       0       5       0       0       0       4       2       0

在这个示例中,船只1、2、3、4、5分别被放置在了索引为10、18、4、17、13的位置,其余位置均为0。

5. 注意事项与总结

  • 随机数生成器:java.util.Random 是线程安全的,但在高并发场景下可能存在性能瓶颈。对于大多数单线程游戏应用,它是足够的。如果需要更高质量的随机性或并发需求,可以考虑 java.security.SecureRandom 或为每个线程使用独立的 Random 实例。
  • 灵活性:通过修改 BOARD_SIZE 和 NUM_SHIPS 常量,你可以轻松地调整游戏板的大小和船只的数量,而无需修改核心逻辑。
  • 船只标识:本教程中,船只标识从1到 NUM_SHIPS 顺序分配。如果需要船只标识本身也是随机的(但仍需保证唯一性),可以创建一个包含1到 NUM_SHIPS 的列表,然后像处理位置一样,每次取一个随机船只标识并移除。
  • 效率:对于相对较小的板子和船只数量,这种基于 ArrayList 的方法效率很高。remove(index) 操作在 ArrayList 中是O(n)时间复杂度,因为需要移动后续元素。然而,由于 NUM_SHIPS 通常远小于 BOARD_SIZE,且 BOARD_SIZE 本身不大(例如20),这种开销可以忽略不计。如果 BOARD_SIZE 非常大,或者 NUM_SHIPS 接近 BOARD_SIZE,可以考虑使用 Collections.shuffle() 方法先打乱整个 availablePositions 列表,然后直接取前 NUM_SHIPS 个元素,这样每次移除的开销就变为O(1)。

通过本教程介绍的方法,开发者可以轻松地在Java中实现战舰游戏的随机布船逻辑,确保船只位置的唯一性和随机性,为游戏的核心机制奠定坚实基础。

热门AI工具

更多
立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

码上飞
码上飞 Hot

一款基于自然语言的AI应用开发平台,可根据用户描述自动生成应用程序,帮助个人和团队快速完成应用原型与开发。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6284

2023.10.24

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4638

2023.08.10

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

0

2026.11.05

DBeaver安全防护教程大全
DBeaver安全防护教程大全

DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。

0

2026.11.05

DBeaver连接创建与配置教程
DBeaver连接创建与配置教程

本专题聚焦DBeaver数据库连接配置与管理,覆盖从新建连接、选择数据库类型到填写连接参数和验证连接的完整流程。针对MySQL、PostgreSQL、SQL Server等常见数据库,整理相应的连接设置方法,并提供驱动缺失、认证失败和连接异常等问题的排查方向。

0

2026.11.04

XORM框架结构体映射与表结构同步
XORM框架结构体映射与表结构同步

本专题围绕XORM框架的结构体映射展开,说明表名与字段的命名策略、xorm标签常用属性、主键自增与时间字段自动填充,并演示Sync2自动建表、增量字段升级、索引声明与反向生成结构体的完整流程。

0

2026.11.04

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

0

2026.11.04

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

0

2026.11.04

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

0

2026.11.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn