- 자바스크립트로 숫자 야구를 만들어보자2024년 04월 28일
- Lv. 34 라이츄
- 작성자
- 2024.04.28.:02
아니 이게 되더라고?
https://codepen.io/koreanraichu/pen/VwNNZGW
거기서도 제대로 작동할지는 모르겠는데 일단 코드펜에도 올렸다. 테스트는 월욜에 점심 먹으면서 해봐야징.
숫자야구가 약간 코더들에게는 국룰같은건지 언어별로 이게 하나씩 있다. 물론 파이썬에도 있지… 그러다보니 궁금해진게 그럼 JS도 프로그래밍 할 때 쓰는건데 숫자야구가 있겠지? 예, 있습니다. 놀랍게도. 그래서 해봤습니다.
Reference
https://yjg-lab.tistory.com/322
https://www.freecodecamp.org/korean/news/javascript-splice-method/
https://hianna.tistory.com/379
https://ingnoh.tistory.com/172
https://velog.io/@abc2752/JS-Set
일단 숫자야구에는 기본적인 규칙이 있는데
1. 숫자 세자리(네자리 하는 경우도 있다)를 맞추면 되는 대단히 심플한 게임인데, 일단 세자리 수에 중복이 없다. 그니까 111 666 이딴거 없음.
2. 몇 번째 자리인지랑 숫자를 정확히 맞추면 스트라이크다.
3. 몇 번째 자리인지는 틀렸는데 그 숫자가 있으면 볼이다.
4. 만약 세자리 수가 다 없으면 아웃이다. (근데 이럴 일은 잘 없음)
그래서 세 자리 숫자를 맞추면 되는 정말 대단히 심플한(데 코딩하기 빡센) 게임이다. 횟수는 10회로 제한하는 코드도 있긴 한데 일단 내껀 제한 없으니까 편히 즐기십셔.
숫자야구 코드는 크게 두 파트인데 첫번째가 맞춰야 할 숫자를 만드는거고, 두번째가 본게임 로직이다. 빡세기는 아래가 제일 빡셌음... 근데 배열 만드는데도 버그터져서 아오... 그 얘기는 인제 지금부터 할거니까 VScode 켜고 오십시오.
문제 만들기
for (let i = 0;i < 3;i++) { ballQuestion[i] = Math.floor(Math.random() * 10); }
길이가 3인 배열을 만들려면 이렇게 하면 된다. 근데 이렇게 하면 숫자가 중복될 수 있다. 아, 참고로 자바스크립트는 Python처럼 randrange 이딴거 없습니다.
let numberArray = ['0','1','2','3','4','5','6','7','8','9']; let ballQuestion = []; for (let i = 0;i < 3;i++) { let ballPick = []; ballPick = numberArray.splice(Math.floor(Math.random() * (10 - i)),1)[0]; ballQuestion.push(ballPick); }
그래서 이렇게 했는데 문제가 뭐냐면 가끔 1부터 9까지를 다 입력했는데 2스트라이크인 경우가 생겼다. 그래서 확인해보니까 배열에 숫자가 아니라 undefined가 들어가있는겨. 저 코드는 배열을 만들 숫자를 하나씩 빼가면서 배열 길이가 줄어들어서 최종적으로 6이 되는 구조여야 맞는데, undefined가 껴버리면 배열 길이가 7이 되는거다.
let numberArray = ['1','2','3','4','5','6','7','8','9']; let ballQuestion = []; for (let i = 0;i < 3;i++) { let ballPick = []; ballPick = numberArray.splice(Math.floor(Math.random() * (numberArray.length - i)),1)[0]; console.log(ballPick, numberArray) ballQuestion.push(ballPick); } // 배열 만들기
응~ 짤르고 길이 줄여버리면 그만이여~
로직짜기
round ++; strike = 0; //스트라이크 ball = 0; //볼 let ballOut = `<p>아웃!</p>` ballButton.addEventListener('click',()=>{ console.log(ballInput.value, ballInput.value[0]) for (let i = 0;i < 3;i++) { if (ballQuestion[i] == ballInput.value[i]) { strike ++; } else if (ballQuestion[i] == ballInput.value[i]) { ball ++; } }; let ballText = document.createElement('p'); ballText.innerText = `Round ${round}: ${strike}S ${ball}B`; ballAnswer.appendChild(ballText); });
이 코드는 아직 문제가 매우 많은 상태인데, 일단 스트라이크는 로직이 저게 맞다. 맞는데 볼은 저게 아니기때문에 수정해야 한다. 잘 보면 스트라이크랑 볼이랑 로직 같은데 일단 저 상태로 스트라이크는 잘 찾나 봤다. 그리고 잘찾는다.
ballButton.addEventListener('click',()=>{ strike = 0; //스트라이크 ball = 0; //볼 round ++; for (let i = 0;i < 3;i++) { if (ballQuestion[i] == ballInput.value[i]) { strike ++; } else if (ballInput.value.indexOf([i]) != -1) { ball ++; } }; let ballText = document.createElement('p'); ballText.innerText = `Round ${round}: ${ballInput.value}, ${strike}S ${ball}B`; ballAnswer.appendChild(ballText); });
라운드 안 더래지는 문제도 손봤음... 위에도 썼지만 스트라이크는 숫자가 있고 위치까지 딱 맞는거고 볼은 숫자는 있는데 자리수가 다른경우다. 일단 저거 몇번 해봤는데 맞긴 맞았음... 그럼 이제 자잘한 기능을 붙여보자.
ballButton.addEventListener('click',()=>{ if (ballInput.value.length != 3) { strike = 0; //스트라이크 ball = 0; //볼 alert('세 자리 숫자를 입력해주세요! '); ballInput.value = ''; } else if (new Set(ballInput.value).size < 3) { strike = 0; //스트라이크 ball = 0; //볼 alert('숫자는 중복되지 않는 세 자리 숫자입니다. '); ballInput.value = ''; } else { strike = 0; //스트라이크 ball = 0; //볼 round ++; for (let i = 0;i < 3;i++) { if (ballQuestion[i] == ballInput.value[i]) { strike ++; } else if (ballInput.value.indexOf([i]) != -1) { ball ++; } }; if (ball == 0 && strike == 0) { let ballText = document.createElement('p'); ballText.innerText = `Round ${round}: ${ballInput.value}, Out! 😥`; ballText.classList.add('nohit'); ballAnswer.appendChild(ballText); } else if (strike == 3) { let ballText = document.createElement('p'); ballText.innerText = `Round ${round}: ${ballInput.value}, ${strike}S ${ball}B ⚾`; ballText.classList.add('homerun'); ballAnswer.appendChild(ballText); } else { let ballText = document.createElement('p'); ballText.innerText = `Round ${round}: ${ballInput.value}, ${strike}S ${ball}B`; ballAnswer.appendChild(ballText); } ballInput.value = ''; } }); //아 정말 힘들다...
뭐가 많이 추가됐는데 일단 1) 입력한 숫자가 세자리수가 아니거나 2) 입력한 숫자에 중복이 있을 경우(예: 222) 알림창을 띄워준다. 그리고 아웃일 때랑 정답을 맞췄을 때 텍스트 색이 다르고(클래스 안더해져서 몇번 고생함...) 입력하고 버튼을 누르면 인풋창을 알아서 비워주기까지 한다. 솔직히 이정도면 장족의 발전이여...
결과물
그래서 3스트라이크, 그러니까 정답일 때는 이렇게 된다.
정말 작정하지 않는 이상 볼 일은 없지만 아웃 뜨면 이렇게 나온다.
PS.
이게 하다보니까 2S 1B가 나올 때가 있는데, 문제가 뭐냐면 2스트라이크 1볼은 나와서는 안 된다. 4자리수면 몰라도 3자리수에서 이건 패러독스다. 숫자 두 개가 자리가 맞는데 하나가 자리가 뻑났다? 이거는 있을 수 없는 일인겁니다.
이거는 어떻게 해결하느냐...
for (let i = 0; i < 3; i++) { if (ballQuestion[i] == ballInput.value[i]) { strike++; } else if (ballInput.value.indexOf([i]) != -1) { ball++; } };
저기 자리수 안맞는거 밑에 중복 밑에 보여요? 그 스트라이크 0 볼 0 그거. 거기 보면 반복문 있는데 이 부분에 else if문을
for (let i = 0; i < 3; i++) { if (ballQuestion[i] == ballInput.value[i]) { strike++; } else if (ballInput.value.indexOf(ballQuestion[i]) != -1) { ball++; } };
이걸로 바꿔주자. 사실 나도 제보받긴 했는데 코드펜은 모바일에서조작하기가 개 그지같아서 정확히 어떤 현상인지는 모르겠음. 근데 코드만 놓고 보면 i가 0, 1, 2니까 아마 답에 1이나 2가 들어가있으면 볼로 치는 듯…
'Coding > JavaScript' 카테고리의 다른 글
슬라이드 버튼 만들기 (0) 2024.05.06 숫자 야구에 새 게임 버튼을 넣어보자 (0) 2024.04.29 자바스크립트향 첨가 드롭다운 메뉴 (0) 2024.04.21 [HTML 요소] 체크박스 (0) 2024.04.09 현재 시각을 십이지시로 바꿔보자 Ver.JS (0) 2024.02.12 다음글이전글이전 글이 없습니다.댓글