whatisthis?

javaScript. 숫자야구게임 - (2) 본문

PRACTICE/SELF

javaScript. 숫자야구게임 - (2)

thisisyjin 2022. 1. 19. 12:04
 

javaScript. 숫자야구게임 -(1)

 Bulls and Cows (숫자야구) - Rule - - 숫자 제시 횟수 : 10회 이내 - 4자리의 숫자를 임의로 정함. - 0에서 9까지의 다른 숫자로 구성됨. 숫자는 맞지만 위치가 틀림 = B(볼) 숫자와 위치가 맞음 = S(스트라

mywebproject.tistory.com

 

 

let list = [0,1,2,3,4,5,6,7,8,9];
let number = [];

for(let i=0; i<4; i++) {
    let select = Math.floor(Math.random() * list.length);
    number[i] = list.splice(select, 1)[0];
}

 

지난 시간 작성했던 코드이다.

 

 

+)

let select = Math.floor(Math.random() * list.length);

위 부분에서 왜 * 10이 아닌 list.length를 이용했을까?

>> splice를 통해 하나를 뽑는다면 list 배열의 length가 줄어듬.

이해 🔻

더보기

예를 들면, select로 첫번째로 4를 뽑았다면

splice에 의해 list 배열은 [0, 1, 2, 3, 5, 6, 7, 8, 9]가 될 것이고,

number 배열은 number[0] = list.splice(select, 1)[0]에 의해 4라는 값이 들어가서 [4]가 될 것이다.

 

따라서, list배열의 length는 10에서 9로 줄어들었다.

 

다음 인덱스에서( i=1 )

다시 select를 뽑게 되는데, 이 때 list 배열의 length가 9이므로

0부터 9미만까지 중에서 랜덤으로 select값이 결정된다.

 

** 이때, splice의 첫번째 인자인 select는 값이 아닌 배열에서 n번째 요소를 의미하므로 값과는 상관 없는 것.

 


이제, 사용자가 숫자를 맞추기 위해 '입력을 받는' 동작이 필요하다.

prompt()라는 함수로 입력을 받을 수 있다.

 

- 열 번 반복적으로 숫자를 받을 것이기 때문에 반복문을 만든다.

- 단, 열 번 이전에 숫자를 맞출 수 있으므로 조건 설정 필요.

- 여기서, prompt()로 받는 입력은 String이고, 우리가 위 코드에서 저장한 number은 배열임을 생각하자.

 

 

1. 사용자의 입력을 받는다. (10회 반복)

- string을 array로 변환하자.

let input = prompt('숫자를 입력하세요');
let inputArr = input.split('');     // 한자리씩 쪼개서 배열로 저장해줌

 

2. S, B, O를 판단하여 출력한다.

- 위치와 값이 같으면 S

- 위치가 다르고 값이 같으면 B

- 다 다르면 O

 

- 숫자 한번 입력받을때마다 S,B 갯수를 세서 출력해줘야함.

- S, B 값을 저장하는 변수 만들고 0으로 초기화 (매번 0으로 초기화되도록 loop안에)

 

 

3. number과 동일하면, 즉 숫자를 맞췄다면? - 반복문 break

 

let strike = 0;
let ball = 0;
let count = 0;

while (count < 10) {         // 10회 반복
	let input = prompt('숫자를 입력하세요');
    let inputArr = input.split('')      // inputArr = [2, 5, 9, 7]
    
    strike = 0;
    ball = 0;
    
    count++;            // count 증가시킴 
    
    if(let j=0; j<4; j++) {
    	for(let k=0; k<4; k++) {
        	if(number[j] == inputArr[k]) {      // 숫자 일치하면
            	if(j === k){                   
                	strike++;       // 인덱스(순서, 즉 위치)도 일치하면 Strike
                } else { 
                	ball++;         // 인덱스(순서, 즉 위치)가 다르면 ball    
                }
              	break;              //    ❓  왜 break를 해주는지 
              }
          }
      }
      
      if(strike === 4) {              // S가 4개면 정답이므로
      console.log(`숫자를 맞췄습니다. 시도횟수 : $(count-1)회`);     // count는 0부터시작이므로 -1회임
      break;          // ❗❗ 10번 전에 맞추면 반복문 break할 수 있도록
      } else if (count >= 10) {             // 0부터 9까지 총 10회 가능
      console.log('시도 횟수를 초과했습니다.');
      } else {
      console.log(inputArr.join('') + ': ' + strike + 'S' + ball + 'B');        // join - 문자열로 이어줌
      }
}

 

count는 0부터 9까지 진행. (총 10회)

>> 마지막에 몇회만에 맞췄는지 보여줌

 

 

 

왜 for문이 아니라 while을 썼나?

>> 중간에 10회 전에 맞출수도 있으니 몇번 반복될지 모르기 때문.

 

 

 

 

-prompt는 문자열로 입력됨. 따라서 split('')로 배열로 바꿔줌.
let input = prompt('숫자를 입력해라.');    //   '1234'

💡 string.split(구분자)

구분자가 '' 이므로 그냥 한글자씩 쪼개서 배열로 만들라는 의미.   

let arr = '1234'.split('');
// arr = ['1', '2', '3', '4']

+)만약 ' ' 라면, 띄어쓰기(spacebar)를 기준으로 쪼개서 배열로 만듬.

 

 

 

숫자 비교 - 중복 for loop
for(let k=0; k<4; k++) {
        	if(number[j] == inputArr[k]) {      // 숫자 일치하면
            	if(j === k){                   
                	strike++;       // 인덱스(순서, 즉 위치)도 일치하면 Strike
                } else { 
                	ball++;         // 인덱스(순서, 즉 위치)가 다르면 ball    
                }
              	break;              //    ❓  왜 break를 해주는지 
              }
          }
      }

 

순서대로

number[0]과 inputArr[0]을 비교하고, number[0]과 inputArr[1]을 비교하고, number[0]과 inputArr[2]을 비교하고, ..

마지막으로 number[3]과 inputArr[3]을 비교하면 끝난다.

 

그리고, number[j]과 inputArr[k]가 일치할 때, (즉 number[k] == inputArr[j])

>> ❗❗ 여기서, inputArr문자열로 (split에 의해) 구성된 배열이므로 값만 비교하는 ==를 이용.

 

만약 위치까지 같다면 ( j = k ) Strike

위치가 다르다면 ( else ) Ball이 된다. 

 

그리고 위 코드의 물음표❓ 부분을 살펴보자.

왜 break를 저 위치에 써줬을까?

>> 만약 number[j] == inputArr[k]인 경우 다음 자리로 넘어가기 위해서.(즉, k++부분 건너뛰고 j++로)

가장 가까운 중복문을 하나 break하는 것임.

 

물론 이 break는 없어도 된다만, 효율을 위해 사용된 것.

= 불필요한 비교를 멈추고 바로 다음것으로 넘어가라고 알려주는 것과 같다.

 

 

이렇게 loop를 돌면서 자동으로 네자리 수를 서로 비교해서 strike와 ball이 누적된다.(++에 의해)

 

 

 

결과 출력

결과는 크게 세가지를 출력할 수 있다.

 

  • 4 Strike, 즉 정답
  • 4 Strike가 아닌 경우 - S와 B의 누적된 값을 알려줌 
  • count가 10이상일때. (즉, 횟수 초과시) - for문 돌기전에 count++되니까

if- else if - else문을 활용하자.

if(strike === 4) {              // S가 4개면 정답이므로
      console.log(`숫자를 맞췄습니다. 시도횟수 : $(count-1)회`);     // count는 0부터시작이므로 -1회임
      break;          // ❗❗ 10번 전에 맞추면 반복문 break할 수 있도록
      } else if (count >= 10) {             // 0부터 9까지 총 10회 가능
      console.log('시도 횟수를 초과했습니다.');
      } else {
      console.log(inputArr.join('') + ': ' + strike + 'S' + ball + 'B');        // join - 문자열로 이어줌
      }
}

💡array.join(구분자)

- 배열을 합쳐서 문자열로 만듬.

- 배열의 각 아이템 사이에 구분자를 넣음. (위 예제에서는 '', 즉 구분자없이 합침)

 

 

 


최종 코드

let list = [0,1,2,3,4,5,6,7,8,9];
let number = [];

for(let i=0; i<4; i++) {
    let select = Math.floor(Math.random() * list.length);
    number[i] = list.splice(select, 1)[0];
}

let strike = 0;
let ball = 0;
let count = 0;

while (count < 10) {         
	let input = prompt('숫자를 입력하세요');
    let inputArr = input.split('')      
    
    strike = 0;
    ball = 0;
    
    count++;          
    
    if(let j=0; j<4; j++) {
    	for(let k=0; k<4; k++) {
        	if(number[j] == inputArr[k]) {  
            	if(j === k){                   
                	strike++;
                } else { 
                	ball++;         
                }
              	break;          
              }
          }
      }
      
      if(strike === 4) {              
      console.log(`숫자를 맞췄습니다. 시도횟수 : $(count-1)회`);     
      break;          
      } else if (count >= 10) {            
      console.log('시도 횟수를 초과했습니다.');
      } else {
      console.log(inputArr.join('') + ': ' + strike + 'S' + ball + 'B');     
      }
}

 

 

 


REFERENCE

www.zerocho.com
이 포스팅은 zerocho님의 javascript 강의와 책을 보고 작성한 글입니다.
공부+기록 용으로 작성한 것입니다.