まだ全然実装できていないけど、とても勉強になっているので途中経過をブログに書いてみる。
github.com
なぜやっているのか
トランプくらい簡単に実装できる・・・そう思っていた時期が(ry
環境
この環境で勉強を始めたのが間違いだったかもしれない。
やりたいこと
- 汎用的にトランプのゲームを作れるようなライブラリ設計にする
- ポーカー、七並べ、大富豪など、メジャーなゲームを実装する
設計など
- Card が Rank ( 1 〜 13 ) と Suit (スペード、ハート、クラブ、ダイヤ) を持つ
- Card の強弱をゲームによって変える
- まだ Jocker は未実装
Swift で実装方法が分からなかった箇所など
stringLiteralConvertible で特定文字だけ許容したい
let card: Card<DefaultComparing> = "13S"
これで「スペード13」が生成したかった。結局、できなかったので、 init?
を使った。
https://github.com/sinsoku/PlayingCard/blob/908faee6fe4fe1d66e028ee481b6ad07c06f4322/Sources/PlayingCard/Card.swift#L14-L33
init?(_ value: String) {
var characters = value.characters
let suit = characters.popLast()
let rank = Int(String(characters))
guard let rankInt = rank where 1...13 ~= rankInt else {
return nil
}
guard let suitStr = suit where ["S", "H", "C", "D"].contains(suitStr) else {
return nil
}
switch suitStr {
case "S": self = Card<T>(rank: Rank(rawValue: rankInt)!, suit: .Spade)
case "H": self = Card<T>(rank: Rank(rawValue: rankInt)!, suit: .Heart)
case "C": self = Card<T>(rank: Rank(rawValue: rankInt)!, suit: .Club)
case "D": self = Card<T>(rank: Rank(rawValue: rankInt)!, suit: .Diamond)
default: return nil
}
}
無理矢理感がある・・・。
もうちょい綺麗になりそうだけど、よく分からんかったので他の実装を進めている。
戻り値を Set, Array で切り替えたい
https://github.com/sinsoku/PlayingCard/blob/908faee6fe4fe1d66e028ee481b6ad07c06f4322/Sources/PlayingCard/Util.swift
class Util {
static func factory<C: CardInitializeable>(_ values: String...) -> Set<C> {
let cards = values.map { C($0)! }
return Set(cards)
}
}
戻り値も Generics でうまく返したかったけど、よく分からなかった。
let arrCards: Array<Card<DefaultComparing>> = Util.factory("1S", "2S", "3S", "4S", "5S")
let setCards: Set<Card<DefaultComparing>> = Util.factory("1S", "2S", "3S", "4S", "5S")
本当は ArrayLiteral で定義できると綺麗なんだけど、これ init?
だから出来ないんですよね・・・。
let setCards: Set<Card<DefaultComparing>> = ["1S", "2S", "3S", "4S", "5S"]