"use strict"; (function() { function generateElement(args) { const elementOutput = document.createElement(args.element); for (let arg in args) { if (typeof arg !== "undefined") { if (arg == "_for") { elementOutput.setAttribute("for", args[arg]); } else { elementOutput[arg] = args[arg]; } } } return elementOutput; } function generateForm() { const form = document.createElement("form"); const title = generateElement( {element: "h1", id: "title", textContent: "Tic Tac Toe"}); const player1NameLabel = generateElement( {element: "label", _for: "p1name", textContent: "Player 1 name"}); const player1Name = generateElement( {element: "input", type: "text", name: "p1name", id: "p1name", required: true}); const player2NameLabel = generateElement( {element: "label", _for: "p2name", textContent: "Player 2 name"}); const player2Name = generateElement( {element: "input", type: "text", name: "p2name", id: "p2name", required: true}); const markerInfo = generateElement( {element: "label", textContent: "Marker for player 1:"}); const markerO = generateElement( {element: "input", type: "radio", name: "marker", value: "O", id: "mo", checked: true, required: true}); const markerOLabel = generateElement( {element: "label", _for: "mo", textContent: "O"}); const markerX = generateElement( {element: "input", type: "radio", name: "marker", value: "X", id: "mx"}); const markerXLabel = generateElement( {element: "label", _for: "mx", textContent: "X"}); const markerInfoAddition = generateElement( {element: "label", innerText: "\n(other one will go to player 2)"}); const firstInfo = generateElement( {element: "label", textContent: "Who goes first?"}); const firstPlayer1 = generateElement( {element: "input", type: "radio", name: "first", value: "1", id: "fp1", checked: true, required: true}); const firstPlayer1Label = generateElement( {element: "label", _for: "fp1", textContent: "1"}); const firstPlayer2 = generateElement( {element: "input", type: "radio", name: "first", value: "2", id: "fp2"}); const firstPlayer2Label = generateElement( {element: "label", _for: "fp2", textContent: "2"}); const submit = generateElement( {element: "button", type: "submit", textContent: "Save"}); form.append( title, player1NameLabel, player1Name, player2NameLabel, player2Name, markerInfo, markerO, markerOLabel, markerX, markerXLabel, markerInfoAddition, document.createElement("br"), firstInfo, firstPlayer1, firstPlayer1Label, firstPlayer2, firstPlayer2Label, submit, ); return form; } function addDismissivePopup(popup) { function dismissPopup() { popup.remove(); } popup.addEventListener("click", function(event) { if (this !== event.target) return; dismissPopup(); }, false); function dismissPopupKey(event) { if (event.key.toLowerCase() == "escape") { popup.remove(); document.body.removeEventListener("keydown", dismissPopupKey); } } const dismissBtn = document.createElement("button"); dismissBtn.setAttribute("type", "button"); dismissBtn.classList.add("dismiss-button"); dismissBtn.textContent = "Dismiss"; dismissBtn.addEventListener("click", dismissPopup); document.body.addEventListener("keydown", dismissPopupKey); return dismissBtn; } function generatePopup(dismissive) { const popup = document.createElement("div"); popup.classList.add("popup"); const popupContent = document.createElement("div"); popupContent.classList.add("popup-content"); popup.append(popupContent); document.body.append(popup); if (dismissive) { const dismissBtn = addDismissivePopup(popup, popupContent); return {popup, popupContent, dismissBtn}; } return {popup, popupContent}; } function getFormOutput(event, popup) { event.preventDefault(); const form = event.target; const formFetch = new FormData(form); let vals = []; for (let value of formFetch.values()) { vals.push(value); } popup.remove(); game({ player1: { name: vals[0], marker: vals[2], }, player2: { name: vals[1], marker: vals[2] == "O" ? "X" : "O", }, }, vals[3]) } (function popupStartInput() { const {popup, popupContent} = generatePopup(false); const form = generateForm(); popupContent.append(form); form.addEventListener("submit", function(event) {getFormOutput(event, popup)}); })() const game = function(playersInput, first) { const mainGameDiv = document.querySelector("#main-game"); const infoDiv = document.querySelector("#info"); let gameboard = new Array(9); gameboard.fill(null); // ----------------- function checkWin() { const combinations = [ "123", "456", "789", "147", "258", "369", "159", "357", ]; let combinationsValidate = {}; const allEqualInArray = arr => arr.every( v => v === arr[0] ) const player = activePlayer.player; let win = false; combinations.forEach(combination => { combinationsValidate[combination] = []; combination.split('').forEach(box => { combinationsValidate[combination].push(gameboard[+box - 1] == player.marker); }) if (allEqualInArray(combinationsValidate[combination]) && combinationsValidate[combination][0]) { player.addPoint(); console.log(`${JSON.stringify({name:player.name, marker:player.marker, points:player.points})} won`); pubsub.publish("winTrue"); return; } }); if (!win) { if (gameboard.find(field => field === null) === null) { pubsub.publish("continueGame"); } else { pubsub.publish("draw"); } } } // ----------------- function updateInfo() { const player1Info = document.querySelector("#p1info"); player1Info.textContent = `1) ${players.player1.name} (${players.player1.marker}) - ${players.player1.points} points`; const player2Info = document.querySelector("#p2info"); player2Info.textContent = `2) ${players.player2.name} (${players.player2.marker}) - ${players.player2.points} points`; const playerTurnInfo = document.querySelector("#pturn"); playerTurnInfo.textContent = `${activePlayer.number}) ${activePlayer.player.name} (${activePlayer.player.marker})`; console.log(activePlayer.number); } // ----------------- function popupWin() { const {popup, popupContent, dismissBtn} = generatePopup(true); popupContent.textContent = `${activePlayer.player.name} (${activePlayer.player.marker}) won!`; popupContent.append(dismissBtn); } function popupDraw() { const {popup, popupContent, dismissBtn} = generatePopup(true); popupContent.textContent = `It's a draw!`; popupContent.append(dismissBtn); } // ----------------- function clearController() { while(mainGameDiv.lastElementChild) { mainGameDiv.lastElementChild.remove(); } } function displayController() { clearController(); let boxes = []; for (let i = 0; i < 9; i++) { let boxDiv = document.createElement("div"); boxDiv.classList.add("box"); boxDiv.setAttribute("data-id", i); boxDiv.textContent = gameboard[boxDiv.getAttribute("data-id")]; boxDiv.addEventListener("click", function(event) { changeField(boxDiv.getAttribute("data-id")); }); boxes.push(boxDiv); } boxes.forEach(box => mainGameDiv.appendChild(box)); } // ----------------- class Player { constructor(name, marker) { this.name = name; this.marker = marker; this.points = 0; } changeName(newName) { this.name = newName; } changeMarker(newMarker) { this.marker = newMarker; } addPoint() { this.points++; } } let players = { player1: new Player(playersInput.player1.name, playersInput.player1.marker), player2: new Player(playersInput.player2.name, playersInput.player2.marker), } let activePlayer = Object.create({ change() { this.player == players.player1 ? this.player = players.player2 : this.player = players.player1; this.player == players.player1 ? this.number = 1 : this.number = 2; }, set(player) { if (player instanceof Player) { this.player = player; this.player == players.player1 ? this.number = 1 : this.number = 2; } else { throw new Error("No such player exists"); } } }); // ----------------- function changeField(field) { if (gameboard[field] === null) { gameboard[field] = activePlayer.player.marker; pubsub.publish("fieldChange"); } else if (gameboard[field] === undefined) { console.warn("No such field exists"); } else { console.warn("Value already set"); } } // ----------------- function setupButtons() { const resetPointsBtn = document.querySelector("#reset-points"); const resetEverythingBtn = document.querySelector("#reset-everything"); resetPointsBtn.addEventListener("click", () => { gameboard.fill(null); players.player1.points = 0; players.player2.points = 0; updateInfo(); displayController(); }) resetEverythingBtn.addEventListener("click", () => { if(confirm("For sure?")) { window.location.reload(); } }) } // ----------------- (function initializeLaunch() { pubsub.subscribe("fieldChange", displayController); pubsub.subscribe("fieldChange", checkWin); pubsub.subscribe("continueGame", () => {activePlayer.change(); updateInfo()});; // pubsub.subscribe("continueGame", ); // pubsub.subscribe("fieldChange", updateInfo); pubsub.subscribe("draw", popupDraw); pubsub.subscribe("winTrue", popupWin); pubsub.subscribe("draw", () => {gameboard.fill(null);}) pubsub.subscribe("winTrue", () => {gameboard.fill(null);}) activePlayer.set( first == "1" ? players.player1 : players.player2 ) displayController(); updateInfo(); setupButtons(); })(); } })()