なぜ、あなたはJavaでオブジェクト指向開発ができないのか―Javaの壁を克服する実践トレーニング
- 作者: 小森裕介,アクロクエストテクノロジー株式会社
- 出版社/メーカー: 技術評論社
- 発売日: 2004/12/01
- メディア: 単行本
- 購入: 10人 クリック: 217回
- この商品を含むブログ (50件) を見る
とりあえずコード。Linux 向けなので Mac の人は import を変更して下さい。
import Glibc import Foundation //再追記参照 let (STONE, SCISSORS, PAPER) = (0, 1, 2) class Player { let name: String var wincount: Int init(playername: String) { name = playername wincount = 0 } func showHand() -> Int { let hand: Int let rnd = random() % 3 if rnd < 1 { hand = STONE } else if rnd < 2 { hand = SCISSORS } else { hand = PAPER } return hand } func notifyResult() { wincount += 1 } } class Judge { func janken(_ player1: Player,_ player2: Player) { srand(UInt32(time(nil))) print("【ジャンケン開始】") for c in 1...3 {playJanken(c, player1, player2)} print("\n【ジャンケン終了】\n\n") let final_winner = judgeFinalWinner(player1, player2) print("\(player1.wincount) 対 \(player2.wincount)で", terminator: "") if final_winner != nil { print(final_winner!.name + "の勝ちです!") } else { print("引き分けです") } } func playJanken(_ c: Int,_ player1: Player,_ player2: Player) { print("\n【\(c)回戦目】") let winner = judgeJanken(player1, player2) if winner != nil { print(winner!.name + "が勝ちました!") winner!.notifyResult() } else { print("引き分けです") } } func judgeJanken(_ player1: Player,_ player2: Player) -> Player? { var winner: Player? let p1hand: Int = player1.showHand() let p2hand: Int = player2.showHand() printHand(p1hand) print(" vs. ", terminator: "") printHand(p2hand) print() if p1hand == STONE && p2hand == SCISSORS || p1hand == SCISSORS && p2hand == PAPER || p1hand == PAPER && p2hand == STONE { winner = player1 } else if p1hand == STONE && p2hand == PAPER || p1hand == SCISSORS && p2hand == STONE || p1hand == PAPER && p2hand == SCISSORS { winner = player2 } return winner } func judgeFinalWinner(_ player1: Player,_ player2: Player) -> Player? { var winner: Player? let p1: Int = player1.wincount let p2: Int = player2.wincount if p1 > p2 { winner = player1 } else if p1 < p2 { winner = player2 } return winner } func printHand(_ hand: Int) { switch hand { case STONE: print("グー", terminator: "") case SCISSORS: print("チョキ", terminator: "") case PAPER: print("パー", terminator: "") default: break } } } let player1 = Player(playername: "村田さん") let player2 = Player(playername: "山田さん") let judge = Judge() judge.janken(player1, player2)
実行例。
【ジャンケン開始】 【1回戦目】 パー vs. グー 村田さんが勝ちました! 【2回戦目】 グー vs. パー 山田さんが勝ちました! 【3回戦目】 パー vs. グー 村田さんが勝ちました! 【ジャンケン終了】 2 対 1で村田さんの勝ちです!
いちばんハマったのは、関数の呼び出しです。デフォルトでは引数には必ずラベルをつけて呼び出さなくてはならないので、省略する場合には _(アンダースコア)を関数定義の引数の前につけねばなりません。それから、変数に nil は代入できないので、そうしたければオプショナル型(変数定義の際に型の最後に ? をつける)というものを使います。オプショナル型を呼び出すときは、変数のあとに ! をつけて unwrap(ラップを解く)しなければなりません。あと、ささいなことですが、print() で改行したくないときは、引数の最後に terminator: "" をつけます。
このくらいですかね。ああ、初心者には疲れた。
ごらんのとおり、かなりスッキリとは書けます。自分のような初心者でも使いやすい感じです。
※注記
上で random() 関数を使っていますが、これは僕の OS が Linux で、Linux 向けの Swift では arc4dandom() がサポートされていない(!)からです。random() はインタプリタでは普通に使えますが、コンパイルすると実行毎にすべて同じ乱数になってしまいます。このへんはほとんど BUG です。回避の方法もあるようですが、面倒です(ここなど)。
後記:
解決しました。srand() で random() の seed を与えることができるので、srand(UInt32(time(nil))) を追加しました。これでコンパイルしても実行毎に異なった乱数を発生させることができました。なお、time() は import Fondation が必要です。
※再追記
Swift 3.1-dev だと 2行目の import Foundation
は必要ないようです(あるとエラーになります)。これでコンパイルしても time() は使えます。