⛵ 항해99/TIL · WIL ✏️
[TIL] 2023.08.16 - 숫자 야구 프로그램 / Math.random() /문자열 변경(숫자 + '') / 문자열 인덱스 접근 / includes()
hhhhy
2023. 8. 16. 19:47
[팀과제] 숫자 야구 프로그램 만들기
팀으로 진행된 숫자야구 프로그램 만들기 과제! 같이 풀었다기보다는 팀장님의 주도로 한 줄 한 줄 이해하면서 작성을 해나갔다. 덕분에 코드의 흐름을 이해하는데 큰 도움이 됐지만, 혼자서 작성하기엔 아직 무리가 있어 코드에 주석을 달아보면서 다시 읽어봤다. 언젠가는 혼자서도 술술 풀 수 있기를 ㅎㅎ😅
<과제 조건>
1) 컴퓨터는 0과 9 사이의 서로 다른 숫자 3개를 무작위로 뽑습니다. (ex) 123, 759
2) 사용자는 컴퓨터가 뽑은 숫자를 맞추기 위해 시도합니다.
3) 컴퓨터는 사용자가 입력한 세자리 숫자에 대해서, 아래의 규칙대로 스트라이크(S)와 볼(B)을 알려줍니다. - 숫자의 값과 위치가 모두 일치하면 S - 숫자의 값은 일치하지만 위치가 틀렸으면 B
4) 기회는 무제한이며, 몇 번의 시도 후에 맞췄는지 기록됩니다.
5) 숫자 3개를 모두 맞춘 경우, 게임을 종료합니다.
- 알게 된 것
📍 Math.random()
- 0 이상 1 미만의 구간에서 부동소숫점 의사난수를 반환함
# 예시
let ranNum = Math.random();
console.log(ranNum)
// 0 이상 1 미만의 부동소숫점 의사 난수로, 찍을때 마다 값이 다름 (0.987654.. 등등)
# 참고
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math/random
📍 숫자 + '' : 문자열로 변경
- 숫자에 빈 문자열("")을 연결하면 숫자가 문자로 변경됨
# 예시
let a = 123 + '';
console.log(a) // 123
console.log(typeof a) // string
# 참고
https://hianna.tistory.com/491
📍 문자열 인덱스 접근
- JavaScript에서 문자열은 문자의 배열로 취급되기 때문에, 문자열[index]와 같은 방식으로 특정 위치에 있는 문자에 접근할 수 있음
- 문자열은 불변(immutable)하기 때문에 특정 인덱스에 접근해서 값을 변경하는 것은 불가능
# 예시
const str = "Hello";
console.log(str[0]); // H
console.log(str[2]); // l
📍 includes()
- 배열이 특정 요소를 포함하고 있는지 판별
- . 앞이 큰 범위가 들어가고 () 안에 확인할 특정 요소 넣으면 됨
# 예시
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
# 참고
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
- 완성 코드
더보기
// 터미널에서 입력받기 위해 내장 모듈인 readline 가져오기
const readline = require("readline");
// readline 인터페이스를 생성 => 이를 통해 터미널에서 입력을 받고 출력할 수 있음
const rl = readline.createInterface({
input: process.stdin, // 입력은 표준 입력으로 설정
output: process.stdout // 출력은 표준 출력으로 설정
});
let count = 0; // 시도 횟수를 나타내는 변수를 초기화
let random_num = ''; // 컴퓨터가 생성한 랜덤한 숫자를 담을 변수를 초기화
// 1. 랜덤 숫자 생성하기
for(let i = 0; i < 3; i++) { // 3개의 서로 다른 숫자로 이루어진 랜덤한 숫자를 생성하기
let ran = Math.floor(Math.random() * 10) + ''; // 0부터 9까지의 랜덤한 정수를 생성하고 문자로 변환하기
if(random_num[0] === '0') { // random_num의 0번째(=첫번째) 숫자가 0이 나오면,
i--; // 현재 반복을 다시 실행하기 위해 i를 감소시킴
} else if(random_num.includes(ran)) { // 0번째 숫자가 0이 아니지만, 이미 생성된 숫자와 중복된 경우가 있으면,
i--; // 현재 반복을 다시 실행하기 위해 i를 감소시킴
} else { // 위 두가지 상황이 아니라면,
random_num += ran; // 생성된 랜덤 숫자(ran)를 변수 random_num에 추가해줘
}
}
console.log(random_num); // 생성된 랜덤 숫자 출력하기
console.log('컴퓨터가 숫자를 생성하였습니다. 답을 맞춰보세요!');
// rl.on("line", function (line) { ... }): 이 코드는 rl 변수에 line 이벤트 리스너를 등록
// 이 리스너는 사용자가 터미널에서 한 줄을 입력하고 엔터 키를 눌렀을 때 발생
// 사용자 입력은 line 매개변수를 통해 전달되며, 이후 리스너 함수 내부에서 사용자 입력을 처리
rl.on("line", function (line) { // line : 한 줄을 키보드로 입력받기 (여러줄을 입력받으려면 반복문)
count++; // 입력이 되면, 바로 시도한 횟수가 증가함
console.log(`${count}번째 시도 : ${line}`); // 시도 횟수(count)와 상용자 입력 내용(line)을 가져와서 찍어줌
let ball = 0; // B 개수 초기화
let strike = 0; // S 개수 초기화
let result = ''; // 결과 나타낼 문자열 초기화
// 인덱스 번호(위치)가 같고 값도 같으면 => 스트라이크, 인덱스 번호(위치)가 다르지만 같은 값이 있다면(includes()) => 볼
for(let i = 0 ; i < line.length; i++) { // 사용자 입력값의 길이만큼 도는 반복문
if(line[i] === random_num[i]) { // 사용자 입력값의 i번째와 랜덤숫자의 i번째가 같으면,
strike++; // S를 1 증가시킴
} else if(random_num.includes(line[i])) { // 만약 랜덤숫자 중에 사용자 입력값의 i번째와 중복인게 있으면,
ball++; // B를 1 증가시킴
}
}
// 볼과 스트라이크 개수에 따라 결과 문자열 다르게 출력하기
if(ball === 0 && strike === 0) { // 볼도 없고, 스트라이크도 없으면
result += `${ball}B${strike}S`; // result에 볼 값과 스트라이크 값 넣기 => 0B0S
}
if(ball !== 0) { // 볼만 있는 경우
result += `${ball}B` // result에 볼 값 넣기 => 1B
}
if(strike !==0) { // 스트라이크만 있는 경우
result += `${strike}S` // result에 스트라이크 값 넣기 => 1S
}
console.log(result);
if(result === '3S') { // 3S(=정답)인 경우,
rl.close(); // readline 인터페이스를 닫아 입력을 종료함
}
// .on("close", function () { ... })는 readline 인터페이스에서 "close" 이벤트가 발생했을 때 실행할 함수를 등록하는 역할을 함
}).on("close", function () { // 입력 종료 후 실행되는 코드
console.log(`${count}번만에 맞히셨습니다.`); // 시도횟수 넣어서 시도결과 출력
console.log('게임을 종료합니다.');
process.exit(); //이 부분은 Node.js 프로세스를 종료하는 명령어
});