{"id":1839,"date":"2025-01-09T11:46:29","date_gmt":"2025-01-09T11:46:29","guid":{"rendered":"https:\/\/bcn.myplacenet.app\/?page_id=1839"},"modified":"2025-02-11T18:56:18","modified_gmt":"2025-02-11T18:56:18","slug":"three-in-a-row","status":"publish","type":"page","link":"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/","title":{"rendered":"Three in a row"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"1839\" class=\"elementor elementor-1839 elementor-812\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3058e1c e-flex e-con-boxed e-con e-parent\" data-id=\"3058e1c\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-feb51a1 elementor-widget elementor-widget-mobiokit-minijuegos-widget\" data-id=\"feb51a1\" data-element_type=\"widget\" data-widget_type=\"mobiokit-minijuegos-widget.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<style>\r\n\r\n\r\n    #container {\r\n\r\n    }\r\n\r\n    .game-narrative {\r\n        margin: 0 auto; \/* Center the item vertically & horizontally *\/\r\n        position: fixed; \/* Break it out of the regular flow *\/\r\n        top: 0;\r\n        left: 0;\r\n        bottom: 0;\r\n        right: 0; \/* Set the bounds in which to center it, relative to its parent\/container *\/\r\n\r\n        padding: 20px;\r\n        display: flex;\r\n        justify-content: center;\r\n        align-items: center;\r\n        resize: both;\r\n        \/* overflow: auto; *\/\r\n\r\n        max-width: 700px;\r\n        flex-direction: column;\r\n        text-align: center;\r\n\r\n        background: url(https:\/\/bcn.myplacenet.app\/wp-content\/uploads\/2025\/01\/tres.webp) no-repeat center center;\r\n        background-size: cover;\r\n\r\n        color:white;\r\n        text-shadow: 2px 2px 4px #000000;\r\n    }\r\n\r\n    .game-narrative-text {\r\n        font-family: 'Share Tech', sans-serif;\r\n        font-size: 2em;\r\n        margin: 10px;\r\n    }\r\n\r\n    .game-btn {\r\n        font-family: 'Share Tech', sans-serif;\r\n        font-size: 2em;\r\n        margin: 20px;\r\n        -webkit-border-radius: 8;\r\n        -moz-border-radius: 8;\r\n        border-radius: 8px;\r\n        color: #ffffff;\r\n        font-size: 20px;\r\n        background-color: #d35400;\r\n        padding: 10px 20px 10px 20px;\r\n        border: solid #F89406 2px;\r\n        text-decoration: none;\r\n\r\n    }\r\n\r\n    .game-btn:hover {\r\n        background-color: #e67e22;\r\n        text-decoration: none;\r\n    }\r\n\r\n    .game-btn:focus {\r\n        outline:0;\r\n    }\r\n\r\n    #narrative-three-btns {\r\n        display: flex;\r\n        flex-flow: row;\r\n    }\r\n\r\n    .dramatic-text {\r\n        font-family: 'Trade Winds', cursive;\r\n        font-size: 3em;\r\n    }\r\n\r\n    .computer-threat {\r\n        font-family: 'Trade Winds', cursive;\r\n        font-size: 1.5em;\r\n        margin-top: 20px;\r\n        color: #c0392b;\r\n    }\r\n\r\n    #header {\r\n        text-align: center;\r\n        margin: 10px;\r\n        margin-top: 30px;\r\n        color: #c0392b;\r\n    }\r\n\r\n    #game-configuration {\r\n\r\n        margin: 0 auto; \/* Center the item vertically & horizontally *\/\r\n\r\n        padding: 20px;\r\n        display: flex;\r\n        flex-direction: column;\r\n        justify-content: center;\r\n        align-items: center;\r\n        resize: both;\r\n\r\n    }\r\n\r\n    #identity-selection {\r\n        display: flex;\r\n        justify-content: center;\r\n        flex-direction: row;\r\n    }\r\n\r\n    .identity {\r\n        margin: 0px 20px;\r\n    }\r\n\r\n    #identity-label {\r\n        color: #FFF;\r\n        font-family: 'Share Tech', sans-serif;\r\n        font-size: 2em;\r\n        text-align: center;\r\n        vertical-align: middle;\r\n        margin: 20px;\r\n    }\r\n\r\n    #game-grid {\r\n        display: flex;\r\n        flex-direction: column;\r\n        flex-wrap: nowrap;\r\n        justify-content: center;\r\n        align-items: center;\r\n    }\r\n\r\n    .row {\r\n        display: flex;\r\n        flex-direction: row;\r\n        flex-wrap: nowrap;\r\n    }\r\n\r\n    .cell {\r\n        font-family: 'Gloria Hallelujah', cursive;\r\n        color: #FFFFFF;\r\n        background-color: #121a21;\r\n        text-align: center;\r\n        width: 100px;\r\n        height: 100px;\r\n        font-size: 3em;\r\n        margin: 5px;\r\n        border-radius: 10px;\r\n        box-shadow: 6px 6px 0px 0px #090d10;\r\n        -webkit-transition-duration: 0.5s;\r\n        transition-duration: 0.5s;\r\n        display: flex;\r\n        flex-direction: row;\r\n        justify-content: center;\r\n        align-items: center;\r\n        font-size: 65px;\r\n    }\r\n\r\n    .cell:hover {\r\n        color: #e74c3c;\r\n        background-color: #34495e;\r\n    }\r\n\r\n    .cell-selected {\r\n        color: #c0392b;\r\n        transform: translate(3px,3px);\r\n        box-shadow: 3px 3px 0px 0px #000000;\r\n        background-color: #121a21;\r\n\r\n    }\r\n\r\n    .cell-selected:hover {\r\n        \/* Disabling hover on already selected cells *\/\r\n        color: #c0392b;\r\n        background-color: #121a21;\r\n    }\r\n\r\n    .cell-win {\r\n        color: #e74c3c;\r\n        background-color: #34495e;\r\n        transition: all 1s ease-in-out;\r\n        transform: scale(1.05);\r\n    }\r\n\r\n    .cell-win:hover {\r\n        \/* Disabling hover on win animation cells *\/\r\n        background-color: #34495e;\r\n    }\r\n\r\n    #game-over {\r\n        color: #FFF;\r\n        font-family: 'Share Tech', sans-serif;\r\n\r\n        margin: 0 auto; \/* Center the item vertically & horizontally *\/\r\n        position: fixed; \/* Break it out of the regular flow *\/\r\n        top: 0; left: 0; bottom: 0; right: 0; \/* Set the bounds in which to center it, relative to its parent\/container *\/\r\n\r\n        padding: 20px;\r\n        display: flex;\r\n        justify-content: center;\r\n        align-items: center;\r\n        resize: both;\r\n        \/* overflow: auto; *\/\r\n\r\n        max-width: 700px;\r\n        flex-direction: column;\r\n        text-align: center;\r\n    }\r\n\r\n    #game-end-heading {\r\n        font-size: 2em;\r\n        margin: 10px;\r\n    }\r\n\r\n    #game-end-subheading {\r\n        font-size: 1.5em;\r\n        margin: 10px;\r\n    }\r\n\r\n    #game-reset-btn {\r\n        font-family: 'Share Tech', sans-serif;\r\n        font-size: 2em;\r\n        margin: 20px;\r\n\r\n        -webkit-border-radius: 8px;\r\n        -moz-border-radius: 8px;\r\n        border-radius: 8px;\r\n        color: #ffffff;\r\n        font-size: 20px;\r\n        background-color: #d35400;\r\n        padding: 10px 20px 10px 20px;\r\n        border: solid #F89406 2px;\r\n        text-decoration: none;\r\n\r\n    }\r\n\r\n    #game-reset-btn: hover {\r\n        background: #3cb0fd;\r\n        text-decoration: none;\r\n    }\r\n\r\n    #cover {\r\n        display: flex;\r\n        justify-content: center;\r\n        align-items: center;\r\n        height: 400px;\r\n        width: 100%;\r\n        margin: 20px auto;\r\n        background: url(https:\/\/bcn.myplacenet.app\/wp-content\/uploads\/2025\/01\/tres.webp) no-repeat center center;\r\n        background-size: cover;\r\n    }\r\n    @keyframes confetti {\r\n        0% {transform: translateY(0) rotate(0deg); opacity: 1;}\r\n        100% {transform: translateY(500px) rotate(720deg); opacity: 0;}\r\n    }\r\n\r\n    .confetti {\r\n        position: fixed;\r\n        width: 10px;\r\n        height: 10px;\r\n        background-color: randomColor;\r\n        animation: confetti 3s linear infinite;\r\n        opacity: 0;\r\n    }\r\n    .volver{\r\n        z-index: 999999;\r\n        display: block;\r\n        clear: both;\r\n        color: #ffffff;\r\n        position: relative;\r\n        font-size: 24px;\r\n    }\r\n<\/style>\r\n<button class=\"volver\" onclick=\"window.history.back()\">\r\n    <i class=\"fas fa-arrow-left\"><\/i> Volver<\/button>\r\n\r\n<div id=\"container\">\r\n    <div class=\"game-narrative\" id=\"game-narrative-one\">\r\n        <p class=\"game-narrative-text\">En un mundo donde dos fuerzas luchan por el dominio de un paisaje devastado por la guerra, solo una trazar\u00e1 la l\u00ednea y reinar\u00e1 de forma suprema..<\/p>\r\n        <button class=\"game-btn\" id=\"narrative-one-btn\">Comenzar<\/button>\r\n    <\/div>\r\n\r\n    <div class=\"game-narrative\" id=\"game-narrative-two\">\r\n        <p class=\"game-narrative-text\">Estamos en el a\u00f1o 2048.<\/p>\r\n        <p class=\"game-narrative-text\">En una galaxia postapocal\u00edptica dirigida por corporaciones gigantes, eres un marine espacial mejorado cibern\u00e9ticamente que no recuerda nada de su pasado.<\/p>\r\n        <button class=\"game-btn\" id=\"narrative-two-btn\">Continuar<\/button>\r\n    <\/div>\r\n\r\n    <div class=\"game-narrative\" id=\"game-narrative-three\">\r\n        <p class=\"game-narrative-text\">\u00bfEres el elegido predicho por la profec\u00eda?<\/p>\r\n        <p class=\"game-narrative-text\">\u00bfTienes la fuerza para sobrevivir...<\/p>\r\n        <div id=\"narrative-three-btns\">\r\n            <button class=\"game-btn\" id=\"narrative-three-btn\">S\u00cd<\/button>\r\n            <div><\/div>\r\n            <a class=\"game-btn\" id=\"puppies-btn\" href=\"\/explora\">NO<\/a>\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <div id=\"header\">\r\n        <p class=\"dramatic-text\">\r\n            <span id=\"tic-text\">Tres<\/span>\r\n            <span id=\"tac-text\">En<\/span>\r\n            <span id=\"doom-text\">Raya<\/span>\r\n        <\/p>\r\n    <\/div>\r\n\r\n    <div id=\"game-configuration\">\r\n        <h2 id=\"identity-label\">Elige tu marca<\/h2>\r\n        <div id=\"identity-selection\" class=\"row\">\r\n            <div class=\"cell identity-cell\" value=\"X\">X<\/div>\r\n            <div class=\"cell identity-cell\" value=\"O\">O<\/div>\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <div id=\"game-grid\">\r\n        <div class=\"row\">\r\n            <div class=\"cell game-cell\" id=\"c00\"><\/div>\r\n            <div class=\"cell game-cell\" id=\"c01\"><\/div>\r\n            <div class=\"cell game-cell\" id=\"c02\"><\/div>\r\n        <\/div>\r\n        <div class=\"row\">\r\n            <div class=\"cell game-cell\" id=\"c10\"><\/div>\r\n            <div class=\"cell game-cell\" id=\"c11\"><\/div>\r\n            <div class=\"cell game-cell\" id=\"c12\"><\/div>\r\n        <\/div>\r\n        <div class=\"row\">\r\n            <div class=\"cell game-cell\" id=\"c20\"><\/div>\r\n            <div class=\"cell game-cell\" id=\"c21\"><\/div>\r\n            <div class=\"cell game-cell\" id=\"c22\"><\/div>\r\n        <\/div>\r\n        <div class=\"computer-threat\">\r\n            <p><span id=\"computer-threat-text\"><\/span><\/p>\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <div id=\"game-over\">\r\n        <h2 id=\"game-end-heading\"><\/h2>\r\n        <h3 id=\"game-end-subheading\"><\/h3>\r\n        <button class=\"game-btn\" id=\"game-reset-btn\">&#8634; Play again<\/button>\r\n    <\/div>\r\n<\/div>\r\n\r\n<\/div>\r\n<script>\r\n    \/\/ The game object, used to store current state of the game.\r\n    var game = {\r\n        board: [[null, null, null],\r\n            [null, null, null],\r\n            [null, null, null]], \/\/ Rows of the game grid in 2D array form.\r\n        playerMark: \"\", \/\/ The mark 'X' or 'O' the player uses to select a cell.\r\n        aiMark: \"\", \/\/ The mark the computer uses to select a cell.\r\n        turnsPlayed: 0, \/\/ If reaches 9 without a win, its a draw.\r\n        playerTurn: true, \/\/ Flag tracking who's turn it is.\r\n        nextMove: [null, null], \/\/ Used to store move calculated by minimax.\r\n        winner: \"\", \/\/ Stores winning mark.\r\n        gameOver: false \/\/ Flag indicating whether the game has ended.\r\n    }\r\n\r\n    var darkColor = \"#2c3e50\";\r\n\r\n    var $narrativeOne = $(\"#game-narrative-one\");\r\n    var $narrativeTwo = $(\"#game-narrative-two\");\r\n    var $narrativeThree = $(\"#game-narrative-three\");\r\n    var $narrativeFour = $(\"#game-narrative-four\");\r\n\r\n    var computerThreats = [\"Prepare to suffer extreme humiliation!\",\r\n        \"I will destroy you!\",\r\n        \"I am invincible!\",\r\n        \"You cannot defeat me!\",\r\n        \"You will be annihilated!\",\r\n        \"You will fail!\",\r\n        \"Fear me!\",\r\n        \"Vengeance is mine!\",\r\n        \"I hunger!\"]\r\n\r\n    var $identityBtn = $(\".identity-cell\");\r\n    var $gameBtn = $(\".game-cell\");\r\n    var $gameResetBtn = $(\"#game-reset-btn\");\r\n\r\n    $(document).ready(function() {\r\n        $narrativeOne.hide();\r\n        $narrativeTwo.hide();\r\n        $narrativeThree.hide();\r\n        $narrativeFour.hide();\r\n        $(\"#header\").hide();\r\n        $(\"#game-configuration\").hide();\r\n        $(\"#game-grid\").hide();\r\n        $(\"#game-over\").hide();\r\n\r\n        $narrativeOne.fadeIn(500);\r\n    });\r\n\r\n    $(\"#narrative-one-btn\").on('click', function() {\r\n        var transitionPeriod = 500;\r\n        $narrativeOne.fadeOut(transitionPeriod);\r\n        setTimeout(function() {\r\n            $narrativeTwo.fadeIn(transitionPeriod);\r\n        }, transitionPeriod);\r\n    });\r\n\r\n    $(\"#narrative-two-btn\").on('click', function() {\r\n        var transitionPeriod = 500;\r\n        $narrativeTwo.fadeOut(transitionPeriod);\r\n        setTimeout(function() {\r\n            $narrativeThree.fadeIn(transitionPeriod);\r\n        }, transitionPeriod);\r\n    });\r\n\r\n    $(\"#narrative-three-btn\").on('click', function() {\r\n        var transitionPeriod = 500;\r\n        $narrativeThree.fadeOut(transitionPeriod);\r\n        setTimeout(function() {\r\n            $(\"#tic-text\").hide();\r\n            $(\"#tac-text\").hide();\r\n            $(\"#doom-text\").hide();\r\n            $(\"#header\").show();\r\n\r\n            $(\"#tic-text\").show();\r\n            setTimeout(function(){\r\n                $(\"#tac-text\").show();\r\n                setTimeout(function() {\r\n                    \/\/ $(\"body\").css(\"background-color\", darkColor);\r\n                    $(\"#doom-text\").show();\r\n\r\n                    setTimeout(function(){\r\n                        $(\"#game-configuration\").fadeIn(transitionPeriod);\r\n\r\n                    }, transitionPeriod * 2);\r\n                }, transitionPeriod * 2);\r\n            }, transitionPeriod * 2);\r\n        }, transitionPeriod * 2);\r\n    });\r\n\r\n\r\n\r\n    \/\/ When a player initially chooses their mark before playing.\r\n    $identityBtn.on('click', function() {\r\n\r\n        \/\/ Grabbing value from the HTML element\r\n        game.playerMark = $(this).attr(\"value\");\r\n        if (game.playerMark === \"X\"){\r\n            game.aiMark = \"O\";\r\n        } else {\r\n            game.aiMark = \"X\";\r\n        }\r\n\r\n        startGame();\r\n    });\r\n\r\n    function startGame(){\r\n        \/\/ Transitioning between config menu to game grid.\r\n        $(\"#game-configuration\").hide();\r\n        $(\"#game-grid\").fadeIn(500);\r\n\r\n        if (!game.playerTurn)\r\n            aiPlay();\r\n    }\r\n\r\n    $gameBtn.on('click', function() {\r\n        if (game.playerTurn) {\r\n            \/\/ Parsing player's move\r\n            var cell = $(this).attr(\"id\");\r\n            var row = parseInt(cell[1]);\r\n            var col = parseInt(cell[2]);\r\n\r\n            if (spaceFree(game.board, row, col)) {\r\n                makePlay(game.playerMark, row, col); \/\/ Commit move to the game board.\r\n                checkPlay(game.playerMark); \/\/ Check if the move resulted in a win.\r\n            } else {\r\n                \/\/ Do nothing (space already taken)\r\n            }\r\n        } else {\r\n            \/\/ Do nothing (not player's turn)\r\n        }\r\n\r\n    });\r\n\r\n    function aiPlay() {\r\n        var aiThinkingDelay = 1000;\r\n        setTimeout(function() {\r\n\r\n            minimax(game, 0); \/\/ Use minimax to calculate the next optimal move.\r\n            makePlay(game.aiMark, game.nextMove[0], game.nextMove[1]); \/\/ Commit move to the game board.\r\n            checkPlay(game.aiMark); \/\/ Check if the move resulted in a win.\r\n\r\n\r\n            var randThreat = computerThreats[Math.floor(Math.random() * computerThreats.length)];\r\n            $(\"#computer-threat-text\").text(randThreat);\r\n            $(\"#computer-threat-text\").fadeIn(250);\r\n            setTimeout(function() {\r\n                $(\"#computer-threat-text\").fadeOut(250);\r\n            }, 2000);\r\n\r\n        }, aiThinkingDelay);\r\n\r\n\r\n    }\r\n\r\n    function checkPlay(mark) {\r\n        const gameOverDelay = 2000;\r\n        if (hasWon()) {\r\n            const gameOverDelay = 2000; \/\/ Wait two second to allow win animation to play out.\r\n            \/\/ Turn has resulted in a valid win\r\n            setTimeout(function() {\r\n                gameOver(mark); \/\/ After delay, transition to game-over menu.\r\n            }, gameOverDelay);\r\n\r\n        } else if (game.turnsPlayed >= 9) {\r\n            \/\/ There are no more turns that can be made, it is a draw.\r\n            \/\/ Draw animation?\r\n            setTimeout(function() {\r\n                gameOver(\"draw\");\r\n            }, gameOverDelay);\r\n\r\n        } else {\r\n            game.playerTurn = !game.playerTurn; \/\/ Toggle turn between pc and player.\r\n            if (!game.playerTurn) {\r\n                aiPlay(); \/\/ If it's not the players turn, initiate computer turn.\r\n            }\r\n        }\r\n    }\r\n\r\n    function spaceFree(board, row, col) {\r\n        \/\/ Checks if a player can mark a selected cell.\r\n        return (board[row][col] === null)\r\n    }\r\n\r\n    function makePlay(mark, row, col) {\r\n        \/\/ Saving move to game\r\n        game.board[row][col] = mark;\r\n        game.turnsPlayed++;\r\n\r\n        var cellId = \"#c\" + row + \"\" + col;\r\n        \/\/ Stylising game cell to reflect an ai move.\r\n        $(cellId).text(mark);\r\n        $(cellId).addClass(\"cell-selected\");\r\n\r\n    }\r\n\r\n    function minimax(state, depth){\r\n        \/\/ Inspired by http:\/\/neverstopbuilding.com\/minimax\r\n\r\n        \/\/ Creating a replicated object of the game state to avoid\r\n        \/\/ editing the existing game state (it has been passed 'byRef')\r\n        \/\/ See http:\/\/stackoverflow.com\/questions\/122102\/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript\/5344074#5344074\r\n        var gameState = JSON.parse(JSON.stringify(state));\r\n\r\n        if (gameState.gameOver){\r\n            \/\/ If game is in an end state (win, lose, draw) return corresponding score (10, -10, 0)\r\n            return getScore(gameState, depth);\r\n\r\n        } else {\r\n            depth++; \/\/ Iterate depth as algorithm gets recursively deeper. Used to choose moves that prolong defeat, hasten victory.\r\n            var moves = []; \/\/ Used to store all possible moves in this current game state.\r\n            var scores = []; \/\/ Used to store the corresponding scores resulting from each of those moves.\r\n\r\n            moves = generateAllAvailableMoves(gameState); \/\/ Generate an array of all available coordinates on the game board.\r\n\r\n            for (var i = 0; i < moves.length; i++) {\r\n                \/\/ For each possible move, create a simulation game state where the move has been played.\r\n                var possibleGameState = generatePossibleGame(gameState, moves[i]);\r\n                \/\/ Then store the resultant score, recursively calling the minimax algorithm.\r\n                scores.push(minimax(possibleGameState, depth));\r\n            }\r\n\r\n            if (gameState.playerTurn) {\r\n                \/\/ MAX\r\n                var maxScoreIndex = findIndexOfMax(scores); \/\/ In the case of it being the protagonist's turn, find the highest equating score.\r\n                game.nextMove = moves[maxScoreIndex]; \/\/ Store move to be executed.\r\n                return scores[maxScoreIndex];\r\n            } else {\r\n                \/\/ MIN\r\n                var minScoreIndex = findIndexOfMin(scores); \/\/ In the case of it being the opponent's turn, find the lowest equating score.\r\n                game.nextMove = moves[minScoreIndex];\r\n                return scores[minScoreIndex];\r\n            }\r\n        }\r\n    }\r\n\r\n    \/\/ Equates game states to scores\r\n    \/\/ Wins equating to 10, loses equating to -10, draws or continued gameplay equating to 0.\r\n    function getScore(gameState, depth) {\r\n        if (gameState.gameOver && gameState.winner === gameState.playerMark) {\r\n            return 10 - depth;\r\n        } else if (gameState.gameOver && gameState.winner === gameState.aiMark) {\r\n            return depth - 10;\r\n        } else {\r\n            return 0;\r\n        }\r\n    }\r\n\r\n    \/\/ Returns an array of the coordinates (row, column) of all available cells in a particular game state.\r\n    function generateAllAvailableMoves(gameState){\r\n        const rowLength = 3;\r\n        const colLength = 3;\r\n        var availableMoves = [];\r\n\r\n        for (var row = 0; row < rowLength; row++){\r\n            for (var col = 0; col < colLength; col++){\r\n                if (spaceFree(gameState.board, row, col)){\r\n                    \/\/ Scanning the game board for free spaces\r\n                    availableMoves.push([row, col]);\r\n                }\r\n            }\r\n        }\r\n        return availableMoves;\r\n    }\r\n\r\n    \/\/ Creates a simulated game state when a specified move is executed.\r\n    function generatePossibleGame(state, move){\r\n        var gameState = JSON.parse(JSON.stringify(state));\r\n\r\n        \/\/ Execute the move\r\n        if (gameState.playerTurn){\r\n            gameState.board[move[0]][move[1]] = gameState.playerMark;\r\n        } else {\r\n            gameState.board[move[0]][move[1]] = gameState.aiMark;\r\n        }\r\n        gameState.turnsPlayed++;\r\n\r\n        \/\/ Check if the move has resulted in an end game state.\r\n        if (checkWin(gameState)) {\r\n            gameState.gameOver = true;\r\n            if (gameState.playerTurn){\r\n                gameState.winner = gameState.playerMark;\r\n            } else {\r\n                gameState.winner = gameState.aiMark;\r\n            }\r\n        } else if (gameState.turnsPlayed >= 9) {\r\n            gameState.gameOver = true;\r\n            gameState.winner = \"draw\";\r\n        } else {\r\n            gameState.playerTurn = !gameState.playerTurn;\r\n        }\r\n\r\n        return gameState;\r\n    }\r\n\r\n    \/\/ Finds the index of the highest value in an array.\r\n    function findIndexOfMax(arr) {\r\n        var maxIndex = 0;\r\n        if (arr.length > 1) {\r\n            for (var i = 1; i < arr.length; i++){\r\n                if (arr[i] > arr[maxIndex]){\r\n                    maxIndex = i;\r\n                }\r\n            }\r\n        }\r\n        return maxIndex;\r\n    }\r\n\r\n    \/\/ Finds the index of the lowest value in an array.\r\n    function findIndexOfMin(arr) {\r\n        var minIndex = 0;\r\n        if (arr.length > 1) {\r\n            for (var i = 1; i < arr.length; i++){\r\n                if (arr[i] < arr[minIndex]){\r\n                    minIndex = i;\r\n                }\r\n            }\r\n        }\r\n        return minIndex;\r\n    }\r\n\r\n    \/\/ Used to check if the last played move has resulted in a win.\r\n    function checkWin(gameState) {\r\n        const numRows = 3;\r\n        const numCols = 3;\r\n\r\n        \/\/ Check for diagonal win right to left\r\n        if (gameState.board[0][0] === gameState.board[1][1] &&\r\n            gameState.board[1][1] === gameState.board[2][2] &&\r\n            gameState.board[0][0] !== null) {\r\n            \/\/ Right to left, top to bottom diagonal win\r\n            return true;\r\n        }\r\n\r\n        \/\/ Check for diagonal win left to right\r\n        if (gameState.board[0][2] === gameState.board[1][1] &&\r\n            gameState.board[1][1] === gameState.board[2][0] &&\r\n            gameState.board[0][2] !== null) {\r\n            \/\/ Left to right, top to bottom diagonal win\r\n            return true;\r\n        }\r\n\r\n        \/\/ Checking each row for a horizontal win\r\n        for (var row = 0; row < numRows; row++) {\r\n            if (gameState.board[row][0] === gameState.board[row][1] &&\r\n                gameState.board[row][1] === gameState.board[row][2] &&\r\n                gameState.board[row][0] !== null) {\r\n                \/\/ Horizontal win\r\n                return true;\r\n            }\r\n        }\r\n\r\n        \/\/ Checking each column for a vertical win\r\n        for (var col = 0; col < numCols; col++) {\r\n            if (gameState.board[0][col] === gameState.board[1][col] &&\r\n                gameState.board[1][col] === gameState.board[2][col] &&\r\n                gameState.board[0][col] !== null) {\r\n                \/\/ Vertical win\r\n                return true;\r\n            }\r\n        }\r\n        return false;\r\n    }\r\n\r\n    \/**\r\n\r\n     \/\/ Pre-Minimax AI, randomly selecting a space on the board.\r\n\r\n     function aiGenerateRandomPlay() {\r\n     var randRow = Math.floor(Math.random() * 3);\r\n     var randCol = Math.floor(Math.random() * 3);\r\n     var validMove = spaceFree(randRow, randCol);\r\n     while (!validMove) {\r\n     randRow = Math.floor(Math.random() * 3);\r\n     randCol = Math.floor(Math.random() * 3);\r\n     validMove = spaceFree(randRow, randCol);\r\n     }\r\n     return [randRow, randCol];\r\n     }\r\n\r\n     *\/\r\n\r\n\r\n\/\/ Checking whether the last move made has triggered a win, and if so triggers a win animation.\r\n    function hasWon() {\r\n        const numRows = 3;\r\n        const numCols = 3;\r\n\r\n        \/\/ Check for diagonal win right to left\r\n        if (game.board[0][0] === game.board[1][1] &&\r\n            game.board[1][1] === game.board[2][2] &&\r\n            game.board[0][0] !== null) {\r\n            \/\/ Win animation\r\n            $(\"#c00\").addClass(\"cell-win\");\r\n            $(\"#c11\").addClass(\"cell-win\");\r\n            $(\"#c22\").addClass(\"cell-win\");\r\n\r\n            return true;\r\n        }\r\n\r\n        \/\/ Check for diagonal win left to right\r\n        if (game.board[0][2] === game.board[1][1] &&\r\n            game.board[1][1] === game.board[2][0] &&\r\n            game.board[0][2] !== null) {\r\n            \/\/ Left to right, top to bottom diagonal win\r\n\r\n            \/\/ Win animation\r\n            $(\"#c02\").addClass(\"cell-win\");\r\n            $(\"#c11\").addClass(\"cell-win\");\r\n            $(\"#c20\").addClass(\"cell-win\");\r\n\r\n            return true;\r\n        }\r\n\r\n        \/\/ Checking each row for a horizontal win\r\n        for (var row = 0; row < numRows; row++) {\r\n            if (game.board[row][0] === game.board[row][1] &&\r\n                game.board[row][1] === game.board[row][2] &&\r\n                game.board[row][0] !== null) {\r\n                \/\/ Horizontal win\r\n\r\n                \/\/ Win animation\r\n                $(\"#c\" + row + \"0\").addClass(\"cell-win\");\r\n                $(\"#c\" + row + \"1\").addClass(\"cell-win\");\r\n                $(\"#c\" + row + \"2\").addClass(\"cell-win\");\r\n                return true;\r\n            }\r\n        }\r\n\r\n        \/\/ Checking each column for a vertical win\r\n        for (var col = 0; col < numCols; col++) {\r\n            if (game.board[0][col] === game.board[1][col] &&\r\n                game.board[1][col] === game.board[2][col] &&\r\n                game.board[0][col] !== null) {\r\n                \/\/ Vertical win\r\n\r\n                \/\/ Win animation\r\n                $(\"#c0\" + col).addClass(\"cell-win\");\r\n                $(\"#c1\" + col).addClass(\"cell-win\");\r\n                $(\"#c2\" + col).addClass(\"cell-win\");\r\n                return true;\r\n            }\r\n        }\r\n\r\n        return false;\r\n    }\r\n\r\n    \/\/ Transitions the screen from the game grid to a game over menu.\r\n    function gameOver(winCase) {\r\n        $(\"#game-grid\").hide();\r\n        $(\"#game-over\").fadeIn(500);\r\n\r\n        if (winCase === game.playerMark) {\r\n            \/\/ Player wins\r\n            $(\"#game-end-heading\").text(\"\u00a1Has reclamado la victoria!\");\r\n            $(\"#game-end-subheading\").text(\"Que te ba\u00f1es en la gloria del tres en raya.\");\r\n\r\n        } else if (winCase === game.aiMark) {\r\n\/\/ PC gana\r\n            $(\"#game-end-heading\").text(\"\u00a1Ay, la computadora ha reclamado la victoria!\");\r\n            $(\"#game-end-subheading\").text(\"Que sus circuitos se ba\u00f1en en la gloria del tres en raya.\");\r\n        } else {\r\n\/\/ Empate\r\n            $(\"#game-end-heading\").text(\"X y O, antiguos enemigos, han concluido su combate en un empate.\");\r\n            $(\"#game-end-subheading\").text(\"Quiz\u00e1s su disputa se resuelva en otra vida, en otra dimensi\u00f3n...\");\r\n        }\r\n\r\n    }\r\n\r\n    $gameResetBtn.on('click', resetGame);\r\n\r\n    function resetGame() {\r\n        $(\"#game-over\").hide();\r\n        $(\"#game-grid\").hide();\r\n        $(\"#game-configuration\").fadeIn(500);\r\n\r\n        $(\".game-cell\").empty();\r\n        $(\".cell\").removeClass(\"cell-selected\");\r\n        $(\".cell\").removeClass(\"cell-win\");\r\n\r\n        game.board = [\r\n            [null, null, null],\r\n            [null, null, null],\r\n            [null, null, null]\r\n        ];\r\n        game.turnsPlayed = 0;\r\n        game.playerTurn = true;\r\n    }\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":1713,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1839","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Three in a row - Placenet BCN<\/title>\n<meta name=\"robots\" content=\"noindex, nofollow\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Three in a row - Placenet BCN\" \/>\n<meta property=\"og:url\" content=\"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/\" \/>\n<meta property=\"og:site_name\" content=\"Placenet BCN\" \/>\n<meta property=\"article:modified_time\" content=\"2025-02-11T18:56:18+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/\",\"url\":\"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/\",\"name\":\"Three in a row - Placenet BCN\",\"isPartOf\":{\"@id\":\"https:\/\/bcn.myplacenet.app\/en\/#website\"},\"datePublished\":\"2025-01-09T11:46:29+00:00\",\"dateModified\":\"2025-02-11T18:56:18+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\/\/bcn.myplacenet.app\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Explore\",\"item\":\"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Three in a row\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/bcn.myplacenet.app\/en\/#website\",\"url\":\"https:\/\/bcn.myplacenet.app\/en\/\",\"name\":\"Placenet BCN\",\"description\":\" Conoce Gente y \u00danete a Planes en Tu Zona en Tiempo Real\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/bcn.myplacenet.app\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Three in a row - Placenet BCN","robots":{"index":"noindex","follow":"nofollow"},"og_locale":"en_US","og_type":"article","og_title":"Three in a row - Placenet BCN","og_url":"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/","og_site_name":"Placenet BCN","article_modified_time":"2025-02-11T18:56:18+00:00","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/","url":"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/","name":"Three in a row - Placenet BCN","isPartOf":{"@id":"https:\/\/bcn.myplacenet.app\/en\/#website"},"datePublished":"2025-01-09T11:46:29+00:00","dateModified":"2025-02-11T18:56:18+00:00","breadcrumb":{"@id":"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/three-in-a-row\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/bcn.myplacenet.app\/en\/"},{"@type":"ListItem","position":2,"name":"Explore","item":"https:\/\/bcn.myplacenet.app\/en\/explore-placenet\/"},{"@type":"ListItem","position":3,"name":"Three in a row"}]},{"@type":"WebSite","@id":"https:\/\/bcn.myplacenet.app\/en\/#website","url":"https:\/\/bcn.myplacenet.app\/en\/","name":"Placenet BCN","description":" Conoce Gente y \u00danete a Planes en Tu Zona en Tiempo Real","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/bcn.myplacenet.app\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/bcn.myplacenet.app\/en\/wp-json\/wp\/v2\/pages\/1839","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bcn.myplacenet.app\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bcn.myplacenet.app\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bcn.myplacenet.app\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bcn.myplacenet.app\/en\/wp-json\/wp\/v2\/comments?post=1839"}],"version-history":[{"count":1,"href":"https:\/\/bcn.myplacenet.app\/en\/wp-json\/wp\/v2\/pages\/1839\/revisions"}],"predecessor-version":[{"id":1840,"href":"https:\/\/bcn.myplacenet.app\/en\/wp-json\/wp\/v2\/pages\/1839\/revisions\/1840"}],"up":[{"embeddable":true,"href":"https:\/\/bcn.myplacenet.app\/en\/wp-json\/wp\/v2\/pages\/1713"}],"wp:attachment":[{"href":"https:\/\/bcn.myplacenet.app\/en\/wp-json\/wp\/v2\/media?parent=1839"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}