Java Batteship:文本打印两次而不是一次打击

时间:2016-07-11 17:41:18

标签: java debugging

我写了一段代码来实现战舰游戏。方法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.");   

    }
}

1 个答案:

答案 0 :(得分:2)

您的代码在点击后调用isHit方法两次。

第一次在main方法内的正确位置:

First call

在此之后,您可以在adaptBoardAfterAttempt(playerAttempt, ships, board);方法中拨打main,但这会导致第二次调用isHit

Second call

您可以通过不让isHit打印自己来解决问题。然后在main

中添加打印逻辑
if (isHit(ships, playerAttempt)) {
    nrOfHits++
    // Add the print stuff here
    System.out.println("Hit...");
} else { ...

下次你如何自己调试这些东西?您使用的是像Eclipse这样的IDE吗?如果是这样,您可以在打印的位置添加断点(通过双击此行的行号来实现)。
之后,在调试模式下启动程序,这是这里的小错误:Debug-Mode Eclipse

在第一次打印之前玩游戏,然后使用 Step-Over(F6)执行代码的下一行,然后再次停止:Step-Over

重复此过程,直到再次到达isHit方法,然后您就会看到为什么再次调用它:)

您也可以单击isHit方法,然后Eclipse将突出显示此方法的所有实例。然后,您将立即看到可能出现问题的位置。