├── README.md ├── .gitignore ├── src └── com │ └── almasb │ └── battleship │ ├── Ship.java │ ├── BattleshipMain.java │ └── Board.java └── LICENSE /README.md: -------------------------------------------------------------------------------- 1 | # Battleship 2 | Implementation of classic battleship game 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.war 5 | *.ear 6 | /bin 7 | 8 | # Eclipse # 9 | .classpath 10 | .project 11 | .settings/ 12 | /bin 13 | /target 14 | 15 | # maven # 16 | dependency-reduced-pom.xml 17 | 18 | # logs # 19 | *.log -------------------------------------------------------------------------------- /src/com/almasb/battleship/Ship.java: -------------------------------------------------------------------------------- 1 | package com.almasb.battleship; 2 | 3 | import javafx.scene.Parent; 4 | 5 | public class Ship extends Parent { 6 | public int type; 7 | public boolean vertical = true; 8 | 9 | private int health; 10 | 11 | public Ship(int type, boolean vertical) { 12 | this.type = type; 13 | this.vertical = vertical; 14 | health = type; 15 | 16 | /*VBox vbox = new VBox(); 17 | for (int i = 0; i < type; i++) { 18 | Rectangle square = new Rectangle(30, 30); 19 | square.setFill(null); 20 | square.setStroke(Color.BLACK); 21 | vbox.getChildren().add(square); 22 | } 23 | 24 | getChildren().add(vbox);*/ 25 | } 26 | 27 | public void hit() { 28 | health--; 29 | } 30 | 31 | public boolean isAlive() { 32 | return health > 0; 33 | } 34 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Almas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/com/almasb/battleship/BattleshipMain.java: -------------------------------------------------------------------------------- 1 | package com.almasb.battleship; 2 | 3 | import java.util.Random; 4 | 5 | import javafx.application.Application; 6 | import javafx.geometry.Pos; 7 | import javafx.scene.Parent; 8 | import javafx.scene.Scene; 9 | import javafx.scene.input.MouseButton; 10 | import javafx.scene.layout.BorderPane; 11 | import javafx.scene.layout.VBox; 12 | import javafx.scene.text.Text; 13 | import javafx.stage.Stage; 14 | 15 | import com.almasb.battleship.Board.Cell; 16 | 17 | public class BattleshipMain extends Application { 18 | 19 | private boolean running = false; 20 | private Board enemyBoard, playerBoard; 21 | 22 | private int shipsToPlace = 5; 23 | 24 | private boolean enemyTurn = false; 25 | 26 | private Random random = new Random(); 27 | 28 | private Parent createContent() { 29 | BorderPane root = new BorderPane(); 30 | root.setPrefSize(600, 800); 31 | 32 | root.setRight(new Text("RIGHT SIDEBAR - CONTROLS")); 33 | 34 | enemyBoard = new Board(true, event -> { 35 | if (!running) 36 | return; 37 | 38 | Cell cell = (Cell) event.getSource(); 39 | if (cell.wasShot) 40 | return; 41 | 42 | enemyTurn = !cell.shoot(); 43 | 44 | if (enemyBoard.ships == 0) { 45 | System.out.println("YOU WIN"); 46 | System.exit(0); 47 | } 48 | 49 | if (enemyTurn) 50 | enemyMove(); 51 | }); 52 | 53 | playerBoard = new Board(false, event -> { 54 | if (running) 55 | return; 56 | 57 | Cell cell = (Cell) event.getSource(); 58 | if (playerBoard.placeShip(new Ship(shipsToPlace, event.getButton() == MouseButton.PRIMARY), cell.x, cell.y)) { 59 | if (--shipsToPlace == 0) { 60 | startGame(); 61 | } 62 | } 63 | }); 64 | 65 | VBox vbox = new VBox(50, enemyBoard, playerBoard); 66 | vbox.setAlignment(Pos.CENTER); 67 | 68 | root.setCenter(vbox); 69 | 70 | return root; 71 | } 72 | 73 | private void enemyMove() { 74 | while (enemyTurn) { 75 | int x = random.nextInt(10); 76 | int y = random.nextInt(10); 77 | 78 | Cell cell = playerBoard.getCell(x, y); 79 | if (cell.wasShot) 80 | continue; 81 | 82 | enemyTurn = cell.shoot(); 83 | 84 | if (playerBoard.ships == 0) { 85 | System.out.println("YOU LOSE"); 86 | System.exit(0); 87 | } 88 | } 89 | } 90 | 91 | private void startGame() { 92 | // place enemy ships 93 | int type = 5; 94 | 95 | while (type > 0) { 96 | int x = random.nextInt(10); 97 | int y = random.nextInt(10); 98 | 99 | if (enemyBoard.placeShip(new Ship(type, Math.random() < 0.5), x, y)) { 100 | type--; 101 | } 102 | } 103 | 104 | running = true; 105 | } 106 | 107 | @Override 108 | public void start(Stage primaryStage) throws Exception { 109 | Scene scene = new Scene(createContent()); 110 | primaryStage.setTitle("Battleship"); 111 | primaryStage.setScene(scene); 112 | primaryStage.setResizable(false); 113 | primaryStage.show(); 114 | } 115 | 116 | public static void main(String[] args) { 117 | launch(args); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/com/almasb/battleship/Board.java: -------------------------------------------------------------------------------- 1 | package com.almasb.battleship; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javafx.event.EventHandler; 7 | import javafx.geometry.Point2D; 8 | import javafx.scene.Parent; 9 | import javafx.scene.input.MouseEvent; 10 | import javafx.scene.layout.HBox; 11 | import javafx.scene.layout.VBox; 12 | import javafx.scene.paint.Color; 13 | import javafx.scene.shape.Rectangle; 14 | 15 | public class Board extends Parent { 16 | private VBox rows = new VBox(); 17 | private boolean enemy = false; 18 | public int ships = 5; 19 | 20 | public Board(boolean enemy, EventHandler handler) { 21 | this.enemy = enemy; 22 | for (int y = 0; y < 10; y++) { 23 | HBox row = new HBox(); 24 | for (int x = 0; x < 10; x++) { 25 | Cell c = new Cell(x, y, this); 26 | c.setOnMouseClicked(handler); 27 | row.getChildren().add(c); 28 | } 29 | 30 | rows.getChildren().add(row); 31 | } 32 | 33 | getChildren().add(rows); 34 | } 35 | 36 | public boolean placeShip(Ship ship, int x, int y) { 37 | if (canPlaceShip(ship, x, y)) { 38 | int length = ship.type; 39 | 40 | if (ship.vertical) { 41 | for (int i = y; i < y + length; i++) { 42 | Cell cell = getCell(x, i); 43 | cell.ship = ship; 44 | if (!enemy) { 45 | cell.setFill(Color.WHITE); 46 | cell.setStroke(Color.GREEN); 47 | } 48 | } 49 | } 50 | else { 51 | for (int i = x; i < x + length; i++) { 52 | Cell cell = getCell(i, y); 53 | cell.ship = ship; 54 | if (!enemy) { 55 | cell.setFill(Color.WHITE); 56 | cell.setStroke(Color.GREEN); 57 | } 58 | } 59 | } 60 | 61 | return true; 62 | } 63 | 64 | return false; 65 | } 66 | 67 | public Cell getCell(int x, int y) { 68 | return (Cell)((HBox)rows.getChildren().get(y)).getChildren().get(x); 69 | } 70 | 71 | private Cell[] getNeighbors(int x, int y) { 72 | Point2D[] points = new Point2D[] { 73 | new Point2D(x - 1, y), 74 | new Point2D(x + 1, y), 75 | new Point2D(x, y - 1), 76 | new Point2D(x, y + 1) 77 | }; 78 | 79 | List neighbors = new ArrayList(); 80 | 81 | for (Point2D p : points) { 82 | if (isValidPoint(p)) { 83 | neighbors.add(getCell((int)p.getX(), (int)p.getY())); 84 | } 85 | } 86 | 87 | return neighbors.toArray(new Cell[0]); 88 | } 89 | 90 | private boolean canPlaceShip(Ship ship, int x, int y) { 91 | int length = ship.type; 92 | 93 | if (ship.vertical) { 94 | for (int i = y; i < y + length; i++) { 95 | if (!isValidPoint(x, i)) 96 | return false; 97 | 98 | Cell cell = getCell(x, i); 99 | if (cell.ship != null) 100 | return false; 101 | 102 | for (Cell neighbor : getNeighbors(x, i)) { 103 | if (!isValidPoint(x, i)) 104 | return false; 105 | 106 | if (neighbor.ship != null) 107 | return false; 108 | } 109 | } 110 | } 111 | else { 112 | for (int i = x; i < x + length; i++) { 113 | if (!isValidPoint(i, y)) 114 | return false; 115 | 116 | Cell cell = getCell(i, y); 117 | if (cell.ship != null) 118 | return false; 119 | 120 | for (Cell neighbor : getNeighbors(i, y)) { 121 | if (!isValidPoint(i, y)) 122 | return false; 123 | 124 | if (neighbor.ship != null) 125 | return false; 126 | } 127 | } 128 | } 129 | 130 | return true; 131 | } 132 | 133 | private boolean isValidPoint(Point2D point) { 134 | return isValidPoint(point.getX(), point.getY()); 135 | } 136 | 137 | private boolean isValidPoint(double x, double y) { 138 | return x >= 0 && x < 10 && y >= 0 && y < 10; 139 | } 140 | 141 | public class Cell extends Rectangle { 142 | public int x, y; 143 | public Ship ship = null; 144 | public boolean wasShot = false; 145 | 146 | private Board board; 147 | 148 | public Cell(int x, int y, Board board) { 149 | super(30, 30); 150 | this.x = x; 151 | this.y = y; 152 | this.board = board; 153 | setFill(Color.LIGHTGRAY); 154 | setStroke(Color.BLACK); 155 | } 156 | 157 | public boolean shoot() { 158 | wasShot = true; 159 | setFill(Color.BLACK); 160 | 161 | if (ship != null) { 162 | ship.hit(); 163 | setFill(Color.RED); 164 | if (!ship.isAlive()) { 165 | board.ships--; 166 | } 167 | return true; 168 | } 169 | 170 | return false; 171 | } 172 | } 173 | } --------------------------------------------------------------------------------