I would like to develop a tic-tac-toe game using socket.io. Players playing the game in their own browser, i want once player1 clicks on any one button, all the button will be disabled, until player2 finish to click on the buttton in his own browser, and vice versa. The name of my server file is index.js, while the name of my html document is index.html.
index.js:
const express = require("express");
const app = express();
const path = require("path");
const http = require("http");
const {Server} = require("socket.io");
const server = http.createServer(app);
const io = new Server(server)
app.use(express.static(path.resolve("")))
let arr = [];
let playingArray = [];
io.on("connection", (socket)=>{
socket.on("find", (e)=>{
if(e.name != null){
arr.push(e.name)
if(arr.length >=2){
let p1obj = {
p1name: arr[0],
p1value: "X",
p1move: ""
}
let p2obj = {
p2name: arr[1],
p2value: "O",
p2move: ""
}
let obj = {
p1: p1obj,
p2: p2obj,
sum:1
}
playingArray.push(obj);
arr.splice(0,2);
io.emit("find", {allPlayers: playingArray})
}
}
})`
socket.on("playing", (e)=>{
if(e.value=="X"){
let objToChange=playingArray.find(obj=>obj.p1.p1name===e.name);
objToChange.p1.p1move=e.id;
objToChange.sum++
}
else if(e.value=="O"){
let objToChange=playingArray.find(obj=>obj.p2.p2name===e.name);
objToChange.p2.p2move=e.id;
objToChange.sum++
}
io.emit("playing", {allPlayers: playingArray})
})
io.emit("enableButtonsClient");
});
app.get("/", (req,res)=>{
return res.sendFile("index.html")
})
server.listen(3000,()=>{
console.log("port connected to 3000")
})
Below is the index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="https://fonts.googleapis.com/css2?family=Tilt+Warp&display=swap" rel="stylesheet">
</head>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: rgb(255, 255, 255);
display: grid;
place-items: center;
font-family: 'Tilt Warp', cursive;
}
h1 {
margin: 50px 0 50px 0;
font-size: 5rem;
color: rgb(32, 183, 93);
-webkit-text-stroke: .5px black;
}
input {
margin-bottom: 20px;
padding: 5px;
font-size: 1.2rem;
}
button {
font-size: 1.2rem;
margin-bottom: 10px;
}
img {
width: 30px;
}
#cont {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.btn {
font-size: 2rem;
width: 100px;
height: 100px;
cursor: pointer;
margin: 0;
background-color: rgb(206, 203, 203);
border-radius: 10px;
}
#find {
font-size: 1.5rem;
color: white;
cursor: pointer;
padding: 7px;
border-radius: 10px;
width: 250px;
background-color: rgb(0, 0, 0);
}
.btn:hover {
background-color: rgb(226, 228, 230);
}
button.enabled {
opacity: 1;
}
p {
font-size: 2rem;
}
</style>
<body>
<h1>Tic-Tac-Toe</h1>
<div style="display: flex; width: 95vw; position: relative;">
<p id="userCont">You : <span id="user"></span></p>
<p style="position: absolute; right: 0;" id="oppNameCont">Opponent : <span id="oppName"></span></p>
</div>
<br>
<p id="valueCont">You are placing as <span id="value"></span></p>
<br>
<p id="whosTurn">X's Turn</p>
<div>
<p style="font-size: 1.2rem;" id="enterName">Enter your name : </p>
<input type="text" placeholder="Name" id="name" autocomplete="off">
</div>
<button id="find">Search for a player</button>
<img id="loading" src="loading.gif" alt="">
<div id="bigcont">
<div id="cont">
<button id="btn1" class="btn"></button>
<button id="btn2" class="btn"></button>
<button id="btn3" class="btn"></button>
<button id="btn4" class="btn"></button>
<button id="btn5" class="btn"></button>
<button id="btn6" class="btn"></button>
<button id="btn7" class="btn"></button>
<button id="btn8" class="btn"></button>
<button id="btn9" class="btn"></button>
</div>
</div>
</body>
<script src="/socket.io/socket.io.js"></script>
<script>
document.getElementById("loading").style.display = "none"
document.getElementById("bigcont").style.display = "none"
document.getElementById("userCont").style.display = "none"
document.getElementById("oppNameCont").style.display = "none"
document.getElementById("valueCont").style.display = "none"
document.getElementById("whosTurn").style.display = "none"
const socket = io();
let name;
document.getElementById('find').addEventListener("click", function () {
name = document.getElementById("name").value
document.getElementById("user").innerText = name
if (name == null || name == '') {
alert("Please enter a name")
}
else {
socket.emit("find", { name: name })
document.getElementById("loading").style.display = "block"
document.getElementById("find").disabled = true;
}
})
socket.on("find", (e) => {
let allPlayersArray = e.allPlayers;
console.log("html", allPlayersArray)
if (name !=''){
document.getElementById("loading").style.display = "none";
document.getElementById("name").style.display = "none";
document.getElementById("find").style.display = "none";
document.getElementById("enterName").style.display = "none";
document.getElementById("bigcont").style.display = "block";
document.getElementById("userCont").style.display = "block";
document.getElementById("oppNameCont").style.display = "block";
document.getElementById("valueCont").style.display = "block";
document.getElementById("whosTurn").style.display = "block";
document.getElementById("whosTurn").innerText = "X's Turn";
}
let oppName
let value
const foundObject = allPlayersArray.find(obj=>obj.p1.p1name == `${name}` || obj.p2.p2name == `${name}`);
foundObject.p1.p1name == `${name}` ? oppName = foundObject.p2.p2name : oppName = foundObject.p1.p1name;
foundObject.p1.p1name == `${name}` ? value = foundObject.p1.p1value : value = foundObject.p2.p2value;
document.getElementById("oppName").innerText = oppName
document.getElementById("value").innerText = value
})
document.querySelectorAll(".btn").forEach(e => {
e.addEventListener("click", function () {
let value = document.getElementById("value").innerText
e.innerText = value
socket.emit("playing", { value: value, id: e.id, name: name })
})
})
socket.on("playing", (e) => {
const foundObject = (e.allPlayers).find(obj => obj.p1.p1name == `${name}` || obj.p2.p2name == `${name}`);
p1id = foundObject.p1.p1move
p2id = foundObject.p2.p2move
if ((foundObject.sum) % 2 == 0) {
document.getElementById("whosTurn").innerText = "O's Turn"
}
else {
document.getElementById("whosTurn").innerText = "X's Turn"
}
if (p1id != '') {
document.getElementById(`${p1id}`).innerText = "X"
document.querySelectorAll('.btn').forEach(btn => {
btn.disabled = true;
btn.style.color = 'black';
});
}
if (p2id != '') {
document.getElementById(`${p2id}`).innerText = "O"
document.querySelectorAll('.btn').forEach(btn => {
btn.disabled = true;
btn.style.color = 'black';
});
}
})
socket.on("enableButtonsClient", () => {
document.querySelectorAll(".btn").forEach((btn) => {
if (btn.innerText !== "X" && btn.innerText !== "O") {
btn.disabled = false;
btn.style.color = "initial";
}
});
});
</script>
</html>
I had run the above program, once player1 click on any one button in one browser, all buttons are disabled, I expect all the button with no"X" and "O" are enable in another browser, however they are kept disabled, why? You see in my index.js, i already have the statement "io.emit("enableButtonsClient");" and in index.html, i have this code snippet:
socket.on("enableButtonsClient", () => {
document.querySelectorAll(".btn").forEach((btn) => {
if (btn.innerText !== "X" && btn.innerText !== "O")
{ btn.disabled = false; btn.style.color = "initial";
}
});
});
Therefore i expect the buttons without “X” or “O” are enabled again in player2’s browser, what’s wrong?