🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
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

解決済

4回答

3181閲覧

乱数 重複しない

退会済みユーザー

退会済みユーザー

総合スコア0

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クリップ

投稿2017/04/17 09:48

編集2017/04/19 06:59

###前提・実現したいこと
今カルタの文を読んでくれるアプリ?を作っています。今できているところは48種類のカルタの文をランダムに読んでくれるところです。しかし、一度読んだ文もまた繰り返されます。それを一度読んだものはもう読まないようにしたいです。

ボタンを押すと次の文と最初の文字を表示しその文を
読み上げてくれるようになっています。

###該当のソースコード

swift

1 import UIKit 2 3import AVFoundation 4 5class ViewController: UIViewController { 6 7 @IBOutlet weak var QuestionLabel: UILabel! 8 9 @IBOutlet weak var Button1: UIButton! 10 11 @IBOutlet weak var Next: UIButton! 12 13 var CorrectAnswer = String\(\) 14 15 override func viewDidLoad\(\) { 16 super\.viewDidLoad\(\) 17 18 Hide\(\) 19 RandomQuestions\(\) 20 21 } 22 23 override func didReceiveMemoryWarning\(\) { 24 super\.didReceiveMemoryWarning\(\) 25 26 } 27 func RandomQuestions\(\){ 28 29 var RandomNumber = arc4random\(\) % 48 30 31 RandomNumber \+= 1 32 33 switch \(RandomNumber\) { 34 35 case 1: 36 37 QuestionLabel\.text = "モンゴルの民族模様は自由の印" 38 Button1\.setTitle\("も", for: \.normal\) 39//文を読む 40 let synthesizer = AVSpeechSynthesizer\(\) 41 let utterance = AVSpeechUtterance\(string: "モンゴルの民族模様は自由の印。"\) 42 synthesizer\.speak\(utterance\) 43 44 break 45 46 case 2: 47 48 QuestionLabel\.text = "三色の統一ドイツ黒赤金" 49 Button1\.setTitle\("さ", for: \.normal\) 50 51 let synthesizer = AVSpeechSynthesizer\(\) 52 let utterance = AVSpeechUtterance\(string: "三色の統一ドイツ黒赤金"\) 53 synthesizer\.speak\(utterance\) 54 55 56 57 break 58 59 case 3: 60 61 62 QuestionLabel\.text = "エクアドルコンドルが飛ぶアンデスへ" 63 Button1\.setTitle\("え", for: \.normal\) 64 65 let synthesizer = AVSpeechSynthesizer\(\) 66 let utterance = AVSpeechUtterance\(string: "エクアドルコンドルが飛ぶアンデスへ"\) 67 synthesizer\.speak\(utterance\) 68 69 70 break 71 72//略 73 74 75 76 case 48: 77 78 79 QuestionLabel\.text = "バーレーンはギザギザ模様で鮮やかに" 80 Button1\.setTitle\("ば", for: \.normal\) 81 82 let synthesizer = AVSpeechSynthesizer\(\) 83 let utterance = AVSpeechUtterance\(string: "バーレーンはギザギザ模様で鮮やかに"\) 84 synthesizer\.speak\(utterance\) 85 break 86 87 default: 88 89 break 90 91 } 92 93 } 94 95 func Hide\(\){ 96 97 Next\.isHidden = true 98 } 99 100 func UnHide\(\){ 101 102 Next\.isHidden = false 103 } 104 105 @IBAction func Button1Action\(_ sender: AnyObject\) { 106 107 UnHide\(\) 108 109 } 110 111 @IBAction func Next\(_ sender: AnyObject\) { 112 RandomQuestions\(\) 113 } 114 115} 116 117 118

###試したこと
nsuser defaultsを使ったり、空の配列を作り一度つかったものを入れたりなどと案は思いつきますが、どのようにコードを書くのかわかりません。

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

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

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

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

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

fuzzball

2017/04/18 01:38

質問とは関係ありませんが、乱数生成には arc4random_uniform() を使った方がいいです。
ozwk

2017/04/19 06:52

質問内容消してアカウント消すのってたまに見ますけど何がしたいんでしょうね?乗っ取り?
guest

回答4

0

Fisher-Yates法というのが、配列をシャッフルする定番のアルゴリズムです(ランダムな箇所をシャッフルし続ける方法では、「完璧に均等にはできない」ことが、比較的容易に証明できます)。

# 擬似コード while(i = arr.length; i >= 2; --i) { j = (0以上i-1以下の乱数) arr[i]とarr[j]を交換 }

投稿2017/04/17 10:30

編集2017/04/17 10:32
maisumakun

総合スコア145967

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

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

退会済みユーザー

退会済みユーザー

2017/04/17 10:49

ウィキペディア見ました。私もこれを作っている時に何回も同じものが繰り返されました。 どのようにwhile(i = arr.length; i >= 2; --i) { j = (0以上i-1以下の乱数) arr[i]とarr[j]を交換 } を使うと解決しますかね?
guest

0

ベストアンサー

欲しいのは1~48の乱数ではなく、
「1から48までの数字が、重複なく1回だけ出てくる、48個の値を持つリスト」だということを理解しましょう。

この場合乱数でランダムに1~48を作るのではなく、
0. 1~48までを順に並べたリストを用意する
0. 十分な回数(リスト内の個数の半分やればよいことが数学的に証明されています)、リストの任意の2か所の内容を入れ替える(シャッフル)

とやるのが定法です。

投稿2017/04/17 10:00

tacsheaven

総合スコア13703

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

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

maisumakun

2017/04/17 10:35

この方法では、理想的な乱数を使っても「完全な均等」は実現できません。 例えば、3個の配列を、n回の入れ替えでシャッフルしようとすると、入れ替え方の組み合わせは3のn乗通りになりますが、一方で目指すべき配列の並び方は6通りなので、割り切れません。
tacsheaven

2017/04/18 02:14

ん? 個数 n の順列で考えると、1回で2か所のデータを入れ替えますから n/2 回(ただし小数点以下切り上げ)入れ替えを行えば、どのような順列にも並び変わるのでは。あくまでも理論上は、ですが。これ以上の回数やっても、冗長な入れ替えが発生していることになります。
tacsheaven

2017/04/18 02:23

あー、そういうことか。個数が 2n+1 の順列の場合、任意の2か所を入れ替える方法では、何回入れ替えをやっても辿りつくことができない順列の並び順が存在するから、それらが出てこない、ですな。 今回の場合は個数が 2n なんで考えなくてもいいけど。
ozwk

2017/04/18 02:30 編集

> 任意の2か所 そもそも任意じゃダメなのでは
tacsheaven

2017/04/18 02:33 編集

いえ、「動かさない」(=同一の箇所を入れ替える)というパターンが存在しうるので、任意の2か所でよかったはず。最適手を取った場合(入れ替える位置が一切重複しない)、個数 2n であれば最大 n 回の入替で目標の順列にたどり着くことができる、はず。もう数学の授業は20年以上前のことなので忘れちゃってますが(棒
ozwk

2017/04/18 02:37

いや、「任意」じゃなくて「無作為」では?と言いたかったんです
tacsheaven

2017/04/18 02:46

ああ、そういうことですか。納得しました。確かに無作為の方が良かったかもしれません。
guest

0

var RandomNumber = arc4random() % 48

の取得結果を配列に格納していって、
二回目以降のRandomNumberと配列に格納された数値を比較して等しいものがあったら
RandomNumberを実行しなおすようにしたら出来るんじゃないかな。

まぁ48枚目のとき1/48を引くまで無限にランダム数字取得しに行くことになるけど。。。

投稿2017/04/19 04:48

King_of_Flies

総合スコア382

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

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

0

質問とは関係ありませんが、長々と続くswitch文を見て思わず筆を執ってしまいました。

swift

1//配列+タプルでカルタを定義 2let Q = [ 3 ("も", "モンゴルの民族模様は自由の印"), 4 ("さ", "三色の統一ドイツ黒赤金"), 5 ("ば", "バーレーンはギザギザ模様で鮮やかに"), 6] 7 8/* 9//.0で1番目の項目にアクセス 10print(Q[0].0) //=> も 11//.1で2番目の項目にアクセス 12print(Q[0].1) //=> モンゴルの民族模様は自由の印 13*/ 14 15func RandomQuestions() { 16 var rand = arc4random_uniform(Q.count) //0~(問題数-1)の乱数を生成 17 18 QuestionLabel.text = Q[rand].1 19 Button1.setTitle(Q[rand].0, for: .normal) 20 let synthesizer = AVSpeechSynthesizer() 21 let utterance = AVSpeechUtterance(string: QuestionLabel.text) //表示と同じなのであればQuestionLabel.textをそのまま使えばOK 22 synthesizer.speak(utterance) 23}

投稿2017/04/18 01:50

編集2017/04/18 02:21
fuzzball

総合スコア16733

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

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

退会済みユーザー

退会済みユーザー

2017/04/18 12:08

配列を使っているんですよね? これを使えば、重複なくできるのでしょうか?
fuzzball

2017/04/18 12:16

いえ、最初に書いてある通り質問とは関係のない回答で、重複を解決するものではありません。
退会済みユーザー

退会済みユーザー

2017/04/18 12:19

重複しないためにこうすると良いというアドバイスありますかね・・・?
fuzzball

2017/04/18 12:21

それは他の方の回答を参考にされては?
退会済みユーザー

退会済みユーザー

2017/04/18 12:25

わかりました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問