본문 바로가기
공부/javascript

2022.06.08 - (6/10완료) 숫자야구

by 기묜몬 2022. 6. 8.

자바스크립트 과제로 많이 하는 숫자야구 진행해봤다.

html, css 는 코드가 너무 길어서 일단 생략하기루~~

 

코드를 작성하고 하나하나 뜯다보니 주석이 굉장히 많은데

깃허브에 올릴땐 주석을 삭제하고 올릴것~~!

 

[ 숫자야구 순서도 ]

1. 무작위의 숫자 4개를 랜덤으로 선정한다. (numbers)

2. 참여자는 숫자 4개를 랜덤으로 입력한다. (answer)

3. 입력받은 숫자가 오류가 없는지 검증한다. 

 - 4개의 숫자가 맞는지? (길이 4)

 - 중복된 숫자가 없는지? (1233불가능)

 - 이미 시도한 값은 아닌지? (1234 입력 후 재 입력 불가능)

4. 선정된 4개의 값과 입력된 4개의 값이 맞으면 " 홈런 "

5. 10회 이상 입력시 실패 메세지와 함께 답 공개

=> 여기까지 구현완료 

6. 4개의 값 중 몇개가 맞았는지 힌트 제공 ( 1 볼, 1 스트라이크 )

=> 6번은 내일 구현 예정 

 

====> 2차 구현 목표

7. 다시하기 누르면 초기화

8. 홈런 popup 으로 띄워보기..?

 

 

[ 숫자야구 규칙 ]

정답 예시 : 1234 

참여자 예시 : 1356

1. 참여자는 중복되지않은 네개의 숫자를 콤마 없이 입력한다. 

2. 자릿수와 값이 같을 경우 스트라이크

3. 자릿수는 다르지만 이 있을경우 볼 

 ex) 1234 -> 1356 : 1스트라이크 (숫자,자리 1), 1볼 (숫자 3)

4. 네자리 모두 틀리면 아웃 

 ex) 1234 -> 5678 일때, 0스트라이크 0볼이 아닌 아웃

5. 쓰리아웃되면 패배 

6. 10회 이상 시도하면 패배

7. 자릿수와 숫자 모두 같을 경우 홈런

 

 

 

[ 예시 ]

- 콘솔에 찍힌 랜덤한 4개의 숫자값 ( 1452 )

 

 

- 스트라이크, 볼 예시 (1스트라이크, 1볼)

  자릿수와 값이 같을 경우 스트라이크, 자릿수는 다르지만 이 있을경우 

 

 

- 아웃 예시 

원아웃, 투아웃 표시, 쓰리아웃시에는 패배

 

 

- 홈런 

 

[ JS ]

const $input = document.querySelector("#input");
const $form = document.querySelector("#form");
const $numResult = document.querySelector("#numResult");

const numbers = []; // 숫자를 담을 배열 생성
for (let n = 0; n < 9; n += 1) {
  // 보통 0부터 시작이기때문에 n+1;
  numbers.push(n + 1); //배열에 push 로 넣어줌
}
const answer = []; //뽑을 숫자 담을 배열 생성
// 네 번 반복
for (let n = 0; n < 4; n += 1) {
  const index = Math.floor(Math.random() * (numbers.length - n)); //0~8까지
  answer.push(numbers[index]);
  numbers.splice(index, 1); //numbers에서 splice 로 지워줌
  // index => 랜덤 뽑기로 나온 숫자, 1 => 배열에서 하나 지움
  // -> 이값은 answer에 들어간다.
  // 뽑다보면 numbers에서 숫자가 뽑혀나오기때문에 undefined가 나올수도 있음.
  // Math.floor(Math.random() * 9) -> 변경 Math.floor(Math.random() * (9 - n))
  // -> 반복문이 줄때마다 9에서 n을 하나씩 빼주면 undefined가 나오지 않음..
  // -> 9 - n 을 수시로 바꿔줄 수 없으니 length를 이용하자 (numbers.length - n)
}
console.log(answer);

const tries = [];
// 검사하는 코드
// 순서 (2) 밑에 tries 배열에 input submit된 값을 여기서 검증
function checkInput(input) {
  // 길이는 4가 아닌가?
  if (input.length !== 4) {
    // 4가 아니라면 alert
    return alert("숫자 4개를 입력해주세요.");
  }
  // 중복된 숫자가 있는가?
  if (new Set(input).size !== 4) {
    // 중복되었다면 alert
    return alert("중복된 숫자입니다. 다시 입력하세요.");
  }
  // 이미 시도한 값인가?
  if (tries.includes(input)) {
    // inclues -> 배열에 tries 값이 들어있는가?
    //이미 시도되었다면 alert
    return alert("이미 시도한 값입니다. ");
  }
  return true;
  //if문 다 돌고 true 면 맞는 값 반환
}

//out 변수
let out = 0;

// form 저장
// 순서 (1)
$form.addEventListener("submit", (e) => {
  //event e  매개변수로 사용
  // 기본동작 막기
  e.preventDefault();
  const value = $input.value; // 사용자가 입력한 숫자를 변수(value)에 저장한 다음에
  $input.value = ""; // 글자를 지워준다.

  if (!checkInput(value)) {
    return;
  }
  // checkInput (검사) 함수에서 value를 보내줌
  // 입력값에 문제가 없음
  if (answer.join("") === value) {
    // join("") -> 배열의 원소를 ""를 제거하고, 문자열로 합치기 / [3,1,4,6] ->3146
    $numResult.textContent = "홈런~! 정답입니다!!";
    return;
  }
  if (tries.length >= 9) {
    // 10번이상 시도했을때도 못맞추면
    const msg = document.createTextNode(`패배! 정답은 ${answer.join("")}`);
    $numResult.appendChild(msg);
    return;
  }
  // 몇 스트라이크 몇 볼인지 검사
  // answer: 3146, value(사용자입력): 1234
  let strike = 0; // 변수 만들어서 count
  let ball = 0;
  // value에 answer i 값이 있나 확인 (3 있음)
  for (let i = 0; i < answer.length; i++) {
    const index = value.indexOf(answer[i]);
    // 3의 index는 (012->2임)
    if (index > -1) {
      // 해당값을 찾지 못하면 index는 -1이 됨, 찾으면 0 이상이 나옴
      //일치하는 숫자 확인
      if (index === i) {
        //숫자와 자릿수 모두 같음
        strike += 1;
      } else {
        //숫자만 같음
        ball += 1;
      }
    }
  }

  if (strike === 0 && ball === 0) {
    out++;
    $numResult.append(`${value} : 아웃`, document.createElement("br"));
  } else {
    $numResult.append(
      `${value}: ${strike} 스트라이크, ${ball} 볼`,
      document.createElement("br")
    );
  }
  if (out === 1) {
    $numResult.append(`원 아웃~!`, document.createElement("br"));
  }
  if (out === 2) {
    $numResult.append(`투 아웃~!`, document.createElement("br"));
  }
  if (out === 3) {
    const msg = document.createTextNode(
      `쓰리아웃으로 패배입니다! 정답은 ${answer.join("")}`
    );
    $numResult.appendChild(msg);
  }
  return;

  tries.push(value);

  console.log("submit", e);
});