-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBattleShip.java
More file actions
406 lines (350 loc) · 12.8 KB
/
BattleShip.java
File metadata and controls
406 lines (350 loc) · 12.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
import javafx.application.*;
import javafx.event.*;
import javafx.scene.control.*;
import javafx.scene.control.Labeled;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.stage.*;
import javafx.geometry.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.*;
import javafx.event.ActionEvent;
import javafx.scene.control.Alert.AlertType;
public class BattleShip extends Application
{
//Declare Menu fields.
private Menu gameMenu;
private Menu helpMenu;
private MenuItem menuNew;
private MenuItem menuExit;
private MenuItem menuHelp;
private RadioMenuItem menuEasy;
private RadioMenuItem menuMedium;
private RadioMenuItem menuHard;
private Menu menuDifficulty;
private MenuBar menuBar;
//Declare variables for gameplay.
private int hits = 0;
private int misses = 0;
private int shipsRemaining;
//Declare the game object.
private BattleshipsGame game;
//Declare array for the buttons.
private Button[] btnArray;
//Create image objects.
private Image space = new Image("images/space.png");
private Image hit = new Image("images/HIT.png");
private Image miss = new Image("images/Miss.png");
private Image life = new Image("images/batteryLife.png");
private Image notHit = new Image("images/notHit.png");
//Create information labels.
private Label lbl1;
private Label lifeLbl;
private Label lifeLbl2;
private Label hitsLbl;
private Label missesLbl;
private Label shipsLbl;
//Declare vbox for the lives remaining display and declare the stage.
private VBox lifeBox;
private Stage stage;
public void start(Stage primaryStage)
{
stage = primaryStage;
game = new BattleshipsGame();
shipsRemaining = 6;
Scene scene = new Scene(createBorderPane() );
scene.getStylesheets().add("BattleShipCSS.css");
primaryStage.setScene(scene);
primaryStage.setTitle("BattleSpaceShip");
primaryStage.show();
}
//Method to create a borderpane.
//This method contains other methods for creating the parts of the borderpane.
private BorderPane createBorderPane()
{
BorderPane bPane = new BorderPane();
bPane.setCenter(createPane() );
bPane.setBottom(createResultPane() );
bPane.setLeft(createLivesPane() );
bPane.setRight(createProgressPane() );
VBox menuPane = new VBox();
menuPane.getChildren().add(createMenu() );
bPane.setTop(menuPane);
bPane.setId("bPane");
return bPane;
}
//Method to create a VBox showing remaining lives on the left side of the BorderPane.
private VBox createLivesPane()
{
lifeBox = new VBox();
lifeBox.setAlignment(Pos.TOP_CENTER);
lifeBox.setId("lifeBox");
lifeLbl = new Label(" Shots \nRemaining");
lifeLbl.setTextFill(Color.RED);
lifeBox.getChildren().addAll(lifeLbl);
for(int i=0; i<game.getLives(); i++)
lifeBox.getChildren().add(new ImageView(life) );
return lifeBox;
}
//Method to update the lives if a shot misses.
private void updateLives()
{
lifeBox.getChildren().clear();
lifeBox.getChildren().addAll(lifeLbl);
for(int i=0; i<game.getLives(); i++)
lifeBox.getChildren().add(new ImageView(life) );
}
//Method to create a VBox showing hits, misses & ships remaining on the right side of the BorderPane.
private VBox createProgressPane()
{
VBox progressBox = new VBox();
progressBox.setAlignment(Pos.TOP_LEFT);
progressBox.setId("lifeBox");
hitsLbl = new Label("Hits: \n" + hits);
hitsLbl.setTextFill(Color.RED);
missesLbl = new Label("Misses: \n" + misses);
missesLbl.setTextFill(Color.RED);
shipsLbl = new Label("Remaining \nSpaceships: \n" + shipsRemaining);
shipsLbl.setTextFill(Color.RED);
progressBox.getChildren().addAll(hitsLbl, missesLbl, shipsLbl);
return progressBox;
}
//Method to update the hits, misses & ships remaining.
private void updateProgress()
{
hitsLbl.setText("Hits: \n" + hits);
missesLbl.setText("Misses: \n" + misses);
shipsLbl.setText("Remaining \nSpaceships: \n" + shipsRemaining);
}
/*Method to create a HBox informing the player of the outcome of their last move
at the bottom of the BorderPane.*/
private HBox createResultPane()
{
HBox resultBox = new HBox(10);
resultBox.setAlignment(Pos.CENTER);
resultBox.setId("lifeBox");
lbl1 = new Label("Outcome: ");
lbl1.setTextFill(Color.RED);
resultBox.getChildren().add(lbl1);
return resultBox;
}
/*This method crates the 16 buttons used in the game. It also creates an array of the 16 button
objects. The method creates a 4 column by 4 row TilePane and inserts the buttons into it. The
TilePane is then inserted into a Pane to keep the 4x4 layout. The Pane is then returned to the
center of the BorderPane.*/
private Pane createPane()
{
//Create array to hold buttons and a TilePane to act as a grid.
btnArray = new Button[16];
TilePane tPane = new TilePane();
tPane.setPrefColumns(4);
tPane.setPrefRows(4);
tPane.setPrefTileHeight(110);
tPane.setPrefTileWidth(110);
//Create 16 buttons, set size and action.
for(int i=0; i<16; i++)
{
Button b = new Button ("" + i);
btnArray[i] = b;
b.setOnAction(e -> shootBtn(e) );
b.setMinHeight(100);
b.setPrefHeight(100);
b.setMinWidth(100);
b.setPrefWidth(100);
b.setPadding(new Insets(3) );
tPane.getChildren().add(b);//Add buttons to the TilePane.
}
//
Pane pane = new Pane();
pane.getChildren().add(tPane);
return pane;
}
//Method creates the MenuBar at the top.
private MenuBar createMenu()
{
//Create menu items for the game Menu.
gameMenu = new Menu("_Game");
menuNew = new MenuItem("_New");
menuExit = new MenuItem("E_xit");
//Set Actions for above MenuItems.
menuNew.setOnAction(e -> newGame() );
menuExit.setOnAction(e -> exit() );
//Create RadioMenuItems for the Difficulty sub-menu.
menuEasy = new RadioMenuItem("Easy");
menuMedium = new RadioMenuItem("Medium");
menuHard = new RadioMenuItem("Hard");
menuMedium.setSelected(true); //Set medium as default difficulty.
//Create and set toggleGroup for RadioMenuItems.
ToggleGroup difficultyGroup = new ToggleGroup();
menuEasy.setToggleGroup(difficultyGroup);
menuMedium.setToggleGroup(difficultyGroup);
menuHard.setToggleGroup(difficultyGroup);
//Create the new submenu and add difficulty items to it.
menuDifficulty = new Menu("_Difficulty");
menuDifficulty.getItems().add(menuEasy);
menuDifficulty.getItems().add(menuMedium);
menuDifficulty.getItems().add(menuHard);
helpMenu = new Menu("_Help");
menuHelp = new MenuItem("Help");
menuHelp.setOnAction(e -> help() );
/*Add all MenuItems to the gameMenu with a SeparatorMenuItem. Then add the gameMenu to
a menuBar and return the menuBar.*/
gameMenu.getItems().addAll(menuNew, new SeparatorMenuItem(), menuDifficulty, menuExit);
helpMenu.getItems().add(menuHelp);
menuBar = new MenuBar(gameMenu, helpMenu);
return menuBar;
}
//Method which defines what happens when a button is clicked.
private void shootBtn(ActionEvent e)
{
if((game.getLives() != 0) && (shipsRemaining >0) )
{
//get the button source
Button b = (Button)e.getSource();
//disable the button
b.setDisable(true);
//Convert the text from the buttons from String to Integer.
int btnVal = Integer.parseInt(b.getText());
//Calculate the row and column based on the number of the button in the GUI.
int r = btnVal/4;
int c = btnVal %4;
//Shoot the corresponding cell in battleshipgame using the shoot() method from the game.
String output = game.shoot(r,c);
//Display outcome of the shot to the player, at the bottom of the BorderPane.
lbl1.setText("Outcome: " + output);
//
if (output.equals("Miss!"))
{
b.setGraphic(new ImageView(miss) );
misses++;
updateLives();
updateProgress();
}
else
{
b.setGraphic(new ImageView(hit) );
hits++;
shipsRemaining--;
updateProgress();
}
}
if(shipsRemaining == 0)
{
hits =0;
misses =0;
lbl1.setText("!!!Winner!!!");
for(Button btn: btnArray)
{
btn.setDisable(true);
}
Alert alert = new Alert(AlertType.INFORMATION, "!!!WINNER!!!");
alert.showAndWait();
}
if(game.getLives() == 0)
{
hits =0;
misses =0;
lbl1.setText("GAME OVER \n Use the game menu to start again.");
for(Button btn: btnArray)
{
int btnVal = Integer.parseInt(btn.getText() );
int r = btnVal/4;
int c = btnVal%4;
if (game.checkIfShip(r,c) && (!btn.isDisabled()) )
btn.setGraphic(new ImageView(notHit) );
btn.setDisable(true);
}
}
}//shootBtn()
private void exit()
{
stage.close();
}
private BattleshipsGame newGame() //Alertbox if restart mid-game
{
if(game.getLives() > 0)
{
//CONFIRMATION Dialog
Alert alert = new Alert(AlertType.CONFIRMATION, "Are you sure you want to abandon this game?");
//alert.showAndWait();
if (alert.showAndWait().get() == ButtonType.OK)
{
for (Button b: btnArray)
{
b.setGraphic(null);
b.setDisable(false);
}
if(menuEasy.isSelected() )
{
game = new BattleshipsGame(10, 6);
shipsRemaining = 6;
updateLives();
updateProgress();
return game;
}
else if(menuHard.isSelected() )
{
game = new BattleshipsGame(5, 6);
shipsRemaining = 6;
updateLives();
updateProgress();
return game;
}
else
{
game = new BattleshipsGame();
shipsRemaining = 6;
updateLives();
updateProgress();
return game;
}
}
}
else
{
for (Button b: btnArray)
{
b.setGraphic(null);
b.setDisable(false);
}
if(menuEasy.isSelected() )
{
game = new BattleshipsGame(10, 6);
updateLives();
updateProgress();
return game;
}
else if(menuHard.isSelected() )
{
game = new BattleshipsGame(5, 6);
updateLives();
updateProgress();
return game;
}
else
{
game = new BattleshipsGame();
updateLives();
updateProgress();
return game;
}
}
return game;
}
private void help()
{
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Game Instructions");
//alert.setHeaderText("This is an Information Dialog");
//alert.setHeaderText("this is the header text"); //without header text
alert.setHeaderText(null);
alert.setContentText("1. You are flying a spaceship. \n2. Enemy ships are hiding behind some of the panels on the grid. "
+ "\n3. Click a number to shoot your lazer. \n4. When you hit a ship you absorb their power and don't lose lazer battery charge. "
+ "\n5. When you miss you lose battery charge. \n6. Charges are shown on the left. When you have no more charges you are dead in the proverbial water.");
alert.showAndWait();
}
}