新Swiftで行こう…第61回「トランプ3解説」 田部井保
無限ループを防ぐ方法、カードの残り枚数を数える。
//
// ViewController.swift
// Card
//
// Created by 保 Tabei on 2024/09/25.
//
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
///既に出ているかチェックする、出ていたらtrue
///出ていなかったらfalse、とりあえず
///EnumCard.Count枚分falseで埋める
var check = [Bool](repeating: false, count: EnumCard.Count)
///ボタン押下時処理
@IBAction func btnGoTouch(_ sender: Any) {
//残り枚数0なら初期化
if rest == 0 {
//check配列を全部falseに
for i in 0 ..< EnumCard.Count
{
check[i] = false
}
//残り枚数をEnumCard.Countに
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 {
//カード乱数発生(0〜EnumCard.Count - 1)
card = Int.random(in: 0 ..< EnumCard.Count)
//既に出ていたら繰り返す
} while check[card]
//新たに出たカード既に出ているとマークする
check[card] = true
//残り枚数を−1
rest -= 1
//ジョーカーの場合
if card == 52 {
lblCard.text = "JK"
//ジョーカー以外の場合
} else {
//カード表示用ラベルにマークとナンバーを表示
lblCard.text = mark[card / 13] + number[card % 13]
}
}
}
30行目で、残り枚数を数える rest という変数を定義しています。ここには、最初 EnumCard.Count が入ります。そして、1枚引く毎に68行目で、−1しています。そして rest が0になったら、40〜54行目で初期化してメッセージを出しています。42行目ですが、for i in 0 ..< EnumCard.Count となっています。これもループ(繰り返し)の一種で、i が0からEnumCard.Count – 1 まで44行目を繰り返します。このループは、一番分かり易いと思います。
68行目の rest -= 1 ですが、これは rest = rest – 1 と書いたのと同じになります。Swiftの以前のバージョンでは、同じ意味で rest– とも書けたのですが、現在この書き方はエラーになります。
2巡目の最初のカードが初期化アラートが出た時にもう出てしまっているのを防ぐ書き方です。
//
// ViewController.swift
// Card
//
// Created by 保 Tabei on 2024/09/25.
//
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
///既に出ているかチェックする、出ていたらtrue
///出ていなかったらfalse、とりあえず
///EnumCard.Count枚分falseで埋める
var check = [Bool](repeating: false, count: EnumCard.Count)
///ボタン押下時処理
@IBAction func btnGoTouch(_ sender: Any) {
//残り枚数0なら初期化
if rest == 0 {
//check配列を全部falseに
for i in 0 ..< EnumCard.Count
{
check[i] = false
}
//残り枚数をEnumCard.Countに
rest = EnumCard.Count
//アラート
let alert = UIAlertController()
alert.title = "初期化"
alert.message = "カードを配り直します"
alert.addAction(UIAlertAction(title: "OK", style: .default))
present(alert, animated: true, completion: nil)
}
//残り枚数0以上
else {
//カード番号保持変数
var card:Int
repeat {
//カード乱数発生(0〜EnumCard.Count - 1)
card = Int.random(in: 0 ..< EnumCard.Count)
//既に出ていたら繰り返す
} while check[card]
//新たに出たカード既に出ているとマークする
check[card] = true
//残り枚数を−1
rest -= 1
//ジョーカーの場合
if card == 52 {
lblCard.text = "JK"
//ジョーカー以外の場合
} else {
//カード表示用ラベルにマークとナンバーを表示
lblCard.text = mark[card / 13] + number[card % 13]
}
}
}
}
if 文の後に書かれていたものを else の中に移すだけで大丈夫です。
全部使っているかチェックするバージョンです。
//
// ViewController.swift
// Card
//
// Created by 保 Tabei on 2024/09/25.
//
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
}
///既に出ているかチェックする、出ていたらtrue
///出ていなかったらfalse、とりあえず
///EnumCard.Count枚分falseで埋める
var check = [Bool](repeating: false, count: EnumCard.Count)
///ボタン押下時処理
@IBAction func btnGoTouch(_ sender: Any) {
//チェックをするbool変数を定義
var chk: Bool = true
//全カードを調べる
for i in 0 ..< EnumCard.Count {
//chkにcheck配列の値を入れる
chk = check[i]
//chkがfalseなら、まだ出ていないカードがある
if chk == false {
//chk が false でループを抜ける
break
}
}
//全カードがtrueなら
if chk {
//check配列を全部falseに
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)
}
//1枚でも false (出ていない)があれば
else {
//カード番号保持変数
var card:Int
repeat {
//カード乱数発生(0〜EnumCard.Count - 1)
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]
}
}
}
}
rest 関連を削除しました。
37行目
var chk: Bool = true
としましたが、
var chk = true
で大丈夫です。
39行目から47行目で、全 check 配列を調べて、まだ出ていない false があったら、break でループを抜けています。
カードの残り枚数を数えて表示するようにしました。
//
// ViewController.swift
// Card
//
// Created by 保 Tabei on 2024/09/25.
//
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
}
///既に出ているかチェックする、出ていたらtrue
///出ていなかったらfalse、とりあえず
///EnumCard.Count枚分falseで埋める
var check = [Bool](repeating: false, count: EnumCard.Count)
///残り枚数を保持する変数
var count = EnumCard.Count
///ボタン押下時処理
@IBAction func btnGoTouch(_ sender: Any) {
//チェックをするbool変数を定義
var chk = true
//全カードを調べる
for i in 0 ..< EnumCard.Count {
//chkにcheck配列の値を入れる
chk = check[i]
//chkがfalseなら、まだ出ていないカードがある
if chk == false {
//chk が false でループを抜ける
break
}
}
//全カードがtrueなら
if chk {
//check配列を全部falseに
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
}
//1枚でも false (出ていない)があれば
else {
//残り枚数を1減算
count -= 1
//残り枚数表示用ラベルに残り枚数を表示
lblCount.text = count.description
//カード番号保持変数
var card:Int
repeat {
//カード乱数発生(0〜EnumCard.Count - 1)
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]
}
}
}
}
ここは、そんなに難しくは無いのではないでしょうか。
この場合は、カードの残り枚数を数えていた方がすんなりいきます。
//
// ViewController.swift
// Card
//
// Created by 保 Tabei on 2024/09/25.
//
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
}
///既に出ているかチェックする、出ていたらtrue
///出ていなかったらfalse、とりあえず
///EnumCard.Count枚分falseで埋める
var check = [Bool](repeating: false, count: EnumCard.Count)
///残り枚数を保持する変数
var count = EnumCard.Count
///ボタン押下時処理
@IBAction func btnGoTouch(_ sender: Any) {
//残り枚数0なら初期化
if count == 0 {
//check配列を全部falseに
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
}
//残り枚数0以上
else {
//残り枚数を1減算
count -= 1
//残り枚数表示用ラベルに残り枚数を表示
lblCount.text = count.description
//カード番号保持変数
var card:Int
repeat {
//カード乱数発生(0〜EnumCard.Count - 1)
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]
}
}
}
}
ここも、そんなに難しくないと思います。回り回って、最初に戻った様な感じです。
とりあえず♣️だけ、全13枚が配られるか分かるソースコードにしてみます。
//
// ViewController.swift
// Card
//
// Created by 保 Tabei on 2024/09/25.
//
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
}
///既に出ているかチェックする、出ていたらtrue
///出ていなかったらfalse、とりあえず
///EnumCard.Count枚分falseで埋める
var check = [Bool](repeating: false, count: EnumCard.Count)
///残り枚数を保持する変数
var count = EnumCard.Count
///ボタン押下時処理
@IBAction func btnGoTouch(_ sender: Any) {
//残り枚数0なら初期化
if count == 0 {
//check配列を全部falseに
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
}
//残り枚数0以上
else {
//残り枚数を1減算
count -= 1
//残り枚数表示用ラベルに残り枚数を表示
lblCount.text = count.description
//カード番号保持変数
var card:Int
repeat {
//カード乱数発生(0〜EnumCard.Count - 1)
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
}
}
}
}
今回は、ラベルを並べて、名前を付けるのが大変でしたね。♣️限定にするのに、43行目を53から13にするだけで済むのは非常に楽ですね。今回は面倒くさいだけで、内容的には簡単だったと思います。