반응형
초등학생 시절..
수업시간에 연습장 펴고 몰래 했던 숫자야구게임을
과제로 받게되었다
룰따윈.. 너무 잘 알기 때문에 어떤걸 사용해서 구현할 지 고민하였다
기록용관리 매니저
게임 로직
시작화면
이렇게 세 클래스로 나눠서 진행을 하였다
기록관리용
RecordManager
몇 번째 게임에 시도횟수를 관리하는용도 + 3스트라이크 했을 시 기록관리에 데이터가 추가되는 용도 이기 때문에
recordValue를 Int형 배열로 만들어 getValues와 updateValue로 만들면 될것같다라고 생각했다
시작화면에 들어가게되면
게임 / 기록 / 게임종료 / 이외의 숫자나 문자를 누르게되면 "올바른 숫자를 다시 입력하세요"가 나오도록 해야하므로
우선 enum으로 ViewType으로 설정하고 시작 / 기록 / 나가기 케이스를 만들어주고
startGame 함수가 호출되면 while구문으로 누르는 버튼에 따라서 실행하면 될것같다라고 생각했습니다
그리고 게임로직은
컴퓨터에서 랜덤 숫자 생성을 배열로 잡고
시도횟수
게임 시작할 때 초기화해주는 메서드와
유효성검사 / 유효성 검사완료 후 ball, strike판별 함수로 넘어가게끔 작성하면 될것 같다 생각한 후 작업을 했습니다
enum ViewType: Int {
case start = 1
case record
case exit
}
class RecordManager {
private var recordValues: [Int] = []
func updateValue(_ value: Int) {
recordValues.append(value)
}
func getValues() {
if recordValues.isEmpty {
print("기록이 없습니다 게임을 시작하세요")
} else {
print("⭐️ 게임 기록 ⭐️")
recordValues.enumerated().map { idx, record in
print("\(idx + 1)번째 게임 : 시도 횟수 - \(record)")
}
}
}
}
class SceneManager {
private let recordManager: RecordManager
private let game: BaseballGame
init(recordManager: RecordManager, game: BaseballGame) {
self.recordManager = recordManager
self.game = game
}
func startGame() {
while true {
print("환영합니다! 원하시는 번호를 입력해주세요 \n 1. 게임 시작하기 2. 게임 기록 보기 3. 종료하기")
guard let pick = readLine(), let option = Int(pick) else {
print("올바른 숫자를 입력하세요")
continue
}
switch option {
case 1 :
game.startGame()
break
case 2 :
recordManager.getValues()
case 3 :
print("게임종료")
return
default :
print("올바른 숫자를 다시 입력하세요")
}
}
}
}
class BaseballGame {
private var answer: [Int] = []
private var attempt: Int = 0
private var record: RecordManager
init(record: RecordManager) {
self.record = record
}
private func updateRandomNumber() {
// var answer = Array(0...9).shuffled().prefix(3).map{ $0 }
// while answer.contains(0) {
// answer = Array(0...9).shuffled().prefix(3).map{ $0 }
// }
var answer = Array(Array(1...9).shuffled().prefix(3))
self.answer = answer
//print("⭐️ \(answer) ⭐️")
}
func startGame() {
answer = []
attempt = 0
updateRandomNumber()
playGame()
}
func validationNumber(number: String) -> [Int]? {
guard number.count == 3, let checkNum = Int(number) else { return nil }
let digit = String(checkNum).compactMap { $0.wholeNumberValue }
return Set(digit).count == 3 && !digit.contains(0) ? digit : nil
}
func checkNumber(_ number: [Int]) -> (strike: Int, ball: Int) {
let strike = zip(number, answer).filter { $0 == $1 }.count
let ball = number.filter { answer.contains($0) }.count - strike
return (strike, ball)
}
func incrementAttemp() {
attempt += 1
}
func playGame() {
while true {
print("숫자를 입력하세요")
guard let value = readLine(), let checkNum = validationNumber(number: value) else {
print("올바르지 않은 입력값입니다 다시 입력하세요")
continue
}
incrementAttemp()
let valid = checkNumber(checkNum)
if valid.strike != 3 {
print("\(valid.strike)strike \(valid.ball)ball")
}
else {
record.updateValue(attempt)
print("빙고 입니다")
break
}
}
}
}
let recordManager = RecordManager()
let baseballGame = BaseballGame(record: recordManager)
let sceneManager = SceneManager(recordManager: recordManager, game: baseballGame)
sceneManager.startGame()
하지만 여기서 마음에 들지 않는 점이
recordManager는 고유하기 때문에 굳이 저렇게 여기저기 넣을 필요 없이 딱 한번 선언하고 사용하면 되지 않을까라는 생각이 들어서 기록 매니저를 싱글톤 패턴으로 변경하였습니다
import Foundation
enum ViewType: Int {
case start = 1
case record
case exit
}
class RecordManager {
private var recordValues: [Int] = []
static let instance = RecordManager()
private init() {
}
func updateValue(_ value: Int) {
recordValues.append(value)
}
func getValues() {
if recordValues.isEmpty {
print("기록이 없습니다 게임을 시작하세요")
} else {
print("⭐️ 게임 기록 ⭐️")
recordValues.enumerated().map { idx, record in
print("\(idx + 1)번째 게임 : 시도 횟수 - \(record)")
}
}
}
}
class SceneManager {
private let game: BaseballGame
init(game: BaseballGame) {
self.game = game
}
func startGame() {
while true {
print("환영합니다! 원하시는 번호를 입력해주세요 \n 1. 게임 시작하기 2. 게임 기록 보기 3. 종료하기")
guard let pick = readLine(), let option = Int(pick) else {
print("올바른 숫자를 입력하세요")
continue
}
switch option {
case 1 :
game.startGame()
break
case 2 :
RecordManager.instance.getValues()
case 3 :
print("게임종료")
return
default :
print("올바른 숫자를 다시 입력하세요")
}
}
}
}
class BaseballGame {
private let recordManager:RecordManager
private var answer: [Int] = []
private var attempt: Int = 0
init(recordManager: RecordManager) {
self.recordManager = recordManager
}
private func updateRandomNumber() {
// var answer = Array(0...9).shuffled().prefix(3).map{ $0 }
// while answer.contains(0) {
// answer = Array(0...9).shuffled().prefix(3).map{ $0 }
// }
var answer = Array(Array(1...9).shuffled().prefix(3))
self.answer = answer
//print("⭐️ \(answer) ⭐️")
}
func startGame() {
answer = []
attempt = 0
updateRandomNumber()
playGame()
}
func validationNumber(number: String) -> [Int]? {
guard number.count == 3, let checkNum = Int(number) else { return nil }
let digit = String(checkNum).compactMap { $0.wholeNumberValue }
return Set(digit).count == 3 && !digit.contains(0) ? digit : nil
}
func checkNumber(_ number: [Int]) -> (strike: Int, ball: Int) {
let strike = zip(number, answer).filter { $0 == $1 }.count
let ball = number.filter { answer.contains($0) }.count - strike
return (strike, ball)
}
func incrementAttemp() {
attempt += 1
}
func playGame() {
while true {
print("숫자를 입력하세요")
guard let value = readLine(), let checkNum = validationNumber(number: value) else {
print("올바르지 않은 입력값입니다 다시 입력하세요")
continue
}
incrementAttemp()
let valid = checkNumber(checkNum)
if valid.strike != 3 {
print("\(valid.strike)strike \(valid.ball)ball")
}
else {
RecordManager.instance.updateValue(attempt)
print("빙고 입니다")
break
}
}
}
}
let baseballGame = BaseballGame(recordManager: RecordManager.instance)
let sceneManager = SceneManager(game: baseballGame)
sceneManager.startGame()
반응형
'혼자만의 미니 프로젝트' 카테고리의 다른 글
UIKit | 계산기 만들기 (0) | 2024.06.06 |
---|---|
UIKit | 팀소개 만들기 - 1일차 (0) | 2024.05.30 |