-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgame.js
331 lines (300 loc) · 8.33 KB
/
game.js
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
// I feel like I have no idea what I am doing with CSS and how to organize it
// Game object
// in charge of game functions
const Game = (function () {
let gameboard;
let player1;
let player2;
const newGame = () => {
gameboard = createGameboard(3, 3);
Game.setPlayer1(localStorage.getItem("player_1"), "X");
Game.setPlayer2(localStorage.getItem("player_2"), "O");
player1.setTurn(true);
Display.removeWin();
Display.addBlockListeners();
Display.updateBoard();
Display.displayTurn();
};
const getGameboard = () => gameboard;
const getPlayer1 = () => player1;
const setPlayer1 = (name, symbol) => {
player1 = createPlayer(name, symbol);
};
const getPlayer2 = () => player2;
const setPlayer2 = (name, symbol) => {
player2 = createPlayer(name, symbol);
};
const getWhosTurn = () => {
if (player1.isTurn()) return player1;
return player2;
};
const changeTurn = () => {
player1.setTurn(!player1.isTurn());
player2.setTurn(!player2.isTurn());
};
// checks for a winner
const checkWinner = function () {
const winner =
checkRow(gameboard) || checkColumn(gameboard) || checkDiagonal(gameboard);
return winner;
};
// checks if grid is full
const checkFullGrid = function () {
for (let i = 0; i < gameboard.length; i++) {
for (let j = 0; j < gameboard[i].length; j++) {
if (!gameboard[i][j].isOccupied()) {
return false;
}
}
}
return true;
};
const checkGameEnd = function () {
const winner = Game.checkWinner();
const fullGrid = Game.checkFullGrid();
return winner || fullGrid;
};
return {
newGame,
getGameboard,
getPlayer1,
setPlayer1,
getPlayer2,
setPlayer2,
getWhosTurn,
changeTurn,
checkWinner,
checkFullGrid,
checkGameEnd,
};
})();
// Display object
// controls all the display related functions
const Display = (function () {
const displayText = document.querySelector(".display-text");
const gameboardBlocks = document.querySelectorAll(".gameboard-block");
const newGameButton = document.querySelector(".new-game.button");
newGameButton.addEventListener("click", Game.newGame);
const addBlockListeners = function () {
gameboardBlocks.forEach((block) => {
block.addEventListener("click", () => {
const row = block.dataset.row;
const col = block.dataset.col;
const gameboard = Game.getGameboard();
if (!gameboard[row][col].isOccupied() && !Game.checkGameEnd()) {
gameboard[row][col].setOccupied(true);
gameboard[row][col].setOccupiedBy(Game.getWhosTurn());
updateBoard();
const winner = Game.checkWinner();
const fullGrid = Game.checkFullGrid();
if (!winner && !fullGrid) {
Game.changeTurn();
displayTurn();
} else {
if (winner) {
changeDisplayText(`${winner.getWinner().getName()} wins!`);
displayWin(winner);
} else if (fullGrid) changeDisplayText("Game is a tie!");
}
}
});
});
};
const updateBoard = function () {
const gameboard = Game.getGameboard();
for (let i = 0; i < gameboard.length; i++) {
for (let j = 0; j < gameboard[i].length; j++) {
const gameboardBlock = document.querySelector(
`.gameboard-block[data-row="${i}"][data-col="${j}"]`
);
if (gameboard[i][j].isOccupied()) {
gameboardBlock.textContent = gameboard[i][j]
.getOccupiedBy()
.getSymbol();
} else {
gameboardBlock.textContent = "";
}
}
}
};
const displayTurn = function () {
const player = Game.getWhosTurn();
changeDisplayText(`${player.getName()}'s Turn`);
};
const displayWin = function (winner) {
if (winner) {
const winBlocks = winner.getWinBlocks();
winBlocks.forEach((block) => {
const gameboardBlock = document.querySelector(
`.gameboard-block[data-row="${block.getRow()}"][data-col="${block.getCol()}"]`
);
gameboardBlock.classList.add("winning");
});
}
};
const removeWin = function () {
const gameboardBlocks = document.querySelectorAll(".gameboard-block");
gameboardBlocks.forEach((block) => {
block.classList.remove("winning");
});
};
const changeDisplayText = function (text) {
displayText.textContent = text;
};
return {
addBlockListeners,
updateBoard,
displayTurn,
displayWin,
removeWin,
changeDisplayText,
};
})();
// creates a gameboard (2D array of Block objects)
// Number rows, Number cols
function createGameboard(rows, cols) {
const gameboard = [];
for (let i = 0; i < rows; i++) {
const row = [];
for (let j = 0; j < cols; j++) {
row.push(createBlock(i, j));
}
gameboard.push(row);
}
return gameboard;
}
// Block object factory function
// creates a block object thats stored in the gameboard
// Number row, Number col
function createBlock(row, col) {
let occupied = false; // bool
let occupiedBy; // Player
const getRow = () => row;
const getCol = () => col;
const isOccupied = () => occupied;
const setOccupied = function (bool) {
occupied = bool;
};
const getOccupiedBy = () => occupiedBy;
const setOccupiedBy = function (player) {
occupiedBy = player;
};
return {
getRow,
getCol,
isOccupied,
setOccupied,
getOccupiedBy,
setOccupiedBy,
};
}
// Player object factory function
// creates a player for the game
// String name, String symbol
function createPlayer(name, symbol) {
let turn = false;
const getName = () => name;
const getSymbol = () => symbol;
const isTurn = () => turn;
const setTurn = function (bool) {
turn = bool;
};
return {
getName,
getSymbol,
isTurn,
setTurn,
};
}
// Winner object factory function
// stores player and the winning blocks
// Player player, Array[Block] winBlocks
function createWinner(player, winBlocks) {
const getWinner = () => player;
const getWinBlocks = () => winBlocks;
return {
getWinner,
getWinBlocks,
};
}
// return undefined for no win
// return player for win
function checkRow(gameboard) {
for (let i = 0; i < gameboard.length; i++) {
const winBlocks = [gameboard[i][0]];
for (let j = 1; j < gameboard[i].length; j++) {
if (
!gameboard[i][j].isOccupied() ||
gameboard[i][j - 1].getOccupiedBy() != gameboard[i][j].getOccupiedBy()
) {
break;
}
winBlocks.push(gameboard[i][j]);
if (j == gameboard[i].length - 1) {
const player = gameboard[i][j].getOccupiedBy();
return createWinner(player, winBlocks);
}
}
}
return;
}
// return undefined for no win
// return player for win
function checkColumn(gameboard) {
for (let j = 0; j < gameboard[0].length; j++) {
const winBlocks = [gameboard[0][j]];
for (let i = 1; i < gameboard.length; i++) {
if (
!gameboard[i][j].isOccupied() ||
gameboard[i - 1][j].getOccupiedBy() != gameboard[i][j].getOccupiedBy()
) {
break;
}
winBlocks.push(gameboard[i][j]);
if (i == gameboard[0].length - 1) {
const player = gameboard[i][j].getOccupiedBy();
return createWinner(player, winBlocks);
}
}
}
return;
}
// return undefined for no win
// return player for win
function checkDiagonal(gameboard) {
let winBlocks = [gameboard[0][0]];
for (let i = 1; i < gameboard.length; i++) {
if (
!gameboard[i][i].isOccupied() ||
gameboard[i - 1][i - 1].getOccupiedBy() != gameboard[i][i].getOccupiedBy()
) {
break;
}
winBlocks.push(gameboard[i][i]);
if (i == gameboard.length - 1) {
const player = gameboard[i][i].getOccupiedBy();
return createWinner(player, winBlocks);
}
}
winBlocks = [gameboard[0][gameboard.length - 1]];
for (let i = 1; i < gameboard.length; i++) {
const colIdx = gameboard.length - i - 1;
if (
!gameboard[i][colIdx].isOccupied() ||
gameboard[i - 1][colIdx + 1].getOccupiedBy() !=
gameboard[i][colIdx].getOccupiedBy()
) {
break;
}
winBlocks.push(gameboard[i][colIdx]);
if (i == gameboard.length - 1) {
const player = gameboard[i][colIdx].getOccupiedBy();
return createWinner(player, winBlocks);
}
}
return;
}
function main() {
Game.newGame();
}
main();