본문 바로가기
프로그래밍/Algorithm

[백준 BAEKJOON] 17215번 볼링 점수 계산

by bantomak 2024. 1. 22.

문제

소현이는 친구들과 함께 볼링을 치러 볼링장에 갔다. 그런데 볼링장의 시스템 오류로 인해 점수판에 점수가 집계 되지 않는 문제가 있었다. 밖이 너무 추운 나머지 소현이와 친구들은 그냥 치기로 하였고 1게임이 끝났지만 각자 점수가 얼마나 되는지를 계산하지 못하고 있다. 소현이와 친구들을 위해 볼링 점수를 계산해주는 프로그램을 작성해 보자.

 

볼링 규칙

  • 1게임은 총 10프레임으로 구성되어 있다.
  • 각 프레임마다 볼링핀 10개를 세워두고 공으로 쓰러뜨리는 것이며 기본적으로 볼링핀 1개당 1점이다.
  • 각 프레임마다 2번의 기회가 주어지며 첫 번째 기회에 10개의 핀을 모두 쓰러뜨리는 것을 스트라이크(S)라고 한다.
  • 두 번째 기회까지 사용하여 10개의 핀을 쓰러뜨리는 것을 스페어(P)라고 한다.
  • 스트라이크를 치면 다음 두 번의 기회동안 쓰러뜨린 볼링핀의 개수만큼 추가점수를  얻게 된다.
  • 10프레임을 제외한 프레임에서 스트라이크를 치면 해당 프레임의 두 번째 기회는 사라진다.
  • 스페어를 치면 다음 한번의 기회동안 쓰러뜨린 볼링핀의 개수만큼 추가점수를 얻게 된다.
  • 마지막 10번째 프레임에서 스트라이크를 칠 경우 두번의 보너스 기회가 제공된다. 이때 두번의 보너스 기회동안 추가점수는 존재하지 않는다.
  • 마지막 10번째 프레임에서 스페어를 칠 경우 한번의 보너스 기회가 제공된다. 이때 한번의 보너스 기회동안 추가점수는 존재하지 않는다.

 

입력

첫째 줄에 각 기회마다 소현이가 쓰러뜨린 볼링핀의 개수가 공백없이 주어진다. 이때 스트라이크는 S, 스페어는 P, 핀을 하나도 못 쓰러뜨린 것은 -으로 주어진다.

 

출력

첫째 줄에 소현이의 점수를 출력한다.

 

 

17215번: 볼링 점수 계산

첫째 줄에 각 기회마다 소현이가 쓰러뜨린 볼링핀의 개수가 공백없이 주어진다. 이때 스트라이크는 S, 스페어는 P, 핀을 하나도 못 쓰러뜨린 것은 -으로 주어진다.

www.acmicpc.net

 

 

풀이 코드

using System;
using System.Collections.Generic;
using System.Linq;

namespace backjun
{
    public class Bowling
    {
        private (int, int, int, int)[] m_score;
        private List<Action<int>> m_action = new();
        private int m_frame;
        private int m_ballCount;
        private int m_prevPin;
        private const int STRIKE = 10;
        private const int SPARE = 10;
        private const int LAST_FRAME = 9;

        public Bowling()
        {
            m_score = new (int, int, int, int)[10];
            m_frame = 0;
            m_ballCount = 0;
            m_prevPin = 0;
        }

        public void ThrowBall(char pin)
        {
            var frame = m_frame;
            var pinScore = InputScore(pin);
            m_prevPin = pinScore;

            if (m_ballCount == 0)
            {
                m_score[m_frame].Item1 = pinScore;
            }
            else if (m_ballCount == 1)
            {
                m_score[m_frame].Item2 = pinScore;
            }
            else
            {
                m_score[m_frame].Item3 = pinScore;
            }

            m_score[m_frame].Item4 += pinScore;
            m_ballCount++;

            foreach (var func in m_action.ToList())
            {
                func.Invoke(pinScore);
                m_action.Remove(func);
            }

            if (m_frame < LAST_FRAME)
            {
                if (m_score[m_frame].Item1 == STRIKE)
                {
                    m_action.Add(pin =>
                    {
                        m_score[frame].Item4 += pin;
                        m_action.Add(pin => m_score[frame].Item4 += pin);
                    });
                }
                else if (m_score[m_frame].Item1 + m_score[m_frame].Item2 == SPARE)
                {
                    m_action.Add(pin => m_score[frame].Item4 += pin);
                }

                if (pinScore == 10 || m_ballCount == 2)
                {
                    m_frame++;
                    m_ballCount = 0;
                    m_prevPin = 0;
                }
            }
        }

        private int InputScore(char pin)
        {
            int add;

            if (pin == 'S')
            {
                add = 10;
            }
            else if (pin == 'P')
            {
                add = 10 - m_prevPin;
            }
            else if (pin == '-')
            {
                add = 0;
            }
            else
            {
                add = Int32.Parse(pin.ToString());
            }

            return add;
        }

        public int TotalScore()
        {
            int sum = 0;

            foreach (var i in m_score)
            {
                sum += i.Item4;
            }

            return sum;
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            var inputs = Console.ReadLine();

            Bowling bowling = new Bowling();

            for (int i = 0; i < inputs?.Length; i++)
            {
                bowling.ThrowBall(inputs[i]);
            }

            Console.WriteLine(bowling.TotalScore());
        }
    }
}

 

후기

정답이라고 생각했는데 계속 틀려서 여러가지 넣어서 확인해본 결과

 

SSSSSSSSSS4P

 

 

10프레임 3번째 스페어 처리에서 버그가 있었다. 이전 투구의 나머지 값을 처리하는 식으로 코드를 처음부터 작성했다면 발생하지 않을 버그였는데 다음에는 그렇게 작성해야겠다고 반성했다.

댓글