Advertisement
Guest User

Board.java

a guest
Feb 5th, 2017
747
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 13.00 KB | None | 0 0
  1. /**
  2.  * The Board class represents a players battle ship board.
  3.  *
  4.  * It keeps track of where all the players ships are located as well as what
  5.  * points have been fired on and if they were a hit or miss.
  6.  *
  7.  * The Board class also serves as the interface for placing ships and firing
  8.  * shots as well as printing the board (target board and ships board)
  9.  */
  10. public class Board {
  11.  
  12.     // 2d array which keeps track of whether each square of the board has been hit ("HIT"),
  13.     // missed ("MISSED")or not shot on ("CLEAN")
  14.     private SquareState[][] boardState;
  15.  
  16.     // 2d array which keeps track of the ships on the board. for example, if there is a ship at
  17.     // column = 3, row = 7, then boardShips[7][3] will be "true", otherwise it will be "false"
  18.     private boolean[][] boardShips;
  19.    
  20.     // Store the column and row sizes for the board
  21.     private int numColumns;
  22.     private int numRows;
  23.  
  24.     /**
  25.      * This method is a constructor for a Board object. This means whenever a new Board object
  26.      * is created, this is called method right away.
  27.      *
  28.      * This constructor takes in an array of ship objects and should store this
  29.      * information in the boardShips variable.
  30.      *
  31.      * The boardState variable should also be initialized such that it represents
  32.      * a numRows x numColumns sized 2d array. We should initialize each
  33.      * SquareState of the board to "CLEAN"
  34.      *
  35.      *
  36.      * @param ships array of Ships to place on board
  37.      * @param coordinates coordinates of board
  38.      */
  39.     public Board(Ship[] ships, int numColumns, int numRows) {
  40.         // Initialize boardShips
  41.         this.numColumns = numColumns;
  42.         this.numRows = numRows;
  43.         this.boardShips = new boolean[numRows][numColumns];
  44.  
  45.         for (int i = 0; i < this.numRows; i++) {
  46.             boolean[] newRow = new boolean[this.numColumns];
  47.             for (int j = 0; j < this.numColumns; j++) {
  48.                 newRow[j] = false;
  49.             }
  50.             this.boardShips[i] = newRow;
  51.         }
  52.  
  53.         for (int i = 0; i < ships.length; i++) {
  54.             try {
  55.                 addShipToBoard(ships[i]);
  56.             } catch (Exception e) {
  57.                 e.printStackTrace();
  58.             }
  59.         }
  60.        
  61.         this.boardState = new SquareState[numRows][numColumns];
  62.        
  63.         for (int i=0; i<this.numRows; i++) {
  64.             for (int j=0; j<this.numColumns; j++) {
  65.                 this.boardState[i][j] = SquareState.CLEAN;
  66.             }
  67.         }
  68.        
  69.     }
  70.  
  71.     /**
  72.      * Add a ship to the board.
  73.      *
  74.      * @param ship the ship to add to this board
  75.      * @throws IllegalArgumentException if the ship is out of bounds, or if it
  76.      *   intersects another ship. The state ofthe Board is undefined after this
  77.      *   exception is thrown.
  78.      */
  79.     private void addShipToBoard(Ship ship) {
  80.         int column = ship.getCoordinate()[0];
  81.         int row = ship.getCoordinate()[1];
  82.         Direction direction = ship.getDirection();
  83.         ShipType shipType = ship.getShipType();
  84.  
  85.         if (!shipInBounds(this.numRows, this.numColumns, column, row, direction, shipType)) {
  86.             throw new IllegalArgumentException("Ships not in bounds of the board. Please check ship positions.");
  87.         }
  88.  
  89.         int[][] spannedSquares = squaresShipSpans(column, row, ship.getDirection(), ship.getShipType());
  90.  
  91.         for (int[] coordinate : spannedSquares) {
  92.             row = coordinate[1];
  93.             column = coordinate[0];
  94.             if (boardShips[row][column]) {
  95.                 throw new IllegalArgumentException("Ships overlap. Please check ship positions.");
  96.             }
  97.             boardShips[row][column] = true;
  98.         }
  99.     }
  100.  
  101.     /**
  102.      * Getter method that returns the board's state
  103.      *
  104.      * @return a 2d array of SquareStates representing the board's state
  105.      */
  106.     public SquareState[][] getBoardState() {
  107.         return this.boardState;
  108.     }
  109.  
  110.     /**
  111.      * Fires a shot on the board. The board state {@code boardState} should be
  112.      * updated to reflect a shot on the inputed coordinate. If the shot is not in
  113.      * bounds, please print the string "Shot was out of bounds. Please try again.\n"
  114.      *
  115.      * @param square the square's coordinate (e.g., "B7")
  116.      */
  117.     public void fireShot(String square) {
  118.         int shotColNum = squareToColumnNumber(square);
  119.         int shotRowNum = squareToRowNumber(square);
  120.         if (!shotInBounds(this.numColumns, this.numRows, shotColNum, shotRowNum)) {
  121.             System.out.println("Shot was out of bounds. Please try again.");
  122.         } else {
  123.             if (this.boardShips[shotRowNum][shotColNum]) {
  124.                 this.boardState[shotRowNum][shotColNum] = SquareState.HIT;
  125.             } else {
  126.                 this.boardState[shotRowNum][shotColNum] = SquareState.MISS;
  127.             }
  128.         }
  129.     }
  130.  
  131.     /**
  132.     * Checks the board to see if all ships have been sunk
  133.     *
  134.     * @return true iff all the ships on the board have sunk else false
  135.     */
  136.     public boolean checkShipsSunk() {
  137.         boolean areAllShipsSunk = false;
  138.         int numSquaresShipsSpan = 0;
  139.         int numHits = 0;
  140.        
  141.         //the way i'm going to do this is kind of stupid but i'm too lazy to come up with a better way
  142.         for (int i=0; i<this.numRows; i++) {
  143.             for (int j=0; j<this.numColumns; j++) {
  144.                 if (this.boardShips[i][j]) {
  145.                     numSquaresShipsSpan++;
  146.                 }
  147.             }
  148.         }
  149.        
  150.         for (int i=0; i<this.numRows; i++) {
  151.             for (int j=0; j<this.numColumns; j++) {
  152.                 if (this.boardState[i][j] == SquareState.HIT) {
  153.                     numHits++;
  154.                 }
  155.             }
  156.         }
  157.        
  158.         if (numSquaresShipsSpan == numHits) {
  159.             areAllShipsSunk = true;
  160.         }
  161.        
  162.         return areAllShipsSunk;
  163.     }
  164.  
  165.     /**
  166.      * Prints the board reflecting shots fired as hits or misses. A square with
  167.      * a Miss should print as a "O", a square with a hit should print as a "X",
  168.      * and a "Clean" square (may or may not have a ship, but hasn't been fired
  169.      * on) should print as "-". The end of each row should be terminated with a
  170.      * "\n" for a new line. There should be no spaces between the points
  171.      *
  172.      * For example
  173.      *
  174.      * "---XX\n-OO--\n-----\nOO---\n-----\n"
  175.      */
  176.     public void printShots() {
  177.         for(int i=0;i<this.numRows;i++) {
  178.             for(int j=0;j<this.numColumns;j++) {
  179.                 if(this.boardState[i][j] == SquareState.CLEAN) {
  180.                     System.out.print("-");
  181.                 } else if(this.boardState[i][j] == SquareState.HIT) {
  182.                     System.out.print("X");
  183.                 } else if(this.boardState[i][j] == SquareState.MISS) {
  184.                     System.out.print("O");
  185.                 }
  186.             }
  187.             System.out.print("\n");
  188.         }
  189.     }
  190.  
  191.     /**
  192.      * Print the ships on board to the console.
  193.      *
  194.      *  Mark each square that has a ship with "O" and
  195.      *  other squares with '-'. End each row with "\n"
  196.      *  
  197.      *  For example, a 3x3 board with on horizontal destroyer in the upper left
  198.      *  would print:
  199.      *  
  200.      *  "OO-\n---\n---\n"
  201.      *
  202.      * @param board the 2d boolean array to be printed containing true's (hits) and false's (misses)
  203.      */
  204.     public void printShips() {
  205.         for(int i=0;i<this.numRows;i++) {
  206.             for(int j=0;j<this.numColumns;j++) {
  207.                 if(this.boardShips[i][j]) {
  208.                     System.out.print("O");
  209.                 } else if(!this.boardShips[i][j]) {
  210.                     System.out.print("-");
  211.                 }
  212.             }
  213.             System.out.print("\n");
  214.         }
  215.     }
  216.  
  217.     // Begin methods from ps1, TODO: should fill in with staff solutions, and
  218.     // make note of this
  219.     /**
  220.      * Convert the square's letter, representing a column on the board, to a
  221.      * 0-based column number.
  222.      *
  223.      * @param square the square's coordinate (e.g., "B7")
  224.      * @return the 0-based column number, numbered from left to right
  225.      */
  226.     public static int squareToColumnNumber(String square) {
  227.         String letters = "ABCDEFGHIJ";
  228.  
  229.         return letters.indexOf(square.substring(0, 1));
  230.     }
  231.  
  232.     /**
  233.      * Convert the square's number, representing a row on the board, to a
  234.      * 0-based row number.
  235.      *
  236.      * @param square the square's coordinate (e.g., "B7")
  237.      * @return the 0-based row number, numbered from top to bottom
  238.      */
  239.     public static int squareToRowNumber(String square) {
  240.         int number = Integer.parseInt(square.substring(1));
  241.         int rowNumber = number - 1;
  242.  
  243.         return rowNumber;
  244.     }
  245.  
  246.     /**
  247.      * Determine the coordinates of the squares that the given ship spans
  248.      *
  249.      * @param shipColumn the 0-based column number of the upper-left square of the ship
  250.      * @param shipRow the 0-based row number of the upper-left square of the ship
  251.      * @param shipDirection the orientation of the ship
  252.      * @param shipType the class of the ship
  253.      * @return 2d integer array of coordinates of squares that the ship spans
  254.      */
  255.     public static int[][] squaresShipSpans(int shipColumn, int shipRow, Direction shipDirection, ShipType shipType) {
  256.         int[][] squares = new int[shipType.length()][2];
  257.         int column = 0;
  258.         int row = 1;
  259.  
  260.         if (shipDirection == Direction.HORIZONTAL) {
  261.             for (int i = 0; i < shipType.length(); i++) {
  262.                 squares[i][column] = shipColumn + i;
  263.                 squares[i][row] = shipRow;
  264.             }
  265.         } else if (shipDirection == Direction.VERTICAL) {
  266.             for (int j = 0; j < shipType.length(); j++) {
  267.                 squares[j][column] = shipColumn;
  268.                 squares[j][row] = shipRow + j;
  269.             }
  270.         }
  271.  
  272.         return squares;
  273.     }
  274.  
  275.     /**
  276.      * Determine whether the shot would hit the ship.
  277.      *
  278.      * @param shotColumn the 0-based column number of the shot
  279.      * @param shotRow the 0-based row number of the shot
  280.      * @param shipColum the 0-based column number of the upper-left square of the ship
  281.      * @param shipRow the 0-based row number of the upper-left square of the ship
  282.      * @param shipDirection the orientation of the ship
  283.      * @param shipType the class of the ship
  284.      * @return true iff the shot intersects with some part of the ship
  285.      */
  286.     public static boolean isHit(int shotColumn, int shotRow, int shipColumn, int shipRow, Direction shipDirection,
  287.             ShipType shipType) {
  288.         int[][] squares = squaresShipSpans(shipColumn, shipRow, shipDirection, shipType);
  289.  
  290.         // Go through every square the ship spans and check if the shot is one of them.
  291.         for (int i = 0; i < shipType.length(); i++) {
  292.             if (shotColumn == squares[i][0] && shotRow == squares[i][1]) {
  293.                 return true;
  294.             }
  295.         }
  296.         // If none of the squares have the shot, then it is not a hit.
  297.         return false;
  298.     }
  299.  
  300.     /**
  301.      * Determine whether a ship position is within the game board.
  302.      *
  303.      * @param height the number of rows in the game board
  304.      * @param width the number of columns in the game board
  305.      * @param column the 0-based column number of the upper-left square of the ship
  306.      * @param row the 0-based row number of the upper-left square of the ship
  307.      * @param direction the orientation of the ship
  308.      * @param shipType the class of the ship
  309.      * @return true iff the entirety of the ship is within the bounds of the game board
  310.      */
  311.     public static boolean shipInBounds(int height, int width, int column, int row, Direction direction,
  312.             ShipType shipType) {
  313.         int[][] squares = squaresShipSpans(column, row, direction, shipType);
  314.  
  315.         // Check if each square the ship spans is within the boundaries of the board
  316.         for (int i = 0; i < shipType.length(); i++) {
  317.             if (squares[i][0] >= width || squares[i][1] >= height) {
  318.                 return false;
  319.             }
  320.         }
  321.  
  322.         // If no square was out of the boundaries, all the squares were in  bounds.
  323.         return true;
  324.     }
  325.  
  326.     /**
  327.      * Determine whether a shot is within the game board.
  328.      *
  329.      * @param height the number of rows in the game board
  330.      * @param width the number of columns in the game board
  331.      * @param column the 0-based column number of the shot
  332.      * @param row the 0-based row number of the shot
  333.      * @return true iff the shot is within the bounds of the game board
  334.      */
  335.     public static boolean shotInBounds(int height, int width, int column, int row) {
  336.         // check whether column coordinate is between 0 and width - 1, inclusive,
  337.         // and row coordinate is between 0 and height - 1, inclusive
  338.         boolean inBounds = true;
  339.         if (column < 0 || column >= width) {
  340.             inBounds = false;
  341.         }
  342.         if (row < 0 || row >= height) {
  343.             inBounds = false;
  344.         }
  345.         return inBounds;
  346.     }
  347. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement