Trouble Arising in Showing the "X" Symbol upon Initial Click in Tic-Tac-Toe Match

Description:

I'm currently developing a tic-tac-toe game, and I've run into an interesting issue. When I click on any box for the first time, the "X" symbol doesn't show up. However, it works fine after the initial click.

Problem Details:

  1. Issue 1: "X" not appearing on initial click

    • Upon clicking on a box in the game, the "X" symbol fails to display initially. Subsequent clicks work as expected without any issues.

If you come across any other issues or have suggestions for improvement, please share them with me as I am relatively new to coding.

Code Snippets:

Below is the essential code snippet for my tic-tac-toe game:

... (code has been omitted for brevity)

Regards

A big thank you to those who are trying to help me solve this problem!

What I've Tried:

In response to advice from an experienced user on the OpenAI platform, I meticulously checked the turner and tosswinner functions. I confirmed that the tosswinner function is properly triggered upon box clicks.

Additional Information:

This game is being developed using HTML, CSS, and JavaScript. There seems to be a potential conflict with event handling or timing, but I haven't been able to pinpoint the exact cause of the problem.

Request for Help:

Any guidance or recommendations on resolving the aforementioned issues would be highly appreciated. If you can detect any errors in my code or propose alternative solutions, your assistance would be invaluable.

Thank you for your support!

Answer №1

Your issue stems from the fact that your click event listener is only activated after the initial click, as it is part of the tosswinner function.

To resolve this, you need to relocate the click event listener for boxes to the global scope. This way, even if the first click is not triggered, the event will still be registered in advance.

//move the click event listener to the global scope
boxes.forEach((box) => {
  box.addEventListener("click", function() {
    tosswinner.call(this);
  });
});

let boxes = document.querySelectorAll('.boxes');
let arr = Array.from(boxes);
console.log(arr);
let pop = document.getElementById("pop");
let tossing = document.getElementById("tossing");
let tosser = document.getElementById("tosser");
let toss1 = document.getElementById("toss1");
let tossing1 = document.getElementById("tossing1");
setTimeout(() => {
  pop.classList.add("popup");
}, 3000);
let botTurn = "";
let choosedToss = "";
let count = 0;

//move the click event listener to the global scope
boxes.forEach((box) => {
  box.addEventListener("click", function() {
    tosswinner.call(this);
  });
});

async function turner() {
  let selected = arr[Math.floor(Math.random() * arr.length)];
  setTimeout(() => {
    if (selected.innerHTML == "") {
      setTimeout(() => {
        selected.innerHTML = "O";
      }, 50);
    } else {
      return turner();
    }
  }, 50);
  count++;
}

function tosswinner() {
  let box = this;
  if (box.innerHTML === "") {
    box.innerHTML = "X";
  }
  boxes.forEach((box) => {
    //you don't need this anymore
    //box.addEventListener("click", function() {
    //  tosswinner.call(this);
    //});
    count++;
  });
}

async function FinalFunc() {
  let Hulk = new Promise((resolve, reject) => {
    setTimeout(() => {
      toss1.classList.remove("open1");
      resolve(1);
    }, 2000);
  });
  const result = await Hulk;
  console.log(result);
}

async function R() {
  let THOR = new Promise((resolve, reject) => {
    setTimeout(() => {
      if (choosedToss == botTurn) {
        tossing1.innerHTML = "you won , first turn is yours";
      } else {
        tossing1.innerHTML =
          "you have losted , you will play next to the winner ";
      }
      tossing1.classList.add("text1");
      resolve("Thor");
    }, 1500);
  });
  const result = await THOR;
  console.log(result);
}

async function botTurns() {
  let TOSS = ["Heads", "Tail"];
  botTurn = TOSS[Math.floor(Math.random() * TOSS.length)];
  tossing1.innerHTML = `<h1>${botTurn}</h1>`;
  tossing1.classList.add("text");
}

async function Messi() {
  let cap = new Promise((resolve, reject) => {
    setTimeout(() => {
      tossing1.classList.remove("load");
      botTurns();
      resolve(botTurn);
    }, 3000);
  });
  const result = await cap;
  console.log(result);
}

async function Message() {
  let stark = new Promise((resolve, reject) => {
    setTimeout(() => {
      tossing.classList.remove("load");
      tossing.innerHTML = `you choosed ${choosedToss} !`;
      resolve(`you choosed ${choosedToss}`);
    }, 1000);
  });
  const result = await stark;
  console.log(result);
}

async function popdown() {
  let tony = new Promise((resolve, reject) => {
    setTimeout(() => {
      tosser.classList.remove("tosseropen");
      resolve("rate");
    }, 2000);
  });
  const result = await tony;
  console.log(result);
}

async function Heads() {
  choosedToss = "Heads";
  pop.classList.remove("popup");
  tosser.classList.add("tosseropen");
  await Message();
  await popdown();
  toss1.classList.add("open1");
  await Messi();
  await R();
  await FinalFunc();
}

async function Tail() {
  choosedToss = "Tail";
  pop.classList.remove("popup");
  tosser.classList.add("tosseropen");
  await Message();
  await popdown();
  toss1.classList.add("open1");
  await Messi();
  await R();
  await FinalFunc();
}
body {
  display: flex;
  justify-content: center;
  height: 100vh;
  width: 100vw;
  align-items: center;
}

#mainbox { 
  width: 240px;
  height: 240px;
  display: flex;
  position: absolute;
  right: 60px;
  flex-flow: row wrap;
  background-color: yellow;
}

.boxes {
  height: 75px;
  width: 75px;
  background: red;
  margin: 2px;
  color: white;
  font-size: 25px;
}

#pop,
#tosser,
#toss1 {
  height: 200px;
  width: 280px;
  background: skyblue;
  position: absolute;
  top: 0%;
  left: 12.5%;
  visibility: hidden;
  transform: translate(0px, 0px) scale(0.01);
  transition: transform 0.4s, top 0.4s;
  display: flex;
  flex-flow: column wrap;
  border-radius: 20px;
  justify-content: space-between;
  align-items: center;
}

#pop.popup,
#tosser.tosseropen,
#toss1.open1 {
  visibility: visible;
  display: flex;
  top: 0%;
  transform: translate(0px, 100px) scale(1);
}

.head {
  width: 280px;
  height: 50px;
  background: darkblue;
  color: white;
  font-size: 30px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-weight: bolder;
  border-top-left-radius: 20px;
  border-top-right-radius: 20px;
}

#para {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 20px;
  color: white;
  font-weight: bold;
}

.toss {
  height: 40px;
  width: 90px;
  margin: 0px 20px 30px 18px;
  background: royalblue;
  color: white;
  font-size: 20px;
  border: none;
  border-radius: 10px;
  font-weight: bold;
  
}

#tossing {
  color: white;
  font-size: 27px;
  font-weight: bolder;
  margin-bottom: 60px;
}

.text {
  color: white;
  font-size: 15px;
  font-weight: bolder;
  margin-bottom: 38px;
}

.text1 {
  color: white;
  font-size: 15px;
  font-weight: bolder;
  margin-bottom: 65px;
}

.load {
  height: 50px;
  width: 50px;
  border: 5px black solid;
  border-top: 5px royalblue solid;
  border-radius: 50%;
  position: fixed;
  top: 80px;
  animation: SpinAnimate 1s linear 0s infinite normal;
}

@keyframes SpinAnimate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
<div id="mainbox">
  <div class="boxes" onclick="tosswinner(this);turner();"></div>
  <div class="boxes" onclick="tosswinner(this);turner();"></div>
  <div class="boxes" onclick="tosswinner(this);turner();"></div>
  <div class="boxes" onclick="tosswinner(this);turner();"></div>
  <div class="boxes" onclick="tosswinner(this);turner();"></div>
  <div class="boxes" onclick="tosswinner(this);turner();"></div>
  <div class="boxes" onclick="tosswinner(this);turner();"></div>
  <div class="boxes" onclick="tosswinner(this);turner();"></div>
  <div class="boxes" onclick="tosswinner(this);turner();"></div>

</div>

<div id="pop">
  <div class="head">TOSS</div>
  <div id="para">HEADS OR TAILS ? </div>
  <br />
  <div>
    <button class="toss" onclick="Heads()">HEADS</button>
    <button class="toss" onclick="Tail()">TAIL</button>
  </div>

</div>

<div id="tosser">
  <div class="head">CHOOSED</div>
  <div id="tossing" class="load"> </div>

</div>

<div id="toss1">
  <div class="head">TOSSING</div>
  <div id="tossing1" class="load">
  </div>

</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The function 'find' cannot be invoked on an undefined object

I'm currently working on implementing objects in my jQuery code. So far, I have the following: var options = { ul: $(this).find('.carousel'), li: options.ul.find('li') } The li property is causing an error - Cannot call meth ...

MUI Alert: Encountered an Uncaught TypeError - Unable to access properties of undefined when trying to read 'light' value

After utilizing MUI to create a login form, I am now implementing a feature to notify the user in case of unsuccessful login using a MUI Alert component. import Alert from '@mui/material/Alert'; The code snippet is as follows: <CssVarsProvide ...

Styling Table Headers with JavaScript and CSS

Currently, I have a Javascript function that returns a specific value. When this value is returned, I want to dynamically change the colors of different table headers based on their id. Is there a way to change the color of a table header in javascript wi ...

Using a CSS gradient with a variable in React.js - A guide to implementation

Looking to incorporate the following CSS property into the Navlink component. In the CSS file, the property is usually written like this using gradient. .ele { background-image: linear-gradient(45deg, #808080 25%, transparent 25%), li ...

Is there a way to adjust the width of the info panel in an SVG to automatically match the width of the SVG itself?

I am looking to place the information panel at the bottom of my SVG map and have it adjust its width according to the width specified in the viewBox. This way, even if I resize the map, the info panel will automatically adjust to fill completely based on t ...

Retrieve a string value in Next.JS without using quotation marks

Using .send rather than .json solved the problem, thank you I have an API in next.js and I need a response without Quote Marks. Currently, the response in the browser includes "value", but I only want value. This is my current endpoint: export ...

"Troubleshooting a callback problem in jQuery involving JavaScript and AJAX

UPDATE3 and FINAL: The problem has been resolved with the help of Evan and meder! UPDATE2: To clarify, I need the existing function updateFilters(a,b) to be called, not created. My apologies for any confusion. The issue with the code below is that udpate ...

What is the correct way to center-align elements?

I have a basic grid layout that has been styled using CSS. #videowall-grid{ width:700px; border:1px dotted #dddddd; display: none; margin: 5px auto; padding: 5px; } #videowall-grid .square{ padding: 5px; margin: 5px; bo ...

Issues with vue-moment.js in Vue

I'm struggling with incorporating vue-moment or moment.js into a .vue file to work with dates. I want to be able to manipulate a date in the Vue method to calculate the timespan between a past and current time, updating it dynamically. After searching ...

Trouble encountered while attempting to save canvas as PNG

In our TShirt design portal, we utilize fabric.js for creating designs. I have encountered an issue when trying to save the canvas as a PNG using canvas.toDataURL('image/png'). This action throws a "DOM exception 18" error on Google Chrome, while ...

Inheritance best practices for node.js applications

In C#, the concept of inheritance can be easily demonstrated through classes like Animal and Dog. class Animal { string name; public Animal() { } } class Dog : Animal { public Dog() : base() { this.name = "Dog"; } } When working ...

Expand the object by clicking on it, causing the surrounding objects to move outside the viewport instead of appearing below

I'm facing a challenge with 3 squares inside one container, each occupying 33.33% of the viewport and placed next to each other. When I click on one square, it should expand to full viewport width and reveal hidden content, while the other two remain ...

Error encountered while using Google Translate with XMLHttpRequest (Missing 'Access-Control-Allow-Origin' header)

Trying to access a page that utilizes Google Translate is resulting in the following error: XMLHttpRequest cannot load http://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit. No 'Access-Control-Allow-Origin' heade ...

Exploring JSON data hierarchies with AngularJS using ng-options

In my web app, I am utilizing AngularJS to create two dropdown lists using ng-options. The first dropdown displays a list of countries The second dropdown provides language preferences for the selected country As I am still new to AngularJS, I am able t ...

Shifting Vue components within the dom structure?

Whenever I am on a mobile device, I move Vue components higher up in the dom so that I can use absolute positioning without being contained within a relative container. if (this.mobile) { this.$el.parentNode.removeChild(this.$el); document.getElem ...

Attempting to retrieve dynamically generated input fields and cross-reference them with structured length .json data

In the process of developing code, I've implemented a for loop to dynamically generate HTML input fields based on the length of some data in a .json file. My goal is to use jQuery to compare the text entered in each input field with the corresponding ...

The Dropzone feature fails to function properly when displayed on a modal window that is being shown via

After attempting to integrate Dropzone and JavaScript into a Bootstrap Modal called through AJAX, I encountered issues. Due to the high number of records, I avoided placing the Modal in a foreach loop and instead used AJAX to call a controller method upon ...

Combining objects using ES6 import/export with async/await functionality

I am facing a situation where I have two files named config.js and config.json and my goal is to combine them into one object and then export it: config.json { "c": 3 } config.js import fs from "fs"; import fse from "fs-extra& ...

Automatically populate fields when the selection changes

Currently, I am facing an issue with a mysql table named clients that I utilize to populate the options of a select in one of the rows. The goal is to automatically fill out 2 input fields with client information when a specific option is selected. To acc ...

Having trouble with the Ajax load function not functioning in your HTML code?

The issue has been resolved. Thank you to everyone who helped! Initially, I was attempting to run a file offline instead of on a web server (XAMPP server). Once I uploaded the file to the web server, it started working properly. I had been trying to load ...