diff --git a/overview.html b/overview.html new file mode 100644 index 0000000..4d014f1 --- /dev/null +++ b/overview.html @@ -0,0 +1,7 @@ + + + + +BattleShip package + + \ No newline at end of file diff --git a/src/battleship/Main.java b/src/battleship/Main.java index 0e963d4..76f53b6 100644 --- a/src/battleship/Main.java +++ b/src/battleship/Main.java @@ -6,8 +6,8 @@ import battleship.model.player.Human; import battleship.model.player.Player; import battleship.model.player.Random; import battleship.utils.Pair; -import battleship.view.AbstractView; import battleship.view.Terminal; +import battleship.view.View; import battleship.view.Window; import java.lang.reflect.InvocationTargetException; @@ -15,9 +15,13 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.NoSuchElementException; +/** + * Main class + * Given arguments are importants, please give attention to {@link Main#parseArgs(String[])} about this + */ public class Main { - public static AbstractView view; + public static View view; public static Game game; public static void main(String[] args) { @@ -36,6 +40,20 @@ public class Main { game.Play(view); } + /** + *

Read and parse launch arguments.
+ * launch arguments need to follow this syntax:

+ *

{@code [nogui]}

+ *

<arg> -> mandatory parameter
+ * [arg] -> optional parameter
+ * player_instance values are: "Human" or "Random"
+ * nogui to launch the game in terminal or nothing to launch in graphical interface

+ * @param args launch arguments + * @throws NoSuchMethodException reflect exception + * @throws IllegalAccessException reflect exception + * @throws InvocationTargetException reflect exception + * @throws InstantiationException reflect exception + */ private static void parseArgs(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Player[] players = new Player[2]; ArrayList>> playerClass = new ArrayList<>(2); diff --git a/src/battleship/control/package-info.java b/src/battleship/control/package-info.java new file mode 100644 index 0000000..c1cc5f0 --- /dev/null +++ b/src/battleship/control/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains keyboard and mouse listeners + */ +package battleship.control; \ No newline at end of file diff --git a/src/battleship/model/Game.java b/src/battleship/model/Game.java index 810bc8e..0690e78 100644 --- a/src/battleship/model/Game.java +++ b/src/battleship/model/Game.java @@ -3,8 +3,11 @@ package battleship.model; import battleship.model.player.Player; import battleship.utils.Pair; import battleship.utils.Triplet; -import battleship.view.AbstractView; +import battleship.view.View; +/** + * Main game class + */ public class Game { public Player[] players; @@ -17,7 +20,6 @@ public class Game { players[1].setId(2); } - public Player getCurrentPlayer(){ return this.currentPlayer; } @@ -34,6 +36,9 @@ public class Game { currentPlayer = getOtherPlayer(); } + /** + * Update ship to know if they're drowned + */ public void checkDrownedShips(){ Player otherPlayer = getOtherPlayer(); for(Ship ship : otherPlayer.getShips()){ @@ -42,6 +47,9 @@ public class Game { } } + /** + * @return player 1 if player 2' ships are drowned, or player 2 if player1' ships are drowned, null otherwise + */ public Player getWinner(){ Ship remainingShip = players[0].getShips().parallelStream().filter(ship -> !ship.isDrown()).findFirst().orElse(null); if(remainingShip == null) @@ -52,6 +60,11 @@ public class Game { return null; } + + /** + * Play the selected move from current player in grid + * @param move selected player move + */ public void move(Pair move){ boolean bool = false; Player otherPlayer = getOtherPlayer(); @@ -68,7 +81,11 @@ public class Game { currentPlayer.addMove(new Triplet<>(move, bool)); } - public void Play(AbstractView view) { + /** + * game loop + * @param view can be {@link battleship.view.Terminal} or {@link battleship.view.Window} + */ + public void Play(View view) { try { view.setShips(players[0]); view.setShips(players[1]); diff --git a/src/battleship/model/package-info.java b/src/battleship/model/package-info.java new file mode 100644 index 0000000..ddd86bc --- /dev/null +++ b/src/battleship/model/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains all main Game classes + */ +package battleship.model; \ No newline at end of file diff --git a/src/battleship/model/player/package-info.java b/src/battleship/model/player/package-info.java new file mode 100644 index 0000000..1ff58cc --- /dev/null +++ b/src/battleship/model/player/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains all players classes instances and theirs super classes and interface + */ +package battleship.model.player; \ No newline at end of file diff --git a/src/battleship/package-info.java b/src/battleship/package-info.java new file mode 100644 index 0000000..e8d3bd2 --- /dev/null +++ b/src/battleship/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains Main Class + */ +package battleship; \ No newline at end of file diff --git a/src/battleship/utils/Pair.java b/src/battleship/utils/Pair.java index 7f1e7f5..16de05f 100644 --- a/src/battleship/utils/Pair.java +++ b/src/battleship/utils/Pair.java @@ -3,7 +3,7 @@ package battleship.utils; import java.util.Objects; /** - * tuple containing 2 unknown type elements + * tuple containing 2 generic type elements * * @param left * @param right diff --git a/src/battleship/utils/Triplet.java b/src/battleship/utils/Triplet.java index a24f088..961a335 100644 --- a/src/battleship/utils/Triplet.java +++ b/src/battleship/utils/Triplet.java @@ -3,10 +3,11 @@ package battleship.utils; import java.util.Objects; /** - * tuple containing 2 unknown type elements + * tuple containing 3 generic type elements * * @param left - * @param right + * @param middle + * @param right */ public class Triplet { diff --git a/src/battleship/utils/package-info.java b/src/battleship/utils/package-info.java new file mode 100644 index 0000000..abd472d --- /dev/null +++ b/src/battleship/utils/package-info.java @@ -0,0 +1,4 @@ +/** + * Utility classes + */ +package battleship.utils; \ No newline at end of file diff --git a/src/battleship/view/AbstractView.java b/src/battleship/view/AbstractView.java index 2da045d..766be35 100644 --- a/src/battleship/view/AbstractView.java +++ b/src/battleship/view/AbstractView.java @@ -9,18 +9,26 @@ import battleship.utils.Triplet; import java.util.ArrayList; +/** + * Abstract view class + * @see View + * @see Window + * @see Terminal + */ public abstract class AbstractView implements View { - protected Game game; public AbstractView(Game game) { this.game = game; } + /** + * Used during debugging, used in terminal to display grids too + * @return all player grids + */ @Override public String toString() { - // String chain = "A vous de joueur "+game.currentPlayer.toString()+ "\n+ - - - - - - - - - - +\n"; String chain = ""; for(int u = 0; u < 2; ++u) { Player player = game.players[u]; @@ -63,6 +71,10 @@ public abstract class AbstractView implements View { return chain; } + /** + * + * @return {@code true} if {@link Ship#getFullCoords()} contains {@code boardsCoords}, {@code false} otherwise + */ private boolean isShipPosition(Ship ship, Pair boardsCoords) { for(Pair coords : ship.getFullCoords()) { if(boardsCoords.equals(coords)) @@ -71,6 +83,12 @@ public abstract class AbstractView implements View { return false; } + /** + * ask player for keyboard input and parse it into one of {@link Direction} value + * @return Direction depending of player input + * @throws InterruptedException see {@link Window#getDirectionFromChar()} + * @see Window#getDirectionFromChar() + */ protected Direction getDirectionFromChar() throws InterruptedException { String dir; while (true) { @@ -84,21 +102,37 @@ public abstract class AbstractView implements View { } } + /** + * ask player for keyboard input and return result + * @return String given by player + * @throws InterruptedException see {@link Window#getKeyInput()} + */ protected abstract String getKeyInput() throws InterruptedException; + /** + * Display a text above the grid on {@link Window}, simply print text on {@link Terminal} + * @param s text to display + * @see Window#setUpperText(String) + * @see Terminal#setUpperText(String) + */ protected abstract void setUpperText(String s); + /** + * used if {@code player} instance of {@link battleship.model.player.Computer} + * @param player player we ask to set position of its ships + * @throws InterruptedException see {@link Window#setShips(Player)} + */ @Override public void setShips(Player player) throws InterruptedException { player.placeShips(); } /** - * * @param other other than the current player - * @param ship check if this ship at this position is touch + * @param ship check if this ship at this position has been hit * @param pair coords * @return 1 if ship fully drowned, 2 if only damaged, 0 if not + * @see */ private int isPositionDrowned(Player other, Ship ship, Pair pair) { if(ship.isDrown()) @@ -106,6 +140,11 @@ public abstract class AbstractView implements View { return isPositionDrowned(other, pair); } + /** + * @param other other than the current player + * @param pair coords to check + * @return 2 if player already played here, 0 otherwise + */ private int isPositionDrowned(Player other, Pair pair) { for(Triplet move : other.getMoves()) { if(pair.getLeft().equals(move.getLeft()) && pair.getRight().equals(move.getMiddle())) { @@ -115,12 +154,33 @@ public abstract class AbstractView implements View { return 0; } + /** + * used by {@link battleship.model.player.Computer} player to play a move in the grid depending of its algorithm + * @param player {@link battleship.model.Game#currentPlayer} + * @return a couple ({@link Pair} containing the x and y coordinate (left side store Y and right side X) + * @throws InterruptedException see {@link Window#chooseMove(Player)} + */ @Override public Pair chooseMove(Player player) throws InterruptedException { return player.chooseMove(); } + /** + * ask {@code player} for mouse input + * @param player {@link Game#currentPlayer} + * @return coordinate of {@code player} opponent grid + * @see Window#mouseInput(Player) + * @throws InterruptedException see {@link Window#mouseInput(Player)} + */ protected abstract Pair mouseInput(Player player) throws InterruptedException; + /** + * ask {@link Game#currentPlayer} for keyboard input + * @return String given by player + * @throws InterruptedException see {@link Window#keyboardInput()} + * @see Window#keyboardInput() + * @see Terminal#keyboardInput() + * @see Terminal#keyboardInputInteger() + */ protected abstract String keyboardInput() throws InterruptedException; } diff --git a/src/battleship/view/Terminal.java b/src/battleship/view/Terminal.java index 899c284..c200b3d 100644 --- a/src/battleship/view/Terminal.java +++ b/src/battleship/view/Terminal.java @@ -10,6 +10,11 @@ import battleship.utils.Pair; import java.util.Scanner; +/** + * Terminal view, instanced if argument 2 equals to "nogui" + * @see View + * @see AbstractView + */ public class Terminal extends AbstractView { public static Scanner scanner = null; @@ -22,16 +27,28 @@ public class Terminal extends AbstractView { keyboardComponent = new TerminalKeyboardListener(scanner); } + /** + * @return given string in terminal + */ @Override protected String getKeyInput() { return scanner.next().toUpperCase(); } + /** + * print string + * @param s text to display + */ @Override protected void setUpperText(String s) { System.out.println(s); } + /** + * Ask {@code player} to set position of its ships + * @param player player we ask to set position of its ships + * @throws InterruptedException see {@link AbstractView#getDirectionFromChar()} + */ @Override public void setShips(Player player) throws InterruptedException { setUpperText("Joueur " + player.getId() + ", placez vos navires"); @@ -69,11 +86,22 @@ public class Terminal extends AbstractView { } } + /** + * print board in terminal + */ @Override public void displayBoard() { System.out.println(this); } + /** + * ask player to choose a coords on its opponent grid, call {@link AbstractView#chooseMove(Player)} if instance of + * player is {@link battleship.model.player.Computer} + * if {@code player} isn't {@link Human} instance + * @param player {@link battleship.model.Game#currentPlayer} + * @return a element containing the x and y coordinate (left side store Y and right side X) + * @throws InterruptedException see {@link AbstractView#chooseMove(Player)} + */ @Override public Pair chooseMove(Player player) throws InterruptedException { if(player instanceof Human) { @@ -97,20 +125,38 @@ public class Terminal extends AbstractView { } + /** + * Never call in Terminal + * @param player {@link Game#currentPlayer} + * @return {@code null} + */ @Override protected Pair mouseInput(Player player) { return null; } + /** + * @see TerminalKeyboardListener#keyboardInput() + * @return given string in terminal + */ @Override protected String keyboardInput() { return keyboardComponent.keyboardInput(); } + /** + * @see Terminal#keyboardInput() + * @return convert string from keyboardInput() and convert it into an integer + * @throws NumberFormatException if given string can't be parse into an integer + */ protected int keyboardInputInteger() throws NumberFormatException { return Integer.parseInt(keyboardComponent.keyboardInput()); } + /** + * print grid, winner player and close scanner, game automatically close after this + * @param winner the winner of the game. + */ @Override public void displayWinner(Player winner) { displayBoard(); diff --git a/src/battleship/view/View.java b/src/battleship/view/View.java index 232cc86..39d8851 100644 --- a/src/battleship/view/View.java +++ b/src/battleship/view/View.java @@ -3,15 +3,44 @@ package battleship.view; import battleship.model.player.Player; import battleship.utils.Pair; +/** + *

View interface, used as an API
+ * This model (interface(s) -> abstract class(es) -> concrete classes) prevent hard code.

+ *

This is the only object which interact with other object
+ * Allows an outside person easily change the code or add a view easily without modifying existing classes

+ * @see AbstractView + * @see Terminal + * @see Window + */ public interface View { int[] shipsSize = { 5, 4, 3, 3, 2}; + /** + * Ask {@code player} to set position of its ships + * @param player player instance we ask + * @throws InterruptedException see {@link Window#setShips(Player)} + */ void setShips(Player player) throws InterruptedException; + /** + * Display all grids + */ void displayBoard(); + /** + * ask the player the choose a position on its opponent grid + * @param player {@link battleship.model.Game#currentPlayer} + * @return a element containing the x and y coordinate (left side store Y and right side X) + * @throws InterruptedException see {@link Window#chooseMove(Player)} + */ Pair chooseMove(Player player) throws InterruptedException; + /** + * Display the winner of the game and then close the game + * @param winner the winner of the game. + * @see Window#displayWinner(Player) + * @see Terminal#displayWinner(Player) + */ void displayWinner(Player winner); } diff --git a/src/battleship/view/Window.java b/src/battleship/view/Window.java index c86d601..5febc70 100644 --- a/src/battleship/view/Window.java +++ b/src/battleship/view/Window.java @@ -15,11 +15,22 @@ import java.awt.*; import java.awt.event.KeyEvent; import java.awt.geom.RoundRectangle2D; +/** + * Window view, instanced if argument 2 equals to "nogui" + * @see View + * @see AbstractView + */ public class Window extends AbstractView { final JFrame frame; + /** + * grids height, do no represent frame size + */ public final int height = 600; + /** + * grids width, do no represent frame size + */ public final int width = 1200; private final WindowMouseListener mouseComponent; private final WindowKeyboardListener keyboardComponent; @@ -46,11 +57,20 @@ public class Window extends AbstractView { return keyboardInput(); } + /** + * Display a text above the grid + * @param s text to display + */ @Override protected void setUpperText(String s) { upperTitle = s; } + /** + * Ask {@code player} to set position of its ships + * @param player player we ask + * @throws InterruptedException see {@link Window#mouseInput(Player)} and {@link Window#getDirectionFromChar()} + */ @Override public void setShips(Player player) throws InterruptedException { if(player instanceof Human) { @@ -80,6 +100,11 @@ public class Window extends AbstractView { } } + /** + * ask {@link Game#currentPlayer} for keyboard input + * @return String given by player + * @throws InterruptedException throw if this Thread is interrupted while {@link Thread#sleep(long) sleeping} + */ @Override protected String keyboardInput() throws InterruptedException { keyboardComponent.requestInput = true; @@ -94,6 +119,12 @@ public class Window extends AbstractView { } } + /** + * ask {@code player} for mouse input + * @param player {@link Game#currentPlayer} + * @return coordinate of {@code player} opponent grid + * @throws InterruptedException throw if this Thread is interrupted while {@link Thread#sleep(long) sleeping} + */ @Override protected Pair mouseInput(Player player) throws InterruptedException { mouseComponent.requestInput = true; @@ -105,7 +136,6 @@ public class Window extends AbstractView { mouseComponent.playerIdLastInput = 0; Pair value = mouseComponent.lastInput; mouseComponent.lastInput = null; - System.out.println(value); return value; } else { openDialog("Vous avez cliquer sur une zone de jeu qui n'est pas la votre"); @@ -116,21 +146,40 @@ public class Window extends AbstractView { } } + /** + * Open a window with {@code message} as content and with a "OK" button + * @param message message to display + * @param exitOnClose {@code true} if when user close this window, the program exit, {@code false} otherwise + */ public void openDialog(String message, boolean exitOnClose) { JOptionPane.showMessageDialog(frame, message); if(exitOnClose) System.exit(0); } + /** + * Open a window with {@code message} as content and with a "OK" button + * @param message message to display + * @see Window#openDialog(String, boolean) + */ public void openDialog(String message) { openDialog(message, false); } + /** + * refresh windows to display updated content + */ @Override public void displayBoard() { frame.paintComponents(frame.getGraphics()); } + /** + * ask player to choose a position in its opponent grid + * @param player {@link battleship.model.Game#currentPlayer} + * @return a couple ({@link Pair} containing the x and y coordinate (left side store Y and right side X) + * @throws InterruptedException see {@link Window#mouseInput(Player)} + */ @Override public Pair chooseMove(Player player) throws InterruptedException { setUpperText("Joueur " + player.getId() + " cliquer sur l'emplacement ou vous souhaitez tirer"); @@ -150,11 +199,19 @@ public class Window extends AbstractView { } + /** + * open a dialog to display the winner and exit the program when window is closed + * @param winner the winner of the game. + */ @Override public void displayWinner(Player winner) { openDialog("Le joueur " + winner.getId() + " a gagné(e)", true); } + /** + * Panel where we paint the board + * @see JPanel + */ class Draw extends JPanel { private final Window window; @@ -240,11 +297,8 @@ public class Window extends AbstractView { g2d.rotate(Math.toRadians(45), x1 + initialWidth - 9, y1 - 9); g2d.fill(cross2); g2d.rotate(Math.toRadians(-45), x1 + initialWidth - 9, y1 - 9); - - } } - System.out.println(window); } } } diff --git a/src/battleship/view/package-info.java b/src/battleship/view/package-info.java new file mode 100644 index 0000000..b104f2e --- /dev/null +++ b/src/battleship/view/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains terminal and windows view classes and theirs super class and interface + */ +package battleship.view; \ No newline at end of file