[Javascript] 숫자 야구 게임

hyejinJo·2023년 2월 3일
0

웹게임 링크

4개의 숫자를 제한된 기회 안에 맞추는 게임으로, 야구의 규칙 용어만 가져옴

게임 규칙 :
1. 상대편이 숫자 1~9 중 중복되지 않게 4개를 고름
2. 10 번의 기회가 주어지고, 그 안에 해당 숫자 4개를 순서포함해서 맞춰야함
3. 10번의 기회 동안 다음의 힌트가 계속 주어진다

- 볼(ball) : 숫자만 맞힌 개수 (순서 상관 x)

- 스트라이크(strike) : 숫자 뿐만 아니라 순서까지 맞힌 개수

- 볼과 스트라이크는 각각 별개로 취급

- 4개의 숫자가 하나도 맞지 않으면 아웃 (out)

- 3 아웃이면 패배

- 4개의 숫자가 맞고 순서도 맞다면 홈런 (home run) 승리!
example)  

상대편이 제시한 숫자 : 

5728

플레이어가 말한 숫자 : 

7129 ⇒ 1 스트라이크 1 볼 (7은 숫자만 맞혔으니 볼, 2는 숫자에 순서까지 맞혔으니 스트라이크)

7528 ⇒ 2 스트라이트 2볼

7285 ⇒ 4볼

1396 ⇒ 아웃 

5728 ⇒ 홈런

원래 random () 은 진짜 무작위가 아니라, 임시비밀번호 다루는곳에 쓰면 위험하다.

window.crypto.getRandomValues() 라는 함수가 더 랜덤효과가 크다


  1. 1 ~ 9 숫자 생성, 랜덤으로 뽑기

html

<form action="">
  <input type="text" />
  <input type="submit" value="제출">
</form>
<div id="logs"></div>
const $form = document.querySelector('form')
const $input = $form.querySelector('input[type=text]')
const $btn = $form.querySelector('input[type=submit]')
const $logs = document.querySelector('#logs')

// 초기 상황
// numbers [1, 2, 3, 4, 5, 6, 7, 8, 9]
// answer []

// 1. 1 ~ 9 의 숫자 생성

const numbers = [] // numbers 배열 안에 1 ~ 9 의 숫자 생성
for (let n = 0; n < 9; n++) {
  numbers.push(n + 1) // [1, 2, 3, 4, 5, 6, 7, 8, 9] => 0 베이스이기 떄문에 1 더해주기
}

// 2. 상대편이 1 ~ 9 의 숫자 중 랜덤의 숫자 뽑기
// answer 부분에서는 numbers 의 숫자중 '몇 번째' 숫자를 골라내는, index 개념으로 뽑음
// 예) 4번째 숫자를 고르고싶다면 index 번호는 그보다 1이 작은 3이여야 한다

const answer = [] // numbers[1 ~ 9] 의 숫자들을 랜덤으로 뽑은 후 answer 배열에 담기 (ex. [3, 1, 4, 6])
for (let n = 0; n < 4; n++) {
	// const index = Math.floor(Math.random() * 9) => x
  const index = Math.floor(Math.random() * (numbers.length))
  // 0 ~ 현재 index 의 정수 (numbers 숫자중 랜덤으로 하려면 numbers.length 값을 곱해야 함)
  answer.push(numbers[index])
  // index 엔 + 1 을 안한 이유는, 순서의 개념이기 때문에, 0이 들어가고 자동으로 1번째부터 시작하는 것이 맞다
  numbers.splice(index, 1)
}
  • const index = Math.floor(Math.random() * 9) 로 하면 안되는 이유 :
    • numbers 에서 랜덤으로 숫자가 계속 뽑혀나가 제거되는 만큼 numbers.length 값은 줄어든다.

    • ex) numbers[2, 3, 4, 6] 만 남은 상황에서 Math.random 을 통해 index 9번째 숫자를 뽑으려 하면, numbers 배열 아이템의 index 값은 현재 3(0, 1, 2, 3)까지 밖에 없기 때문에 undefined 가 되어버린다.

    • ex) console.log(answer) => [3, 4, 1, undefined]

    • 해결책 : 반복문을 거칠 수록 numbers.length 값은 줄어드므로, 9개로 고정시키는 것이 아닌 그냥 numbers.length 자체로 고침

      (반복문을 거칠수록 알아서 number.length 값 자체가 줄어들기 때문)

  • splice(index 값, 제거할 요소의 개수) : 배열에서 아이템을 제거
    • 해석: 반복문에서 선택된 index 값의 숫자를 하나(1) 제거

    • ex) number[1 ~ 9]에서 index 값이 3인 [숫자 4]를 뽑아 answer 배열로 넘어가면,

      다음에 랜덤식별될 숫자가 또 중복되지 않게 하기 위해 number 의 해당 [숫자4]를 삭제

    • (카드게임에서 카드를 뽑으면 해당 카드는 수중에서 사라지는 것처럼)


  1. 제출한 숫자가 제출형식에 맞는지 확인,

  2. 제출형식에 통과한 value 값을 통해

    (1) 홈런인지 식별

    (2) 10번 이상 제출했는지 식별 (한정된 기회)

const $form = document.querySelector('form') // html 태그를 선택하여 담은 변수는 $로 구분
const $input = $form.querySelector('input[type=text]')
const $btn = $form.querySelector('input[type=submit]')
const $logs = document.querySelector('#logs')

// 초기 상황
// numbers [1, 2, 3, 4, 5, 6, 7, 8, 9]
// answer []

// --------------------------------------------------------------------------------------------------

// 1. 1 ~ 9 의 숫자 생성
const numbers = [] // numbers 배열 안에 1 ~ 9 의 숫자 생성 -----------------------------------------------
for (let n = 0; n < 9; n++) {
  numbers.push(n + 1) // [1, 2, 3, 4, 5, 6, 7, 8, 9] => 0 베이스이기 떄문에 1 더해주기
}

// --------------------------------------------------------------------------------------------------

// 2. 상대편이 제시하는 수로, 1 ~ 9 의 숫자 중 랜덤의 숫자 뽑기 -------------------------------------------------
// answer 부분에서는 numbers 의 숫자중 '몇 번째' 숫자를 골라내는, index 개념으로 뽑음
// 예) 4번째 숫자를 고르고싶다면 index 번호는 그보다 1이 작은 3이여야 한다
const answer = [] // numbers[1 ~ 9] 의 숫자들을 랜덤으로 뽑은 후 answer 배열에 담기 (ex. [3, 1, 4, 6])
for (let n = 0; n < 4; n++) {
  const index = Math.floor(Math.random() * (numbers.length))
  // 0 ~ 현재 index 의 정수 (numbers 숫자중 랜덤으로 하려면 numbers.length 값을 곱해야 함)
  answer.push(numbers[index])
  // index 엔 + 1 을 안한 이유는, 순서의 개념이기 때문에, 0이 들어가고 자동으로 1번째부터 시작하는 것이 맞다
  numbers.splice(index, 1)
}

console.log(answer)

const tries = [] // [3416, 3948, 1234, 5289 ...] 등의 형태로 값이 들어가는 배열**

// --------------------------------------------------------------------------------------------------

function checkInput(input) { // 4. 유저가 시도한 숫자인 input의 입력값을 검사 ---------------------------------
  if (input.length !== 4) { // (1) 길이는 4가 아닌가?
    return alert('4자리 숫자를 입력해주세요.')
    // alert 값은 undefined 로, 중간에 if 문에 걸리면 undefined 값이 반환되는 것과 똑같다
  }
  if (new Set(input).size !== 4) { // (2) 중복된 숫자 있는가? (각 숫자리 중복표시)
    return alert('중복되지 않게 입력해주세요.')
  }
  if (tries.includes(input)) { // (3) 이미 시도한 값은 아닌가?
    return alert('이미 시도한 값입니다')
  }
  return true // 위의 if 문의 관문들을 모두 통과하면 true 값을 반환 해줌 (checkInput(value) === true)
  // alert 값은 undefined 로, 중간에 if 문에 하나라도 걸리면 undefined 값이 반환되는 것과 똑같다 
  // (return undefined, 즉 checkInput(value) === false)
}

// --------------------------------------------------------------------------------------------------

$form.addEventListener('submit', (event) => { // 3. 유저가 숫자 맞추기 시도 ------------------------------
  event.preventDefault();
  const value = $input.value // const toDo = input.value 와 같음
  $input.value = '' // 숫자 입력, 제출 후 바로 다음 숫자를 입력이 가능하도록 value 값 비우기
  if (checkInput(value)) { // 위의 checkInput(value)에서 모든 if 문 과정 끝에 true 값을 받으면, 해당 함수가 작동됨
    // 입력값 문제 없음 (합격)
    if (answer.join('') === value) {
      $logs.textContent = '홈런!'
    }
    if (tries.length > 10) { // 10번의 기회를 다 썼는가?
      const message = document.createTextNode(`패배! 정답은 ${answer.join()}`)
      $logs.appendChild(message)
      return
    }
  } else { // 반면 alert 로 인해 undefined 값을 받아 false 를 리턴하면 작동되지 않고 에러가 뜸
    return // 에러 있음 (불합격)
  }
	// 몇 스트라이크 몇 볼인지 검사
  tries.push(value) // 홈런도 안되고, 아웃도 안됐으면 마저 계속 입력값을 넣어 숫자맞추기 진행
})
  • new Set(input).size !== 4
    • new Set 은 배열과 비슷한 개념으로 중복이 없는 배열, 즉 알아서 중복을 제거해줌

    • ex) 만약 3144 라는 중복숫자가 들게 입력하면, 중복되는 두 개의 숫자4 중 하나를 자동으로 제거해서 314 가

          된다. (3144 => 314(실제 new Set 값))
    • 즉 new Set(input).size의 값은 3이 되고 (.length 의 개념으로, new Set 은 .length 가 아닌 .size 이다)

      실제 값인 3 !== 4 로 비교 연산되면서 경고창이 뜨게한다.

  • tries.includes(input)
    • 유저가 answer로 숫자를 뽑는 시도를 행할 때마다 tries 에 유저가 적었던 4자리 값들이 저장됨

    • tries 배열에 들어가는 값 중 이미 한번 시도했던 값이 있는 상태에서, 유저가 똑같은 값을 넣으면

      그 값이 이미 포함 되어있다고 알려준다. (4자리 숫자 전체(숫자, 순서) 중복 표시)

    • value 는 문자열 상태

  • if (answer.join('') === value)
    • join('') : 배열 요소들을 문자열로 바꾸어 나열된 문자형태로 만들어줌

          ex) [3, 1, 4, 6] => 3146 (순서 확인을 위해 문자열로 묶어 나열)
    • join() 과 같이 ''를 안넣으면 3, 1, 4, 6 과 같이 콤마가 붙음 (콤마가 기본값이기 때문에)

    • ex) join(' : ') ⇒ 3 : 1 : 4 : 6

    • split() : join() 과 반대되는 메서드

      ex) '3146'.split() ⇒ [ "3146" ]

      '3146'.split("") ⇒ ["3", "1", "4", "6"]

      '3146'.split("1") ⇒ ["3", "46"] (1을 기점으로 갈라짐)

  • if (checkInput(value)) >> 중첩된 if 문을 풀어보자
if (!checkInput(value)) { 
    return
  } 
  if (answer.join('') === value) {
    $logs.textContent = '홈런!'
  }
  if (tries.length > 10) {
    const message = document.createTextNode(`패배! 정답은 ${answer.join()}`)
    $logs.appendChild(message)
    return
  }
  tries.push(value) 
})
  • 조건문에 !를 붙여 조건을 반전시킨 후 짧은 구문을 위로 올리고 긴 구문을 바깥으로 빼 if 문을 편다

(3) 몇 스트라이크 몇 볼인지 검사

const $form = document.querySelector('form') // html 태그를 선택하여 담은 변수는 $로 구분
const $input = $form.querySelector('input[type=text]')
const $btn = $form.querySelector('input[type=submit]')
const $logs = document.querySelector('#logs')

// 1. 1 ~ 9 의 숫자 생성
const numbers = [] // numbers 배열 안에 1 ~ 9 의 숫자 생성 
for (let n = 0; n < 9; n++) {
  numbers.push(n + 1) // [1, 2, 3, 4, 5, 6, 7, 8, 9] => 0 베이스이기 떄문에 1 더해주기
}

// 2. 상대편이 제시하는 수로, 1 ~ 9 의 숫자 중 랜덤의 숫자 뽑기 
const answer = [] 
for (let n = 0; n < 4; n++) {
  const index = Math.floor(Math.random() * (numbers.length))
  // 0 ~ 현재 index 의 정수 (numbers 숫자중 랜덤으로 하려면 numbers.length 값을 곱해야 함)
  answer.push(numbers[index])
  // index 엔 + 1 을 안한 이유는, 순서의 개념이기 때문에, 0이 들어가고 자동으로 1번째부터 시작하는 것이 맞다
  numbers.splice(index, 1)
  // splice(index 값, 제거할 요소의 개수) : 배열에서 아이템을 제거
}

console.log(answer)

const tries = [] // [3416, 3948, 1234, 5289 ...] 등의 형태로 값이 들어가는 배열

function checkInput(input) { // 4. 유저가 시도한 숫자인 input의 입력값을 검사 ---------------------------------
  if (input.length !== 4) { // (1) 길이는 4가 아닌가?
    return alert('4자리 숫자를 입력해주세요.')
    // alert 값은 undefined 로, 중간에 if 문에 걸리면 undefined 값이 반환되는 것과 똑같다
  }
  if (new Set(input).size !== 4) { // (2) 중복된 숫자 있는가? (각 숫자리 중복표시)
    // new Set 은 배열과 비슷한 개념으로 중복이 없는 배열, 즉 알아서 중복을 제거해줌
    return alert('중복되지 않게 입력해주세요.')
  }
  if (tries.includes(input)) { // (3) 이미 시도한 값은 아닌가?
    return alert('이미 시도한 값입니다')
  }
  return true // 위의 if 문의 관문들을 모두 통과하면 true 값을 반환 해줌 (checkInput(value) === true)
}

$form.addEventListener('submit', (event) => { // 3. 유저가 숫자 맞추기 시도 ------------------------------
  event.preventDefault();
  const value = $input.value // const toDo = input.value 와 같음
  $input.value = '' // 숫자 입력, 제출 후 바로 다음 숫자를 입력이 가능하도록 value 값 비우기
  if (!checkInput(value)) { // 위의 checkInput(value)에서 모든 if 문 과정 끝에 true 값을 받으면, 해당 함수가 작동됨
    return
  } 
  // 입력값 문제 없음 (합격)
  if (answer.join('') === value) {
    // join('') : 배열안의 아이템들을 문자열로 바꾸어 나열된 문자형태로 만들어줌 (순서 확인을 위해 문자열로 묶어 나열)
    // ex) [3, 1, 4, 6] => 3146
    $logs.textContent = '홈런!'
    return
  }
  if (tries.length >= 9) { // 10번째 시도에서는 tries.length 가 9이다
    // 9번째까지 온 상태에서 10번째 턴이 틀리면 
    const message = document.createTextNode(`패배! 정답은 ${answer.join()}`)
    $logs.appendChild(message)
    return
  }

  // 몇 스트라이크 몇 볼인지 검사
  let strike = 0;
  let ball = 0;
  for(let i = 0; i < answer.length; i++) {
    const index = value.indexOf(answer[i])
    // 방법 : answer 의 아이템(answer[i])값을 'value 아이템의 인덱스 확인하는 용도'의 메서드에 넣어 확인
    // value 와 answer 의 아이템 중 겹치는 것이 있는지 확인 후 변수에 담음
    if(index > -1) { // 겹치는 숫자가 있는가? 
      // (indexOf() 로 값을 찾을 때, 값이 안들어있으면 -1 을 반환함)
      if(index === i) { // 순서, 숫자 모두 같은가? (index: value 인덱스순서, i: answer 인덱스 순서)
        strike += 1
      } else { // 순서 x 숫자만 같은가?
        ball += 1
      }
    } 
  }
  $logs.append(`${value}: ${strike} 스트라이크 / ${ball}`, document.createElement('br')) 
  // append() 에는 , 를 찍어 여러 개의 요소를 넣을 수 있음
  tries.push(value) // 홈런도 안되고, 아웃도 안됐으면 마저 계속 입력값을 넣어 숫자맞추기 진행
})
  • includes() , indexOf() : 배열이나 문자열에 원하는 값이 들어있는지 찾는 메서드
  • includes() : 직관적으로 boolean 타입(true, false)으로만 추출
'1234'.includes(3) === true;
[1, 2, 3, 4].includes(5) === false;
  • indexOf() : 요소의 자료형까지 같아야함
    • indexOf 함수는, 문자열(string)에서 특정 문자열(searchvalue)을 찾고, 검색된 문자열이 첫번째로 나타나는 위치 index를 반환
    • 원하는 값이 들어있다면 해당 인덱스를 알려주고, 없으면 -1을 반환함
'2345'.indexOf(3) === 1;
'2345'.indexOf(6) === -1;
['2', '3', '4', '5'].indexOf('5') === 3;
['2', '3', '4', '5'].indexOf(5) === -1; // 요소의 자료형이 같지 x 
  • appendChild(), append() 의 차이
  • appendChild() : createTextNode() 추가 후 안에 입력해야함
const message = document.createTextNode(`패배! 정답은 ${answer.join()}`)
$logs.appendChild(message)
  • append() : Node 추가가 필요 없고, 태그 등 여러 요소를 넣을 수 있음
$logs.append(`${value}: ${strike} 스트라이크 / ${ball}`, document.createElement('br'))

(4) 아웃인지 검사, 3아웃일 때 패배 표시

const $form = document.querySelector('form') // html 태그를 선택하여 담은 변수는 $로 구분
const $input = $form.querySelector('input[type=text]')
const $btn = $form.querySelector('input[type=submit]')
const $logs = document.querySelector('#logs')

// 초기 상황
// numbers [1, 2, 3, 4, 5, 6, 7, 8, 9]
// answer []

// --------------------------------------------------------------------------------------------------

// 1. 1 ~ 9 의 숫자 생성
const numbers = [] // numbers 배열 안에 1 ~ 9 의 숫자 생성 -----------------------------------------------
for (let n = 0; n < 9; n++) {
  numbers.push(n + 1) // [1, 2, 3, 4, 5, 6, 7, 8, 9] => 0 베이스이기 떄문에 1 더해주기
}

// --------------------------------------------------------------------------------------------------

// 2. 상대편이 제시하는 수로, 1 ~ 9 의 숫자 중 랜덤의 숫자 뽑기 -------------------------------------------------
// answer 부분에서는 numbers 의 숫자중 '몇 번째' 숫자를 골라내는, index 개념으로 뽑음
for (let n = 0; n < 4; n++) {
  const index = Math.floor(Math.random() * (numbers.length))
  // 0 ~ 현재 index 의 정수 (numbers 숫자중 랜덤으로 하려면 numbers.length 값을 곱해야 함)
  answer.push(numbers[index])
  // index 엔 + 1 을 안한 이유는, 순서의 개념이기 때문에, 0이 들어가고 자동으로 1번째부터 시작하는 것이 맞다
  numbers.splice(index, 1)
}

console.log(answer)

const tries = [] // [3416, 3948, 1234, 5289 ...] 등의 형태로 값이 들어가는 배열

// --------------------------------------------------------------------------------------------------

function checkInput(input) { // 4. 유저가 시도한 숫자인 input의 입력값을 검사 ---------------------------------
  if (input.length !== 4) { // (1) 길이는 4가 아닌가?
    return alert('4자리 숫자를 입력해주세요.')
    // alert 값은 undefined 로, 중간에 if 문에 걸리면 undefined 값이 반환되는 것과 똑같다
  }
  if (new Set(input).size !== 4) { // (2) 중복된 숫자 있는가? 
    return alert('중복되지 않게 입력해주세요.')
  }
  if (tries.includes(input)) { // (3) 이미 시도한 값은 아닌가?
    return alert('이미 시도한 값입니다')
  }
  return true // 위의 if 문의 관문들을 모두 통과하면 true 값을 반환 해줌 
}

// --------------------------------------------------------------------------------------------------

function defeated() { // 중복 함수 처리
  const message = document.createTextNode(`패배! 정답은 ${answer.join('')}`)
  $logs.appendChild(message)
}

// --------------------------------------------------------------------------------------------------

let out = 0 // 아웃 횟수 담을 변수 설정
$form.addEventListener('submit', (event) => { // 3. 유저가 숫자 맞추기 시도 ------------------------------
  event.preventDefault();
  const value = $input.value // const toDo = input.value 와 같음
  $input.value = '' // 숫자 입력, 제출 후 바로 다음 숫자를 입력이 가능하도록 value 값 비우기
  if (!checkInput(value)) { // 위의 checkInput(value)에서 모든 if 문 과정 끝에 true 값을 받으면, 해당 함수가 작동됨
    return
  }
  // 입력값 문제 없음 (합격)
  if (answer.join('') === value) {
    // join('') : 배열안의 아이템들을 문자열로 바꾸어 나열된 문자형태로 만들어줌 (순서 확인을 위해 문자열로 묶어 나열)
    // ex) [3, 1, 4, 6] => 3146
    $logs.textContent = '홈런!'
    return
  }
  if (tries.length >= 9) { // 10번째 시도에서는 tries.length 가 9이다
    // 9번째까지 온 상태에서 10번째 턴이 틀리면 
    defeated()
    return
  }

  // 몇 스트라이크 몇 볼인지 검사
  // (length 의 길이가 같은 두 개의 배열을 비교해 겹치는 배열아이템 선별 알고리즘)
  // 항상 
  let strike = 0;
  let ball = 0;
  // 예시를 들어가며 코드 풀이 
  // ex) answer = [3, 1, 4, 6] 
  //      value = [1, 3, 4, 7]
  for (let i = 0; i < answer.length; i++) {
    const index = value.indexOf(answer[i])
    // 방법 : answer 의 아이템(answer[i])값을 'value 아이템의 인덱스 확인하는 용도'의 메서드에 넣어 확인
    // value 와 answer 의 아이템 중 겹치는 것이 있는지 확인 후 변수에 담음
    if (index > -1) { // 겹치는 숫자가 있는가? 
      // (indexOf() 로 값을 찾을 때, 값이 안들어있으면 -1 을 반환함)
      if (index === i) { // 순서, 숫자 모두 같은가? (index: value 인덱스순서, i: answer 인덱스 순서)
        strike += 1
      } else { // 순서 x 숫자만 같은가?
        ball += 1
      }
    }
  }
  // 아웃 일 때
  if (strike === 0 && ball === 0) { // 아웃의 조건: 0 스트라이크 0 볼 
    out++ // 실행시 마다 아웃 횟수 증가
    $logs.append(`${value}: ${out}아웃 `, document.createElement('br'))
  } else { // 홈런, 아웃 둘 다 아닐 때 마지막에 실행
    $logs.append(`${value} : ${strike} 스트라이크 / ${ball}`, document.createElement('br'))
    // append() 에는 , 를 찍어 여러 개의 요소를 넣을 수 있음
  }
  if (out === 3) {
    defeated()
    return
  }
  tries.push(value) // 홈런도 안되고, 아웃도 안됐으면 마저 계속 입력값을 넣어 숫자맞추기 진행
})
  • for 문 ⇒ forEach() 형태로 바꾸기

  • forEach( element, index, array )

    1. element : 처리할 현재 요소 (필수 값)
    2. index: 처리할 현재 요소의 인덱스 (optional 값)
    3. array : forEach() 를 호출한 배열 (optional 값)
// for 문

answer = []
let strike = 0;
let ball = 0;

for (let i = 0; i < answer.length; i++) {
    const index = value.indexOf(answer[i])
    if (index > -1) {
      if (index === i) {
        strike += 1
      } else { 
        ball += 1
      }
    }
  }
// forEach(요소 값, 요소 인덱스, 배열)

answer = []
let strike = 0;
let ball = 0;

  answer.forEach((answerItem, i) => {
    const index = value.indexOf(answerItem)
    if (index > -1) {
      if (index === i) {
        strike += 1
      } else {
        ball += 1
      }
    }
  })
  • forEach() 는 함수의 호출때문에 for 문보다 성능이 좀 떨어지는데, 요소 하나하나에 함수를 적용하느라 값을 연달아 처리하지 못하고 (ex 요소가 4개이면 함수도 4번 실행됨) push() 로 일일히 배열에 넣어야하는 번거로움이 있다
  • 하지만 배열 메서드들중 연속적으로 사용할 시 편리한 점이 있다.
  • map() : 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환
    • forEach() 의 역할도 하면서, return 이 있어 적혀진 그대로 기존의 배열에 영향을 주지 않으면서 그로부터

      파생된 새로운 배열의 생성이 가능하다

ex) 2씩 곱해지는 기능

// for 문

const array = [1, 2, 3, 4]
const result = [] // 빈 배열 생성

for (let i = 0; i < 4; i++) {
  result.push(array[i] * 2)
}

// result = [2, 4, 6, 8]
// map()
// 빈 배열 생성할 필요 x

const array = []
array.map((item, i) => {
  return item * 2
})

// [2, 4, 6, 8] => 새로운 배열이 생성됨
// array = [1, 2, 3, 4] => 기존 배열에는 영향 없음
  • Array(), fill()
  • 길이가 정해진 텅 빈 배열 생성 후 요소 집어넣기
  • fill() : 배열의 시작 인덱스부터 끝 인덱스의 이전까지 정적인 값 하나로 채움
Array(5) // length 가 5 인 (텅 빈) 배열
Array(5).fill(0) // 0 값이 채워짐
// => [0, 0, 0, 0, 0] 

// 빈 배열에 1 ~ 9 까지의 요소를 넣고 싶다면?
Array(9).fill().map((item, index) => {
  return index + 1
})
// [1, 2, 3, 4, 5, 6, 7, 8, 9]


리뉴얼 작업

  1. 숫자를 입력할 때마다 차례, 유저가 입력한 숫자, 결과값(볼, 스트라이크, 아웃 여부)을 표시하기에 테이블 태그가 적절하다 생각하여 활용하였다. 이를 통해 화면상으로 결과값들이 더 미적으로 표현되게 하였고, 시멘틱적인 태그 사용을 경험했다.
  2. 처음 게임을 시작할 때 게임룰을 팝업창 형식으로 띄우고, '게임 룰을 읽음'의 여부를 저장하여 그 이후로 유저가 게임을 다시 시작할 때 게임룰 팝업창이 다시 뜨지 않도록 하는 기능을 추가하였다. 또한 해당 게임을 나갔다가 다시 들어오면 다시 게임룰이 뜨게 하게끔 만들어보았다.

문제 해결:

보통 처음 게임을 접할 때 우리는 게임 방법을 인지를 해야하므로 게임 설명을 먼저 읽는다. 하지만 게임을 하고 나면, 룰을 이미 알고있어 설명을 보지 않아도 게임을 진행할 수 있다. 게임 룰 창을 만든 후 테스트해본 결과 게임 창을 열때마다 이미 읽지않아도 되는 룰이 계속 뜨는 부분이 번거로웠다. 이를 해결하기 위해, 이전에 다른 강의에서 localStorage() 를 통해 로컬저장소에 저장하면 새로고침을 해도 데이터의 손상없이 저장되는 방법을 기억하여 그부분을 응용해보았다. 그렇게 하여 게임 룰을 한 번 닫으면 게임 다시하기 버튼을 눌러도 게임룰이 더이상 뜨지 않고 게임을 진행할 수 있게 되었다. 하지만 룰을 잊을 경우를 대비하여 다시 따로 게임 설명을 킬 수 있는 버튼도 만들었다. 그리고 앞으로의 모든 게임에 적용시키기 위해 공통코드로 만들어 주었다.

const $startBtn = document.querySelector('.start')
const $gameRule = document.querySelector('#gameRule')
const $overLay = document.querySelector('.overlay')
const $exitBtn = document.querySelector('.btn--exit')

// 게임 룰 
function hideGameRule() {
  $gameRule.classList.add('hidden')
  $overLay.classList.add('hidden')
}

// 게임 시작하기, 읽음 여부 세팅
$startBtn.addEventListener('click', () => {
  hideGameRule()
  localStorage.setItem('readOrNot', 'read');
})

// gameRule 읽음 여부 확인
const savedRead = localStorage.getItem('readOrNot')
if(savedRead !== null) { 
  hideGameRule()
} else {
  $gameRule.classList.remove('hidden')
  $overLay.classList.remove('hidden')
}

$exitBtn.addEventListener('click', () => {
  localStorage.removeItem('readOrNot')
})
profile
FE Developer 💡

0개의 댓글