Java版战舰游戏开发求助:添加双格战舰功能
解决Java战舰游戏添加两格战舰的问题
看起来你已经搭好了不错的基础框架!要实现需要两次命中才能击沉的两格战舰,我们需要调整战舰的存储结构、生成逻辑,以及命中判断的规则,同时还要避免重复命中同一格子的问题。下面是一步步的解决方案:
核心修改思路
- 调整战舰存储:从原来的3个单格战舰,改为1艘两格战舰(占2个相邻格子)+1艘单格战舰(总共3个格子,保持原有的
shotHit!=3结束条件)。 - 生成合法的两格战舰:确保战舰是水平或垂直放置,不超出棋盘边界,且所有战舰格子互不重叠。
- 跟踪战舰生命值:为每艘战舰添加生命值属性,两格战舰初始生命值为2,单格战舰为1;命中时减少对应战舰的生命值,生命值归0时提示玩家击沉了战舰。
- 避免重复计数:新增一个二维数组记录已命中的格子,防止同一格子被多次计入命中次数。
修改后的完整代码
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
相关产品推荐
相关产品推荐

