[프로그래머스] [1차] 다트 게임 JavaScript

·2024년 4월 8일

문제

카카오톡에 뜬 네 번째 별! 심심할 땐? 카카오톡 게임별~

카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.
갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.

  1. 다트 게임은 총 3번의 기회로 구성된다.
  2. 각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.
  3. 점수와 함께 Single(S), Double(D), Triple(T) 영역이 존재하고 각 영역 당첨 시 점수에서 1제곱, 2제곱, 3제곱으로 계산된다.
  4. 옵션으로 스타상(*) , 아차상(#)이 존재하며 스타상(*) 당첨 시 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다. 아차상(#) 당첨 시 해당 점수는 마이너스된다.
  5. 스타상(*)은 첫 번째 기회에서도 나올 수 있다. 이 경우 첫 번째 스타상(*)의 점수만 2배가 된다.
  6. 스타상(*)의 효과는 다른 스타상(*)의 효과와 중첩될 수 있다. 이 경우 중첩된 스타상(*) 점수는 4배가 된다.
  7. 스타상(*)의 효과는 아차상(#)의 효과와 중첩될 수 있다. 이 경우 중첩된 아차상(#)의 점수는 -2배가 된다.
  8. Single(S), Double(D), Triple(T)은 점수마다 하나씩 존재한다.
  9. 스타상(*), 아차상(#)은 점수마다 둘 중 하나만 존재할 수 있으며, 존재하지 않을 수도 있다.

0~10의 정수와 문자 S, D, T, *, #로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하라.

입력

"점수|보너스|[옵션]"으로 이루어진 문자열 3세트.
예) 1S2D*3T

점수는 0에서 10 사이의 정수이다.
보너스는 S, D, T 중 하나이다.
옵선은 *이나 # 중 하나이며, 없을 수도 있다.

출력

3번의 기회에서 얻은 점수 합계에 해당하는 정수값을 출력한다.

예제 입력

dartResult : 1S2D*3T

예제 출력

37

내가 했던 풀이 방법

사용한 변수는 다음과 같다.

answer : 점수 합계
stage : 보너스+[옵션]
score : 현재 기회 총 점수
prev_score : 이전 기회 총 점수
index : dartResult 문자열 중 현재 위치한 index

  1. 입력받은 문자열을 검사하지 않은 index부터 검사하여 해당 문자열을 숫자로 변환했을 때 NaN이 나오지 않을 때까지의 문자열을 score에 저장해준다. NaN이 나올 경우, score를 number형으로 변환해준다. (점수가 10점이 나올 수 있기 때문에 이와 같은 방법을 사용한다.)
  2. 입력받은 문자열에서 검사하지 않은 index부터 검사하여 해당 문자열을 숫자로 변환했을 때 NaN이 나올 때까지의 문자열을 stage에 저장해준다. NaN이 아닐 경우 또는 index가 입력받은 문자열의 길이 이상이 되기 직전까지의 문자열을 stage에 저장한다.
  3. stage의 첫 문자열이 D, T일 경우 score를 2제곱, 3제곱 해준다. (S일 경우는 변하지 않으므로 무시한다.)
  4. 만약 stage의 옵션이 포함된 경우(length가 2일 경우), 옵션이 *일 경우, score와 prev_score를 2배 해준다. (prev_score를 0으로 초기화해두었기 때문에 첫 번째 기회에서 스타상이 나올 경우에도 문제없이 풀이 가능하다.) #일 경우, score에 -1을 곱해준다.
  5. 총 점수에 prev_score를 더해준 뒤, score를 prev_score에 저장한다. (prev_score을 더해주는 이유는 다음 기회에서 스타상(*)이 등장할 경우, 이전 점수도 영향을 받기 때문에 점수가 영향을 받지 않는 경우(즉, 점수가 확정된 경우)에만 총 점수에 더해주도록 하였다. 이전 점수는 다음 기회부터는 영향을 받지 않기 때문에)
  6. 1~5번까지를 3회 실행한 뒤, 총 점수에 prev_score를 더해준다. (prev_score를 더해주기 때문에 1회 실행했을 때 총 점수에는 0(결과와 상관없는 값)이 더해진다. 즉, 1회 - 반영X, 2회 - 1회 결과, 3회 - 2회 결과가 저장되므로 3회 결과를 for문이 끝난 후, 추가로 더해주어야 한다.)

코드

function solution(dartResult) {
    var answer = 0;
    let stage = '';
    let index = 0;
    let score = 0;
    let prev_score = 0;
    for(let i=0; i<3; i++) {
        stage = '';
        score = 0;
        while(true) {
            if(isNaN(parseInt(dartResult.charAt(index)))) break;
            score += dartResult.charAt(index++);
        }
        score = parseInt(score);
        while(true) {
            if(!isNaN(parseInt(dartResult.charAt(index))) || index >= dartResult.length) break;
            stage += dartResult.charAt(index++);
        }
        
        if(stage.charAt(0)==="D") {
            score **= 2;
        } else if(stage.charAt(0)==="T") {
            score **= 3;
        }
        
        if(stage.length===2) {
            if(stage.charAt(1)==="*") {
                score *= 2;
                prev_score *= 2;
            } else {
                score *= -1;
            }
        }
        answer += prev_score;
        prev_score = score;
    }
    answer += prev_score;
    return answer;
}

회고

스타상 때문에 중간에 막힐 뻔 했으나 prev_score 변수를 추가하여 간단하게 해결할 수 있었다. 프로그래머스 문제가 백준에 비해 지문이 긴 경우가 정말 많은 것 같다. 그리고 현실에 있을 법한 상황이 주어져 구현하는 재미가 더 있는 것 같다. 그렇기 때문에 Lv.1임에도 불구하고 문제가 쉽게 느껴지지 않는다. (풀이는 정말 쉬운 편이긴 한데..) 빠르게 Lv.2까지 달려서 여름 전까지는 Lv.3/골드 문제들을 풀어보고 싶다.

profile
Frontend🍓

0개의 댓글