Skip to content

Instantly share code, notes, and snippets.

@godrm
Last active November 18, 2019 08:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save godrm/6a2abddcb2a19a940aa16f9711677fd5 to your computer and use it in GitHub Desktop.
Save godrm/6a2abddcb2a19a940aa16f9711677fd5 to your computer and use it in GitHub Desktop.
HughLadderGame 리팩토링
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