틱택토 part3

.·2021년 8월 6일
0
post-thumbnail

책에서 생각하는척하는 컴퓨터를 만들라는 미션이 있었고
내가 넣고싶은 기능을 조금 추가해줬는데 아주 골머리를 앓았다

추가 구현사항

  1. player1을 컴퓨터 또는 다른사람으로 선택할 수 있게 할것
  2. player1을 선택하면 랜덤으로 먼저 플레이할 사람을 정해줄것
  3. 언제든(게임중간이던 끝나던) replay-btn을 누르면 모두 reset해줄것

순서도를 그리지 않았다면 아마 아직까지도 어디가 잘못되었는지 모르는 상태로 무한 삽질을 하고 있었을 것이다

player1이 사람이 될 수도 컴퓨터가 될수도 있기에 어떻게 처리해 줄 것인지가 제일 문제였다

게임이 끝나면 현재플레이한 사람의 이름이 이겼다고 표시해 줘야 하기 때문에
currentPlayer라는 변수가 필요했다
하지만 player1이 컴퓨터인지, 사람인지에 따라서 바꿔줘야해서 어떻게 해줄것인지 계속 고민하다가 option의 value를 player1과 computer로 설정해 주고 select했을때 value를 playerOnebutton에 data속성을 이용하여 등록해 주었다

<option value="computer">computer</option>
option value="player1">another player</option>

$playerSelect.addEventListener("change", (e) => {
  const selectedValue = e.target.value;
  $playerOneName.textContent = changeFisrtLetterToCapital(selectedValue);
  $playerOneButton.setAttribute("data-who", selectedValue);
  $selectContainer.style.display = "none";
  selectFirstPlayerRandomly();
});

그리고 바로 누가 먼저 플레이할 것인지 랜덤으로 결정하는 함수를 실행시켜 주었다

const selectFirstPlayerRandomly = () => {
  $playerOneButton.classList.add("playing");
  classMoveIntervalId = setInterval(() => {
    $playerOneButton.classList.toggle("playing");
    $playerTwoButton.classList.toggle("playing");
  }, 100);
  randomTimer = setTimeout(() => {
    clearInterval(classMoveIntervalId);
    playing = true;
    currentPlayer = document.querySelector(".players .btn.playing").dataset.who;
    if (currentPlayer === "computer") {
      handleComputerMove();
      playing = false;
    }
  }, Math.random() * 300 + 1000);
};
  1. 첫번째 플레이어를 정할 때는 playing=false로 해서 클릭이벤트를 막는다
  2. 한버튼에 playing 클래스를 준다(둘중에 상관없다)
  3. 0.1초 간격으로 두버튼의 클래스를 toggle해주고 1~1.3초사이의 랜덤시간이 지나면 멈추게 해준다
  4. 멈췄을때 playing class를 가지고 있는 버튼을 이용하여(data-who 속성으로 찾아준다)currentPlayer에 할당해 준다
  5. 하지만 만약 currentPlayer가 computer이면 따로 처리를 해주고 아니면 player가 클릭할때까지 대기한다

컴퓨터 move 다루기

생각하는척하는 컴퓨터를 만들기 위해 setTimeOut을 이용해준다
filter method를 이용해서 비어있는 곳을 찾은뒤에 random으로 Index를 선택해준다
꼭 컴퓨터 턴이 끝난 뒤에 playing=true로 바꿔준다

const handleComputerMove = () => {
  computerTimer = setTimeout(() => {
    const emptyCells = gameBoard.flat().filter((cell) => !cell.textContent);
    const randomIndex = Math.floor(Math.random() * emptyCells.length);
    const randomCell = emptyCells[randomIndex];
    randomCell.textContent = mark[currentPlayer];
    const hasWinner = checkHasWinner(randomCell);
    if (hasWinner) {
      finishGame();
      return;
    }
    if (checkDraw()) {
      finishGame(isDraw);
      return;
    }
    changeTurn();
    playing = true;
  }, 1000);
};

턴 바꿔주기

const changeTurn = () => {
  $playerOneButton.classList.toggle("playing");
  $playerTwoButton.classList.toggle("playing");
  const currentButton = document.querySelector(".players .btn.playing");
  currentPlayer = currentButton.dataset.who;
  if (currentPlayer === "computer") handleComputerMove();
};
  1. playing 클래스가 있으면 없애주고 없으면 넣어준다
  2. 현재 playing 이라는 클래스가 있는 버튼을 찾아주고 currentPlayer를 변경해준다
  3. 턴바꿔 줄때마다 다음사람이 computer인지 확인해준다
const mark = { player1: "❌", computer: "❌", player2: "⭕️" };
  1. player1을 select 할 때 option의 value를 이용하여 buttonOne의 data-who 할당해주었다
  2. playing이라는 class를 button에 부여하여 querySelector로 찾아주고 data-who를 끄집어내어 currentPlayer에 할당해 주었다
  3. plyaer1은 사람또는 computer인데 자기 차례일 때 "❌"를 textContent에 표시해줘야 하므로 mark라는 object를 만들었다 그리고 mark[currentPlayer]로 사용해 주었다
    분명 더 효율적인 방법이 있을텐데 이게 나에겐 최선이었다

게임 reset하기

const resetGame = () => {
  playing = false;
  gameBoard.forEach((row) => row.forEach((cell) => (cell.textContent = "")));
  $result.textContent = "";
  $replayBtn.classList.remove("activate");
  $selectContainer.style.display = "block";
  $playerSelect.options.selectedIndex = 0;
  $playerOneButton.classList.remove("playing");
  $playerTwoButton.classList.remove("playing");
  clearInterval(classMoveIntervalId);
  clearTimeout(randomTimer);
  clearTimeout(computerTimer);
};

언제 replay-btn이 클릭될지 모르기 때문에 모든 setInterval과 setTimout을 clear해준다

개선해야 하는점

  1. 비기는 경우 finishGame에 인자로 boolean을 전달해주고 한번더 거쳐서 $showResult로 전달되는것 - > 파악하기 힘들 것같고 boolean을 전달하는게 별로 안좋다고 알고있다
  2. if(currentPlayer==="computer") 이 때 바로 string으로 비교하는게 별로 안좋은 것 같다
  3. 반복되는 코드
  • 드림코딩 브라우저 101강의를 다시 한번 살펴본 뒤에 코드를 개선해 봐야겠다

출처 Let's get it 자바스크립트 프로그래밍

profile
Divde & Conquer

0개의 댓글