Home > Software design >  using JS to make tic tac toe
using JS to make tic tac toe

Time:10-18

I have made a tic tac toe using JS however it has some problems My code is:

let x = [];
let o = [];
let xTurn = false;
let winPat = [
  ['00', '10', '20'],
  ['01', '11', '21'],
  ['02', '12', '22'],
  ['00', '01', '02'],
  ['10', '11', '12'],
  ['20', '21', '22'],
  ['00', '11', '22'],
  ['02', '11', '20']
];

const tableR = document.getElementsByClassName('tableR');
const button = document.getElementById('btn')

for (let i = 0; i <= 2; i  ) {
  for (let j = 0; j <= 2; j  ) {
    let newElement = document.createElement('td');
    tableR.item(i).appendChild(newElement);
    newElement.addEventListener('click', () => {
      if (elementIsEmpty(newElement)) {
        const img = document.createElement('img');
        if (xTurn) {
          img.src = 'https://www.google.com/url?sa=i&url=https://commons.wikimedia.org/wiki/File:Red_X.svg&psig=AOvVaw1B-fppvlN2x5oSCGllnXGc&ust=1634565535566000&source=images&cd=vfe&ved=0CAkQjRxqFwoTCMjbg6XN0fMCFQAAAAAdAAAAABAD';
          x.push(String(i)   String(j))
        } else {
          img.src = 'https://www.google.com/imgres?imgurl=https://upload.wikimedia.org/wikipedia/commons/thumb/d/d0/Letter_o.svg/407px-Letter_o.svg.png&imgrefurl=https://commons.wikimedia.org/wiki/File:Letter_o.svg&tbnid=p-B77Lz3DDttwM&vet=12ahUKEwizlYTWzdHzAhXMg9gFHTSaBJkQMygAegUIARDaAQ..i&docid=K2HPZsIMOu4d5M&w=407&h=768&q=pixture of o&ved=2ahUKEwizlYTWzdHzAhXMg9gFHTSaBJkQMygAegUIARDaAQ';
          o.push(String(i)   String(j))
        }
        newElement.append(img)
        checkWinOrDraw(xTurn)
        xTurn = !xTurn
      }
    })
  }
}

const td = document.getElementsByTagName('td')
button.addEventListener('click', () => {
  reset();
});

function elementIsEmpty(el) {
  return (/^(\s|&nbsp;)*$/.test(el.innerHTML));
}

function checkWinOrDraw(xTurn) {
  for (let i = 0; i < winPat.length; i  ) {
    if (xTurn) {
      if (winPat[i].every(element => x.includes(element))) {
        alert('X wins')
        reset()
        return
      }
    } else {
      if (winPat[i].every(element => o.includes(element))) {
        alert('O wins')
        reset()
        return
      }
    }
  }

  for (let item of td) {
    if (elementIsEmpty(item))
      return
  }
  alert('Draw')
  reset()
}


function reset() {
  x = [];
  o = [];
  for (let item of td) {
    item.textContent = ''
  }
}
body {
  margin: 0px;
  background-color: #3c4552;
  color: aliceblue;
  text-align: center;
}

header {
  height: 75px;
  background-color: #1f1e1c;
  padding: 20px;
  font-size: large;
}

table {
  border-collapse: collapse;
  margin: 40px auto;
}

td {
  border: 7px solid black;
  height: 121px;
  width: 121px;
  cursor: pointer;
}

button {
  background-color: #1f1e1c;
  color: white;
  width: 25%;
  height: 50px;
  font-size: larger;
  border: black solid 2px;
  border-radius: 7px;
  cursor: pointer;
}

img {
  display: block;
  width: 100%;
  height: 100%;
}
<header>
  <h1>TicTacToe</h1>
</header>
<main>
  <table>
    <tr class="tableR"></tr>
    <tr class="tableR"></tr>
    <tr class="tableR"></tr>
  </table>
</main>
<footer>
  <button id="btn">RESET</button>
</footer>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

my problem is that when the game ends, say X wins, the image is not rendered on the screen, and alert() is called. I googled a lot and found no solutions.

details and clarity: the image is not rendered on screen at the end of the game. try on your computer and see. alert() is called before the image is present in-game which results in a bad user experience. hence I need a solution.

CodePudding user response:

Here your append() function is not able to complete image load & your checkWinOrDraw() function got called that's why this is happening.

Please try with the below code i am calling the checkWinOrDraw() once image gets loaded or failed.

for (let i = 0; i <= 2; i  ) {
  for (let j = 0; j <= 2; j  ) {
    let newElement = document.createElement('td');
    tableR.item(i).appendChild(newElement);
    newElement.addEventListener('click', () => {
      if (elementIsEmpty(newElement)) {
        const img = document.createElement('img');
        if (xTurn) {
          img.src =  'https://dummyimage.com/20x20/3a4ca6/fff';
          x.push(String(i)   String(j))
        } else {
          img.src = 'https://dummyimage.com/30x30/fff/fff';
          o.push(String(i)   String(j))
        }
        console.log(xTurn)
         xTurn = !xTurn
        img.addEventListener('load', checkWinOrDraw)
  img.addEventListener('error', checkWinOrDraw)
        newElement.appendChild(img)
      }
    })
  }
}

function checkWinOrDraw(e,xTurn) {
        
  //console.log('checking',xTurn)
  for (let i = 0; i < winPat.length; i  ) {
    if (xTurn) {
      if (winPat[i].every(element => x.includes(element))) {
        alert('X wins')
        reset()
        return
      }
    } else {
      if (winPat[i].every(element => o.includes(element))) {
        alert('O wins')
        reset()
        return
      }
    }
  }

  for (let item of td) {
    if (elementIsEmpty(item))
      return
  }
  alert('Draw')
  reset()
}
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related