이번 주는 야구 게임을 만들기를 해보았다. 이번 앱은 Command Line Tool을 이용한 값을 입력 받아 실행되게 하는 앱이다.
숫자 야구 게임
은 두 명이 즐길 수 있는 추리 게임으로, 상대방이 설정한 3자리의 숫자를 맞히는 것이 목표입니다. 각 자리의 숫자와 위치가 모두 맞으면 '스트라이크', 숫자만 맞고 위치가 다르면 '볼'로 판정됩니다. 예를 들어, 상대방의 숫자가 123일 때 132를 추리하면 1스트라이크 2볼이 됩니다. 이러한 힌트를 활용하여 상대방의 숫자를 추리해 나가는 게임입니다.
이번 과제로는 6단계를 나눔으로써 단계별로 기능을 추가하는 과정을 경험해 보는 느낌이였다.
기본적으로 게임에 있어 2명의 사람이 필요하지만 우리는 앱을 이용하기에 상대방의 정답을 우리가 모르게 생성해야한다.
💡 1 ~ 9 까지의 서로 다른 임의의 수를 3개를 만드는게 목표이다.
Int
에서 제공해주는 random메서드
를 이용하여 범위를 설정해서 생성Set
를 이용해서 임의의 중복되지 않은 3자리 만들어서 다시 배열
에 넣는 방식으로 생성 💡 이번엔 정답 값을 생성했기에 유저가 값을 입력받고 그 값이 생성된 정답 값을 비교해서 정답을 찾는 기능을 구현하는게 목표다. 이 게임의 핵심 기능이라고 볼 수 있다.
-> 같은 자리에 같은 숫자가 있는 경우 strike, 다른 자리에 숫자가 있는 경우 ball 이라고 한다.
readline
을 활용해 커맨드창에서 값을 받아서 유저의 입력 값을 배열
에 저장(순서를 보장하기 위해)do try catch
와 throws
를 활용하여 에러가 발생할 메서드에 에러 처리Error타입
을 미리 enum (커스텀 타입)
에 채택해 에러 요소를 미리 정의guard
문을 활용해 에러를 throw
하도록 구성 정답 값을 배열
에 저장 해놓았고 Lv.2에서 생성한 유저 입력 값을 배열
에 저장해 놓았는데 이 이유는 두 배열의 각 자리를 비교해 동일한 자리는 strike를 표현하기 위해서다. Set
으로 변경 후, 정답에 유저 입력 값이 몇개가 intersection
하는지 그래서 그 수를 구해서 총 ball의 갯수가 몇개인지 알아냈다. 그리고 앞에서 언급했듯이 두 배열의 값이 같다면 strike수를 +1, ball -1을 하는 방식으로 힌트를 주는 방식으로 구성했다.ex) 정답 : 256, 유저 입력 : 261
- 유저 값이 정답에 "6","2"가 겹치므로 [ 2 ball ]
- 두 값을 저장한 배열에서 각 순서대로 값을 비교 "2"가 같은 자리 strike +1, ball -1
- 계산 결과 < 1 strike, 1 ball >
while
문을 이용해 strike값이 정답의 길이인 "3"이 될 때까지 반복하도록 구성했다.# 1. 에러처리를 위해 do try catch
를 썼을 당시에 오류를 발생할 수 있는 메서드를 정의한 안에서 함수를 호출하는 재귀함수로 코드를 처음에 작성해 무한루프에 빠지게 되는 불상사가 일어나게 되었다. 재귀함수에 대해서 부족하게 알고 있다가 발생한 문제였다.
이 문제는 재귀함수로 썼던 do try catch
문을 함수를 호출하는 부분으로 옮겨 수정했다. (아래의 코드로 이동)
# 2. 에러 처리에 do try catch
문을 적용하는데 미리 정의한 Error를 나열한 enum 케이스를 모두 다 구현했지만 나타나는 오류가 있었다.
이 오류는 알고보니 모든 에러처리를 하더라도 혹시나 미리 정의한 에러케이스를 벗어나 발생할 수 있는 걸 대비해 아래와 같이 모든 에러를 받을 수 있는 catch
문을 하나 더 생성해야 했다.
💡 0 ~ 9 까지의 서로 다른 임의의 3자릿 수로 변경, 맨 앞자리에 0이 오는 것은 불가능
Set
값은 3자리이기에 다시 값을 생성할 순 없어서 로직을 바꾸게 되었다.for
문을 활용해 정답 값이 3개의 서로 다른 임의의 수가 될 때까지 반복하며< 초기 >
< 수정 >
💡 초기 앱이 시작 되었을 때 기능을 선택할 수 있는 안내문구를 생성, 게임의 정답을 맞춘 경우 종료 후 다시 앱의 초기화면으로 이동
ex) 환영합니다! 원하시는 번호를 입력해주세요.
1. 게임 시작하기 2. 게임 기록 보기 3. 종료하기
while
문을 이용해 앱의 초기화면을 호출하고 switch
문을 활용해 옵션을 선택할 수 있게 case
를 나눠서 선택된 옵션이 호출되게 하였다. 1번 게임 시작하기를 눌러 게임이 끝나면 다시 앱의 초기화면을 호출했다.💡 게임을 몇번 했는지, 게임안에서 몇번만에 정답을 맞췄는지 기록을 확인하는 기능을 추가
환영합니다! 원하시는 번호를 입력해주세요
1. 게임 시작하기 2. 게임 기록 보기 3. 종료하기
2 // 2번 게임 기록 보기 입력
< 게임 기록 보기 >
1번째 게임 : 시도 횟수 - 14
2번째 게임 : 시도 횟수 - 9
3번째 게임 : 시도 횟수 - 12
(초기화면-게임시작) while
문에서 게임 횟수를 카운트strike 수가 3이 될때까지 반복하는 while
문에서 시도 횟수를 카운트💡 앱 초기 화면에서 3번 종료하기의 경우 프로그램이 종료되도록 구현, 옵션 1,2,3 외의 값이 들어오면 오류 메세지로 알림
case
문에 앱의 초기화면으로 진입하지 못하도록 호출하지 않으면 게임이 종료 후 돌아기지 않는다.if
문을 활용해 처음 런타임을 가지면 진입하는 부분에서 게임의 끝나는 포인트를 변수로 만들고 0은 참
으로 앱의 초기화면으로 진입하도록 호출, 1이면 거짓
으로 앱의 초기화면을 부르지 않고 게임이 종료되도록 구성해 3번에 해당하는 케이스에서 이 변수를 1로 변경하도록 만들었다.readLine
으로 값을 입력받는데 이 값이 옵셔널값
이기에 이 부분에서 범위를 정해 1~3까지는 옵셔널 바인딩을 거쳐 제대로 출력하고 이외의 값이 들어오면 기본값인 0을 출력하도록 바꿔 switch
문에서 default
를 실행하게 구성했다.이번 과제를 시작하면서 저번에는 무작정 개발을 시작했다면 이번엔 내가 이 앱의 흐름을 직접 글로 적어서 만들어보았다. 이 흐름도를 이용해 내가 어디까지 개발했는지, 어느 부분에서 내가 생각한 로직대로 작동하지 않는지 등 개발하는 과정에서 길잡이처럼 도움이 되었다. 그리고 단계별로 나누어 기능을 어떤식으로 추가를 해야할지 왜 앱의 구조와 흐름을 잘 구성해야하는지 어떻게해야 나중에 유지보수와 기능 추가를 할 때 기존의 코드에 영향이 가지 않을지에 대해 한번 더 생각해보게 된거 같다.
오... guard let이랑 throw를 이용하면 저렇게 깔꼼하게 에러처리가 가능하군요... 저도 연습해야겠습니다