-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
287 additions
and
432 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
node_modules | ||
dist | ||
dist | ||
live-vanilla-build | ||
live-react-build |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,148 +1,59 @@ | ||
const App = { | ||
// All of our selected HTML elements | ||
$: { | ||
menu: document.querySelector('[data-id="menu"]'), | ||
menuItems: document.querySelector('[data-id="menu-items"]'), | ||
resetBtn: document.querySelector('[data-id="reset-btn"]'), | ||
newRoundBtn: document.querySelector('[data-id="new-round-btn"]'), | ||
squares: document.querySelectorAll('[data-id="square"]'), | ||
modal: document.querySelector('[data-id="modal"]'), | ||
modalText: document.querySelector('[data-id="modal-text"]'), | ||
modalBtn: document.querySelector('[data-id="modal-btn"]'), | ||
turn: document.querySelector('[data-id="turn"]'), | ||
import Store from "./store.js"; | ||
import View from "./view.js"; | ||
|
||
const players = [ | ||
{ | ||
id: 1, | ||
name: "Player 1", | ||
iconClass: "fa-x", | ||
colorClass: "turquoise", | ||
}, | ||
|
||
state: { | ||
moves: [], | ||
}, | ||
|
||
getGameStatus(moves) { | ||
const p1Moves = moves | ||
.filter((move) => move.playerId === 1) | ||
.map((move) => +move.squareId); | ||
const p2Moves = moves | ||
.filter((move) => move.playerId === 2) | ||
.map((move) => +move.squareId); | ||
|
||
const winningPatterns = [ | ||
[1, 2, 3], | ||
[1, 5, 9], | ||
[1, 4, 7], | ||
[2, 5, 8], | ||
[3, 5, 7], | ||
[3, 6, 9], | ||
[4, 5, 6], | ||
[7, 8, 9], | ||
]; | ||
|
||
let winner = null; | ||
|
||
winningPatterns.forEach((pattern) => { | ||
const p1Wins = pattern.every((v) => p1Moves.includes(v)); | ||
const p2Wins = pattern.every((v) => p2Moves.includes(v)); | ||
|
||
if (p1Wins) winner = 1; | ||
if (p2Wins) winner = 2; | ||
}); | ||
|
||
return { | ||
status: moves.length === 9 || winner != null ? "complete" : "in-progress", // in-progress | complete | ||
winner, // 1 | 2 | null | ||
}; | ||
}, | ||
|
||
init() { | ||
App.registerEventListeners(); | ||
{ | ||
id: 2, | ||
name: "Player 2", | ||
iconClass: "fa-o", | ||
colorClass: "yellow", | ||
}, | ||
]; | ||
|
||
registerEventListeners() { | ||
// DONE | ||
App.$.menu.addEventListener("click", (event) => { | ||
App.$.menuItems.classList.toggle("hidden"); | ||
}); | ||
|
||
// TODO | ||
App.$.resetBtn.addEventListener("click", (event) => { | ||
console.log("Reset the game"); | ||
}); | ||
|
||
// TODO | ||
App.$.newRoundBtn.addEventListener("click", (event) => { | ||
console.log("Add a new round"); | ||
}); | ||
|
||
App.$.modalBtn.addEventListener("click", (event) => { | ||
App.state.moves = []; | ||
App.$.squares.forEach((square) => square.replaceChildren()); | ||
App.$.modal.classList.add("hidden"); | ||
}); | ||
|
||
// TODO | ||
App.$.squares.forEach((square) => { | ||
square.addEventListener("click", (event) => { | ||
// Check if there is already a play, if so, return early | ||
const hasMove = (squareId) => { | ||
const existingMove = App.state.moves.find( | ||
(move) => move.squareId === squareId | ||
); | ||
return existingMove !== undefined; | ||
}; | ||
function init() { | ||
const view = new View(); | ||
const store = new Store("live-t3-storage-key", players); | ||
|
||
if (hasMove(+square.id)) { | ||
return; | ||
} | ||
// Current tab state changes | ||
store.addEventListener("statechange", () => { | ||
view.render(store.game, store.stats); | ||
}); | ||
|
||
// Determine which player icon to add to the square | ||
const lastMove = App.state.moves.at(-1); | ||
const getOppositePlayer = (playerId) => (playerId === 1 ? 2 : 1); | ||
const currentPlayer = | ||
App.state.moves.length === 0 | ||
? 1 | ||
: getOppositePlayer(lastMove.playerId); | ||
const nextPlayer = getOppositePlayer(currentPlayer); | ||
// A different tab state changes | ||
window.addEventListener("storage", () => { | ||
console.log("State changed from another tab"); | ||
view.render(store.game, store.stats); | ||
}); | ||
|
||
const squareIcon = document.createElement("i"); | ||
const turnIcon = document.createElement("i"); | ||
const turnLabel = document.createElement("p"); | ||
turnLabel.innerText = `Player ${nextPlayer}, you are up!`; | ||
// The first load of the document | ||
view.render(store.game, store.stats); | ||
|
||
if (currentPlayer === 1) { | ||
squareIcon.classList.add("fa-solid", "fa-x", "yellow"); | ||
turnIcon.classList.add("fa-solid", "fa-o", "turquoise"); | ||
turnLabel.classList = "turquoise"; | ||
} else { | ||
squareIcon.classList.add("fa-solid", "fa-o", "turquoise"); | ||
turnIcon.classList.add("fa-solid", "fa-x", "yellow"); | ||
turnLabel.classList = "yellow"; | ||
} | ||
view.bindGameResetEvent((event) => { | ||
store.reset(); | ||
}); | ||
|
||
App.$.turn.replaceChildren(turnIcon, turnLabel); | ||
view.bindNewRoundEvent((event) => { | ||
store.newRound(); | ||
}); | ||
|
||
App.state.moves.push({ | ||
squareId: +square.id, | ||
playerId: currentPlayer, | ||
}); | ||
view.bindPlayerMoveEvent((square) => { | ||
const existingMove = store.game.moves.find( | ||
(move) => move.squareId === +square.id | ||
); | ||
|
||
square.replaceChildren(squareIcon); | ||
if (existingMove) { | ||
return; | ||
} | ||
|
||
// Check if there is a winner or tie game | ||
const game = App.getGameStatus(App.state.moves); | ||
|
||
if (game.status === "complete") { | ||
App.$.modal.classList.remove("hidden"); | ||
|
||
let message = ""; | ||
if (game.winner) { | ||
message = `Player ${game.winner} wins!`; | ||
} else { | ||
message = "Tie game!"; | ||
} | ||
|
||
App.$.modalText.textContent = message; | ||
} | ||
}); | ||
}); | ||
}, | ||
}; | ||
// Advance to the next state by pushing a move to the moves array | ||
store.playerMove(+square.id); | ||
}); | ||
} | ||
|
||
window.addEventListener("load", App.init); | ||
window.addEventListener("load", init); |
Oops, something went wrong.