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

Java版战舰游戏开发求助:添加双格战舰功能

解决Java战舰游戏添加两格战舰的问题

看起来你已经搭好了不错的基础框架!要实现需要两次命中才能击沉的两格战舰,我们需要调整战舰的存储结构、生成逻辑,以及命中判断的规则,同时还要避免重复命中同一格子的问题。下面是一步步的解决方案:

核心修改思路

  1. 调整战舰存储:从原来的3个单格战舰,改为1艘两格战舰(占2个相邻格子)+1艘单格战舰(总共3个格子,保持原有的shotHit!=3结束条件)。
  2. 生成合法的两格战舰:确保战舰是水平或垂直放置,不超出棋盘边界,且所有战舰格子互不重叠。
  3. 跟踪战舰生命值:为每艘战舰添加生命值属性,两格战舰初始生命值为2,单格战舰为1;命中时减少对应战舰的生命值,生命值归0时提示玩家击沉了战舰。
  4. 避免重复计数:新增一个二维数组记录已命中的格子,防止同一格子被多次计入命中次数。

修改后的完整代码

import java.util.Random;
import java.util.Scanner;

public class BattleshipGame {
    public static void main(String[] args) {
        int[][] board = new int[5][5];
        int[][] shipPositions = new int[3][2]; // 前2个元素是两格战舰的格子,第3个是单格战舰
        int[] shipHealth = {2, 1}; // 两格战舰生命值2,单格战舰生命值1
        boolean[][] hitCells = new boolean[5][5]; // 记录已命中的格子,避免重复计数
        int[] shoot = new int[2];
        int attempts = 0, shotHit = 0;

        initBoard(board);
        initShips(shipPositions);

        System.out.println();
        do {
            showBoard(board);
            shoot(shoot);
            attempts++;

            boolean isHit = hit(shoot, shipPositions, shipHealth, hitCells);
            if (isHit) {
                hint(shoot, shipPositions, attempts);
                shotHit++;
            } else {
                hint(shoot, shipPositions, attempts);
            }
            changeboard(shoot, hitCells, board);

        } while (shotHit != 3);

        System.out.println("\n\n\nBattleship Java game finished! You hit 3 ship cells in " + attempts + " attempts");
        System.out.println("You sunk 2 battleships!");
        showBoard(board);
    }

    public static void initBoard(int[][] board) {
        for (int row = 0; row < 5; row++)
            for (int column = 0; column < 5; column++)
                board[row][column] = -1;
    }

    public static void showBoard(int[][] board) {
        System.out.println("\t1 \t2 \t3 \t4 \t5");
        System.out.println();
        for (int row = 0; row < 5; row++) {
            System.out.print((row + 1) + "");
            for (int column = 0; column < 5; column++) {
                if (board[row][column] == -1) {
                    System.out.print("\t" + "~");
                } else if (board[row][column] == 0) {
                    System.out.print("\t" + "*");
                } else if (board[row][column] == 1) {
                    System.out.print("\t" + "X");
                }
            }
            System.out.println();
        }
    }

    public static void initShips(int[][] shipPositions) {
        Random random = new Random();
        // 随机选择两格战舰的放置方向:水平或垂直
        boolean isHorizontal = random.nextBoolean();
        int row, col;

        // 确保战舰不超出棋盘边界
        if (isHorizontal) {
            row = random.nextInt(5);
            col = random.nextInt(4); // 水平放置时,列最大为3(索引),保证col+1不超过4
            shipPositions[0][0] = row;
            shipPositions[0][1] = col;
            shipPositions[1][0] = row;
            shipPositions[1][1] = col + 1;
        } else {
            row = random.nextInt(4); // 垂直放置时,行最大为3,保证row+1不超过4
            col = random.nextInt(5);
            shipPositions[0][0] = row;
            shipPositions[0][1] = col;
            shipPositions[1][0] = row + 1;
            shipPositions[1][1] = col;
        }

        // 生成单格战舰,确保不与两格战舰的格子重叠
        do {
            shipPositions[2][0] = random.nextInt(5);
            shipPositions[2][1] = random.nextInt(5);
        } while ((shipPositions[2][0] == shipPositions[0][0] && shipPositions[2][1] == shipPositions[0][1]) ||
                 (shipPositions[2][0] == shipPositions[1][0] && shipPositions[2][1] == shipPositions[1][1]));
    }

    public static void shoot(int[] shoot) {
        Scanner input = new Scanner(System.in);
        System.out.print("Row: ");
        shoot[0] = input.nextInt();
        shoot[0]--; // 转换为数组索引(从0开始)
        System.out.print("Column: ");
        shoot[1] = input.nextInt();
        shoot[1]--;
    }

    public static boolean hit(int[] shoot, int[][] shipPositions, int[] shipHealth, boolean[][] hitCells) {
        // 检查是否命中未被击中过的战舰格子
        for (int i = 0; i < shipPositions.length; i++) {
            if (shoot[0] == shipPositions[i][0] && shoot[1] == shipPositions[i][1] && !hitCells[shoot[0]][shoot[1]]) {
                hitCells[shoot[0]][shoot[1]] = true;
                // 判断命中的是哪艘战舰:前2个格子属于两格战舰(索引0),第3个属于单格战舰(索引1)
                int shipIndex = (i < 2) ? 0 : 1;
                shipHealth[shipIndex]--;

                System.out.printf("You hit a ship located in (%d,%d)\n", shoot[0] + 1, shoot[1] + 1);
                // 如果战舰生命值归0,提示玩家击沉了战舰
                if (shipHealth[shipIndex] == 0) {
                    System.out.println("You sunk a battleship!");
                }
                return true;
            }
        }
        return false;
    }

    public static void hint(int[] shoot, int[][] shipPositions, int attempt) {
        int rowCount = 0, columnCount = 0;
        for (int[] shipCell : shipPositions) {
            if (shipCell[0] == shoot[0]) rowCount++;
            if (shipCell[1] == shoot[1]) columnCount++;
        }
        System.out.printf("\nHint %d: \nRow %d -> %d ship cells\n" + "Column %d -> %d ship cells\n",
                attempt, shoot[0] + 1, rowCount, shoot[1] + 1, columnCount);
    }

    public static void changeboard(int[] shoot, boolean[][] hitCells, int[][] board) {
        if (hitCells[shoot[0]][shoot[1]]) {
            board[shoot[0]][shoot[1]] = 1; // 命中标记为X
        } else {
            board[shoot[0]][shoot[1]] = 0; // 未命中标记为*
        }
    }
}

关键修改点说明

  • 战舰生成逻辑:initShips方法先随机确定两格战舰的放置方向,再计算合法的起始坐标,确保战舰不会超出棋盘;随后生成单格战舰并检查是否与两格战舰的格子重叠。
  • 命中跟踪机制:新增hitCells数组记录已命中的格子,避免同一格子被多次计入命中次数;hit方法中会减少对应战舰的生命值,当生命值归0时,会提示玩家击沉了战舰。
  • 棋盘更新优化:changeboard方法现在直接通过hitCells数组判断是否命中,逻辑更简洁准确。
  • 反馈体验提升:游戏结束时新增了击沉战舰数量的提示,让玩家的游戏反馈更清晰。

内容的提问来源于stack exchange,提问作者Dominik Fuček

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:34:23