質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

2441閲覧

xcodeで乱数がおかしい・デッキ制限ありのときのトランプランダム配布の処理

zukain5

総合スコア8

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2015/09/19 12:59

編集2015/09/20 00:53

###前提・実現したいこと
Xcode6.4 (6E35b),iOS SDK8.4の環境でアプリを作ろうとしています。ボタンを押すと、手札にランダムなマーク、数字のカードが追加されるというようなプログラムを作りました。しかし、その「ランダム」がなんだかおかしいです。。。

###発生している問題・エラーメッセージ
実際のiOS Simulatorの画像
このように、まあランダムではあるんですが、明らかに偏りが生じています。。。これじゃあトランプでゲーム!なんてとてもじゃないけどできません。。。

下記のソースコードのランダムの部分を作ってるコードはplaygroundで作ったものなのですが、playgroundでは正常に作動していました。しかし実際にアプリの方に移したらこのような結果になっています。。。

###ソースコード

swift

1import UIKit 2 3class ViewController: UIViewController { 4 5 var w = UIScreen.mainScreen().bounds.size.width 6 var h = UIScreen.mainScreen().bounds.size.height 7 var imageView :Array<UIImageView> = [] 8 var n = 0 9 var tefuda = [Int](count: 21, repeatedValue: 0) 10 11 override func viewDidLoad() { 12 super.viewDidLoad() 13 // Do any additional setup after loading the view, typically from a nib. 14 15 for i in 0...20 { 16 tefuda[i] = Int(arc4random_uniform(51)) + 1 17 } 18 } 19 20 override func didReceiveMemoryWarning() { 21 super.didReceiveMemoryWarning() 22 // Dispose of any resources that can be recreated. 23 } 24 25 @IBOutlet weak var imageButton: UIButton! 26 27 @IBAction func buttonAction(sender: AnyObject) { 28 29 var color = "c" 30 var number = 0 31 var show = "c01" 32 33 34 //println("\(tefuda[n])") 出力されず… 35 36 switch tefuda[n] { 37 38 case 1...13: 39 color = "c" 40 case 14...26: 41 color = "d" 42 case 27...39: 43 color = "h" 44 case 40...52: 45 color = "s" 46 default: 47 break 48 49 } 50 51 if tefuda[n] % 13 == 0 { 52 number = 13 53 } else { 54 number = tefuda[0] % 13 //←ここの0がnでした 55 } 56 57 if number < 10 { 58 show = color + "0" + String(number) 59 } else { 60 show = color + String(number) 61 } 62 63 imageView.append(UIImageView(frame: CGRectMake(CGFloat(10+20*n), CGFloat(9*h/10-150), CGFloat(100), CGFloat(150)))) 64 65 self.view.addSubview(imageView[n]) 66 67 imageView[n].image = UIImage(named: show) 68 69 n++ 70 71 } 72} 73

###補足情報(言語/FW/ツール等のバージョンなど)

  • 画像はc01.png(クローバーの1)からc13.png(クローバーの13)まで、といった感じにリソースファイル(?)に読み込んであります。ダイヤはd、ハートはh、スペードはsが数字の前についています。
  • 配列tehudaをprintln()で出力しようとしたのですがなぜか出力されず。。。何回再起動しても同じ数字ばっかりでます…なぜか時々挟まってくるキングが不思議です笑
  • arc4random_uniformのところをarc4randomでやったりもしましたがダメでした
  • 内容的には、ブラックジャックを意識してます。6デッキ以上使うことを想定しているため、Aが21枚出るかも…と思ったので、tehuda[]の要素数は21個です。
  • プログラミングは趣味でやってます。初心者ですので、とても初歩的なミスをしてるかもしれません。そうだったらごめんなさい。
  • 初めて質問します。何か無礼なことがあったら、申し訳ございません。もしよろしければ、分かる方、ご教授お願いいたします

####解決
ランダムに
ミスを修正した結果、ちゃんとランダムになりました!やった!回答してくださったお二方、本当にありがとうございました。

####複数のデッキを使った時のシャッフル

swift

1import UIKit 2 3class ViewController: UIViewController { 4 5 var w = UIScreen.mainScreen().bounds.size.width 6 var h = UIScreen.mainScreen().bounds.size.height 7 var imageView :Array<UIImageView> = [] 8 var n = 0 9var deckCount = 6 //デッキ数 10 var tefuda = [Int](count: 21, repeatedValue: 0) 11 12 override func viewDidLoad() { 13 super.viewDidLoad() 14 // Do any additional setup after loading the view, typically from a nib. 15 16var card = [Int](count: 52*deckCount, repeatedValue: 0) 17 18 //シャッフルされた配列 19var shuffledCard :Array<Int> = [] 20 21 //1~52がデッキ数並んだ配列card 22for i in 0...52*deckCount-1 { 23 ☆ card[i] = i % 52 + 1 24} 25 26 //シャッフル 27for i in 0...52*deckCount-1 { 28var index = Int(arc4random()) % card.count 29 30 ☆ shuffledCard.append(card[index]) 31 ☆ card.removeAtIndex(index) 32} 33 34 for i in 0...20 { 35 ☆ tefuda[i] = shuffledCard[i] 36 } 37 } 38 39 override func didReceiveMemoryWarning() { 40 super.didReceiveMemoryWarning() 41 // Dispose of any resources that can be recreated. 42 } 43 44 @IBOutlet weak var imageButton: UIButton! 45 46 47 48 49 50 51 @IBAction func buttonAction(sender: AnyObject) { 52 53 var color = "c" 54 var number = 0 55 var show = "c01" 56 57 58 //println("\(tefuda[n])") 59 60 switch tefuda[n] { 61 62 case 1...13: 63 color = "c" 64 case 14...26: 65 color = "d" 66 case 27...39: 67 color = "h" 68 case 40...52: 69 color = "s" 70 default: 71 break 72 73 } 74 75 if tefuda[n] % 13 == 0 { 76 number = 13 77 } else { 78 number = tefuda[n] % 13 79 } 80 81 if number < 10 { 82 show = color + "0" + String(number) 83 } else { 84 show = color + String(number) 85 } 86 87 imageView.append(UIImageView(frame: CGRectMake(CGFloat(10+20*n), CGFloat(9*h/10-150), CGFloat(100), CGFloat(150)))) 88 89 self.view.addSubview(imageView[n]) 90 91 imageView[n].image = UIImage(named: show) 92 93 n++ 94 95 } 96} 97

☆の部分を変更、及び追記しました。
良いプログラムではないと思いますが、正常に動作するのを確認できました。
シャッフルの処理はこちらより丸コピさせていただきました。勝手に使ってごめんなさい。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

トランプですから、単純にランダムカードを表示するのではなく、
同じカードが現れないようシャッフル処理すべきという話はありますが、
このコーディングで同じ数字ばっかり出る理由は

swift

1 if tefuda[n] % 13 == 0 { 2 number = 13 3 } else { 4 number = tefuda[0] % 13 5 } 6 7```の部分が誤っているからです。 8 9`number = tefuda[0] % 13` 10ではなく 11`number = tefuda[n] % 13` 12にしないと、全部tefuda[0]の数字のカードが表示されてしまいます。 13そして、tefuda[n]%130の時だけキングのカードが表示されます。

投稿2015/09/19 14:50

TakeOne

総合スコア6299

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zukain5

2015/09/19 15:16

TakeOne様 回答ありがとうございます。 本当ですね!! 初歩的なミスを犯していました…申し訳ありません。 playgroundの方では追加していく方式ではなく、一枚表示するだけだったので、tefuda配列の[0]しか使ってませんでした。まさかの移植ミス… おかげさまで、見事ちゃんとしたランダムを生成することができました。 同じカードがデッキ数より多く存在しないように調整しつつ、アプリを作っていこうと思います。ありがとうございました。
guest

0

サイコロを振る動作を乱数で行う場合と、トランプを配るのを乱数で行う場合は処理が変わります。
サイコロの場合は、同じ目が出てもよいですが、トランプを配る場合は、同じカードが2回以上 出てはいけないからです。

for i in 0...20 {
tefuda[i] = Int(arc4random_uniform(51)) + 1
}
では、同じカードが選ばれてしまう可能性があります。

シャッフルについての参考記事を紹介します。
参考:

投稿2015/09/19 14:26

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zukain5

2015/09/19 14:40

katoy様 回答ありがとうございます。 実際のカジノのように6デッキ以上使おうと考えていたのでとりあえずかぶりは無視しようかなと考えていました。そのことを記さずにいて申し訳ありません。自分は軽視していましたが、重大な問題であることにたった今、気づきました。ありがとうございます。 Arrayをシャッフルする方法を利用する新しいランダム配布の方法を思いついたので、それを試してみようと思います。 自分の頭になかった方法が浮かんでとても嬉しいです。 本当にありがとうございました。これからも頑張っていこうと思います。
zukain5

2015/09/19 15:13

申し訳ありません。 もう一人の回答者様から最適な回答をいただいてしまったので、本当に惜しいですがベストアンサーを外させていただきます。 しかし、単純にランダムだけでは確かにゲームとして成り立たないので、その点についてはミスがあったと気づかせていただきました。本当にありがとうございました。 また何かあったら宜しくお願いします。
katoy

2015/09/19 15:39 編集

質問文 (修正済) のコードでは 1..52 を カードに割り当てて、カードの番号を次のように計算してます。 if tefuda[n] % 13 == 0 { number = 13 } else { number = tefuda[n] % 13 } それよりは 0..51 をカードに割り当てて、カードの番号を次のように計算するほうが良いかもしれません。 number = (tefuda[n] % 13) + 1 (もちろん カードの C,S,D,H の判定方法も変更する必要があります) トランプを扱う場合は、 配列に 0..51 をいれて処理するか、"C1", ... "C13", ... "S13" を入れて処理するとよいと思います。 (1, 11, 12, 13 は (A, J, Q, K) で表すことにして、 Space King は "S13" よりは "SK" としたほうがいいかもしれません) カードを数字でなく、"C2" のようにして扱うことにした場合は、カードの種類、番号の計算処理そのものが不要になります。
zukain5

2015/09/19 16:27

多数のアドバイス、ありがとうございます。 確かに、"C2"のようにして扱えば、楽になりますね! 何よりわかりやすいですね。 ありがとうございました。 がんばります!
katoy

2015/09/19 21:28

ぜひ、複数トランプの組みのシャッフル処理の最終コードをここに載せて欲しいです。 同じことをしたい方へのよい助けになると思います。
zukain5

2015/09/20 00:55

追記しました! プログラムはだらだらと長くなってしまいましたが、正常に動作したので自分の中では満足しています。 この度は色々とありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問