Last active
November 18, 2019 08:06
-
-
Save godrm/6a2abddcb2a19a940aa16f9711677fd5 to your computer and use it in GitHub Desktop.
HughLadderGame 리팩토링
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct InputView { | |
enum Prompt : String { | |
case height = "> 사다리 높이를 입력해주세요.\n> " | |
case names = "> 참여할 사람 이름을 입력하세요.\n> " | |
} | |
static private func read(with prompt: Prompt) -> String { | |
print(prompt.rawValue) | |
let value = readLine() ?? "" | |
return value | |
} | |
static private func read(with prompt: Prompt, default value: Int) -> Int { | |
return Int(read(with: prompt)) ?? value | |
} | |
static func readLadderHeight() -> Int { | |
let count = read(with: .height, default: 0) | |
return count | |
} | |
static func readPlayerNames() -> String { | |
let names = read(with: .names) | |
return names | |
} | |
} | |
struct Utility { | |
static func commaSplit(string: String) -> [String] { | |
return string.split(separator: ",").map{ String($0) } | |
} | |
} | |
protocol LadderPlayerPrintable { | |
func displayName() -> String | |
} | |
struct Player : Equatable { | |
private var name : String | |
init(with name: String) { | |
self.name = name | |
} | |
} | |
extension Player : LadderPlayerPrintable{ | |
func displayName() -> String { | |
let padding = name + " " | |
let lastIndex = padding.index(padding.startIndex, offsetBy: 6, limitedBy: padding.endIndex) ?? padding.endIndex | |
return String(padding[..<lastIndex]) | |
} | |
} | |
protocol Stepable { | |
func canStepable() -> Bool | |
} | |
struct RandomStep : Stepable { | |
private var value : Int | |
init(with number: Int) { | |
value = number % 10 | |
} | |
func canStepable() -> Bool { | |
return value > 4 | |
} | |
} | |
protocol LadderPrintable { | |
func hasStep() -> Bool | |
} | |
struct LadderStep : LadderPrintable { | |
private var step : Bool | |
init(with random: Stepable) { | |
step = random.canStepable() | |
} | |
func hasStep() -> Bool { | |
return step | |
} | |
} | |
struct LadderRow { | |
let steps : Array<LadderPrintable> | |
init(with steps: [LadderPrintable]) { | |
self.steps = steps | |
} | |
subscript(index: Int) -> LadderPrintable { | |
return steps[index] | |
} | |
} | |
extension IndexPath { | |
init(row: Int, index: Int) { | |
self.init(indexes: [row, index]) | |
} | |
var row : Int { | |
return first ?? 0 | |
} | |
var index : Int { | |
return last ?? 0 | |
} | |
} | |
struct Ladders { | |
private var rows = [LadderRow]() | |
init(rows: Int, columns: Int) { | |
(0..<rows).forEach{ _ in | |
var row = [LadderStep]() | |
(0..<columns).forEach{ _ in | |
let random = RandomStep.init(with: Int.random(in: 0..<10)) | |
row.append(LadderStep(with: random)) | |
} | |
self.rows.append(LadderRow(with: row)) | |
} | |
} | |
subscript(indexPath : IndexPath) -> LadderPrintable { | |
rows[indexPath.row][indexPath.index] | |
} | |
} | |
struct LadderPlayers { | |
let players : [LadderPlayerPrintable] | |
init(with names : [String]) { | |
self.players = names.map{ | |
Player(with: $0) | |
} | |
} | |
var count : Int { | |
return self.players.count | |
} | |
subscript(index: Int) -> LadderPlayerPrintable { | |
return players[index] | |
} | |
} | |
protocol OutputPrintable { | |
func numberOfHeights(in view: OutputView) -> Int | |
func numberOfPlayers(in view: OutputView) -> Int | |
func output(_ view: OutputView, playerAt: Int) -> LadderPlayerPrintable | |
func output(_ view: OutputView, ladderAt: IndexPath) -> LadderPrintable | |
} | |
struct LadderGame : OutputPrintable { | |
private var height : Int | |
private var players : LadderPlayers | |
private var ladders : Ladders | |
init(with height: Int, names: [String]) { | |
self.height = height | |
self.players = LadderPlayers(with: names) | |
self.ladders = Ladders(rows: height, columns: names.count-1) | |
} | |
func numberOfHeights(in view: OutputView) -> Int { | |
return height | |
} | |
func numberOfPlayers(in view: OutputView) -> Int { | |
return players.count | |
} | |
func output(_ view: OutputView, playerAt: Int) -> LadderPlayerPrintable { | |
return players[playerAt] | |
} | |
func output(_ view: OutputView, ladderAt: IndexPath) -> LadderPrintable { | |
return ladders[ladderAt] | |
} | |
} | |
struct OutputView { | |
enum StepFormat : String { | |
case wall = "|" | |
case fill = "-----" | |
case empty = " " | |
} | |
private var printSource: OutputPrintable? | |
init(with source: OutputPrintable) { | |
self.printSource = source | |
} | |
private func displayPlayer(count: Int) { | |
guard let source = printSource else { return } | |
for index in 0..<count { | |
let player = source.output(self, playerAt: index) | |
print(player.displayName(), terminator:"") | |
} | |
print("") | |
} | |
private func displayLadder() { | |
let heights = printSource?.numberOfHeights(in: self) ?? 1 | |
let players = printSource?.numberOfPlayers(in: self) ?? 0 | |
for rowIndex in 0..<heights { | |
print(StepFormat.wall.rawValue, terminator:"") | |
for index in 0..<players-1 { | |
print(printSource?.output(self, ladderAt: IndexPath(row: rowIndex, index: index)).hasStep() ?? false | |
? StepFormat.fill.rawValue | |
: StepFormat.empty.rawValue, | |
terminator:StepFormat.wall.rawValue) | |
} | |
print("") | |
} | |
displayPlayer(count: players) | |
} | |
func display() { | |
displayLadder() | |
} | |
} | |
let height = InputView.readLadderHeight() | |
let name = InputView.readPlayerNames() | |
let players = Utility.commaSplit(string: name) | |
let game = LadderGame(with: height, names: players) | |
let output = OutputView.init(with: game) | |
output.display() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment