LoginSignup
12
9

More than 5 years have passed since last update.

Kotlinでブラックジャック作ってみた

Last updated at Posted at 2018-05-08

プログラミング入門者からの卒業試験は『ブラックジャック』を開発すべし」という記事に感化されて、
Kotlinでブラックジャックを作成してみました。

私のスキル

  • エンジニア8年目
  • Java,PHP:業務で書いている
  • Kotlin:実務経験なし,ハンズオンに参加して得た知識のみ

ソースコード

https://github.com/matyahiko2831/BlackJackKotlin
参考サイトの開発開始以降はなるべく見ずに作成しました。
10時間くらいで作れたかなと思います。。。!

開発環境

  • Kotlin 1.2.40
  • Gradle 4.7
  • IntelliJ IDEA

実行結果

image.png
↑2018/05/08追記
PLAYERとあなた、DEALERとディーラー 文言統一されてないですねorz

作ってみた感想

  • 成果物が明確なので「調べながら開発する」という実務に近い営みが出来る。そのため、漫然とチュートリアルやったり参考書読むよりは身になると思いました!
  • ブラックジャックという題材はルールがわかりやすく難易度的にちょうどよいと思いました。
  • Kotlinがほぼ未経験ということを置いといても、クラス設計が下手くそ。。。
  • (本題から外れますが)無からKotlinが動作する環境を整えるということを経験できてよかったです。Gradleの設定やgitignoreがイケてないかもしれませんorz

ソース抜粋

メインクラス

Main.kt

package blackjack

import model.*
import exception.*

fun main(args: Array<String>) {

    println("☆★☆☆★☆ブラックジャックへようこそ!☆★☆☆★☆")
    println("ゲームを開始します")

    // デッキ初期化
    var deck = Deck()

    // プレイヤー・ディーラー初期化
    var player = User()
    var dealer = User()

    // プレイヤー 最初のドロー
    player.hand.add(deck.draw(Role.PLAYER))
    player.hand.add(deck.draw(Role.PLAYER))

    // ディーラー 最初のドロー
    dealer.hand.add(deck.draw(Role.DEALER))
    // 2枚目は何を引いたか表示させない
    dealer.hand.add(deck.draw(Role.DEALER,true))

    println("あなたの現在の得点は${player.getScore()}です。")

    var input: String?

    // ユーザーのターン
    while (true) {
        println("カードを引きますか?引く場合はYを、引かない場合はNを入力して下さい")
        input = readLine()

        if("Y" == input || "y" == input) {
            player.hand.add(deck.draw(Role.PLAYER))

            println("あなたの現在の得点は${player.getScore()}です。")

            if(player.isBurst()) {
                println("バーストしました。")
                println("あなたの負けです。")
                println("ブラックジャック終了!また遊んでね★")
                System.exit(0)
            }

        } else if("N" == input || "n" == input) {
            break
        } else {
            println("YかNを入力して下さい。")
        }
    }

    // ディーラーのターン
    println("ディーラーの2枚目のカードは${dealer.hand[1]}でした。")
    println("ディーラーの現在の得点は${dealer.getScore()}です。")

    // 得点が17点以上になるまで繰り返す
    while(dealer.getScore() < 17) {
        dealer.hand.add(deck.draw(Role.DEALER))
    }

    println("あなたの得点は${player.getScore()}です。")
    println("ディーラーの得点は${dealer.getScore()}です。")

    if(dealer.isBurst()
            || player.getScore() > dealer.getScore()) {
        println("あなたの勝ちです。")
    } else if (player.getScore() == dealer.getScore()){
        println("引き分けです。")
    } else {
        println("あなたの負けです。")
    }

    println("ブラックジャック終了!また遊んでね★")
}

所感

  • 「カードを引いてユーザの手札に加える」というユースケースをもっとうまく表現出来たと思う。(Userクラスにdrawメソッドを持たせる?)
  • RoleはUserクラスに持たせるべきだったかな。

カードクラス

Card.kt

package model

/**
 *
 * カードクラス
 * @param suit マーク
 * @param index 表示
 * @param rank ランク
 * @param used 使用済み
 *
 * */
class Card(val suit: Suit, val index: String, val rank: Int, var used: Boolean = false){

    public override fun toString(): String {
        return "${suit}の${index}"
    }
}

所感

  • PHPではおなじみの引数の初期値が設定できるのが良い。
  • フィールドもgetterもsetterもいらないんですね。

デッキクラス

Deck.kt
package model

import java.util.Random
import exception.*

/**
 * デッキクラス
 * */
class Deck {

    /** デッキ残数 */
    private var remaining: Int = 52

    public val cards = arrayOf<Card>(
            Card(Suit.SPADE, "1", 1),
            Card(Suit.SPADE, "2", 2),
            Card(Suit.SPADE, "3", 3),
            Card(Suit.SPADE, "4", 4),
            Card(Suit.SPADE, "5", 5),
            Card(Suit.SPADE, "6", 6),
            Card(Suit.SPADE, "7", 7),
            Card(Suit.SPADE, "8", 8),
            Card(Suit.SPADE, "9", 9),
            Card(Suit.SPADE, "10", 10),
            Card(Suit.SPADE, "J", 10),
            Card(Suit.SPADE, "Q", 10),
            Card(Suit.SPADE, "K", 10),
            Card(Suit.HART, "1", 1),
            Card(Suit.HART, "2", 2),
            Card(Suit.HART, "3", 3),
            Card(Suit.HART, "4", 4),
            Card(Suit.HART, "5", 5),
            Card(Suit.HART, "6", 6),
            Card(Suit.HART, "7", 7),
            Card(Suit.HART, "8", 8),
            Card(Suit.HART, "9", 9),
            Card(Suit.HART, "10", 10),
            Card(Suit.HART, "J", 10),
            Card(Suit.HART, "Q", 10),
            Card(Suit.HART, "K", 10),
            Card(Suit.DIAMOND, "1", 1),
            Card(Suit.DIAMOND, "2", 2),
            Card(Suit.DIAMOND, "3", 3),
            Card(Suit.DIAMOND, "4", 4),
            Card(Suit.DIAMOND, "5", 5),
            Card(Suit.DIAMOND, "6", 6),
            Card(Suit.DIAMOND, "7", 7),
            Card(Suit.DIAMOND, "8", 8),
            Card(Suit.DIAMOND, "9", 9),
            Card(Suit.DIAMOND, "10", 10),
            Card(Suit.DIAMOND, "J", 10),
            Card(Suit.DIAMOND, "Q", 10),
            Card(Suit.DIAMOND, "K", 10),
            Card(Suit.CLUB, "1", 1),
            Card(Suit.CLUB, "2", 2),
            Card(Suit.CLUB, "3", 3),
            Card(Suit.CLUB, "4", 4),
            Card(Suit.CLUB, "5", 5),
            Card(Suit.CLUB, "6", 6),
            Card(Suit.CLUB, "7", 7),
            Card(Suit.CLUB, "8", 8),
            Card(Suit.CLUB, "9", 9),
            Card(Suit.CLUB, "10", 10),
            Card(Suit.CLUB, "J", 10),
            Card(Suit.CLUB, "Q", 10),
            Card(Suit.CLUB, "K", 10)
    )

    /**
     * カードドロー
     * デッキが0枚になったらException
     * @return Card
     * @throws DeckOutException
     * */
    public fun draw(role: Role, hide: Boolean = false): Card {

        while (true) {
            val card = cards[Random().nextInt(cards.size)]

            if(!card.used) {
                card.used = true;
                remaining--

                if(hide) {
                    println("${role}の引いたカードは分かりません。")
                } else {
                    println("${role}の引いたカードは${card}です。")
                }
                return card
            }

            if (remaining == 0) {
                // いらないけど例外の勉強のために
                throw DeckOutException("デッキ切れ")
            }
        }
    }

}

所感

  • カードリストは絶対もっと良い実装があったと思う。

ご意見お待ちしておりますm(_ _)m

12
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
9