Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
9
Help us understand the problem. What is going on with this article?
@matyahiko2831

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

More than 1 year has passed since last update.

プログラミング入門者からの卒業試験は『ブラックジャック』を開発すべし」という記事に感化されて、
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

9
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
matyahiko2831
インプットしたこと・考えたことを言語化する練習をしています!お気軽にコメントください♪

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
9
Help us understand the problem. What is going on with this article?