我写了一段代码来实现战舰游戏。方法isHit
旨在检查玩家输入是否导致击中船只。它通过循环通过int [3] [2](ships
)保持船舶坐标并将它们与用户提供的坐标进行比较来实现。如果它是一个点击,isHit
打印文本,让用户知道他们击中了一艘船。但是,在运行代码并命中船只时,文本将打印到控制台两次而不是一次。我似乎无法弄明白为什么,所以如果有人能帮助我,我会很高兴。完整代码包含在下面:
import java.util.Random;
import java.util.Scanner;
public class BattleShip {
static int[][] board = new int[5][5];
static int[][] ships = new int[3][2];
static int row, column;
static int[] playerAttempt = new int[2];
static int nrOfAttempts = 0, nrOfHits = 0;
public static void welcome() {
//Welcomes the user and introduces rules of the game
System.out.println("WELCOME TO BATTLESHIP!");
System.out.println("In this game, it's your task to localize the three ships that are present in the see.");
System.out.println("Now, the board is filled with ~ signs, representing waves.");
System.out.println("You will be asked to provide coordinates, first a row number and then a column number.");
System.out.println("When you hit a ship at the provided coordinates, an X will appear on the map. If you miss, a 0 will appear.");
System.out.println("You have unlimited attempts to sink the ships, but the less attempts, the better.");
System.out.println("Good luck!\n");
}
public static void createBoard(int[][] board) {
//creates a new playing board of 5x5
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
board[i][j] = 0;
}
}
}
public static void placeShips(int[][] ships) {
//places 3 battleships at random places in the board
Random randomCoordinate = new Random();
//generates random coordinates for the first ship
for (int i = 0; i < ships.length; i++) {
ships[i][0] = randomCoordinate.nextInt(5);
ships[i][1] = randomCoordinate.nextInt(5);
//checks if coordinates of new ship are the same as previous ship
//by using j<i in for-statement, this will only be checked from the second ship onwards
//if coordinates are the same, new random coordinates are generated
for (int j = 0; j < i; j++) {
if (ships[i][0] == (ships[j][0]) && ships[i][1] == (ships[j][1])) {
do {
ships[i][0] = randomCoordinate.nextInt(5);
ships[i][1] = randomCoordinate.nextInt(5);
} while (ships[i][0] == (ships[j][0]) && ships[i][1] == (ships[j][1]));
}
}
}
}
public static void showBoard(int[][] board) {
//displays the board to the user
System.out.println("Playing board:\n");
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
if (board[i][j] == 0) {
System.out.print("~ "); //represents unknown territory
} else if (board[i][j] == 1) {
System.out.print("0 "); //represents a miss
} else {
System.out.print("X "); //represents a hit
}
}
System.out.println("\t"); //prints a return after each row
}
System.out.println(""); //prints a blank line below the board
}
public static void printShips(int[][] ships) {
//shows coordinates of ships for testing purposes
System.out.println("Ships are located at these 3 coordinates:");
for (int i = 0; i < ships.length; i++) {
for (int j = 0; j < ships[i].length; j++) {
System.out.print((ships[i][j]+1)+" ");
}
System.out.println("\t");
}
System.out.println("");
}
public static boolean isWithinBoundaries (int input) {
if (input >= 1 && input <= 5) {
//input is within boundaries of the playing board
return true;
} else {
//input is outside boundaries of the playing board
return false;
}
}
public static int pickRow() {
//method to let the user pick a row
Scanner rowInput = new Scanner(System.in);
String response; //temporary variable to store user input
while (true) { /*loop is infinite as long as input is invalid.
as soon as it's valid, the method exits the loop by
the return statement*/
//checks if user input is an integer by using try-catch statement
System.out.print("Pick a row (1-5): ");
response = rowInput.nextLine();
try {
row = Integer.valueOf(response);
} catch (NumberFormatException e) {
System.out.println("Sorry, invalid input. Please provide a number from 1 to 5.");
continue;
}
if (!isWithinBoundaries(row))
{ //checks if user input is within boundaries of the playing board
System.out.println("That's outside the sea. Please provide a number from 1 to 5.");
} else {
row = row - 1; //adjusts value because Java starts counting at 0, not 1
return row; //value is valid, so return
}
}
}
public static int pickColumn () {
//method to let the user pick a column
Scanner columnInput = new Scanner(System.in);
String response; //temporary variable to store user input
while (true) { /*loop is infinite as long as input is invalid
as soon as it's valid, the method exits the loop by
returning*/
//checks if user input is an integer by using try-catch statement
System.out.print("Pick a column (1-5): ");
response = columnInput.nextLine();
try {
column = Integer.valueOf(response);
} catch (NumberFormatException e) {
System.out.println("Sorry, invalid input. Please provide a number from 1 to 5.");
continue;
}
if (!isWithinBoundaries(column))
{ //checks if user input is within boundaries of the playing board
System.out.println("That's outside the sea. Please provide a number from 1 to 5.");
} else {
column = column - 1; //adjusts value because Java starts counting at 0, not 1
return column; //value is valid, so return
}
}
}
public static void playerAttempt(int[] playerAttempt) {
//method that incorporates player's picks of row and column into an attempt
playerAttempt[0] = pickRow();
playerAttempt[1] = pickColumn();
}
public static boolean isHit(int[][] ships, int[] playerAttempt) {
//checks whether the player attempt hits a ship
for (int i = 0; i < ships.length; i++) {
if (playerAttempt[0] == ships[i][0] && playerAttempt[1] == ships[i][1]) {
System.out.println("That's a hit!");
System.out.println("You sunk the ship located at coordinates "+(playerAttempt[0]+1)+","+(playerAttempt[1]+1)+".\n");
return true;
}
}
return false;
}
public static void adaptBoardAfterAttempt (int[] playerAttempt, int[][] ships, int[][] board) {
//adapts the playing board after a player attempt to indicate a hit (X) or a miss (0)
if (isHit(ships,playerAttempt)) {
board[playerAttempt[0]][playerAttempt[1]]=2;
} else {
board[playerAttempt[0]][playerAttempt[1]]=1;
}
}
public static void main(String[] Args) {
//carries out the main program
welcome();
createBoard(board);
placeShips(ships);
//printShips(ships);
//player has opportunity to make attempts until all 3 ships are hit
do {
showBoard(board);
playerAttempt(playerAttempt);
nrOfAttempts++;
if (isHit(ships, playerAttempt)) {
nrOfHits++;
} else {
System.out.println("You missed! But keep trying...\n");
}
adaptBoardAfterAttempt(playerAttempt,ships,board);
} while (nrOfHits <= 2);
//finishes the game
System.out.println("\nBATTLESHIP IS OVER.\n");
showBoard(board);
System.out.println("");
System.out.println("You needed "+nrOfAttempts+" attempts to sink all ships.");
}
}
答案 0 :(得分:2)
您的代码在点击后调用isHit
方法两次。
第一次在main
方法内的正确位置:
在此之后,您可以在adaptBoardAfterAttempt(playerAttempt, ships, board);
方法中拨打main
,但这会导致第二次调用isHit
:
您可以通过不让isHit
打印自己来解决问题。然后在main
:
if (isHit(ships, playerAttempt)) {
nrOfHits++
// Add the print stuff here
System.out.println("Hit...");
} else { ...
下次你如何自己调试这些东西?您使用的是像Eclipse这样的IDE吗?如果是这样,您可以在打印的位置添加断点(通过双击此行的行号来实现)。
之后,在调试模式下启动程序,这是这里的小错误:
在第一次打印之前玩游戏,然后使用 Step-Over(F6)执行代码的下一行,然后再次停止:
重复此过程,直到再次到达isHit
方法,然后您就会看到为什么再次调用它:)
您也可以单击isHit
方法,然后Eclipse将突出显示此方法的所有实例。然后,您将立即看到可能出现问题的位置。