My first JS program - Tic Tac Toe game











up vote
3
down vote

favorite












I just completed some beginner web-dev courses (cs:50 and such) and wanted to try my skills.



The CSS centering - ugh I just gave up on that, I wanted to make it responsive and the letters centered perfectly, but whatever...



So overall, how is this coded? is there a better way to code this?






let turn = true;
let children;
let winnerFound = false;

document.addEventListener('DOMContentLoaded', load);

function load() {
children = document.getElementsByClassName("child");
for (let i = 0; i < children.length; i++) {
children[i].addEventListener("click", function () {
clicked(i);
});
}
document.getElementById("clear").addEventListener("click", function () {
clearBoard();
}
);
updateTurn();
}

function clearBoard() {
for (let i = 0; i < children.length; i++) {
children[i].innerHTML = '';
children[i].classList.remove('animate');
}
turn = true;
winnerFound = false;
updateTurn();
}

//text at the top
function updateTurn() {
if (turn)
document.getElementById("turn").innerHTML = "X";
else
document.getElementById("turn").innerHTML = "O";
}

function clicked(i) {
if (winnerFound)
return;
if (children[i].childElementCount !== 0)
return;
const div = document.createElement('div');
if (turn) {
div.textContent = 'X';
}
else {
div.textContent = 'O';
}
children[i].appendChild(div);
children[i].classList.add('animate');
turn = !turn;
checkWinner();
updateTurn();
}

function checkWinner() {
//check rows
for (let x = 0; x < 9; x += 3) {
if (childContent(x) === childContent(x + 1) && childContent(x) === childContent(x + 2)) {
alert(childContent(x) + " won!");
winnerFound = true;
}
}
//check columns
for (let x = 0; x < 3; x += 1) {
if (childContent(x) === childContent(x + 3) && childContent(x) === childContent(x + 6)) {
alert(childContent(x)+ " won!");
winnerFound = true;
}
}
//check diagonals
if (childContent(0) === childContent(4) && childContent(0) === childContent(8)) {
alert(childContent(0)+ " won!");
winnerFound = true;
}
if (childContent(2) === childContent(4) && childContent(2) === childContent(6)) {
alert(childContent(2)+ " won!");
winnerFound = true;
}
}

function childContent(i) {
if (children[i].childElementCount === 0) {
return i;
}
return children[i].getElementsByTagName('div')[0].innerHTML;
}

 body {
background: lightgray;
text-align: center;
vertical-align: middle;
}

.child:hover {
background-color: darkgrey;
}

.parent {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}

.child {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}

.animate {
animation: changeColor 0.5s forwards;
}

@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}

<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turn"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>












share|improve this question


























    up vote
    3
    down vote

    favorite












    I just completed some beginner web-dev courses (cs:50 and such) and wanted to try my skills.



    The CSS centering - ugh I just gave up on that, I wanted to make it responsive and the letters centered perfectly, but whatever...



    So overall, how is this coded? is there a better way to code this?






    let turn = true;
    let children;
    let winnerFound = false;

    document.addEventListener('DOMContentLoaded', load);

    function load() {
    children = document.getElementsByClassName("child");
    for (let i = 0; i < children.length; i++) {
    children[i].addEventListener("click", function () {
    clicked(i);
    });
    }
    document.getElementById("clear").addEventListener("click", function () {
    clearBoard();
    }
    );
    updateTurn();
    }

    function clearBoard() {
    for (let i = 0; i < children.length; i++) {
    children[i].innerHTML = '';
    children[i].classList.remove('animate');
    }
    turn = true;
    winnerFound = false;
    updateTurn();
    }

    //text at the top
    function updateTurn() {
    if (turn)
    document.getElementById("turn").innerHTML = "X";
    else
    document.getElementById("turn").innerHTML = "O";
    }

    function clicked(i) {
    if (winnerFound)
    return;
    if (children[i].childElementCount !== 0)
    return;
    const div = document.createElement('div');
    if (turn) {
    div.textContent = 'X';
    }
    else {
    div.textContent = 'O';
    }
    children[i].appendChild(div);
    children[i].classList.add('animate');
    turn = !turn;
    checkWinner();
    updateTurn();
    }

    function checkWinner() {
    //check rows
    for (let x = 0; x < 9; x += 3) {
    if (childContent(x) === childContent(x + 1) && childContent(x) === childContent(x + 2)) {
    alert(childContent(x) + " won!");
    winnerFound = true;
    }
    }
    //check columns
    for (let x = 0; x < 3; x += 1) {
    if (childContent(x) === childContent(x + 3) && childContent(x) === childContent(x + 6)) {
    alert(childContent(x)+ " won!");
    winnerFound = true;
    }
    }
    //check diagonals
    if (childContent(0) === childContent(4) && childContent(0) === childContent(8)) {
    alert(childContent(0)+ " won!");
    winnerFound = true;
    }
    if (childContent(2) === childContent(4) && childContent(2) === childContent(6)) {
    alert(childContent(2)+ " won!");
    winnerFound = true;
    }
    }

    function childContent(i) {
    if (children[i].childElementCount === 0) {
    return i;
    }
    return children[i].getElementsByTagName('div')[0].innerHTML;
    }

     body {
    background: lightgray;
    text-align: center;
    vertical-align: middle;
    }

    .child:hover {
    background-color: darkgrey;
    }

    .parent {
    display: inline-flex;
    flex-wrap: wrap;
    width: 400px;
    }

    .child {
    flex: 1 0 calc(33% - 10px);
    margin: 5px;
    height: 80px;
    background-color: grey;
    }

    .animate {
    animation: changeColor 0.5s forwards;
    }

    @keyframes changeColor {
    0% {
    background-color: darkgrey;
    }
    100% {
    background-color: khaki;
    font-size: 60px;
    }
    }

    <div>
    <h1>Tic Tac Toe</h1>
    <h2>It is now the turn of: <span id="turn"></span></h2>
    <button id="clear">CLEAR</button>
    </div>
    <div class="parent">
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    </div>












    share|improve this question
























      up vote
      3
      down vote

      favorite









      up vote
      3
      down vote

      favorite











      I just completed some beginner web-dev courses (cs:50 and such) and wanted to try my skills.



      The CSS centering - ugh I just gave up on that, I wanted to make it responsive and the letters centered perfectly, but whatever...



      So overall, how is this coded? is there a better way to code this?






      let turn = true;
      let children;
      let winnerFound = false;

      document.addEventListener('DOMContentLoaded', load);

      function load() {
      children = document.getElementsByClassName("child");
      for (let i = 0; i < children.length; i++) {
      children[i].addEventListener("click", function () {
      clicked(i);
      });
      }
      document.getElementById("clear").addEventListener("click", function () {
      clearBoard();
      }
      );
      updateTurn();
      }

      function clearBoard() {
      for (let i = 0; i < children.length; i++) {
      children[i].innerHTML = '';
      children[i].classList.remove('animate');
      }
      turn = true;
      winnerFound = false;
      updateTurn();
      }

      //text at the top
      function updateTurn() {
      if (turn)
      document.getElementById("turn").innerHTML = "X";
      else
      document.getElementById("turn").innerHTML = "O";
      }

      function clicked(i) {
      if (winnerFound)
      return;
      if (children[i].childElementCount !== 0)
      return;
      const div = document.createElement('div');
      if (turn) {
      div.textContent = 'X';
      }
      else {
      div.textContent = 'O';
      }
      children[i].appendChild(div);
      children[i].classList.add('animate');
      turn = !turn;
      checkWinner();
      updateTurn();
      }

      function checkWinner() {
      //check rows
      for (let x = 0; x < 9; x += 3) {
      if (childContent(x) === childContent(x + 1) && childContent(x) === childContent(x + 2)) {
      alert(childContent(x) + " won!");
      winnerFound = true;
      }
      }
      //check columns
      for (let x = 0; x < 3; x += 1) {
      if (childContent(x) === childContent(x + 3) && childContent(x) === childContent(x + 6)) {
      alert(childContent(x)+ " won!");
      winnerFound = true;
      }
      }
      //check diagonals
      if (childContent(0) === childContent(4) && childContent(0) === childContent(8)) {
      alert(childContent(0)+ " won!");
      winnerFound = true;
      }
      if (childContent(2) === childContent(4) && childContent(2) === childContent(6)) {
      alert(childContent(2)+ " won!");
      winnerFound = true;
      }
      }

      function childContent(i) {
      if (children[i].childElementCount === 0) {
      return i;
      }
      return children[i].getElementsByTagName('div')[0].innerHTML;
      }

       body {
      background: lightgray;
      text-align: center;
      vertical-align: middle;
      }

      .child:hover {
      background-color: darkgrey;
      }

      .parent {
      display: inline-flex;
      flex-wrap: wrap;
      width: 400px;
      }

      .child {
      flex: 1 0 calc(33% - 10px);
      margin: 5px;
      height: 80px;
      background-color: grey;
      }

      .animate {
      animation: changeColor 0.5s forwards;
      }

      @keyframes changeColor {
      0% {
      background-color: darkgrey;
      }
      100% {
      background-color: khaki;
      font-size: 60px;
      }
      }

      <div>
      <h1>Tic Tac Toe</h1>
      <h2>It is now the turn of: <span id="turn"></span></h2>
      <button id="clear">CLEAR</button>
      </div>
      <div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      </div>












      share|improve this question













      I just completed some beginner web-dev courses (cs:50 and such) and wanted to try my skills.



      The CSS centering - ugh I just gave up on that, I wanted to make it responsive and the letters centered perfectly, but whatever...



      So overall, how is this coded? is there a better way to code this?






      let turn = true;
      let children;
      let winnerFound = false;

      document.addEventListener('DOMContentLoaded', load);

      function load() {
      children = document.getElementsByClassName("child");
      for (let i = 0; i < children.length; i++) {
      children[i].addEventListener("click", function () {
      clicked(i);
      });
      }
      document.getElementById("clear").addEventListener("click", function () {
      clearBoard();
      }
      );
      updateTurn();
      }

      function clearBoard() {
      for (let i = 0; i < children.length; i++) {
      children[i].innerHTML = '';
      children[i].classList.remove('animate');
      }
      turn = true;
      winnerFound = false;
      updateTurn();
      }

      //text at the top
      function updateTurn() {
      if (turn)
      document.getElementById("turn").innerHTML = "X";
      else
      document.getElementById("turn").innerHTML = "O";
      }

      function clicked(i) {
      if (winnerFound)
      return;
      if (children[i].childElementCount !== 0)
      return;
      const div = document.createElement('div');
      if (turn) {
      div.textContent = 'X';
      }
      else {
      div.textContent = 'O';
      }
      children[i].appendChild(div);
      children[i].classList.add('animate');
      turn = !turn;
      checkWinner();
      updateTurn();
      }

      function checkWinner() {
      //check rows
      for (let x = 0; x < 9; x += 3) {
      if (childContent(x) === childContent(x + 1) && childContent(x) === childContent(x + 2)) {
      alert(childContent(x) + " won!");
      winnerFound = true;
      }
      }
      //check columns
      for (let x = 0; x < 3; x += 1) {
      if (childContent(x) === childContent(x + 3) && childContent(x) === childContent(x + 6)) {
      alert(childContent(x)+ " won!");
      winnerFound = true;
      }
      }
      //check diagonals
      if (childContent(0) === childContent(4) && childContent(0) === childContent(8)) {
      alert(childContent(0)+ " won!");
      winnerFound = true;
      }
      if (childContent(2) === childContent(4) && childContent(2) === childContent(6)) {
      alert(childContent(2)+ " won!");
      winnerFound = true;
      }
      }

      function childContent(i) {
      if (children[i].childElementCount === 0) {
      return i;
      }
      return children[i].getElementsByTagName('div')[0].innerHTML;
      }

       body {
      background: lightgray;
      text-align: center;
      vertical-align: middle;
      }

      .child:hover {
      background-color: darkgrey;
      }

      .parent {
      display: inline-flex;
      flex-wrap: wrap;
      width: 400px;
      }

      .child {
      flex: 1 0 calc(33% - 10px);
      margin: 5px;
      height: 80px;
      background-color: grey;
      }

      .animate {
      animation: changeColor 0.5s forwards;
      }

      @keyframes changeColor {
      0% {
      background-color: darkgrey;
      }
      100% {
      background-color: khaki;
      font-size: 60px;
      }
      }

      <div>
      <h1>Tic Tac Toe</h1>
      <h2>It is now the turn of: <span id="turn"></span></h2>
      <button id="clear">CLEAR</button>
      </div>
      <div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      </div>








      let turn = true;
      let children;
      let winnerFound = false;

      document.addEventListener('DOMContentLoaded', load);

      function load() {
      children = document.getElementsByClassName("child");
      for (let i = 0; i < children.length; i++) {
      children[i].addEventListener("click", function () {
      clicked(i);
      });
      }
      document.getElementById("clear").addEventListener("click", function () {
      clearBoard();
      }
      );
      updateTurn();
      }

      function clearBoard() {
      for (let i = 0; i < children.length; i++) {
      children[i].innerHTML = '';
      children[i].classList.remove('animate');
      }
      turn = true;
      winnerFound = false;
      updateTurn();
      }

      //text at the top
      function updateTurn() {
      if (turn)
      document.getElementById("turn").innerHTML = "X";
      else
      document.getElementById("turn").innerHTML = "O";
      }

      function clicked(i) {
      if (winnerFound)
      return;
      if (children[i].childElementCount !== 0)
      return;
      const div = document.createElement('div');
      if (turn) {
      div.textContent = 'X';
      }
      else {
      div.textContent = 'O';
      }
      children[i].appendChild(div);
      children[i].classList.add('animate');
      turn = !turn;
      checkWinner();
      updateTurn();
      }

      function checkWinner() {
      //check rows
      for (let x = 0; x < 9; x += 3) {
      if (childContent(x) === childContent(x + 1) && childContent(x) === childContent(x + 2)) {
      alert(childContent(x) + " won!");
      winnerFound = true;
      }
      }
      //check columns
      for (let x = 0; x < 3; x += 1) {
      if (childContent(x) === childContent(x + 3) && childContent(x) === childContent(x + 6)) {
      alert(childContent(x)+ " won!");
      winnerFound = true;
      }
      }
      //check diagonals
      if (childContent(0) === childContent(4) && childContent(0) === childContent(8)) {
      alert(childContent(0)+ " won!");
      winnerFound = true;
      }
      if (childContent(2) === childContent(4) && childContent(2) === childContent(6)) {
      alert(childContent(2)+ " won!");
      winnerFound = true;
      }
      }

      function childContent(i) {
      if (children[i].childElementCount === 0) {
      return i;
      }
      return children[i].getElementsByTagName('div')[0].innerHTML;
      }

       body {
      background: lightgray;
      text-align: center;
      vertical-align: middle;
      }

      .child:hover {
      background-color: darkgrey;
      }

      .parent {
      display: inline-flex;
      flex-wrap: wrap;
      width: 400px;
      }

      .child {
      flex: 1 0 calc(33% - 10px);
      margin: 5px;
      height: 80px;
      background-color: grey;
      }

      .animate {
      animation: changeColor 0.5s forwards;
      }

      @keyframes changeColor {
      0% {
      background-color: darkgrey;
      }
      100% {
      background-color: khaki;
      font-size: 60px;
      }
      }

      <div>
      <h1>Tic Tac Toe</h1>
      <h2>It is now the turn of: <span id="turn"></span></h2>
      <button id="clear">CLEAR</button>
      </div>
      <div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      </div>





      let turn = true;
      let children;
      let winnerFound = false;

      document.addEventListener('DOMContentLoaded', load);

      function load() {
      children = document.getElementsByClassName("child");
      for (let i = 0; i < children.length; i++) {
      children[i].addEventListener("click", function () {
      clicked(i);
      });
      }
      document.getElementById("clear").addEventListener("click", function () {
      clearBoard();
      }
      );
      updateTurn();
      }

      function clearBoard() {
      for (let i = 0; i < children.length; i++) {
      children[i].innerHTML = '';
      children[i].classList.remove('animate');
      }
      turn = true;
      winnerFound = false;
      updateTurn();
      }

      //text at the top
      function updateTurn() {
      if (turn)
      document.getElementById("turn").innerHTML = "X";
      else
      document.getElementById("turn").innerHTML = "O";
      }

      function clicked(i) {
      if (winnerFound)
      return;
      if (children[i].childElementCount !== 0)
      return;
      const div = document.createElement('div');
      if (turn) {
      div.textContent = 'X';
      }
      else {
      div.textContent = 'O';
      }
      children[i].appendChild(div);
      children[i].classList.add('animate');
      turn = !turn;
      checkWinner();
      updateTurn();
      }

      function checkWinner() {
      //check rows
      for (let x = 0; x < 9; x += 3) {
      if (childContent(x) === childContent(x + 1) && childContent(x) === childContent(x + 2)) {
      alert(childContent(x) + " won!");
      winnerFound = true;
      }
      }
      //check columns
      for (let x = 0; x < 3; x += 1) {
      if (childContent(x) === childContent(x + 3) && childContent(x) === childContent(x + 6)) {
      alert(childContent(x)+ " won!");
      winnerFound = true;
      }
      }
      //check diagonals
      if (childContent(0) === childContent(4) && childContent(0) === childContent(8)) {
      alert(childContent(0)+ " won!");
      winnerFound = true;
      }
      if (childContent(2) === childContent(4) && childContent(2) === childContent(6)) {
      alert(childContent(2)+ " won!");
      winnerFound = true;
      }
      }

      function childContent(i) {
      if (children[i].childElementCount === 0) {
      return i;
      }
      return children[i].getElementsByTagName('div')[0].innerHTML;
      }

       body {
      background: lightgray;
      text-align: center;
      vertical-align: middle;
      }

      .child:hover {
      background-color: darkgrey;
      }

      .parent {
      display: inline-flex;
      flex-wrap: wrap;
      width: 400px;
      }

      .child {
      flex: 1 0 calc(33% - 10px);
      margin: 5px;
      height: 80px;
      background-color: grey;
      }

      .animate {
      animation: changeColor 0.5s forwards;
      }

      @keyframes changeColor {
      0% {
      background-color: darkgrey;
      }
      100% {
      background-color: khaki;
      font-size: 60px;
      }
      }

      <div>
      <h1>Tic Tac Toe</h1>
      <h2>It is now the turn of: <span id="turn"></span></h2>
      <button id="clear">CLEAR</button>
      </div>
      <div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      </div>






      javascript beginner css






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 16 at 22:16









      John Mc

      162




      162






















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          4
          down vote













          Review



          Not bad for a beginner and welcome to the world of programing.



          As you are new to coding I will just focus on one aspect of your code. The naming (which is very poor). There are many other things that I had to resist changing, but did not want to overwhelm you with the technicalities of client side Javascript, CSS, DOM, and markup.



          Naming




          • Naming is very important, it gives meaning to code, data, and how it relates to the abstract concepts that make up a project. Bad naming will result in hard to read code, ambiguity and bugs.

          • Good naming is not easy and takes time to learn by experience and example. (Read other peoples code and pay attention to how they name things).

          • Good naming does not name what something is, but what it represents in the current context of the code.

          • Good naming means you don't have to fill your code with comments to explain what can not be deduced from the code. Though you have done well in your comments :)


          Some specific name examples.



          You have the variable children. Yes it is a list of children, that can be worked out by looking at how you declare its content, but in a bigger project there will be many children. The name does not represent what abstractly it holds, and that is board positions. If I ask What are the positions in a game of Tic Tac Toe?, you know what that means, as opposed to What are the children in a game of Tic Tac Toe? whaa! I have renamed children to positions



          You have done the same in the CSS and markup. The classes .child, .parent .animate have no connection to the abstraction of Tic Tac Toe. Better name may be .child is .position, .parent is .board, .animate is .playerMoved



          Most of the function names are good with the exception of childContent and clicked. Better names could be childContent as getPositonContent (as you use this function a lot in checkWinner a better name is getPos so that the code is not cluttered with a long name) and clicked as playerMove



          Refactoring your code.



          The rewrite is mostly just renaming the many poor names you used. There are also a few minor code changes. BTW the names I picked may not be what you would have used to represent the various abstracts, they are just examples.





          • turnDisplay created in load so you dont have to query the DOM each time.


          • playerMove gets the position element rather than the index.

          • The listener for clear is passed the function directly rather than use the indirect call addEventListener("click", function() { clearBoard() })

          • Changed some innerHTML references to textContent





          let turn = true;
          let positions, turnDisplay;
          let winnerFound = false;


          document.addEventListener('DOMContentLoaded', load);

          function load() {
          positions = document.getElementsByClassName("position");
          turnDisplay = document.getElementById("turnDisplay");
          for (let i = 0; i < positions.length; i++) {
          positions[i].addEventListener("click", function() {
          playerMove(positions[i])
          });
          }
          document.getElementById("clear").addEventListener("click", clearBoard);
          displayTurn();
          }

          function clearBoard() {
          for (let i = 0; i < positions.length; i++) {
          positions[i].innerHTML = '';
          positions[i].classList.remove('playerMoved');
          }
          turn = true;
          winnerFound = false;
          displayTurn();
          }

          function displayTurn() {
          if (turn) {
          turnDisplay.textContent = "X";
          } else {
          turnDisplay.textContent = "O";
          }
          }

          function playerMove(position) {
          if (winnerFound) {
          return
          }
          if (position.childElementCount !== 0) {
          return
          }
          const mark = document.createElement('div');
          if (turn) {
          mark.textContent = 'X'
          } else {
          mark.textContent = 'O'
          }
          position.appendChild(mark);
          position.classList.add('playerMoved');
          turn = !turn;
          checkWinner();
          displayTurn();
          }

          function checkWinner() {
          for (let x = 0; x < 9; x += 3) {
          if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          for (let x = 0; x < 3; x += 1) {
          if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
          alert(getPos(0) + " won!");
          winnerFound = true;
          }
          if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
          alert(getPos(2) + " won!");
          winnerFound = true;
          }
          }

          function getPos(index) {
          if (positions[index].childElementCount === 0) {
          return index
          }
          return positions[index].textContent;
          }

          body {
          background: lightgray;
          text-align: center;
          vertical-align: middle;
          }

          .position:hover {
          background-color: darkgrey;
          }

          .board {
          display: inline-flex;
          flex-wrap: wrap;
          width: 400px;
          }

          .position {
          flex: 1 0 calc(33% - 10px);
          margin: 5px;
          height: 80px;
          background-color: grey;
          }

          .playerMoved {
          animation: changeColor 0.5s forwards;
          }

          @keyframes changeColor {
          0% {
          background-color: darkgrey;
          }
          100% {
          background-color: khaki;
          font-size: 60px;
          }
          }

          <div>
          <h1>Tic Tac Toe</h1>
          <h2>It is now the turn of: <span id="turnDisplay"></span></h2>
          <button id="clear">CLEAR</button>
          </div>
          <div class="board">
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          </div>





          Note: the above example is just concerned with naming, and does not represent an ideal code example. The idea was to keep as close to the OP's original code as possible.






          share|improve this answer





















          • Thanks for taking the time to look at my code. Those are very useful tips. Going forward, I will learn some JS Framework (React or Vue I was thinking) so I won't have problems with updating the DOM.
            – John Mc
            Nov 17 at 23:07











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207842%2fmy-first-js-program-tic-tac-toe-game%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          4
          down vote













          Review



          Not bad for a beginner and welcome to the world of programing.



          As you are new to coding I will just focus on one aspect of your code. The naming (which is very poor). There are many other things that I had to resist changing, but did not want to overwhelm you with the technicalities of client side Javascript, CSS, DOM, and markup.



          Naming




          • Naming is very important, it gives meaning to code, data, and how it relates to the abstract concepts that make up a project. Bad naming will result in hard to read code, ambiguity and bugs.

          • Good naming is not easy and takes time to learn by experience and example. (Read other peoples code and pay attention to how they name things).

          • Good naming does not name what something is, but what it represents in the current context of the code.

          • Good naming means you don't have to fill your code with comments to explain what can not be deduced from the code. Though you have done well in your comments :)


          Some specific name examples.



          You have the variable children. Yes it is a list of children, that can be worked out by looking at how you declare its content, but in a bigger project there will be many children. The name does not represent what abstractly it holds, and that is board positions. If I ask What are the positions in a game of Tic Tac Toe?, you know what that means, as opposed to What are the children in a game of Tic Tac Toe? whaa! I have renamed children to positions



          You have done the same in the CSS and markup. The classes .child, .parent .animate have no connection to the abstraction of Tic Tac Toe. Better name may be .child is .position, .parent is .board, .animate is .playerMoved



          Most of the function names are good with the exception of childContent and clicked. Better names could be childContent as getPositonContent (as you use this function a lot in checkWinner a better name is getPos so that the code is not cluttered with a long name) and clicked as playerMove



          Refactoring your code.



          The rewrite is mostly just renaming the many poor names you used. There are also a few minor code changes. BTW the names I picked may not be what you would have used to represent the various abstracts, they are just examples.





          • turnDisplay created in load so you dont have to query the DOM each time.


          • playerMove gets the position element rather than the index.

          • The listener for clear is passed the function directly rather than use the indirect call addEventListener("click", function() { clearBoard() })

          • Changed some innerHTML references to textContent





          let turn = true;
          let positions, turnDisplay;
          let winnerFound = false;


          document.addEventListener('DOMContentLoaded', load);

          function load() {
          positions = document.getElementsByClassName("position");
          turnDisplay = document.getElementById("turnDisplay");
          for (let i = 0; i < positions.length; i++) {
          positions[i].addEventListener("click", function() {
          playerMove(positions[i])
          });
          }
          document.getElementById("clear").addEventListener("click", clearBoard);
          displayTurn();
          }

          function clearBoard() {
          for (let i = 0; i < positions.length; i++) {
          positions[i].innerHTML = '';
          positions[i].classList.remove('playerMoved');
          }
          turn = true;
          winnerFound = false;
          displayTurn();
          }

          function displayTurn() {
          if (turn) {
          turnDisplay.textContent = "X";
          } else {
          turnDisplay.textContent = "O";
          }
          }

          function playerMove(position) {
          if (winnerFound) {
          return
          }
          if (position.childElementCount !== 0) {
          return
          }
          const mark = document.createElement('div');
          if (turn) {
          mark.textContent = 'X'
          } else {
          mark.textContent = 'O'
          }
          position.appendChild(mark);
          position.classList.add('playerMoved');
          turn = !turn;
          checkWinner();
          displayTurn();
          }

          function checkWinner() {
          for (let x = 0; x < 9; x += 3) {
          if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          for (let x = 0; x < 3; x += 1) {
          if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
          alert(getPos(0) + " won!");
          winnerFound = true;
          }
          if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
          alert(getPos(2) + " won!");
          winnerFound = true;
          }
          }

          function getPos(index) {
          if (positions[index].childElementCount === 0) {
          return index
          }
          return positions[index].textContent;
          }

          body {
          background: lightgray;
          text-align: center;
          vertical-align: middle;
          }

          .position:hover {
          background-color: darkgrey;
          }

          .board {
          display: inline-flex;
          flex-wrap: wrap;
          width: 400px;
          }

          .position {
          flex: 1 0 calc(33% - 10px);
          margin: 5px;
          height: 80px;
          background-color: grey;
          }

          .playerMoved {
          animation: changeColor 0.5s forwards;
          }

          @keyframes changeColor {
          0% {
          background-color: darkgrey;
          }
          100% {
          background-color: khaki;
          font-size: 60px;
          }
          }

          <div>
          <h1>Tic Tac Toe</h1>
          <h2>It is now the turn of: <span id="turnDisplay"></span></h2>
          <button id="clear">CLEAR</button>
          </div>
          <div class="board">
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          </div>





          Note: the above example is just concerned with naming, and does not represent an ideal code example. The idea was to keep as close to the OP's original code as possible.






          share|improve this answer





















          • Thanks for taking the time to look at my code. Those are very useful tips. Going forward, I will learn some JS Framework (React or Vue I was thinking) so I won't have problems with updating the DOM.
            – John Mc
            Nov 17 at 23:07















          up vote
          4
          down vote













          Review



          Not bad for a beginner and welcome to the world of programing.



          As you are new to coding I will just focus on one aspect of your code. The naming (which is very poor). There are many other things that I had to resist changing, but did not want to overwhelm you with the technicalities of client side Javascript, CSS, DOM, and markup.



          Naming




          • Naming is very important, it gives meaning to code, data, and how it relates to the abstract concepts that make up a project. Bad naming will result in hard to read code, ambiguity and bugs.

          • Good naming is not easy and takes time to learn by experience and example. (Read other peoples code and pay attention to how they name things).

          • Good naming does not name what something is, but what it represents in the current context of the code.

          • Good naming means you don't have to fill your code with comments to explain what can not be deduced from the code. Though you have done well in your comments :)


          Some specific name examples.



          You have the variable children. Yes it is a list of children, that can be worked out by looking at how you declare its content, but in a bigger project there will be many children. The name does not represent what abstractly it holds, and that is board positions. If I ask What are the positions in a game of Tic Tac Toe?, you know what that means, as opposed to What are the children in a game of Tic Tac Toe? whaa! I have renamed children to positions



          You have done the same in the CSS and markup. The classes .child, .parent .animate have no connection to the abstraction of Tic Tac Toe. Better name may be .child is .position, .parent is .board, .animate is .playerMoved



          Most of the function names are good with the exception of childContent and clicked. Better names could be childContent as getPositonContent (as you use this function a lot in checkWinner a better name is getPos so that the code is not cluttered with a long name) and clicked as playerMove



          Refactoring your code.



          The rewrite is mostly just renaming the many poor names you used. There are also a few minor code changes. BTW the names I picked may not be what you would have used to represent the various abstracts, they are just examples.





          • turnDisplay created in load so you dont have to query the DOM each time.


          • playerMove gets the position element rather than the index.

          • The listener for clear is passed the function directly rather than use the indirect call addEventListener("click", function() { clearBoard() })

          • Changed some innerHTML references to textContent





          let turn = true;
          let positions, turnDisplay;
          let winnerFound = false;


          document.addEventListener('DOMContentLoaded', load);

          function load() {
          positions = document.getElementsByClassName("position");
          turnDisplay = document.getElementById("turnDisplay");
          for (let i = 0; i < positions.length; i++) {
          positions[i].addEventListener("click", function() {
          playerMove(positions[i])
          });
          }
          document.getElementById("clear").addEventListener("click", clearBoard);
          displayTurn();
          }

          function clearBoard() {
          for (let i = 0; i < positions.length; i++) {
          positions[i].innerHTML = '';
          positions[i].classList.remove('playerMoved');
          }
          turn = true;
          winnerFound = false;
          displayTurn();
          }

          function displayTurn() {
          if (turn) {
          turnDisplay.textContent = "X";
          } else {
          turnDisplay.textContent = "O";
          }
          }

          function playerMove(position) {
          if (winnerFound) {
          return
          }
          if (position.childElementCount !== 0) {
          return
          }
          const mark = document.createElement('div');
          if (turn) {
          mark.textContent = 'X'
          } else {
          mark.textContent = 'O'
          }
          position.appendChild(mark);
          position.classList.add('playerMoved');
          turn = !turn;
          checkWinner();
          displayTurn();
          }

          function checkWinner() {
          for (let x = 0; x < 9; x += 3) {
          if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          for (let x = 0; x < 3; x += 1) {
          if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
          alert(getPos(0) + " won!");
          winnerFound = true;
          }
          if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
          alert(getPos(2) + " won!");
          winnerFound = true;
          }
          }

          function getPos(index) {
          if (positions[index].childElementCount === 0) {
          return index
          }
          return positions[index].textContent;
          }

          body {
          background: lightgray;
          text-align: center;
          vertical-align: middle;
          }

          .position:hover {
          background-color: darkgrey;
          }

          .board {
          display: inline-flex;
          flex-wrap: wrap;
          width: 400px;
          }

          .position {
          flex: 1 0 calc(33% - 10px);
          margin: 5px;
          height: 80px;
          background-color: grey;
          }

          .playerMoved {
          animation: changeColor 0.5s forwards;
          }

          @keyframes changeColor {
          0% {
          background-color: darkgrey;
          }
          100% {
          background-color: khaki;
          font-size: 60px;
          }
          }

          <div>
          <h1>Tic Tac Toe</h1>
          <h2>It is now the turn of: <span id="turnDisplay"></span></h2>
          <button id="clear">CLEAR</button>
          </div>
          <div class="board">
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          </div>





          Note: the above example is just concerned with naming, and does not represent an ideal code example. The idea was to keep as close to the OP's original code as possible.






          share|improve this answer





















          • Thanks for taking the time to look at my code. Those are very useful tips. Going forward, I will learn some JS Framework (React or Vue I was thinking) so I won't have problems with updating the DOM.
            – John Mc
            Nov 17 at 23:07













          up vote
          4
          down vote










          up vote
          4
          down vote









          Review



          Not bad for a beginner and welcome to the world of programing.



          As you are new to coding I will just focus on one aspect of your code. The naming (which is very poor). There are many other things that I had to resist changing, but did not want to overwhelm you with the technicalities of client side Javascript, CSS, DOM, and markup.



          Naming




          • Naming is very important, it gives meaning to code, data, and how it relates to the abstract concepts that make up a project. Bad naming will result in hard to read code, ambiguity and bugs.

          • Good naming is not easy and takes time to learn by experience and example. (Read other peoples code and pay attention to how they name things).

          • Good naming does not name what something is, but what it represents in the current context of the code.

          • Good naming means you don't have to fill your code with comments to explain what can not be deduced from the code. Though you have done well in your comments :)


          Some specific name examples.



          You have the variable children. Yes it is a list of children, that can be worked out by looking at how you declare its content, but in a bigger project there will be many children. The name does not represent what abstractly it holds, and that is board positions. If I ask What are the positions in a game of Tic Tac Toe?, you know what that means, as opposed to What are the children in a game of Tic Tac Toe? whaa! I have renamed children to positions



          You have done the same in the CSS and markup. The classes .child, .parent .animate have no connection to the abstraction of Tic Tac Toe. Better name may be .child is .position, .parent is .board, .animate is .playerMoved



          Most of the function names are good with the exception of childContent and clicked. Better names could be childContent as getPositonContent (as you use this function a lot in checkWinner a better name is getPos so that the code is not cluttered with a long name) and clicked as playerMove



          Refactoring your code.



          The rewrite is mostly just renaming the many poor names you used. There are also a few minor code changes. BTW the names I picked may not be what you would have used to represent the various abstracts, they are just examples.





          • turnDisplay created in load so you dont have to query the DOM each time.


          • playerMove gets the position element rather than the index.

          • The listener for clear is passed the function directly rather than use the indirect call addEventListener("click", function() { clearBoard() })

          • Changed some innerHTML references to textContent





          let turn = true;
          let positions, turnDisplay;
          let winnerFound = false;


          document.addEventListener('DOMContentLoaded', load);

          function load() {
          positions = document.getElementsByClassName("position");
          turnDisplay = document.getElementById("turnDisplay");
          for (let i = 0; i < positions.length; i++) {
          positions[i].addEventListener("click", function() {
          playerMove(positions[i])
          });
          }
          document.getElementById("clear").addEventListener("click", clearBoard);
          displayTurn();
          }

          function clearBoard() {
          for (let i = 0; i < positions.length; i++) {
          positions[i].innerHTML = '';
          positions[i].classList.remove('playerMoved');
          }
          turn = true;
          winnerFound = false;
          displayTurn();
          }

          function displayTurn() {
          if (turn) {
          turnDisplay.textContent = "X";
          } else {
          turnDisplay.textContent = "O";
          }
          }

          function playerMove(position) {
          if (winnerFound) {
          return
          }
          if (position.childElementCount !== 0) {
          return
          }
          const mark = document.createElement('div');
          if (turn) {
          mark.textContent = 'X'
          } else {
          mark.textContent = 'O'
          }
          position.appendChild(mark);
          position.classList.add('playerMoved');
          turn = !turn;
          checkWinner();
          displayTurn();
          }

          function checkWinner() {
          for (let x = 0; x < 9; x += 3) {
          if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          for (let x = 0; x < 3; x += 1) {
          if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
          alert(getPos(0) + " won!");
          winnerFound = true;
          }
          if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
          alert(getPos(2) + " won!");
          winnerFound = true;
          }
          }

          function getPos(index) {
          if (positions[index].childElementCount === 0) {
          return index
          }
          return positions[index].textContent;
          }

          body {
          background: lightgray;
          text-align: center;
          vertical-align: middle;
          }

          .position:hover {
          background-color: darkgrey;
          }

          .board {
          display: inline-flex;
          flex-wrap: wrap;
          width: 400px;
          }

          .position {
          flex: 1 0 calc(33% - 10px);
          margin: 5px;
          height: 80px;
          background-color: grey;
          }

          .playerMoved {
          animation: changeColor 0.5s forwards;
          }

          @keyframes changeColor {
          0% {
          background-color: darkgrey;
          }
          100% {
          background-color: khaki;
          font-size: 60px;
          }
          }

          <div>
          <h1>Tic Tac Toe</h1>
          <h2>It is now the turn of: <span id="turnDisplay"></span></h2>
          <button id="clear">CLEAR</button>
          </div>
          <div class="board">
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          </div>





          Note: the above example is just concerned with naming, and does not represent an ideal code example. The idea was to keep as close to the OP's original code as possible.






          share|improve this answer












          Review



          Not bad for a beginner and welcome to the world of programing.



          As you are new to coding I will just focus on one aspect of your code. The naming (which is very poor). There are many other things that I had to resist changing, but did not want to overwhelm you with the technicalities of client side Javascript, CSS, DOM, and markup.



          Naming




          • Naming is very important, it gives meaning to code, data, and how it relates to the abstract concepts that make up a project. Bad naming will result in hard to read code, ambiguity and bugs.

          • Good naming is not easy and takes time to learn by experience and example. (Read other peoples code and pay attention to how they name things).

          • Good naming does not name what something is, but what it represents in the current context of the code.

          • Good naming means you don't have to fill your code with comments to explain what can not be deduced from the code. Though you have done well in your comments :)


          Some specific name examples.



          You have the variable children. Yes it is a list of children, that can be worked out by looking at how you declare its content, but in a bigger project there will be many children. The name does not represent what abstractly it holds, and that is board positions. If I ask What are the positions in a game of Tic Tac Toe?, you know what that means, as opposed to What are the children in a game of Tic Tac Toe? whaa! I have renamed children to positions



          You have done the same in the CSS and markup. The classes .child, .parent .animate have no connection to the abstraction of Tic Tac Toe. Better name may be .child is .position, .parent is .board, .animate is .playerMoved



          Most of the function names are good with the exception of childContent and clicked. Better names could be childContent as getPositonContent (as you use this function a lot in checkWinner a better name is getPos so that the code is not cluttered with a long name) and clicked as playerMove



          Refactoring your code.



          The rewrite is mostly just renaming the many poor names you used. There are also a few minor code changes. BTW the names I picked may not be what you would have used to represent the various abstracts, they are just examples.





          • turnDisplay created in load so you dont have to query the DOM each time.


          • playerMove gets the position element rather than the index.

          • The listener for clear is passed the function directly rather than use the indirect call addEventListener("click", function() { clearBoard() })

          • Changed some innerHTML references to textContent





          let turn = true;
          let positions, turnDisplay;
          let winnerFound = false;


          document.addEventListener('DOMContentLoaded', load);

          function load() {
          positions = document.getElementsByClassName("position");
          turnDisplay = document.getElementById("turnDisplay");
          for (let i = 0; i < positions.length; i++) {
          positions[i].addEventListener("click", function() {
          playerMove(positions[i])
          });
          }
          document.getElementById("clear").addEventListener("click", clearBoard);
          displayTurn();
          }

          function clearBoard() {
          for (let i = 0; i < positions.length; i++) {
          positions[i].innerHTML = '';
          positions[i].classList.remove('playerMoved');
          }
          turn = true;
          winnerFound = false;
          displayTurn();
          }

          function displayTurn() {
          if (turn) {
          turnDisplay.textContent = "X";
          } else {
          turnDisplay.textContent = "O";
          }
          }

          function playerMove(position) {
          if (winnerFound) {
          return
          }
          if (position.childElementCount !== 0) {
          return
          }
          const mark = document.createElement('div');
          if (turn) {
          mark.textContent = 'X'
          } else {
          mark.textContent = 'O'
          }
          position.appendChild(mark);
          position.classList.add('playerMoved');
          turn = !turn;
          checkWinner();
          displayTurn();
          }

          function checkWinner() {
          for (let x = 0; x < 9; x += 3) {
          if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          for (let x = 0; x < 3; x += 1) {
          if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
          alert(getPos(0) + " won!");
          winnerFound = true;
          }
          if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
          alert(getPos(2) + " won!");
          winnerFound = true;
          }
          }

          function getPos(index) {
          if (positions[index].childElementCount === 0) {
          return index
          }
          return positions[index].textContent;
          }

          body {
          background: lightgray;
          text-align: center;
          vertical-align: middle;
          }

          .position:hover {
          background-color: darkgrey;
          }

          .board {
          display: inline-flex;
          flex-wrap: wrap;
          width: 400px;
          }

          .position {
          flex: 1 0 calc(33% - 10px);
          margin: 5px;
          height: 80px;
          background-color: grey;
          }

          .playerMoved {
          animation: changeColor 0.5s forwards;
          }

          @keyframes changeColor {
          0% {
          background-color: darkgrey;
          }
          100% {
          background-color: khaki;
          font-size: 60px;
          }
          }

          <div>
          <h1>Tic Tac Toe</h1>
          <h2>It is now the turn of: <span id="turnDisplay"></span></h2>
          <button id="clear">CLEAR</button>
          </div>
          <div class="board">
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          </div>





          Note: the above example is just concerned with naming, and does not represent an ideal code example. The idea was to keep as close to the OP's original code as possible.






          let turn = true;
          let positions, turnDisplay;
          let winnerFound = false;


          document.addEventListener('DOMContentLoaded', load);

          function load() {
          positions = document.getElementsByClassName("position");
          turnDisplay = document.getElementById("turnDisplay");
          for (let i = 0; i < positions.length; i++) {
          positions[i].addEventListener("click", function() {
          playerMove(positions[i])
          });
          }
          document.getElementById("clear").addEventListener("click", clearBoard);
          displayTurn();
          }

          function clearBoard() {
          for (let i = 0; i < positions.length; i++) {
          positions[i].innerHTML = '';
          positions[i].classList.remove('playerMoved');
          }
          turn = true;
          winnerFound = false;
          displayTurn();
          }

          function displayTurn() {
          if (turn) {
          turnDisplay.textContent = "X";
          } else {
          turnDisplay.textContent = "O";
          }
          }

          function playerMove(position) {
          if (winnerFound) {
          return
          }
          if (position.childElementCount !== 0) {
          return
          }
          const mark = document.createElement('div');
          if (turn) {
          mark.textContent = 'X'
          } else {
          mark.textContent = 'O'
          }
          position.appendChild(mark);
          position.classList.add('playerMoved');
          turn = !turn;
          checkWinner();
          displayTurn();
          }

          function checkWinner() {
          for (let x = 0; x < 9; x += 3) {
          if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          for (let x = 0; x < 3; x += 1) {
          if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
          alert(getPos(0) + " won!");
          winnerFound = true;
          }
          if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
          alert(getPos(2) + " won!");
          winnerFound = true;
          }
          }

          function getPos(index) {
          if (positions[index].childElementCount === 0) {
          return index
          }
          return positions[index].textContent;
          }

          body {
          background: lightgray;
          text-align: center;
          vertical-align: middle;
          }

          .position:hover {
          background-color: darkgrey;
          }

          .board {
          display: inline-flex;
          flex-wrap: wrap;
          width: 400px;
          }

          .position {
          flex: 1 0 calc(33% - 10px);
          margin: 5px;
          height: 80px;
          background-color: grey;
          }

          .playerMoved {
          animation: changeColor 0.5s forwards;
          }

          @keyframes changeColor {
          0% {
          background-color: darkgrey;
          }
          100% {
          background-color: khaki;
          font-size: 60px;
          }
          }

          <div>
          <h1>Tic Tac Toe</h1>
          <h2>It is now the turn of: <span id="turnDisplay"></span></h2>
          <button id="clear">CLEAR</button>
          </div>
          <div class="board">
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          </div>





          let turn = true;
          let positions, turnDisplay;
          let winnerFound = false;


          document.addEventListener('DOMContentLoaded', load);

          function load() {
          positions = document.getElementsByClassName("position");
          turnDisplay = document.getElementById("turnDisplay");
          for (let i = 0; i < positions.length; i++) {
          positions[i].addEventListener("click", function() {
          playerMove(positions[i])
          });
          }
          document.getElementById("clear").addEventListener("click", clearBoard);
          displayTurn();
          }

          function clearBoard() {
          for (let i = 0; i < positions.length; i++) {
          positions[i].innerHTML = '';
          positions[i].classList.remove('playerMoved');
          }
          turn = true;
          winnerFound = false;
          displayTurn();
          }

          function displayTurn() {
          if (turn) {
          turnDisplay.textContent = "X";
          } else {
          turnDisplay.textContent = "O";
          }
          }

          function playerMove(position) {
          if (winnerFound) {
          return
          }
          if (position.childElementCount !== 0) {
          return
          }
          const mark = document.createElement('div');
          if (turn) {
          mark.textContent = 'X'
          } else {
          mark.textContent = 'O'
          }
          position.appendChild(mark);
          position.classList.add('playerMoved');
          turn = !turn;
          checkWinner();
          displayTurn();
          }

          function checkWinner() {
          for (let x = 0; x < 9; x += 3) {
          if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          for (let x = 0; x < 3; x += 1) {
          if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
          alert(getPos(x) + " won!");
          winnerFound = true;
          }
          }
          if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
          alert(getPos(0) + " won!");
          winnerFound = true;
          }
          if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
          alert(getPos(2) + " won!");
          winnerFound = true;
          }
          }

          function getPos(index) {
          if (positions[index].childElementCount === 0) {
          return index
          }
          return positions[index].textContent;
          }

          body {
          background: lightgray;
          text-align: center;
          vertical-align: middle;
          }

          .position:hover {
          background-color: darkgrey;
          }

          .board {
          display: inline-flex;
          flex-wrap: wrap;
          width: 400px;
          }

          .position {
          flex: 1 0 calc(33% - 10px);
          margin: 5px;
          height: 80px;
          background-color: grey;
          }

          .playerMoved {
          animation: changeColor 0.5s forwards;
          }

          @keyframes changeColor {
          0% {
          background-color: darkgrey;
          }
          100% {
          background-color: khaki;
          font-size: 60px;
          }
          }

          <div>
          <h1>Tic Tac Toe</h1>
          <h2>It is now the turn of: <span id="turnDisplay"></span></h2>
          <button id="clear">CLEAR</button>
          </div>
          <div class="board">
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          <div class="position"></div>
          </div>






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 17 at 6:12









          Blindman67

          6,5341521




          6,5341521












          • Thanks for taking the time to look at my code. Those are very useful tips. Going forward, I will learn some JS Framework (React or Vue I was thinking) so I won't have problems with updating the DOM.
            – John Mc
            Nov 17 at 23:07


















          • Thanks for taking the time to look at my code. Those are very useful tips. Going forward, I will learn some JS Framework (React or Vue I was thinking) so I won't have problems with updating the DOM.
            – John Mc
            Nov 17 at 23:07
















          Thanks for taking the time to look at my code. Those are very useful tips. Going forward, I will learn some JS Framework (React or Vue I was thinking) so I won't have problems with updating the DOM.
          – John Mc
          Nov 17 at 23:07




          Thanks for taking the time to look at my code. Those are very useful tips. Going forward, I will learn some JS Framework (React or Vue I was thinking) so I won't have problems with updating the DOM.
          – John Mc
          Nov 17 at 23:07


















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207842%2fmy-first-js-program-tic-tac-toe-game%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Сан-Квентин

          8-я гвардейская общевойсковая армия

          Алькесар