package As7BattleShip; Program: BattleshipBoard.java Author: Kevin Nider Date: 11/18/12 Description: Assignment 7: Runs the battleship game Input: ship placement board files and computer player type Output: Creates a JFrame that displays the battleship board, where ships are placed and where they've been hit. import java.io.file; import java.io.filenotfoundexception; public class BattleshipDriver { Main function @param args Command line arguments public static void main(string args[]) { try { BattleshipBoard b; File boardfile = new File(args[0]); File opponentboardfile = new File(args[1]); b = new BattleshipBoard(boardFile); b.opponentboard(opponentboardfile); b.cpuplayer(); b.setvisible(true); catch (FileNotFoundException BattleshipException e) { System.out.println(e.getMessage()); System.exit(-1); package As7BattleShip; Program: BattleshipBoard.java Author: Kevin Nider Date: 11/18/12 Description: Assignment 7: Runs the battleship game Input: ship placement board files and computer player type Output: Creates a JFrame that displays the battleship board, where ships are placed and where they've been hit. Also announces winner. import java.awt.color; import java.awt.gridlayout; import java.awt.event.actionevent; import java.awt.event.actionlistener; import java.io.; import java.util.arraylist; import javax.swing.jframe; import javax.swing.joptionpane; import javax.swing.jpanel;
@SuppressWarnings("serial") public class BattleshipBoard extends JFrame { Static constant to indicate a board location is empty public static final char EMPTY = '.'; The 2D array representing the board private char board[][]; The 2D array representing the opponent's board private char oppboard[][]; The 2D array representing the CPU's FireButtons private FireButton fboppboard[][]; The 2D array representing the player's FireButtons private FireButton fbboard[][]; The number of battleships left private int numbattleshipsleft; The number of opponent's battleships left private int numoppbattleshipsleft; The ID of the current ship being placed private int currentshipid; The number of rows private int numrows; The number of columns private int numcols; Maintains information about the shots taken by each ship public ArrayList<Integer> shipinfo; Maintains information about the shots taken by each of the opponent's ship public ArrayList<Integer> opponentshipinfo; FireButtons for opponent private FireButton fb; FireButtons for player private FireButton fbp;
Creates the main panel that will hold the 2 boards JPanel mainpanel = new JPanel(new GridLayout(0, 2)); Creates the player's board panel private JPanel playerpanel; Creates the opponent's board panel private JPanel opponentpanel; Creates listener objects for the FireButtons private ButtonListener listener; CPU type public CPU cpu; Constructor for the Battleship Board. File must have 10 lines, with exactly 10 characters per line. '.' represents EMPTY. A unique number (0, 1, 2, 3, or 4) will represent each ship. @param boardfile a text file with a 10x10 character grid, representing a battleship board @throws FileNotFoundException if the board file is not found @author richmaja public BattleshipBoard(File boardfile) throws FileNotFoundException { this.numrows = 10; this.numcols = 10; this.board = new char[numcols][numrows]; this.fbboard = new FireButton[numCols][numRows]; this.listener = new ButtonListener(); this.shipinfo = new ArrayList<>(); this.numbattleshipsleft = 5; //Add 5 entries to shipinfo for (int i = 0; i < 5; i++) { shipinfo.add(0); //create the board frame setsize(700, 400); settitle("battleship Board"); setdefaultcloseoperation(exit_on_close); this.add(mainpanel); try { if (!boardfile.exists()) { throw new FileNotFoundException("Error Reading: " + boardfile.getname()); //Confirm file worked System.out.println("Reading " + boardfile.getname()); //create player board this.playerpanel = new JPanel(new GridLayout(numRows, numcols));
playerpanel.setborder(javax.swing.borderfactory.createtitledborder(null, "Player Board", javax.swing.border.titledborder.left, javax.swing.border.titledborder.top)); mainpanel.add(playerpanel); try (FileReader fr = new FileReader(boardFile); BufferedReader br = new BufferedReader(fr)) { String line; int linecounter = 0; while ((line = br.readline())!= null) { for (int i = 0; i < line.length(); i++) { char currentcharacter = line.charat(i); board[i][linecounter] = currentcharacter; linecounter++; //add the file contents to the board and create the fire buttons for (int c = 0; c < this.numcols; c++) { for (int r = 0; r < this.numrows; r++) { try { this.fbp = new FireButton(c, r); this.fbp.addactionlistener(this.listener); if (!String.valueOf(board[r][c]).equals(String.valueOf(BattleshipBoard.EMPTY))) { this.fbp.settext(string.valueof(board[r][c])); fbp.setbackground(color.yellow); else { fbp.settext(""); fbboard[r][c] = this.fbp; playerpanel.add(fbp); //disable player's board fbp.setenabled(false); //set the margins so the buttons are together fbp.setmargin(new java.awt.insets(0, 0, 0, 0)); //set the ship number into the ship array int shipidval = Integer.parseInt(board[c][r] + ""); shipinfo.set(shipidval, shipinfo.get(shipidval) + 1); catch (NumberFormatException e) { catch (IOException e) { System.out.println("Error: " + e.getmessage()); //print the board to confirm //print(); System.out.println(shipInfo); Builds the opponent's board. File must have 10 lines, with exactly 10 characters per line. '.' represents EMPTY. A unique number (0, 1, 2, 3, or 4) will represent each ship. @param boardfile a text file with a 10x10 character grid, representing a
battleship board @throws FileNotFoundException if the board file is not found public void opponentboard(file boardfile) throws FileNotFoundException { this.numrows = 10; this.numcols = 10; this.oppboard = new char[numcols][numrows]; this.fboppboard = new FireButton[numCols][numRows]; this.listener = new ButtonListener(); this.opponentshipinfo = new ArrayList<>(); //this.shipinfo = new ArrayList<>(); this.numoppbattleshipsleft = 5; //Add 5 entries to shipinfo for (int i = 0; i < 5; i++) { opponentshipinfo.add(0); //shipinfo.add(0); try { if (!boardfile.exists()) { throw new FileNotFoundException("Error Reading: " + boardfile.getname()); System.out.println("Reading " + boardfile.getname()); //Create the opponent panel and add it to the main panel this.opponentpanel = new JPanel(new GridLayout(numRows, numcols)); mainpanel.add(opponentpanel); opponentpanel.setborder(javax.swing.borderfactory.createtitledborder(null, "Opponent Board", javax.swing.border.titledborder.left, javax.swing.border.titledborder.top)); //Read the file to create the board and where to place the ships try (FileReader fr = new FileReader(boardFile); BufferedReader br = new BufferedReader(fr)) { String line; int linecounter = 0; while ((line = br.readline())!= null) { for (int i = 0; i < line.length(); i++) { char currentcharacter = line.charat(i); oppboard[i][linecounter] = currentcharacter; linecounter++; //fill the board with the FireButtons for (int c = 0; c < this.numcols; c++) { for (int r = 0; r < this.numrows; r++) { try { this.fb = new FireButton(r, c); this.fb.addactionlistener(this.listener); //place the ships on the board or empty space where no ship is if (!String.valueOf(oppboard[r][c]).equals(String.valueOf(BattleshipBoard.EMPTY))) { this.fb.setname(string.valueof(oppboard[r][c])); else { fb.setname(""); this.fb.setenabled(true); this.fb.setmargin(new java.awt.insets(0, 0, 0, 0)); //add the FB to the FB board this.fboppboard[r][c] = this.fb; //add the panel to the board
1); opponentpanel.add(this.fb); int shipidval = Integer.parseInt(oppboard[c][r] + ""); opponentshipinfo.set(shipidval, opponentshipinfo.get(shipidval) + catch (NumberFormatException e) { catch (IOException e) { System.out.println("Error: " + e.getmessage()); //print(); System.out.println(opponentshipInfo); Constructs the CPU player type @param cpuplayer Systematic player for "s" and Random player for "r" @throws BattleshipException is neither "s" or "r" //public CPU CPUplayer(String cpuplayer) throws BattleshipException { public CPU CPUplayer() throws BattleshipException { Object[] options = {"Systematic","Random"; int result = JOptionPane.showOptionDialog(null, "Select the type of CPU you would like to play against", "Battleship", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE,null,options,options[0]); if (result == 0) { System.out.println("Systematic opponent selected"); return cpu = new SystematicCPU(); else if (result == 1) { System.out.println("Random opponent selected"); return cpu = new RandomCPU(); else { throw new BattleshipException("Incorrect computer player argument"); if (cpuplayer.equalsignorecase("s")) { System.out.println("Systematic opponent"); return cpu = new SystematicCPU(); else if (cpuplayer.equalsignorecase("r")) { System.out.println("Random opponent"); return cpu = new RandomCPU(); else { throw new BattleshipException("Incorrect computer player argument"); //return cpu = new SystematicCPU(); Getter for the number of rows in the board @return The number of rows in the Battleship board public int getnumrows() { return this.numrows; Getter for the number of columns in the board @return The number of columns in the Battleship board public int getnumcols() { return this.numcols;
Gets the number of Battleships left @return The number of battleships left public int getnumbattleshipsleft() { return this.numbattleshipsleft; Gets the number of opponent's Battleships left @return The number of battleships left public int getoppnumbattleshipsleft() { return this.numoppbattleshipsleft; Checks if the cell is occupied. @param col The column @param row The row @return true if the cell is occupied public boolean isoccupied(int col, int row) { if (row >= 0 && row < getnumrows() && col >= 0 && col < getnumcols()) { return board[col][row]!= EMPTY; return false; Returns the char value at a certain row and column of the board @param col The column on which the cell resides @param row The row on which the cell resides @return the char value at a certain row and column of the board public char getcellcontent(int col, int row) { if (row >= 0 && row < getnumrows() && col >= 0 && col < getnumcols()) { return this.board[col][row]; return EMPTY; public char getoppcellcontent(int col, int row) { if (row >= 0 && row < getnumrows() && col >= 0 && col < getnumcols()) { return this.oppboard[col][row]; return EMPTY; Fires a shot at an opponent's battleship @param col The col coordinate of the shot @param row The row coordinate of the shot @return true if an enemy battleship is hit, false otherwise. If you fire twice at the same spot and a battleship was at that spot, this method returns true both times. @throws IndexOutOfBoundsException if row or col are out of bounds public boolean fireshot(int col, int row) throws IndexOutOfBoundsException {
if (this.getoppcellcontent(col, row)!= BattleshipBoard.EMPTY) { int shipid = Character.digit(this.getOppCellContent(col, row), 10); Integer shotsleft = this.opponentshipinfo.get(shipid); shotsleft--; if (shotsleft == 0) { this.numoppbattleshipsleft--; this.opponentshipinfo.set(shipid, new Integer(shotsLeft)); System.out.println("Hit ship: " + shipid + " Shots left: " + shotsleft + " Ships left:" + this.numoppbattleshipsleft); // Decide winner and alert player if (isgameover()) { endgame(0); else { //Call opponent's shot cpushot(cpu.cpucol(), cpu.cpurow()); //System.out.println("Hit at " + col + ", " + row); return true; else { //MISS //System.out.println("Miss at " + col + ", " + row); //Call opponent's shot cpushot(cpu.cpucol(), cpu.cpurow()); return false; Fires a shot at a player's battleship @param col The col coordinate of the shot @param row The row coordinate of the shot @return true if an enemy battleship is hit, false otherwise. @throws IndexOutOfBoundsException if row or col are out of bounds public boolean cpushot(int col, int row) throws IndexOutOfBoundsException { this.fbp = fbboard[col][row]; if (fbp.getbackground().equals(color.blue) fbp.getbackground().equals(color.red)) { System.out.println("Shooting again"); cpushot(cpu.cpucol(), cpu.cpurow()); return false; System.out.println("CPU shooting at " + col + ", " + row); if (this.getcellcontent(col, row)!= BattleshipBoard.EMPTY) { int shipid = Character.digit(this.getCellContent(col, row), 10); Integer shotsleft = this.shipinfo.get(shipid); shotsleft--; if (shotsleft == 0) { this.numbattleshipsleft--; this.shipinfo.set(shipid, new Integer(shotsLeft)); System.out.println("CPU Hit ship: " + shipid + " Shots left: " + shotsleft + " Ships left:" + this.numbattleshipsleft); if ((fbp.gettext().matches("[0-9]")) this.fbp.getbackground().equals(color.yellow)) { //System.out.println("Hit at " + col.getcolumn() + ", " + row.getrow());
fbp.settext("h"); //if hit twice, skip the fireshot method fbp.setbackground(color.red); //Decide winner and alert player if (isgameover()) endgame(1); return true; else { if (fbp.gettext().equals("")) { fbp.setbackground(color.blue); //System.out.println("Miss at " + col.getcolumn() + ", " + row.getrow()); fbp.settext("m"); System.out.println("CPU Miss at " + col + ", " + row); return false; ButtonListener class for FireButtons When button is pressed, check if it's been hit before and skip if it has. Otherwise if miss, change to M and make blue, if hit change to H and make red public class ButtonListener implements ActionListener { @Override //what cell did the button hit public void actionperformed(actionevent arg0) { fb = (FireButton) arg0.getsource(); Cell col = fb.getcell(); Cell row = fb.getcell(); //if missed or shot at twice, skip the fireshot method if (fb.getbackground().equals(color.blue) fb.getbackground().equals(color.red)) { return; //miss if (fb.getname().equals("")) { //System.out.println("Miss at " + col.getcolumn() + ", " + row.getrow()); fb.setbackground(color.blue); fb.settext("m"); fireshot(col.getcolumn(), row.getrow()); //hit if (fb.getname().matches("[0-9]")) { //System.out.println("Hit at " + col.getcolumn() + ", " + row.getrow()); //int shipid = Integer.parseInt(fb.getName()); fb.settext("h"); fb.setbackground(color.red); fireshot(col.getcolumn(), row.getrow()); Prints the board, for testing only public void print() {
for (int r = 0; r < this.numrows; r++) { StringBuilder sb = new StringBuilder(this.numCols); for (int c = 0; c < this.numcols; c++) { sb.append(this.board[c][r]); System.out.println(sb.toString()); Check if all the ships on either player or CPU board have been sunk Returns true if game is over, false otherwise @return true if game is over, false otherwise public boolean isgameover() { if ((this.numbattleshipsleft <= 0) (this.numoppbattleshipsleft <= 0)) { return true; else { return false; public void resetgame() { this.numbattleshipsleft = 5; this.numoppbattleshipsleft = 5; this.shipinfo.clear(); this.opponentshipinfo.clear(); for (int i = 0; i < 5; i++) { shipinfo.add(0); opponentshipinfo.add(0); //add the file contents to the board and create the fire buttons for (int c = 0; c < this.numcols; c++) { for (int r = 0; r < this.numrows; r++) { try { this.fbp = fbboard[r][c]; if (!String.valueOf(board[r][c]).equals(String.valueOf(BattleshipBoard.EMPTY))) { this.fbp.settext(string.valueof(board[r][c])); fbp.setbackground(color.yellow); else { fbp.settext(""); fbp.setbackground(null); fbboard[r][c] = this.fbp; //set the ship number into the ship array int shipidval = Integer.parseInt(board[c][r] + ""); shipinfo.set(shipidval, shipinfo.get(shipidval) + 1); catch (NumberFormatException e) { cpu.setcpucol(-1);
cpu.setcpurow(-1); //fill the board with the FireButtons for (int c = 0; c < this.numcols; c++) { for (int r = 0; r < this.numrows; r++) { try { this.fb = fboppboard[r][c]; this.fb.settext(""); this.fb.setbackground(null); //place the ships on the board or empty space where no ship is if (!String.valueOf(oppboard[r][c]).equals(String.valueOf(BattleshipBoard.EMPTY))) { this.fb.setname(string.valueof(oppboard[r][c])); else { fb.setname(""); this.fb.setenabled(true); //this.fb.setmargin(new java.awt.insets(0, 0, 0, 0)); int shipidval = Integer.parseInt(oppboard[c][r] + ""); opponentshipinfo.set(shipidval, opponentshipinfo.get(shipidval) + 1); catch (NumberFormatException e) { Handles end of game message @Param boolean - true for player win, false for CPU win @return 0 if play again, 1 if no and exit public void endgame(int winner) { String winnermsg; if (winner == 0) winnermsg = "You win! "; else winnermsg = "You lose. "; //show dialog and ask to play again int result = JOptionPane.showConfirmDialog(null, winnermsg + "Do you want to play again?", "Game Over", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); if (result == 0) resetgame(); else System.exit(0); package As7BattleShip; Program: BattleshipBoard.java Author: Kevin Nider Date: 11/18/12 Description: Assignment 7: Manages the 2 CPU players: RandomCPU and SystematicCPU public class CPU { int numrow = 10; // number of rows for the board int numcol = 10;// number of columns for the board
//set back starting pos 1 column/row from start to make the methods easier for SystematicCPU int currentcol = -1; int currentrow = -1; Default method to get column to shoot at public int CPUcol() { return currentcol; Default method to get row to shoot at public int CPUrow() { return currentrow; public void setcpucol(int col) { currentcol = col; public void setcpurow(int row) { currentrow = row; package As7BattleShip; Program: BattleshipBoard.java Author: Kevin Nider Date: 11/18/12 Description: Assignment 7: Cell defines the cells for FireButton public class Cell { private int row; private int col; public Cell(int col, int row){ this.row = row; this.col = col; public int getrow(){ return this.row; public int getcolumn(){ return this.col; package As7BattleShip; Program: BattleshipBoard.java
Author: Kevin Nider Date: 11/18/12 Description: Assignment 7: FireButtons are used to select target cells on boards import javax.swing.jbutton; @SuppressWarnings("serial") public class FireButton extends JButton { private Cell cell; public FireButton(int col, int row){ cell = new Cell(col,row); @return the cell the button is at public Cell getcell(){ return this.cell; package As7BattleShip; Program: BattleshipBoard.java Author: Kevin Nider Date: 11/18/12 Description: Assignment 7: RandomCPU inherits the CPU class. The random player randomly selects a position on the board and shoots at it. If the player has already shot that location, the player picks a different location and shoots at it. public class RandomCPU extends CPU { public RandomCPU() { super(); Select a random column @Override public int CPUcol() { currentcol = (int) (Math.random()(numCol)); return currentcol; Select a random row @Override public int CPUrow() { currentrow = (int) (Math.random()(numRow)); return currentrow; package As7BattleShip;
Program: BattleshipBoard.java Author: Kevin Nider Date: 11/18/12 Description: Assignment 7: SystematicCPU inherits the CPU class. The systematic player randomly starts at (0,0) and moves across the board and down once it reaches the end. public class SystematicCPU extends CPU { public SystematicCPU() { super(); Start at row one, when column starts over, start on the next row @Override public int CPUrow() { if (currentcol == 0) { currentrow++; else { return currentrow; return currentrow; Start at column 0 and add one until the end, then start at 0 @Override public int CPUcol() { if (currentcol < numcol-1) { currentcol++; else { currentcol = 0; return currentcol;