-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBoard.java
More file actions
238 lines (208 loc) · 7.62 KB
/
Copy pathBoard.java
File metadata and controls
238 lines (208 loc) · 7.62 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
/*
* Board.java - blueprint class for objects that represent a board
* in the game of Battleship.
*
* Computer Science 111, Boston University
*
* ********* YOU SHOULD NOT EDIT THIS FILE. *********
*/
import java.util.*;
public class Board {
// The three possible states for a cell on the board.
public static final int EMPTY = 0;
public static final int UNHIT = 1;
public static final int HIT = 2;
public static final int MISS = 3;
public static final int VERTICAL = 0;
public static final int HORIZONTAL = 1;
public static final Random RAND = new Random();
private int dimension;
private int[][] status; // status of each position on the board
private Ship[][] shipAt; // the ship (if any) located at each position
private int shipsRemaining; // number of unsunk ships
/*
* constructor for a Board with the specified dimension
*/
public Board(int dimension) {
this.dimension = dimension;
// Initially, the array will be filled with 0s,
// which corresponds to all of the positions being empty.
this.status = new int[dimension][dimension];
// Initially, the array will be filled with nulls,
// which corresponds to all of the positions having no ships.
this.shipAt = new Ship[dimension][dimension];
// This will increase as ships are added by the addShip method.
this.shipsRemaining = 0;
}
/*
* getDimension - returns the dimension of the board
*/
public int getDimension() {
return this.dimension;
}
/*
* getShipsRemaining - returns the number of unsunk ships on the board
*/
public int getShipsRemaining() {
return this.shipsRemaining;
}
/*
* addShip - add the specified ship to the board
* at a randomly selected location.
*/
public void addShip(Ship ship) {
int startRow, startCol, direction;
int dRow, dCol;
// Find a position and direction that works.
do {
startRow = RAND.nextInt(dimension);
startCol = RAND.nextInt(dimension);
direction = RAND.nextInt(2);
if (direction == VERTICAL) {
dRow = 1;
dCol = 0;
} else { // HORIZONTAL
dRow = 0;
dCol = 1;
}
} while (!this.canPlaceShip(ship.getLength(), startRow, startCol, dRow, dCol));
// Update the status and shipAt arrays.
int row = startRow;
int col = startCol;
for (int i = 0; i < ship.getLength(); i++) {
this.status[row][col] = UNHIT;
this.shipAt[row][col] = ship;
row += dRow;
col += dCol;
}
this.shipsRemaining++;
}
/*
* canPlaceShip - determines if a ship with the specified length
* can be placed on the board at the starting position
* (startRow, startCol) and with the specified change in row (dRow)
* and change in column (dColumn).
*
* Returns true if a ship can be placed there, and false if it cannot.
*
* This method is private, because we only want it to be accessible
* by other Board methods.
*/
private boolean canPlaceShip(int length, int startRow, int startCol, int dRow, int dCol) {
// Check all of the positions that would be occupied by the ship.
int row = startRow;
int col = startCol;
for (int i = 0; i < length; i++) {
if (row < 0 || row >= this.dimension ||
col < 0 || col >= this.dimension ||
this.status[row][col] != EMPTY) {
return false;
}
row += dRow;
col += dCol;
}
// If we get here, all of the positions must have been valid
// and unoccupied.
return true;
}
/*
* applyGuess - applies the specified guess to the board,
* updating the state accordingly.
*
* If the guess is a hit, the method returns the hit ship.
* Otherwise, it returns null.
*/
public Ship applyGuess(Guess guess) {
if (guess == null) {
throw new IllegalArgumentException("guess cannot be null");
}
int row = guess.getRow();
int col = guess.getColumn();
// Previously tried cell.
if (this.previousHit(row, col) || this.previousMiss(row, col)) {
return null;
}
// Process a miss.
if (this.status[row][col] == EMPTY) {
this.status[row][col] = MISS;
return null;
}
// Process a hit.
this.status[row][col] = HIT;
Ship hitShip = this.shipAt[row][col];
hitShip.applyHit();
if (hitShip.isSunk()) {
this.shipsRemaining--;
}
return hitShip;
}
/*
* previousHit - has the position at (row, col) already been
* the location of a hit?
* Returns true if it has, and false otherwise.
*/
public boolean previousHit(int row, int col) {
return (this.status[row][col] == HIT || this.sunkShipAt(row, col));
}
/*
* previousMiss - has the position at (row, col) already been the
* location of a miss?
* Returns true if it has, and false otherwise.
*/
public boolean previousMiss(int row, int col) {
return (this.status[row][col] == MISS);
}
/*
* hasBeenTried - has the position at (row, col) already been
* tried by a previous guess (either a hit or a miss)?
* Returns true if it has, and false otherwise.
*/
public boolean hasBeenTried(int row, int col) {
return (this.previousHit(row, col) || this.previousMiss(row, col));
}
/*
* sunkShipAt - is their a sunk ship at the position (row, col)?
* Returns true if there is, and false otherwise.
*/
public boolean sunkShipAt(int row, int col) {
return (this.shipAt[row][col] != null && this.shipAt[row][col].isSunk());
}
/*
* getSymbol - returns the single-character symbol that should be
* used for printing the position (row, col) when the board
* is displayed
*/
public char getSymbol(int row, int col) {
if (this.status[row][col] == EMPTY) {
return ' ';
} else if (this.previousHit(row, col)) {
return 'X';
} else if (this.previousMiss(row, col)) {
return '-';
} else {
return this.shipAt[row][col].getSymbol();
}
}
/*
* display - displays the current state of the board,
* calling getSymbol to determine what character to print
* for each position.
*/
public void display() {
// Print the column numbers.
System.out.print(" ");
for (int col = 0; col < this.dimension; col++) {
System.out.printf("%3d", col);
}
System.out.println();
// Print the rows, one at a time.
for (int row = 0; row < this.dimension; row++) {
System.out.printf("%3d:", row);
for (int col = 0; col < this.dimension; col++) {
System.out.print(" " + this.getSymbol(row, col) + " ");
}
System.out.println();
}
System.out.println();
}
}