오늘 이노캠에서 숫자야구 게임을 만들었다.
0-9까지의 숫자 3개를 입력하면 랜덤으로 생성된 숫자3개와 비교하여
숫자와 자리 모두 같으면 S를 숫자는 같지만 위치가 다르면 B를 숫자와 위치 모두 다르면 O를 출력한다.
기회는 무제한이며, n번의 시도 후에 맞췄는지 기록됩니다.
숫자 3개를 모두 맞춘 경우, 게임을 종료합니다. = 3S 일 때 종료
Problem
솔직히 처음에는 입출력을 확인할 수 있는 방법을 알려주지 않아서 당황했다.
자바스크립트로 코드를 짜는 것은 어렵지 않았지만 입출력을 통해 결과가 잘 나오는지,
내가 짠 코드에 이상은 없는지 확인해야 했는데 그 과정이 쉽지 않았다.
TRY
(1) HTML로 확인하기
내가 알고 있는 방법은 입력을 해야 하니까 html에서 값을 입력한 후 제대로 입출력이 되는지 확인하는 방법을 사용해보려 했다.
호기롭게 index.html을 만들고 input창을 만든 후 자바스크립트랑 연결하고 있는데 갑자기 현타가 왔다.
지금 브라우저로 화면을 만드는 것보다는 내가 짠 코드에 이상이 없는지 확인하고 싶은거 뿐이었는데 더 좋은 방법이 있지 않을까
하는 생각이 들었다.
(2) Readline 으로 터미널에서 확인하기
나처럼 의아함을 갖는 사람들이 많았는지 동기 분들이 돌아다니며 의문을 제기했다.
이때 나온 방법이 바로 readline 이었다. readline은 자바스크립트에서 nodejs를 이용하여 터미널에서도
입출력을 할 수 있게 만드는 방법으로 백준에서 많이 쓰는 방법이라 한다.
백준을 풀어본 적 없는 나는 정말 처음 들어보는 용어였고 이 readline을 이용해서 코드를 짜기 시작했다.
하지만 문제는 readline을 이용해서 코드를 짜본 적 없던 나는 계속되는 이상에 내 코드가 문제인지 readline을 사용이 잘못된건지
분간이 가지 않았다.
(3) prompt창 활용하기
검색해보니 prompt창을 활용하여 보다 직관적으로 입력값을 받을 수 있는 방법이 있었다.
따로 데이터 값을 연결하거나 하지 않아도 보다 쉽게 확인할 수 있었다.
Solution
(1) prompt창 활용하기
prompt창을 활용하여 보다 직관적으로 입력값을 받아 확인했는데 다행히 코드에 이상이 없어 바로 성공할 수 있었다!!
물론 바로 성공해서 기분은 좋았지만 조금의 이상 없이 성공해버려서 더 어려운 코드였다면 성공하지 못할거 같다. 흠..
아쉽게도 node.js에서는 prompt창을 사용하지 못해 html에서 돌렸다는 것!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script>
function randomComputerNumbers() {
let numbers = [];
while (numbers.length < 3) {
let randomNum = Math.floor(Math.random() * 10);
if (!numbers.includes(randomNum)) {
numbers.push(randomNum);
}
}
return numbers;
}
function numBaseball(computerNum, userNum) {
let strikes = 0;
let balls = 0;
for (let i = 0; i < 3; i++) {
if (userNum[i] === computerNum[i]) {
strikes++;
} else if (computerNum.includes(userNum[i])) {
balls++;
}
}
return [strikes, balls];
}
function playGame() {
let computerNum = randomComputerNumbers();
let attempts = 0;
while (true) {
// 사용자가 올바른 형식의 숫자 3개를 입력할 때까지 반복하여 입력
let userNum = prompt(
"숫자 3개를 입력하세요 (0부터 9까지 중복 없이):"
);
if (userNum.length !== 3 || !/^\d+$/.test(userNum)) {
alert("유효한 숫자를 입력해주세요.");
continue;
}
let userNumArr = userNum.split("").map(Number);
let [strikes, balls] = numBaseball(computerNum, userNumArr);
attempts++;
alert(`시도 횟수: ${attempts}\n스트라이크: ${strikes}\n볼: ${balls}`);
if (strikes === 3) {
alert(
`축하합니다! 숫자를 모두 맞혔습니다.\n총 시도 횟수: ${attempts}`
);
break;
}
}
}
playGame();
</script>
</head>
<body></body>
</html>
(2) Readline 으로 터미널에서 확인하기
게더 타운에 사람들이 모여서 북적 북적한 재밌어 보이길래 들어갔더니 다같이 코딩중이었다.
코드를 보니 readline을 사용하고, 이중 for문을 돌려 코드를 짜셨는데 처음에 생각했던 방법이랑 결이 비슷하길래 끼어서 들어봤다!!
라이브 쉐어에만 10분이 넘고 심지어는 게더 타운에서 화면공유를 해주셔서 그걸로 보는 분도 있었다!!
대규모 코딩..(누가 대기업 프론트엔드팀 같다하셨는데 진짜 이런 느낌일까 하고 신기했다😝)
// readline 사용하기 위한 셋팅
let readline = require('readline');
let rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// random으로 숫자를 뽑기 - Math.floor, Math.random
function randomNum() {
let num = [];
while(num.length < 3) {
let inputNum = Math.floor(Math.random() * 10);
if(!num.includes(inputNum)) {
num.push(inputNum);
}
}
return num.join("")
}
// 게임결과 반환
function gameResult() {
let strike = 0;
let ball = 0;
let count = 0;
let pc = randomNum();
console.log('pc',pc)
rl.on("line", function(userInput) {
//숫자의 값과 위치가 모두 일치하면 S
for(let i=0; i < 3; i++){
for(let j = 0; j < 3 ; j++){
if(pcInput[i]===userInput[j]){
if(i === j){
strike++
}else{
ball++
}
}
}
}
count++
if(strike===3){
console.log(`${ball}B${strike}S`)
console.log(`${count}번 만에 맞히셨습니다.`)
rl.close();
} else if(ball === 3) {
console.log(`${count}번째 시도 : ${userInput}`)
console.log(`${ball}B`)
}
else {
console.log(`${count}번째 시도 : ${userInput}`)
console.log(`${ball}B${strike}S`)
}
});
}
gameResult()
게임 결과 반환에 보면
if(pcInput[i]===userInput[j]){
if(pc.charAt(i)===userInput.charAt(j)) { // 이걸 쓰는 걸 추천
이 코드가 있는데 아래에 charAt()을 사용하는 걸 권장한다고 한다.
왜냐하면 프론트만 있고 데이터 값을 프론트에서 임의로 넣은거라면 데이터가 없을 걱정이 없지만
협업을 하다보면 서버 측 실수로 데이터가 없기도 하는데 그때 나느 오류를 잡아준다고 한다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/charAt
String.prototype.charAt() - JavaScript | MDN
charAt() 함수는 문자열에서 특정 인덱스에 위치하는 유니코드 단일문자를 반환합니다.
developer.mozilla.org
+) 팀원분께 허락 받고 갖고 온 코드!!
200원짜리 야쿠르트에 허락을 해주셔서 감사할 따름😂
const readline = require('readline');
// 인터페이스 객체를 만들자.
const input = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function getUserNum () {
// 랜덤으로 숫자 생성하기 및 testCount 초기화
let computer = createRandomNum()
// let computer = "280";
let testCount = 0;
// 프로그램 시작을 알리는 msg
console.log(`컴퓨터가 숫자를 생성하였습니다. 답을 맞춰보세요! ${computer}`)
input.question(`${testCount}번째 시도 : `, function program (userValue) {
if(userValue.length !== 3) {
console.log(`숫자는 세자리만 입력 가능합니다.`)
input.question(`${testCount}번째 시도 : `, program)
return
}
// strike 및 ball 초기화
let strike = [] // strike : 숫자의 값과 위치가 일치한 경우
let ball = [] // ball : 숫자의 값은 존재하지만, 위치가 틀렸을 경우
testCount++ // 입력받은 횟수 업데이트
let userValueSplit = userValue.split("") // [1, 2. 3]
// 랜덤숫자와 사용자 숫자의 비교
userValueSplit.forEach((num, index) => num === computer.charAt(index)
? strike.push("S")
: computer.includes(num)
&& ball.push("B"))
// 결과 출격하기
if(ball.length === 0 && strike.length === 0) {
console.log(`0B0S`)
input.question(`${testCount}번째 시도 : `, program)
} else if(ball.length === 3) {
console.log(`3B`)
input.question(`${testCount}번째 시도 : `, program)
} else if(strike.length === 3) {
console.log(`3S`)
console.log(`${testCount}번만에 맞히셨습니다.\n게임을 종료합니다.`)
input.close();
} else {
console.log(`${ball.length}B${strike.length}S`)
input.question(`${testCount}번째 시도 : `, program)
}
})
}
// 중복되지 않는 숫자 생성기
function createRandomNum () {
let numList = []
while (numList.length < 3) {
let randomNumber = parseInt(Math.random() * 10);
if (!numList.includes(randomNumber)) {
numList.push(randomNumber);
}
}
return numList.join("")
}
getUserNum()
(3)HTML 사용하기(추가예정)
우리는 예비 프론트엔드 개발자이기 때문에 html과 css, js를 이용하여 브라우저에서 볼 수 있는 웹을 만들어 보는게 중요하다.
코드가 제대로 작동하는지 확인하기 위해 잠시 접어두었던 코드를 사용해 숫자 야구 게임 페이지를 만들었다.
Learning
readline 을 사용해서 node js를 활용하여 코드를 확인하고 입출력 할 수 있는 방법을 배웠다.
파이썬은이나 다른 언어에서는 따로 이런걸 사용하지 않아도 되는데 자바스크립트는 입출력이 어렵기 때문에
백준에서도 자바스크립트로 문제를 풀 때 readline을 사용한다고 한다. 흥미롭다.
prompt창을 사용해 입출력을 확인 할 수 있었다.
이중 for문을 사용하다 구현이 잘 되지 않아서 방법을 바꿨던 던데 코드의 문제가 아니라 입출력 하는것에 어려움 때문이었다.
다 같이 구현한 코드를 보니 내가 구현했던 코드와 차이가 없었다!! => prompt, readline 메모메모
이번 프로젝트에서 제일 흥미로웠던 점은 여러 사람이 함께 코드를 짜본 일이었다.
각자 사용했던 여러가지 방법들을 사용해 본 것도 재미있었고, 코드 리팩토링 과정도 흥미로웠다.!!
'Diary' 카테고리의 다른 글
이노베이션 캠프 - WIL(1주차) (1) | 2023.06.19 |
---|---|
이노베이션 캠프 - WIL(0주차) (0) | 2023.06.14 |
개발일기1 (0) | 2023.05.29 |
이노베이션 캠프 - WIL(워밍업 기간) (0) | 2023.05.29 |
다시 시작하는 이야기 (0) | 2023.05.22 |