新Swiftで行こう…第13回「トランプ3」 田部井保

目次 解説編

 無限ループを防ぐ方法はいろいろあると思いますが、僕が思いついたのは、カードの残り枚数を数えて、0になったらリセットするという方法と、使ったかどうかで、全部使っているかチェックして使っていたらリセットするという方法です。サンプルを示します。

 カードの残り枚数を数える。以下ソースコードです。

//
//  ViewController.swift
//  Card
//
//  Created by 保 Tabei on 2024/09/01.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var lblCard: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    let mark: [String] = ["♣️","♦️","❤️","♠️"]
    let number: [String] = ["A","2","3","4","5","6","7","8","9","T","J","Q","K"]

    enum EnumCard {
        static let Count = 53
    }
    
    var rest = EnumCard.Count
    
    var check: [Bool] = [Bool](repeating: false, count: EnumCard.Count)
    
    @IBAction func btnGoTouch(_ sender: Any) {
        if rest == 0 {
            for i in 0 ..< EnumCard.Count 
            { 
                check[i] = false
            }
            rest = EnumCard.Count
            let alert = UIAlertController()
            alert.title = "初期化"
            alert.message = "カードを配り直します"
            alert.addAction(UIAlertAction(title: "OK", style: .default))
            present(alert, animated: true, completion: nil)        
        }

        var card:Int
        repeat {
            card = Int.random(in: 0 ..< EnumCard.Count)
        } while check[card]
        
        check[card] = true
        
        rest -= 1
                    
        if card == EnumCard.Count - 1 {
            lblCard.text = "JK"
        } else {
            lblCard.text = mark[card / 13] + number[card % 13]
        }
    }
}

 2巡目の最初のカードが初期化アラートが出た時にもう出てしまっているのを防ごうと思います。

//
//  ViewController.swift
//  Card
//
//  Created by 保 Tabei on 2024/09/01.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var lblCard: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    let mark: [String] = ["♣️","♦️","❤️","♠️"]
    let number: [String] = ["A","2","3","4","5","6","7","8","9","T","J","Q","K"]

    enum EnumCard {
        static let Count = 53
    }
    
    var rest = EnumCard.Count
    
    var check: [Bool] = [Bool](repeating: false, count: EnumCard.Count)
    
    @IBAction func btnGoTouch(_ sender: Any) {
        if rest == 0 {
            for i in 0 ..< EnumCard.Count
            {
                check[i] = false
            }
            rest = EnumCard.Count
            let alert = UIAlertController()
            alert.title = "初期化"
            alert.message = "カードを配り直します"
            alert.addAction(UIAlertAction(title: "OK", style: .default))
            present(alert, animated: true, completion: nil)
        }
        else
        {
            var card:Int
            repeat {
                card = Int.random(in: 0 ..< EnumCard.Count)
            } while check[card]
            
            check[card] = true
            
            rest -= 1
            
            if card == EnumCard.Count - 1 {
                lblCard.text = "JK"
            } else {
                lblCard.text = mark[card / 13] + number[card % 13]
            }
        }
    }
}

 全部使っているかチェックするバージョンです。この場合は全部チェックするので、数を間違えて無限ループに入る心配はありません。
以下ソースコードです。

//
//  ViewController.swift
//  Card
//
//  Created by 保 Tabei on 2024/09/01.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var lblCard: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    let mark: [String] = ["♣️","♦️","❤️","♠️"]
    let number: [String] = ["A","2","3","4","5","6","7","8","9","T","J","Q","K"]

    enum EnumCard {
        static let Count = 53
    }
    
    var check: [Bool] = [Bool](repeating: false, count: EnumCard.Count)
    
    @IBAction func btnGoTouch(_ sender: Any) {
        var chk: Bool = true
        for i in 0 ..< EnumCard.Count {
            chk = check[i] 
            if chk == false {
                break
            }
        }
        if chk {
            for i in 0 ..< EnumCard.Count
            {
                check[i] = false
            }
            let alert = UIAlertController()
            alert.title = "初期化"
            alert.message = "カードを配り直します"
            alert.addAction(UIAlertAction(title: "OK", style: .default))
            present(alert, animated: true, completion: nil)
        }
        else
        {
            var card:Int
            repeat {
                card = Int.random(in: 0 ..< EnumCard.Count)
            } while check[card]
            
            check[card] = true
            
            if card == EnumCard.Count - 1 {
                lblCard.text = "JK"
            } else {
                lblCard.text = mark[card / 13] + number[card % 13]
            }
        }
    }
}

 カードの残り枚数を数えて表示するようにしました。ラベルを画面に一つ追加して下さい。画面が出ているブロックを選んで上のViewメニューShow Libraryで出てくるものから画面にドラッグ&ドロップします。

//
//  ViewController.swift
//  Card
//
//  Created by 保 Tabei on 2024/09/01.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var lblCard: UILabel!
    @IBOutlet weak var lblCount: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    let mark: [String] = ["♣️","♦️","❤️","♠️"]
    let number: [String] = ["A","2","3","4","5","6","7","8","9","T","J","Q","K"]

    enum EnumCard {
        static let Count = 53
    }
    
    var check: [Bool] = [Bool](repeating: false, count: EnumCard.Count)
    
    var count = EnumCard.Count
    
    @IBAction func btnGoTouch(_ sender: Any) {
        var chk: Bool = true
        for i in 0 ..< EnumCard.Count {
            chk = check[i] 
            if chk == false {
                break
            }
        }
        if chk {
            for i in 0 ..< EnumCard.Count
            {
                check[i] = false
            }
            let alert = UIAlertController()
            alert.title = "初期化"
            alert.message = "カードを配り直します"
            alert.addAction(UIAlertAction(title: "OK", style: .default))
            present(alert, animated: true, completion: nil)
            count = EnumCard.Count
        }
        else
        {
            count -= 1
            lblCount.text = count.description
            
            var card:Int
            repeat {
                card = Int.random(in: 0 ..< EnumCard.Count)
            } while check[card]
            
            check[card] = true
            
            if card == EnumCard.Count - 1 {
                lblCard.text = "JK"
            } else {
                lblCard.text = mark[card / 13] + number[card % 13]
            }
        }
    }
}

 この場合は、カードの残り枚数を数えていた方がすんなりいきます。

//
//  ViewController.swift
//  Card
//
//  Created by 保 Tabei on 2024/09/01.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var lblCard: UILabel!
    @IBOutlet weak var lblCount: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    let mark: [String] = ["♣️","♦️","❤️","♠️"]
    let number: [String] = ["A","2","3","4","5","6","7","8","9","T","J","Q","K"]

    enum EnumCard {
        static let Count = 53
    }
    
    var check: [Bool] = [Bool](repeating: false, count: EnumCard.Count)
    
    var count = EnumCard.Count
    
    @IBAction func btnGoTouch(_ sender: Any) {
        if count == 0 {
            for i in 0 ..< EnumCard.Count
            {
                check[i] = false
            }
            let alert = UIAlertController()
            alert.title = "初期化"
            alert.message = "カードを配り直します"
            alert.addAction(UIAlertAction(title: "OK", style: .default))
            present(alert, animated: true, completion: nil)
            count = EnumCard.Count
        }
        else
        {
            count -= 1
            lblCount.text = count.description
            
            var card:Int
            repeat {
                card = Int.random(in: 0 ..< EnumCard.Count)
            } while check[card]
            
            check[card] = true
            
            if card == EnumCard.Count - 1 {
                lblCard.text = "JK"
            } else {
                lblCard.text = mark[card / 13] + number[card % 13]
            }
        }
    }
}

 とりあえず♣️だけ、全13枚が配られるか分かるソースコードにしてみます。ラベルを並べるだけでも結構面倒です。

//
//  ViewController.swift
//  Card
//
//  Created by 保 Tabei on 2024/09/01.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var lblCard: UILabel!
    @IBOutlet weak var lblCount: UILabel!
    
    @IBOutlet weak var lblKA: UILabel!
    @IBOutlet weak var lblK2: UILabel!
    @IBOutlet weak var lblK3: UILabel!
    @IBOutlet weak var lblK4: UILabel!
    @IBOutlet weak var lblK5: UILabel!
    @IBOutlet weak var lblK6: UILabel!
    @IBOutlet weak var lblK7: UILabel!
    @IBOutlet weak var lblK8: UILabel!
    @IBOutlet weak var lblK9: UILabel!
    @IBOutlet weak var lblKT: UILabel!
    @IBOutlet weak var lblKJ: UILabel!
    @IBOutlet weak var lblKQ: UILabel!
    @IBOutlet weak var lblKK: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    let mark: [String] = ["♣️","♦️","❤️","♠️"]
    let number: [String] = ["A","2","3","4","5","6","7","8","9","T","J","Q","K"]

    enum EnumCard {
        static let Count = 13
    }
    
    var check: [Bool] = [Bool](repeating: false, count: EnumCard.Count)
    
    var count = EnumCard.Count
    
    @IBAction func btnGoTouch(_ sender: Any) {
        if count == 0 {
            for i in 0 ..< EnumCard.Count
            {
                check[i] = false
            }
            
            lblKA.text = ""
            lblK2.text = ""
            lblK3.text = ""
            lblK4.text = ""
            lblK5.text = ""
            lblK6.text = ""
            lblK7.text = ""
            lblK8.text = ""
            lblK9.text = ""
            lblKT.text = ""
            lblKJ.text = ""
            lblKQ.text = ""
            lblKK.text = ""

            let alert = UIAlertController()
            alert.title = "初期化"
            alert.message = "カードを配り直します"
            alert.addAction(UIAlertAction(title: "OK", style: .default))
            present(alert, animated: true, completion: nil)
            count = EnumCard.Count
        }
        else
        {
            count -= 1
            lblCount.text = count.description
            
            var card:Int
            repeat {
                card = Int.random(in: 0 ..< EnumCard.Count)
            } while check[card]
            
            check[card] = true
            
            if card == 52 {
                lblCard.text = "JK"
            } else {
                lblCard.text = mark[card / 13] + number[card % 13]
            }
            
            switch card {
            case 0: lblKA.text = lblCard.text
            case 1: lblK2.text = lblCard.text
            case 2: lblK3.text = lblCard.text
            case 3: lblK4.text = lblCard.text
            case 4: lblK5.text = lblCard.text
            case 5: lblK6.text = lblCard.text
            case 6: lblK7.text = lblCard.text
            case 7: lblK8.text = lblCard.text
            case 8: lblK9.text = lblCard.text
            case 9: lblKT.text = lblCard.text
            case 10: lblKJ.text = lblCard.text
            case 11: lblKQ.text = lblCard.text
            default: lblKK.text = lblCard.text
            }
        }
    }
}

 ここで85行目は

            if card == EnumCard.Count - 1 {

となっていたのですが、EnumCard.Countを13にしたので、12(♣️K)の時にJKとなってしまいます。ここは52に戻すべきでしょう。

 実行してみましょう。重複無く配られましたか?

 さて問題です。今は、0〜12のランダムな数を発生させて、もし既に出ていたら、もう一度乱数を発生させるという方法を取っています。13枚なら大した事はないのですが、53枚だとある程度、不発が増えて来ます。最近のコンピュータは、演算速度が早いので問題にはなりませんが、少々気持ち悪いものです。既に一度出ているのでもう一度乱数を発生させるというのを止めさせる事は出来ないでしょうか?53枚だと枚数が多いので、♣️を13枚並べるようにした事で、何かソースコードに問題があった時に、発見しやすいという理由で、今回の最後のソースコードを元にして下さい。

目次 解説編

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA