-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathBoard.java
252 lines (227 loc) · 9.01 KB
/
Board.java
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
//Dylan Wulf
//CSC380: Artificial Intelligence
//Project 2: War Game
//February 26, 2017
import java.util.LinkedList;
public class Board {
private int[][] boardVals; //values of the spaces on the board; indexed by [y][x]
private PieceColor[][] pieces; //colors of pieces currently on board; indexed by [y][x]
private int blueScore;
private int greenScore;
private int emptySpaces; //keep track of how many empty spaces are left.
//Constructor which allows values to be set
//Sets all pieces to BLANK for a new game
public Board(int[][] boardVals) {
blueScore = 0;
greenScore = 0;
emptySpaces = 0;
//copy board vals argument into board vals class field
this.boardVals = new int[boardVals.length][boardVals[0].length];
for (int i = 0; i < boardVals.length; i++) {
for (int j = 0; j < boardVals[i].length; j++) {
this.boardVals[i][j] = boardVals[i][j];
}
}
//make blank pieces array same size as boardVals
pieces = new PieceColor[boardVals.length][boardVals[0].length];
for (int i = 0; i < pieces.length; i++) {
for (int j = 0; j < pieces[i].length; j++) {
pieces[i][j] = PieceColor.BLANK;
emptySpaces++;
}
}
}
//Constructor which allows both values and current piece locations
//to be assigned
public Board(int[][] boardVals, PieceColor[][] pieces) {
blueScore = 0;
greenScore = 0;
emptySpaces = 0;
//copy board vals argument into boardVals class field
this.boardVals = new int[boardVals.length][boardVals[0].length];
for (int i = 0; i < boardVals.length; i++) {
for (int j = 0; j < boardVals[i].length; j++) {
this.boardVals[i][j] = boardVals[i][j];
}
}
//copy pieces vals argument into pieces class field
this.pieces = new PieceColor[pieces.length][pieces[0].length];
for (int i = 0; i < pieces.length; i++) {
for (int j = 0; j < pieces[i].length; j++) {
this.pieces[i][j] = pieces[i][j];
if (pieces[i][j] == PieceColor.BLUE)
blueScore += boardVals[i][j];
else if (pieces[i][j] == PieceColor.GREEN)
greenScore += boardVals[i][j];
else
emptySpaces++;
}
}
}
//Creates a copy of this board.
//Changing the values in the copied board will not affect
//the objects in this board.
public Board copy() {
return new Board(boardVals, pieces);
}
//Gets a list of moves that can possibly be made on this board
//by the player of the specified color.
//if this returns an empty list, then the game has already ended.
public LinkedList<Move> getPossibleMoves(PieceColor playerColor) {
LinkedList<Move> moves = new LinkedList<Move>();
for (int i = 0; i < pieces.length; i++) {
for (int j = 0; j < pieces[i].length; j++) {
if (pieces[i][j] == PieceColor.BLANK)
moves.add(new Move(MoveType.C_PARA_DROP, playerColor, j, i));
if (canDeathBlitz(j, i, playerColor))
moves.add(new Move(MoveType.M1_DEATH_BLITZ, playerColor, j, i));
}
}
return moves;
}
//Takes the moves returned from the getPossibleMoves function
//And creates a separate child board for each one.
//returns all these child boards in a linked list.
public LinkedList<Board> getChildBoards(PieceColor playerColor) {
LinkedList<Move> moves = getPossibleMoves(playerColor);
LinkedList<Board> children = new LinkedList<Board>();
for (Move m : moves) {
Board child = this.copy();
boolean moveSuccess = child.makeMove(m);
if (moveSuccess)
children.add(child);
else
child = null;
}
return children;
}
//Performs the actual action of making the specified move on this board.
//This board will then be updated to represent the new piece locations
//and the player scores will be updated accordingly.
//returns true if the move was valid and successful,
//false if the move was invalid
public boolean makeMove(Move move) {
int playerGain = 0;
int oppLoss = 0;
PieceColor player = PieceColor.BLUE;
PieceColor opp = PieceColor.GREEN;
if (move.getPlayerColor() == PieceColor.GREEN) {
player = PieceColor.GREEN;
opp = PieceColor.BLUE;
}
int x = move.getX();
int y = move.getY();
//Check for invalid moves
if (move.getMoveType() == MoveType.C_PARA_DROP && pieces[y][x] != PieceColor.BLANK)
return false;
if (move.getMoveType() == MoveType.M1_DEATH_BLITZ && !canDeathBlitz(x, y, player))
return false;
pieces[y][x] = player; //set this piece to belong to player, no matter which move type
playerGain += boardVals[y][x];
emptySpaces--; //reduce counter of empty spaces
//Check for pieces to conquer if this is death blitz attack
if (move.getMoveType() == MoveType.M1_DEATH_BLITZ) {
//Check up for opponent piece to conquer
if (y - 1 >= 0 && pieces[y-1][x] == opp) {
pieces[y-1][x] = player;
playerGain += boardVals[y-1][x];
oppLoss += boardVals[y-1][x];
}
//Check down for opponent piece to conquer
if (y + 1 < pieces.length && pieces[y+1][x] == opp) {
pieces[y+1][x] = player;
playerGain += boardVals[y+1][x];
oppLoss += boardVals[y+1][x];
}
//Check left for opponent piece to conquer
if (x - 1 >= 0 && pieces[y][x-1] == opp) {
pieces[y][x-1] = player;
playerGain += boardVals[y][x-1];
oppLoss += boardVals[y][x-1];
}
//Check right for opponent piece to conquer
if (x + 1 < pieces[y].length && pieces[y][x+1] == opp) {
pieces[y][x+1] = player;
playerGain += boardVals[y][x+1];
oppLoss += boardVals[y][x+1];
}
}
if (player == PieceColor.BLUE) {
blueScore += playerGain;
greenScore -= oppLoss;
}
else {
greenScore += playerGain;
blueScore -= oppLoss;
}
return true;
}
//Checks if the game is over
//if the game is over and no more moves can be made, return true
//if there are still moves that can be made, return false
public boolean gameOver() {
return emptySpaces == 0;
}
//Return the score of the blue player
public int getBlueScore() {
return blueScore;
}
//Return the score of the green player
public int getGreenScore() {
return greenScore;
}
//Return the score of the specified color player
public int getScore(PieceColor color) {
return (color == PieceColor.BLUE)? blueScore : greenScore;
}
//Get the 2d-array of colored pieces
public PieceColor[][] getPieces() {
return pieces;
}
//get the 2d-array of square values
public int[][] getValues() {
return boardVals;
}
//Returns the color of the winner
//or blank if it was a tie
public PieceColor getWinner() {
if (blueScore > greenScore)
return PieceColor.BLUE;
else if (blueScore < greenScore)
return PieceColor.GREEN;
else return PieceColor.BLANK;
}
//Returns a string containing a textual representation of this board
public String toString() {
String result = "";
for (int i = 0; i < pieces.length; i++) {
for (int j = 0; j < pieces[i].length; j++) {
if (pieces[i][j] == PieceColor.BLUE)
result += "(" + boardVals[i][j] + ")\t";
else if (pieces[i][j] == PieceColor.GREEN)
result += "<" + boardVals[i][j] + ">\t";
else
result += boardVals[i][j] + "\t";
}
result += "\n";
}
result += "(#) = Blue; <#> = Green; # = Blank";
return result;
}
//private function that calculates if the specified player color can
//death blitz at the specified coordinates
//(Note: pieces is indexed by [y][x])
private boolean canDeathBlitz(int x, int y, PieceColor playerColor) {
if (pieces[y][x] == PieceColor.BLANK) {
if (y - 1 >= 0 && pieces[y-1][x] == playerColor)
return true;
if (y + 1 < pieces.length && pieces[y+1][x] == playerColor)
return true;
if (x - 1 >= 0 && pieces[y][x-1] == playerColor)
return true;
if (x + 1 < pieces[y].length && pieces[y][x+1] == playerColor)
return true;
}
return false;
}
}