import java.util.Random; import javax.swing.JFrame; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JLabel; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Color; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; /** * Simulates solitaire play of the game Battleship. Try to locate all parts of all 5 enemy ships. * Extends the JFrame class. * * @author Spencer DeBuf * @version 1.0 */ public class BattleshipFrame extends JFrame { /** SquarePanel array representing the playing grid of 8 rows by 8 columns*/ SquarePanel panel[][] = new SquarePanel[8][8]; /** Jbutton array representing the 64 possible guesses*/ JButton button[][] = new JButton[8][8]; /** InfoPanel to display gameplay information*/ InfoPanel info; /** JFrame containing a question dialog displayed at the end of a game*/ JFrame playAgain; /** Color representing the default color of each JButton*/ Color defaultColor; /** Integer representing the number of guesses made*/ int guesses = 0; /** Static Integer representing the length of the ship, used in the placement of the ships*/ static int length; /** Array of Integers used for storing the locations of the ships*/ static int board[][] = new int[8][8]; /** * Clears the play area for a new game. */ public void eraseBoard() { guesses = 0; for (int x1 = 0; x1 < 8; x1++) { for (int y1 = 0; y1 < 8; y1++) { board[x1][y1] = 0; //erases the placement of the ships button[x1][y1].setBackground(defaultColor);//sets the buttons to their default color } } info.guesses.setText("Guesses: " + guesses);//displays the number of guesses } /** * Displays a new JFrame asking the user if they wish to play another game. */ public void checkForPlayAgain() { playAgain = new JFrame(); playAgain.setLayout(new FlowLayout()); playAgain.setVisible(true); JButton yes = new JButton("Yes"); JButton no = new JButton("No"); JLabel playAgainLabel = new JLabel("Would you like to play again?"); playAgain.add(playAgainLabel); playAgain.add(yes); playAgain.add(no); no.addActionListener(new ExitGame()); yes.addActionListener(new PlayAgain()); playAgain.setTitle("Play Again?"); playAgain.setDefaultCloseOperation(EXIT_ON_CLOSE); playAgain.pack(); } /** * Class Constructor. Displays the playing field on the JFrame */ public BattleshipFrame() { setDefaultCloseOperation(EXIT_ON_CLOSE); setPreferredSize(new Dimension(425,545)); //setResizable(false); setLayout(new FlowLayout(1,0,0)); setVisible(true); setTitle("Battleship"); setResizable(false); //populates the board with panels with JButtons on them for (int r = 0; r < 8; r++) { for (int c = 0; c < 8; c++) { panel[r][c] = new SquarePanel(); button[r][c] = new JButton(); panel[r][c].setLayout(new FlowLayout()); button[r][c].setPreferredSize(new Dimension(48,48)); button[r][c].addActionListener(new ButtonPressed(r,c)); panel[r][c].add(button[r][c]); add(panel[r][c]); } } defaultColor = button[1][1].getBackground();//set the default Color of the JButtons info = new InfoPanel(); add(info);//adds the InfoPanel to the bottom of the JFrame pack(); } /** * Class to be called when the buttons are pressed. Implements ActionListener Interface. */ public class ButtonPressed implements ActionListener { int r;//integer to store the value of which row the button that was pressed is in int c;//integer to store the value of which column the button that was presses is in /** * Class Constructor. * * @param row which row the button pressed resides in * @param column which column the butotn pressed resides in */ public ButtonPressed(int row, int column) { r = row; c = column; } /** * Checks if the guess was a hit or miss. Displays the result on the JFrame. * * @param evt the specific ActionEvent that was triggered */ public void actionPerformed(ActionEvent evt) { //if the guess was a miss if (board[r][c] == 0) { button[r][c].setBackground(Color.black); board[r][c] = 0; } //if the guess hit a minesweeper if (board[r][c] == 2) { button[r][c].setBackground(Color.green); board[r][c] = -1; } //if the guess hit a frigate if (board[r][c] == 3) { button[r][c].setBackground(Color.blue); board[r][c] = -1; } //if the guess hit a cruiser if (board[r][c] == 4) { button[r][c].setBackground(Color.red); board[r][c] = -1; } //if the guess hit a battleship if (board[r][c] == 5) { button[r][c].setBackground(Color.yellow); board[r][c] = -1; } guesses++; info.guesses.setText("Guesses: " + guesses); if (checkForGameOver()) { checkForPlayAgain(); } } } /** * Exits the application. Implements the ActionListener Interface */ public class ExitGame implements ActionListener { /** * Exits the application. * * @param evt the specific ActionEvent that was triggered */ public void actionPerformed(ActionEvent evt) { System.exit(0); } } /** * Calls the methods necessary for replaying the game. Implements the ActionListener Interface. */ public class PlayAgain implements ActionListener { /** * Calls the methods necessary for replaying the game. * * @param evt the specific ActionEvent that was triggered */ public void actionPerformed(ActionEvent evt) { eraseBoard(); for (int i = 2; i <= 5; i++) { populateBoard(i); } playAgain.setVisible(false);//hides the window asking the user to play again } } /** * Checks if all of the ships have been hit. * * @return false if the game is not over, true if the game is over */ public boolean checkForGameOver() { for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { //if the board doesnt contain a ship or if it contains a ship but the position has already been located if (board[row][col] != 0 && board[row][col] != -1) { return false; } } } return true; } /** * Fills the board randomly with the 4 ships. * * @param lengthOfShip the length of the specific ship currently being placed */ public static void populateBoard(int lengthOfShip) { /** instance used for randomly placing the ships*/ Random random = new Random(); /** used to tell the loop whether to keep trying to place the ship or not*/ boolean cont = false; /** used to designate whether the ship should go backwards or forwards*/ boolean orientation = false; /** used to designate whether the ship should be placed horizontally or vertically*/ boolean direction; /**integer representing the potential x value of the ship position*/ int x; /**integer representing the potential y value of the ship position*/ int y; /** integer representing whethere a specific square is empty or not*/ boolean emptySquare = true; length = lengthOfShip; while (!cont) { emptySquare = true; orientation = random.nextBoolean(); direction = random.nextBoolean(); x = random.nextInt(8); y = random.nextInt(8); //vertical if (orientation) { //placed to the right if (direction) { //both points are one the board if (y + length <= 7) { for (int i = y; i < y + length; i++) { //square is already occupied if (board[x][i] != 0) { emptySquare = false; } } //ship can be placed here if (emptySquare) { for (int i = y; i < y + length; i++) { board[x][i] = length; } return; } } } //placed to the left else { if (y - length >= 0) { for (int i = y; i > y - length; i--) { //square is already occupied if (board[x][i] != 0) { emptySquare = false; } } //ship can be placed here if (emptySquare) { for (int i = y; i > y - length; i--) { board[x][i] = length; } return; } } } } //horizontal if (!orientation) { //placed upward if (!direction) { //both points are one the board if (x - length >= 0) { for (int i = x; i > x - length; i--) { //square is already occupied if (board[i][y] != 0) { emptySquare = false; } } //ship can be placed here if (emptySquare) { for (int i = x; i > x - length; i--) { board[i][y] = length; } return; } } } //placed downward else { if (x + length <= 7) { for (int i = x; i < x + length; i++) { //square is already occupied if (board[i][y] != 0) { emptySquare = false; } } //ship can be placed here if (emptySquare) { for (int i = x; i < x + length; i++) { board[i][y] = length; } return; } } } } } } }