[TIL] 210919

Lee Syong·2021년 9월 19일
0

TIL

목록 보기
32/204
post-thumbnail

📝 오늘 한 것

  1. 숫자 야구(Number Baseball) 게임 구현 시작

📚 배운 것

숫자 야구 게임


📌 요구 사항

  1. 게임 시작 버튼 만들기
  1. 게임 시작 버튼을 클릭 했을때, 랜덤한 세 자리 숫자 만들기 (사용자에게 보여주진 않습니다.)
  1. 숫자 입력칸 만들기

    3.1. 사용자가 엔터 키를 클릭 했을때, 입력값이 세 자리 숫자가 아닌 경우, 경고 창 띄워주기

    3.2. 사용자가 엔터키를 클릭 했을때, 2단계에서 생성한 숫자와 사용자의 입력값 비교하기

    • 각 자리 별로 비교하고, '같은 자리에 같은 숫자가 몇개 있는지' 판별합니다. (스트라이크 개수)
    • 각 자리 별로 비교하고, '다른 자리에 같은 숫자가 몇개 있는지' 판별합니다. (볼 개수)
  1. 화면에 스트라이크와 볼의 갯수를 표기합니다.
  1. 사용자가 10회까지 시도할 수 있도록 제한합니다.
  1. 게임 재시작 버튼을 만들고, 재시작 할 수 있도록 합니다.

단, 특이 케이스에 대한 대응은 하지 않아도 괜찮습니다. 예) 중복 숫자 등


📌 HTML 작성

밑에서 수정


<body>
  <section>
    
      <!-- 야구게임 Start -->
      <div class="box">
        <button class="box-start">START</button>
        <form class="box-field">
          <label for="box-field-input">숫자 입력칸 : </label>
          <input type="number" placeholder="세 자리 숫자 입력" id="box-field-input">
          <button type="button" class="box-field-enter">ENTER</button>
        </form>
        <div class="box-result"></div>
        <button class="box-restart">RESTART</button>
      </div>
      <!-- 야구게임 End -->
   </section>
</body>

📌 CSS 작성

밑에서 수정


* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

button {
  border: 1px solid black;
  background: transparent;
  cursor: pointer;
  border-radius: 5px;
  background-color: white;
}

body {
  padding: 80px;
}

section {
  max-width: 1000px;
  margin: 0 auto;
}

.box {
  text-align: center;
  margin: 40px;
  padding: 40px;
  border: 2px solid black;
  border-radius: 5px;
}

.box-start {
  margin: 20px;
  padding: 10px 20px;
}

.box-field {
  margin: 20px;
}

.box-field-enter {
  margin: 20px;
  padding: 3px 10px;
}

.box-result {
  border: 1px solid black;
  border-radius: 5px;
  background-color: white;
  height: 100px;
  margin: 40px;
  line-height: 5;
}

.box-restart {
  margin-bottom: 20px;
  padding: 10px 20px;
}

📌 javascript 작성


1. 첫 번째 요구 사항

게임 시작 버튼을 클릭했을때, 랜덤한 세 자리 숫자 만들기 (사용자에게 보여주진 않습니다.)

💡 Math.random()Math.floor() 사용

var start = document.querySelector('.box-start');

start.addEventListener('click', function () {
  var random = (Math.random() * (1000 - 0)) + 0;
  var natural = Math.floor(random);
  
  console.log(natural); // 31 (랜덤하게 출력)
});

💡 문제 발생

  • 항상 세 자리 숫자가 나와야 하는데 한 자리, 두 자리 수도 랜덤하게 나옴
    ex. 31 (x) / 031 (o)

💡 해결 방법 (수정한 코드)

  • 세 자리 숫자의 각 자리의 숫자를 따로 만들어서 문자열로 합침
var start = document.querySelector('.box-start');

start.addEventListener('click', function () {
  var naturalOne = Math.floor((Math.random() * (10 - 0)) + 0);
  var naturalTwo = Math.floor((Math.random() * (10 - 0)) + 0);
  var naturalThree = Math.floor((Math.random() * (10 - 0)) + 0);

  var randomString = `${naturalOne}${naturalTwo}${naturalThree}`;
  
  console.log(randomSring); // '040' (랜덤하게 출력) 
});

2. 두 번째 요구 사항

사용자가 엔터 키를 클릭 했을때, 입력 값이 세 자리 숫자가 아닌 경우(조건) 경고 창 띄워주기

💡 사용자가 input에 입력한 값을 변수에 할당

  • input에 입력한 값
    = querySelector를 이용해 선택한 input 요소의 value 속성
var enter = document.querySelector('.box-field-enter');
var userString = document.querySelector('#box-field-input');

enter.addEventListener('click', function () {
  if (userString.value === '2') { // 테스트를 위해 임의로 적은 조건
    alert('세 자리 숫자를 입력해야 합니다.');
  }
  
  console.log(userString.value); // 사용자가 input에 입력한 값
  console.log(typeof userString.value); // string
});

💡 문제 발생

  • 이벤트 리스너 안에 있는 if 구문의 조건을, 요구 사항에 맞게 바꿔야 한다

💡 해결 방법 (수정한 코드)

  • if (세 자리 수가 아니다) 를 구현해야 한다

  • type="number"인 input에 사용자가 입력한 값(userString.value)은 숫자가 아니라 string(문자열)이었다

  • 문자열은 길이 속성을 가지고, '문자열의 길이 = 문자열의 자리 수'이므로
    if (userString.value.length !== 3) 이라고 쓰면 된다

enter.addEventListener('click', function () {
  if (userString.value.length !== 3) { // 요구 사항에 따른 조건
    alert('세 자리 숫자를 입력해야 합니다.');
  }

3. 세 번째 요구 사항

사용자가 엔터 키를 클릭했을 때, '2단계에서 생성한 숫자'와 '사용자의 입력 값' 비교하기

  • 각 자리별로 비교하고, 같은 자리에 같은 숫자가 몇 개 있는지 판별합니다. (스트라이크 개수)
  • 각 자리별로 비교하고, 다른 자리에 같은 숫자가 몇 개 있는지 판별합니다. (볼 개수)

💡 문제 발생

  • ENTER 키 클릭 시 '랜덤 숫자'와 '사용자 입력 값'을 비교해야 한다

  • 이를 위해서는 ENTER 키 클릭 시 실행되는 이벤트 리스너에서, START 버튼 클릭 시 실행된 랜덤 숫자를 할당한 지역 변수에, 접근할 수 있어야 한다

💡 해결 방법

  • 직접적으로 해결하는 방법을 모르겠어서 꼼수를 썼다...

  • START 버튼을 눌렀을 때 랜덤 숫자를 만들고 끝내지 않고, 이를 p 요소의 innerText로 넣어준 후 CSS에서 p 요소가 보이지 않도록 display: none; 을 추가해 주었다

💡 여기까지 작성한 코드 정리

🔎 HTML

<body>
  <section>

    <!-- 야구게임 Start -->
    <div class="box">
      <button class="box-start">START</button>
      <form class="box-field">
        <label for="box-field-input">숫자 입력칸 : </label>
        <input type="number" placeholder="세 자리 숫자 입력" id="box-field-input">
        <button type="button" class="box-field-enter">ENTER</button>
      </form>
      <div class="box-result"></div>
      <button class="box-restart">RESTART</button>
    </div>
    <!-- 야구게임 End -->
  </section>
  
  <p class="hidden"></p>
</body>

🔎 CSS

// 아래 코드만 추가, 그 외 변화 없음

.hidden {
  display: none;
}

🔎 javascript

'use strict';

// 게임 시작 버튼 - 랜덤한 세 자리 숫자 (보이지 않게)
var start = document.querySelector('.box-start');
var hidden = document.querySelector('.hidden');

start.addEventListener('click', function () {
  var naturalOne = Math.floor((Math.random() * (10 - 0)) + 0);
  var naturalTwo = Math.floor((Math.random() * (10 - 0)) + 0);
  var naturalThree = Math.floor((Math.random() * (10 - 0)) + 0);

  var randomString = `${naturalOne}${naturalTwo}${naturalThree}`;

  hidden.innerText = randomString;
});

// 엔터 키 - 세 자리 숫자 x, 경고 창
var enter = document.querySelector('.box-field-enter');
var userString = document.querySelector('#box-field-input');

enter.addEventListener('click', function () {
  if (userString.value.length !== 3) {
    alert('세 자리 숫자를 입력해야 합니다.');
  }
});

// 엔터 키 - '랜덤 숫자' vs '입력 값' 비교, 볼/스트라이크 출력
// 나중에 위와 합칠 것, 지금은 요구 사항을 알아보기 쉽도록 따로 씀
enter.addEventListener('click', function () {
  // hidden.innerText(랜덤 숫자)는 string
  // userString.value(사용자 입력 값)도 string
  var random = hidden.innerText;
  var user = userString.value;
});

💡 다음 요구 사항

  • 2개의 문자열(랜덤 숫자 & 사용자 입력 값)을 각 자리별로 비교해서 스트라이크 개수와 볼 개수를 화면에 표시해야 함

💡 해결 방법

  • 숫자의 크기를 비교하기 위해 Number()를 이용해 2개의 문자열의 각 자리의 값을 숫자로 만든다.

  • 이들을 서로 비교하는 함수 9개를 만든다. 각각의 함수는 strike 혹은 ball을 return 한다.

  • 9개 함수의 return 값을 요소로 가지는 배열을 만든다.

  • array.filter()를 이용해 그 값이 strike인 배열의 요소들만을 모아 새로운 배열을 만들고, 여기에 length를 적용해 strike의 개수를 구한다. (ball의 개수도 동일하게 구한다.)

  • innerText 속성을 이용해 class가 box-result인 div에 strike와 ball의 개수를 표시한다

💡 작성한 코드

// 엔터 키 - '랜덤 숫자' vs '입력 값' 비교, 볼/스트라이크 출력
var result = document.querySelector('.box-result');

enter.addEventListener('click', function () {
  if (user.length !== 3) {
    alert('세 자리 숫자를 입력해야 합니다.');
  }
  
  // hidden.innerText(랜덤 숫자)는 string
  // userString.value(사용자 입력 값)도 string
  var random = hidden.innerText;
  var user = userString.value;

  var a = Number(random[0]);
  var b = Number(random[1]);
  var c = Number(random[2]);
  var x = Number(user[0]);
  var y = Number(user[1]);
  var z = Number(user[2]);

  function compareAX () {
    if (a === x) {
      return 'strike';
    }
  }

  function compareAY () {
    if (a === y) {
      return 'ball';
    }
  }

  function compareAZ () {
    if (a === z) {
      return 'ball';
    }
  }

  function compareBX () {
    if (b === x) {
      return 'ball';
    }
  }

  function compareBY () {
    if (b === y) {
      return 'strike';
    }
  }

  function compareBZ () {
    if (b === z) {
      return 'ball';
    }
  }

  function compareCX () {
    if (c === x) {
      return 'ball';
    }
  }

  function compareCY () {
    if (c === y) {
      return 'ball';
    }
  }

  function compareCZ () {
    if (c === z) {
      return 'strike';
    }
  }

  var array = [compareAX(), compareAY(), compareAZ(), compareBX(), compareBY(), compareBZ(), compareCX(), compareCY(), compareCZ()];

  var strikeCount = array.filter(e => e === 'strike').length;
  var ballCount = array.filter(e => e === 'ball').length;

  result.innerText = `${strikeCount} strike ${ballCount} ball`;
});

💡 문제 발생

  • 되긴 되는데🤩 사용자가 input에 입력한 값이 세 자리 숫자가 아니어도 화면에 ball과 strike의 개수가 표시됨

💡 해결 방법

  • 경고 창을 띄우는 if 구문을, 랜덤 숫자와 입력 값을 비교하는 이벤트 리스너 안으로 옮김 (위에서 나눠놨던 2개의 enter.addEventListener 합침)

  • if 구문 다음에 else if 구문을 만들어서 result.innerText ~ 구문을 넣어줌

  • if, else if 구문을 이벤트 리스너의 제일 마지막으로 이동시킴

  if (user.length !== 3) {
    alert('세 자리 숫자를 입력해야 합니다.');
  } else if (user.length === 3) {
    result.innerText = `${strikeCount} strike ${ballCount} ball`;

✨ 내일 할 것

  1. 숫자 야구(Number Baseball) 구현 계속
profile
능동적으로 살자, 행복하게😁

0개의 댓글