-
Notifications
You must be signed in to change notification settings - Fork 3
/
app-solution.js
146 lines (131 loc) · 3.22 KB
/
app-solution.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
// initial game data
let currentPlayer = "X";
let grid = [
["", "", ""],
["", "", ""],
["", "", ""]
];
// grab elements from DOM
let cells = document.querySelectorAll("td");
let table = document.querySelector("table");
let statusArea = document.querySelector("#status");
// attach event listeners for clicking on cells
for (let i = 0; i < cells.length; i++) {
cells[i].addEventListener("click", handleClick);
}
// tell the player whose turn it is
setStatus(`${currentPlayer}'s turn.`);
/**
* Handles clicking on a cell within the game board.
* Checks to make sure the square is unoccupied;
* if so, it places the current player's marker and checks for a winner.
* If the game isn't over, swaps the current player.
*
* @param {Object} e - event object
*/
function handleClick(e) {
let cell = e.target;
if (!e.target.classList.contains("disabled")) {
// update the view
cell.innerText = currentPlayer;
cell.classList.add("disabled");
// sync up the in-memory board
let coords = cell.id.split("|")
grid[coords[1]][coords[0]] = currentPlayer;
// check if we're in an end game state
if (checkForWinner()) {
endGame(`${currentPlayer} won!`);
} else if (checkForTie()) {
endGame("It's a tie!");
} else {
togglePlayer();
}
}
}
/**
* Set a visible status in the DOM. Used to show whose turn it is,
* and when the game is over.
*
* @param {String} text - text to put in the status element
*/
function setStatus(text) {
statusArea.innerText = text;
}
/**
* Disables the game board with a message.
*/
function endGame(text) {
for (let i = 0; i < cells.length; i++) {
cells[i].classList.add("disabled");
}
setStatus(text);
}
/**
* Toggles the current player
*/
function togglePlayer() {
if (currentPlayer === "X") {
currentPlayer = "O";
} else {
currentPlayer = "X";
}
setStatus(`${currentPlayer}'s turn.`);
}
/**
* Checks for a tie based on grid state.
* A tie exists if the grid is full.
*
* Note that this runs after checkForWinner,
* so we can assume in this function that we know there is no winner.
*/
function checkForTie() {
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[i].length; j++) {
if (grid[i][j] === "") return false;
}
}
return true;
}
/**
* Checks for a winner based on grid state. The game has a winner when
* there is a row, column, or diagonal that are either all "X" or all "O".
*
* @returns {Boolean} true if the game has a winner, false otherwise
*/
function checkForWinner() {
for (let i = 0; i < grid.length; i++) {
// check rows
if (
grid[i][0] === currentPlayer &&
grid[i][1] === currentPlayer &&
grid[i][2] === currentPlayer
) {
return true;
}
// check columns
if (
grid[0][i] === currentPlayer &&
grid[1][i] === currentPlayer &&
grid[2][i] === currentPlayer
) {
return true;
}
}
// check diagonals
if (
grid[0][0] === currentPlayer &&
grid[1][1] === currentPlayer &&
grid[2][2] === currentPlayer
) {
return true;
}
if (
grid[0][2] === currentPlayer &&
grid[1][1] === currentPlayer &&
grid[2][0] === currentPlayer
) {
return true;
}
// no winner
return false;
}