Chen
Chen

Reputation: 291

Onclick, the button moves down, why can that due to?

Whenever I click a button and the value is inputted, the values in the box goes down. I've tried changing some CSS but it doesn't work as I intend it to.

const game = (() => {
  const createPlayer = (name, marker, turn) => {
    return { name, marker, turn }
  }

  player1 = createPlayer('Player 1', "x", true)
  player2 = createPlayer('Player 2', "o", false)

  const gameBoard = () => {
    var gameBoard = []

    const movement = (e) => {
      if (player1.turn === true && e.target.textContent === "") {
        gameBoard[e.target.id] = player1.marker
        e.target.textContent = player1.marker
        player1.turn = false
      } else if (player1.turn === false && e.target.textContent === "") {
        gameBoard[e.target.id] = player2.marker
        e.target.textContent = player2.marker
        player1.turn = true
      }
      if (gameBoard["button-1"] === "x" && gameBoard["button-2"] === "x" && gameBoard["button-3"] === "x") {
        alert("perfect")
      } else if (gameBoard["button-4"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-6"] === "x") {
        alert("you win")
      } else if (gameBoard["button-7"] === "x" && gameBoard["button-8"] === "x" && gameBoard["button-9"] === "x") {
        alert("you win")
      } else if (gameBoard["button-1"] === "x" && gameBoard["button-4"] === "x" && gameBoard["button-7"] === "x") {
        alert("you win")
      } else if (gameBoard["button-2"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-8"] === "x") {
        alert("you win")
      } else if (gameBoard["button-3"] === "x" && gameBoard["button-6"] === "x" && gameBoard["button-9"] === "x") {
        alert("you win")
      } else if (gameBoard["button-1"] === "o" && gameBoard["button-2"] === "o" && gameBoard["button-3"] === "o") {
        alert("perfect")
      } else if (gameBoard["button-4"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-6"] === "o") {
        alert("you win")
      } else if (gameBoard["button-7"] === "o" && gameBoard["button-8"] === "o" && gameBoard["button-9"] === "o") {
        alert("you win")
      } else if (gameBoard["button-1"] === "o" && gameBoard["button-4"] === "o" && gameBoard["button-7"] === "o") {
        alert("you win")
      } else if (gameBoard["button-2"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-8"] === "o") {
        alert("you win")
      } else if (gameBoard["button-3"] === "o" && gameBoard["button-6"] === "o" && gameBoard["button-9"] === "o") {
        alert("you win")
      } else if (gameBoard["button-1"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-9"] === "o") {
        alert("you win")
      } else if (gameBoard["button-3"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-7"] === "o") {
        alert("you win")
      } else if (gameBoard["button-1"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-9"] === "x") {
        alert("you win")
      } else if (gameBoard["button-3"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-7"] === "x") {
        alert("you win")
      }

    }

    const board = document.querySelector('.item-board').addEventListener('click', movement)
  }

  gameBoard()
})

game()
.header {
  background-color: red;
  background-size: cover;
  width: 100%;
  height: 100%;
}
.item-board {
  margin-left: 200px;
  display: inline-block;
}
.TicTac {
  background-size: cover;
  width: 100%;
  height: 100%;
}
.btn-1 {
  width: 100px;
  height: 100px;
  border: 2px solid;
  margin: -2px;
  font-size: 4rem;
  padding: 0px;
}
p {
  font-size: 200px;
}
<header class="header">
  <h1 class="TicTac">Tic-Tac-Toe</h1>
</header>
<div class="item-board">
  <div class="item-board">
    <button type="button" name="button" id="button-1" class="btn-1"></button>
    <button type="button" name="button" id="button-2" class="btn-1"></button>
    <button type="button" name="button" id="button-3" class="btn-1"></button>
  </div>
  <div class="item-board">
    <button type="button" name="button" id="button-4" class="btn-1"></button>
    <button type="button" name="button" id="button-5" class="btn-1"></button>
    <button type="button" name="button" id="button-6" class="btn-1"></button>
  </div>
  <div class="item-board">
    <button type="button" name="button" id="button-7" class="btn-1"></button>
    <button type="button" name="button" id="button-8" class="btn-1"></button>
    <button type="button" name="button" id="button-9" class="btn-1"></button>
  </div>
</div>

I've tried changing some CSS but can't figure out how to make it so that it doesn't go down on each click.

Upvotes: 1

Views: 481

Answers (2)

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48630

Try using a grid layout for your board.

  • I cleaned-up the CSS so that it is easier to follow. I also made the players an array and added a turn counter.
  • The board element is now passed to the function.
  • Cell lookup is easier when using indicies.
  • Cells are now regular <div> elements.
  • The cell dataset (attributes) holds the marker reference.
  • The cell occupied check is also easier now.
  • Cell clicks are delegated by the board.

Hopefully this is much easier to understand. I tried to keep the general structure of your functions.

const game = ((el) => {
  const createPlayer = (name, marker) =>
    ({ name, marker });
  
  let turn = 0;
  const players = [
    createPlayer('Player 1', 'X'),
    createPlayer('Player 2', 'O')
  ];

  const gameBoard = () => {
    var gameBoard = [];
    
    const getCell = index => el.querySelector(`.cell:nth-child(${index + 1})`);
    const getCells = (...indicies) => indicies.map(getCell);
    const allOccupied = (marker, ...indicies) =>
      getCells(...indicies).every(cell => cell.dataset.marker === marker);

    const checkWin = ({ marker }) =>
          allOccupied(marker, 0, 1, 2)  /* horiz / top */
       || allOccupied(marker, 3, 4, 5)  /* horiz / middle */
       || allOccupied(marker, 5, 7, 8)  /* horiz / bottom */
       || allOccupied(marker, 0, 3, 6)  /* vert  / left */
       || allOccupied(marker, 1, 4, 7)  /* vert  / middle */
       || allOccupied(marker, 2, 5, 8)  /* vert  / right */
       || allOccupied(marker, 0, 4, 8)  /* diag  / negative */
       || allOccupied(marker, 2, 4, 6); /* diag  / positive */

    const delagateClick = (e) => {
      if (e.target.classList.contains('cell')) {
        handleMovement(e.target);
      }
    };
    
    const handleMovement = (cell) => {
      const player = players[turn % players.length];
      if (!cell.dataset.marker) {
        cell.dataset.marker = player.marker;
        cell.textContent = player.marker;
        if (checkWin(player)) {
          setTimeout(() => {
            alert(`${player.name} ("${player.marker}") wins`);
          }, 100);
        }
        turn++;
      }
    };

    el.addEventListener('click', delagateClick);
  }

  gameBoard()
})

game(document.querySelector('.board'));
html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

body {
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: Arial;
  background: #000;
  color: #EEE;
}

header {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #C33;
  background-size: cover;
  width: 100%;
  height: 4em;
}

header > div {
  font-size: 2em;
  font-weight: bold;
}

main {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  background: #222;
  width: 100%;
}

.board {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 0.25em;
  border: thin solid grey;
  background: #444;
  padding: 0.25em;
}

.cell {
  display: flex;
  width: 2em;
  height: 2em;
  border: thin solid grey;
  font-size: 2em;
  align-items: center;
  justify-content: center;
  background: #666;
  cursor: pointer;
}

.cell:not([data-marker]):hover {
  background: #888;
}

.cell[data-marker] {
  cursor: not-allowed;
}
<header>
  <div>Tic-Tac-Toe</div>
</header>
<main>
  <div class="board">
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
    <div class="cell"></div>
  </div>
</main>

Upvotes: 0

DBS
DBS

Reputation: 9984

Your .btn-1 styling is aligning the elements based on their text content, this can be solved by applying vertical-align: top; to that class.

Another small change that's worth making would be to change .item-board from inline-block to display: block, as that will prevent the width of the screen affecting whether the rows wrap.

const game = (() => {
  const createPlayer = (name, marker, turn) => {
    return { name, marker, turn }
  }

  player1 = createPlayer('Player 1', "x", true)
  player2 = createPlayer('Player 2', "o", false)

  const gameBoard = () => {
    var gameBoard = []

    const movement = (e) => {
      if (player1.turn === true && e.target.textContent === "") {
        gameBoard[e.target.id] = player1.marker
        e.target.textContent = player1.marker
        player1.turn = false
      } else if (player1.turn === false && e.target.textContent === "") {
        gameBoard[e.target.id] = player2.marker
        e.target.textContent = player2.marker
        player1.turn = true
      }
      if (gameBoard["button-1"] === "x" && gameBoard["button-2"] === "x" && gameBoard["button-3"] === "x") {
        alert("perfect")
      } else if (gameBoard["button-4"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-6"] === "x") {
        alert("you win")
      } else if (gameBoard["button-7"] === "x" && gameBoard["button-8"] === "x" && gameBoard["button-9"] === "x") {
        alert("you win")
      } else if (gameBoard["button-1"] === "x" && gameBoard["button-4"] === "x" && gameBoard["button-7"] === "x") {
        alert("you win")
      } else if (gameBoard["button-2"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-8"] === "x") {
        alert("you win")
      } else if (gameBoard["button-3"] === "x" && gameBoard["button-6"] === "x" && gameBoard["button-9"] === "x") {
        alert("you win")
      } else if (gameBoard["button-1"] === "o" && gameBoard["button-2"] === "o" && gameBoard["button-3"] === "o") {
        alert("perfect")
      } else if (gameBoard["button-4"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-6"] === "o") {
        alert("you win")
      } else if (gameBoard["button-7"] === "o" && gameBoard["button-8"] === "o" && gameBoard["button-9"] === "o") {
        alert("you win")
      } else if (gameBoard["button-1"] === "o" && gameBoard["button-4"] === "o" && gameBoard["button-7"] === "o") {
        alert("you win")
      } else if (gameBoard["button-2"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-8"] === "o") {
        alert("you win")
      } else if (gameBoard["button-3"] === "o" && gameBoard["button-6"] === "o" && gameBoard["button-9"] === "o") {
        alert("you win")
      } else if (gameBoard["button-1"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-9"] === "o") {
        alert("you win")
      } else if (gameBoard["button-3"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-7"] === "o") {
        alert("you win")
      } else if (gameBoard["button-1"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-9"] === "x") {
        alert("you win")
      } else if (gameBoard["button-3"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-7"] === "x") {
        alert("you win")
      }

    }

    const board = document.querySelector('.item-board').addEventListener('click', movement)
  }

  gameBoard()
})

game()
.header {
  background-color: red;
  background-size: cover;
  width: 100%;
  height: 100%;
}
.item-board {
  margin-left: 50px;
  display: block; /* This prevents the rows appearing on the same line on wide screens */
}
.TicTac {
  background-size: cover;
  width: 100%;
  height: 100%;
}
.btn-1 {
  width: 100px;
  height: 100px;
  border: 2px solid;
  margin: -2px;
  font-size: 4rem;
  padding: 0px;
  vertical-align: top; /* Top will fix the alignment issue when text content is added to the button */
}
p {
  font-size: 200px;
}
<header class="header">
  <h1 class="TicTac">Tic-Tac-Toe</h1>
</header>
<div class="item-board">
  <div class="item-board">
    <button type="button" name="button" id="button-1" class="btn-1"></button>
    <button type="button" name="button" id="button-2" class="btn-1"></button>
    <button type="button" name="button" id="button-3" class="btn-1"></button>
  </div>
  <div class="item-board">
    <button type="button" name="button" id="button-4" class="btn-1"></button>
    <button type="button" name="button" id="button-5" class="btn-1"></button>
    <button type="button" name="button" id="button-6" class="btn-1"></button>
  </div>
  <div class="item-board">
    <button type="button" name="button" id="button-7" class="btn-1"></button>
    <button type="button" name="button" id="button-8" class="btn-1"></button>
    <button type="button" name="button" id="button-9" class="btn-1"></button>
  </div>
</div>

Upvotes: 2

Related Questions