初めて投稿させて頂きます。
サイコロを振って、一度出た目はもう出ないような
ゲームをプログラミングしています。
Dim i As Integer
Dim j As Integer
Dim t As Integer
Dim r(6) As Integer 'コンピュータ
Dim b As Integer 'プレイヤー
Private Sub Command1_Click()
b = Val(Text2.Text)
Randomize
r(6) = Int(Rnd * 6 + 1) '1~6までの乱数発生
Text1.Text = r(6)
For i = 1 To n
r(i) = i 'r(i)~r(n)に1~nの値を格納
Next i
For i = n To 2 Step -1
j = Int((i - 1) * Rnd() + 1) '1~i-1の範囲の乱数
t = r(i): r(i) = r(j): r(j) = t 'r(i)とr(j)の交換
Next i
For i = 1 To n
Text1.Text = r(i)
Next i
If r(i) < j Then
Label2.Caption = "あなたの勝ちです"
Else
Label2.Caption = "あなたの負けです"
End If
幾つか考えてこれで落ち着いたのですが、これでは
まだ重複してしまいます。
どこが問題なのかご指摘頂けるようお願いします。
一度出た目は出ないようにするので、全部で6回試行
することになります。またその6回分の結果を表示したいのですが、
Text3.Text = r(1)
Text4.Text = r(2)
Text5.Text = r(3)
Text6.Text = r(4)
Text7.Text = r(5)
Text8.Text = r(6)
としてしまうと全てに0が表示され、結果が表示されません。
これについても回答をお願いします。
まだ初心者ですが、よろしくお願いします。
No.10ベストアンサー
- 回答日時:
#6,8,9です。
さっきのは、全ての乱数が出るまで探し続けるほうほうでしたが、違う方法もあります。
さっきの方法ですと、乱数の範囲が広いと最後の1個が出る確率が減り、処理時間が多くなります。数百程度の組み合わせなら気になりませんが・・・
下は、違う方法の参考例です。
先にformloadで、解を配列に格納します。何もしないうちは、配列の格納番号がそのまま解になります。
そして、乱数で出た配列は0にします。
乱数を出した後で、0を探して、見つかればそれ以降の配列データを1個づつずらします。
次に乱数の範囲を1つ減らしていきます。
この方法ですと、探したい回数分しか乱数は実行されません。
まぁ乱数の幅がどの程度になったときに、速さが逆転するのか、あるいは逆転しないかは検証した事がないので判りませんが・・・
Private ANS(10) As Integer
Private RndWhdth As Integer
Private Sub Form_Load()
Dim i As Integer
RndWhdth = 10
For i = 1 To 10
ANS(i) = i
Next
End Sub
Private Sub Command1_Click()
Dim A As Integer
Dim i1 As Integer
Dim i2 As Integer
Dim DmyANS As Integer
If RndWhdth = 0 Then
MsgBox ("END")
RndWhdth = 10
For i = 1 To 10
ANS(i) = i
Next
Exit Sub
End If
A = Int(Rnd * RndWhdth) + 1
Text1.Text = ANS(A)
ANS(A) = 0
For i1 = 1 To RndWhdth
If ANS(i1) = 0 Then
For i2 = i1 To RndWhdth - 1
ANS(i2) = ANS(i2 + 1)
Next
RndWhdth = RndWhdth - 1
Exit Sub
End If
Next
RndWhdth = RndWhdth - 1
End Sub
わざわざプログラムを組んで頂き、大変感謝しております。
すごくわかりやすかったので、重複しない乱数を発生することが出来ました。ありがとうございます。
あと結果を表示したいのですが、色々やってみているのですがなかなか出来ません。
ボタンをクリックするごとに、所定のテキストに結果を表示していきたいのですが、このプログラムだとANS(A) = 0となっているので結果表示の際ANS(A)は使えないのでしょうか?
No.9
- 回答日時:
#6,8です。
あまり綺麗に書いてなかったので、ちょっと書き直しました。
5列×50行です。全部出るまで探します。
それとクリアボタンを追加してあります。
Private BINGO(5, 50) As Integer
Private Counter As Integer
Private Sub Command1_Click()
Dim A As Integer
Dim B As Integer
Dim C As String
Dim i As Integer
BINGO(0, 0) = 1
Counter = Counter + 1
If Counter > 250 Then
MsgBox ("END")
Exit Sub
End If
Do While BINGO(A, B) = 1
A = Int(Rnd * 5) + 1
B = Int(Rnd * 50) + 1
Loop
Select Case A
Case 1
C = "B-"
Case 2
C = "I-"
Case 3
C = "N-"
Case 4
C = "G-"
Case 5
C = "O-"
End Select
Text1.Text = C & B
BINGO(A, B) = 1
End Sub
Private Sub Command2_Click()
Dim A As Integer
Dim B As Integer
Counter = 0
For A = 1 To 5
For B = 1 To 50
BINGO(A, B) = 0
Next
Next
End Sub
結果を表示するのは、リストボックスを用いることでなんとか自分で解決できました。
本当にわざわざプログラム組んで頂きありがとうございます!
とてもためになりました!
No.8
- 回答日時:
>BINGO(5, 10)なので、5行10列のビンゴカードですよね?
そうです。ですので、例えば5行×50列にしたければ、
Private BINGO(5, 50) As Integer
If i > 5000 Then
と、します。5000と言う数字が良いかどうかは判りません。
>BINGO(0, 0) = 1とBINGO(A, B) = 1は初期値に戻しているのでしょうか
これの考え方を先に説明します。
BINGO(XX,YY)の配列はフラグとして使用します。
配列はXX,YYの部分がアドレスに相当します。ですので、乱数で得られたXXとYYの組み合わせが過去に出たか出なかったかを、1と0で見分けます。
次に
BINGO(0, 0) = 1
と、している部分ですが、プログラム起動時には配列を含む全ての変数には0が入っていますので、
Do While BINGO(A, B) = 1
と、している部分でAとBは乱数を出す前ですので夫々0になっています。
つまり、
Do While BINGO(0, 0) = 1
となるわけです。
Do While は、While 後の条件式を満たしていなければLoop以降の部分に抜けてしまいますので、先に
BINGO(0, 0) = 1
として、BINGO(0, 0) = 0の初期値をBINGO(0, 0) = 1にします。
これで、乱数部分のプログラムが実行されます。
後は、乱数で出たBINGO(A,B)が1(過去に出ていれば)ならばLOOPして、乱数を取り直します。
逆に、乱数で出たBINGO(A,B)が0(初めて出たのならば)ならばLOOPを抜けて表示して、BINGO(A,B)を1にします。
あと、
If i > 50 Then
MsgBox ("END")
Exit Sub
End If
の部分ですが、ここは無限ループを避ける為に入れてあります。
もし、配列の全ての組み合わせが1であれば、永遠に0を探し続けてしまうからです。
ですので、上記の場合なら50回やってBINGO(A,B)=0が見つからなければ、あきらめて終わりにすると言う意味です。
ですので、
If i > 50 Then
の50と言う数字が適切かどうかは判りません。
なぜなら、50個の組み合わせのうち49個の組み合わせが1の場合、残りの1個の組み合わせが50回の乱数実行で出るとは限らないからです。
その辺りは、確率論の話になりそうなので、教育-数学でスレを立ててみてください。
No.7
- 回答日時:
#2です。
> 参考URLに行ってみたんですが、シャッフルする際は参考URLのところにも書いてあったようにArray関数を使わないといけないですか?
ん?参考URLのarrayはシャッフル対象の配列ですよ。(関数じゃないです。)
>> 1. 1番目の要素と、1~6番目(乱数)の要素を入れ替え。
> 最初の1番目の要素は乱数ではないんですよね?ということは、最初に配列r(6)として、この6つの配列に何か数字を入れないといけないということでしょうか?
どの要素も乱数ではないです。(乱数をシャッフルしたいなら乱数で良いけど、乱数ならもうシャッフル必要ない…。)
シャッフルするのですから要素はシャッフル前に準備しておきます。
今回の場合は1~6の数値を入れておけばよいでしょう。
乱数は何番目の要素と入れ替えるかを決定するために使います。
> 図付きで説明してあったのでなんとなく何が起こっているのかは分かるんですが、
とりあえず具体的にコードのどこで何をしているのかが分かるようにしましょう。
(コードを目でたどってみたり、実際に実行させてみるなどして)
> この場合1~6までの乱数を発生させているので、このnは6なのかなって思っています。
その本ではどこかでnに6を代入していたのかもしれませんが、
少なくともこの質問で提示されたコード内にはnに何かを代入しているところはないです。
どこかでちゃんとnに6を代入していますか?
>どこかでちゃんとnに6を代入していますか?
言われてみればそうです…このプログラムではどこにもnは入れてないですね…。
シャッフルについてですが、Wernerさんの解説だと私の組んだプログラムのr(6) = Int(Rnd * 6 + 1)はおかしいですね。シャッフルをするとしたら、r(6)には要素を入れて、何番目かということ(私のではiとjにあたると思いますが)を乱数にすべきですね。
すごくわかりやすい説明でした。
ありがとうございます。
意見を参考にして少し自分で組んでみます。
No.6
- 回答日時:
参考でBINGOの抽選サンプルを書いてみました。
Private BINGO(5, 10) As Integer
Private Sub Command1_Click()
Dim A As Integer
Dim B As Integer
Dim C As String
Dim i As Integer
BINGO(0, 0) = 1
Do While BINGO(A, B) = 1
i = i + 1
A = Int(Rnd * 5) + 1
B = Int(Rnd * 10) + 1
Select Case A
Case 1
C = "B-"
Case 2
C = "I-"
Case 3
C = "N-"
Case 4
C = "G-"
Case 5
C = "O-"
End Select
If i > 50 Then
MsgBox ("END")
Exit Sub
End If
Loop
Text1.Text = C & B
BINGO(A, B) = 1
End Sub
わざわざありがとうございます。
BINGO(5, 10)なので、5行10列のビンゴカードですよね?
BINGO(0, 0) = 1とBINGO(A, B) = 1は初期値に戻しているのでしょうか…本当に初心者でごめんなさい。
No.4
- 回答日時:
>r(6) = Int(Rnd * 6 + 1) '1~6までの乱数発生
1~6までの乱数を発生させるなら...
r(6) = Int(Rnd * 6) + 1
↑の様にするのが定石です。
ところで...
>サイコロを振って、一度出た目はもう出ないような
>ゲーム
との事ですが、上記の条件だと6回目には、何が出るか
プレイヤーに判ってしまいますが、それでゲームとして
成立するのでしょうか?
>6回目には何が出るかプレイヤーに判ってしまいます
確かにそうです。
ゲームと呼ぶべきものではないのですが…目的は、最後には一つしか出る目が残らないなのです。
私個人で作っているのではなく、VBの授業の課題なので…申し訳ないです。
No.3
- 回答日時:
こんちくわ~。
んー。。どこからツッコミましょうかねぇ。。。?(汗
とりあえず、デバッグ。。。って知ってますか?
まず
>>としてしまうと全てに0が表示され、結果が表示されません。
当然です。。。あなたの作ったfor文は全て1度も通りませんので。。。
for文が3つあると思いますが、3つとも、一度も通りません。判定文で弾かれます。
もし、弾かれずにfor文の中を通ってもー。。
途中で用意した配列数よりも数が大きくなってあふれエラーになっちゃいます。。。
とりあえず、「全てにおいて0が表示され結果が表示されない」
のは配列の中に数字が入っていないから。という答えになります。
他の部分に関しては、そこが直った段階で。。。ですかね。
とりあえず、直して~からって事で補足要求~です。
的確なご意見ありがとうございます。
>配列の中に数字が入っていないから
というのはランダムで数字を発生することで数字を各配列に入れているということにはならないですか?
この文だと全ての配列に数字を入れないと通らないということなのでしょうか?
No.2
- 回答日時:
「シャッフル」すればよいと言うのはその通りだと思いますが、
1000回も繰り返す必要はないと思います。
要素数6なら以下の手順で5回のループで良さそうです。
1. 1番目の要素と、1~6番目(乱数)の要素を入れ替え。
2. 2番目の要素と、2~6番目(乱数)の要素を入れ替え。
(中略)
5. 5番目の要素と、5~6番目(乱数)の要素を入れ替え。
参考URL:http://ray.sakura.ne.jp/tips/shaffle.html
参考URLに行ってみたんですが、シャッフルする際は参考URLのところにも書いてあったようにArray関数を使わないといけないですか?
>1. 1番目の要素と、1~6番目(乱数)の要素を入れ替え。
最初の1番目の要素は乱数ではないんですよね?ということは、最初に配列r(6)として、この6つの配列に何か数字を入れないといけないということでしょうか?
No.1
- 回答日時:
1~6をランダムに並べ替えた順列を得たいということですよね?
一番手っ取り早いのは「シャッフル」することです。
1~6が格納された配列を用意して、1~6の乱数を2個発生させ、それぞれの中身を入れ替える、これを1000回くらい繰り返せば、1~6をランダムに並べ替えた順列が得られますよ。
早く回答して頂いたのにも関わらず、お礼が遅くなって申し訳ございません。
>1~6の乱数を2個発生させ、それぞれの中身を入れ替える
ソートのような感じでしょうか?
それぞれの中身を入れ替えて、一度出たものは捨てる
といった感じでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) VBA Userformで一部別シートに転記がしたいのですが 2 2023/05/24 13:08
- Visual Basic(VBA) 九九の答えの計算 3 2022/12/20 22:13
- Visual Basic(VBA) VBA 重複チェック後に値をワークシートに転記する方法を教えてください。 1 2023/03/19 12:43
- Visual Basic(VBA) テーブルを配列に入れて、元のテーブルの行番号を取得したい 1 2022/08/16 20:15
- Excel(エクセル) マクロでテキストファイルを読み込んだ際の最終セルにデータと改行が含まれる問題の改善方法 2 2022/03/25 16:50
- Visual Basic(VBA) ①ExcelVBAでカレンダーを作り、別のユザーフォームで日付を入力したいのですがエラーになります。 1 2023/02/17 18:39
- Visual Basic(VBA) エクセルのマクロについて教えてください。 3 2023/02/17 11:59
- Visual Basic(VBA) ユーザーフォームの書き出しで追加のご相談 ユーザーフォームの値をシートに書き出す際、コードが表示され 2 2022/08/05 10:58
- Visual Basic(VBA) 配列にしたセル範囲でのコメントがあるかどうかを取得するコードの書き方 2 2022/09/17 05:09
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
DataGridViewに配列の値を表示...
-
二次元配列における要素数のは...
-
Strawberry Perl for Windows ...
-
隣同士の数字を足し合わせる
-
Excel VBA ユーザーフォームの...
-
VBAのautofilter、criteriaの配...
-
VBScript 配列
-
VBA 多次元配列を用いてグルー...
-
Perl/Tkで変数名を使って一気に...
-
組み合わせについての質問です...
-
エクセルVBAでTransposeの不思議
-
perlで配列の要素が空なのを知...
-
マクロ Publicでの配列定義
-
リストボックスに縦スクロール...
-
グループ分けの仕方について
-
クラスに配列を渡す方法
-
VBAでの一時停止と再開の方法
-
画面を強制的に再描画させる方法
-
範囲指定したセルを1つずつ飛...
-
Escキーを押すと、中断する時と...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Dim flag(4) as boolean で配列...
-
VBAのautofilter、criteriaの配...
-
二次元配列のインデックスについて
-
二次元配列における要素数のは...
-
エクセルVBAでTransposeの不思議
-
クラスに配列を渡す方法
-
リストボックスに縦スクロール...
-
マクロ Publicでの配列定義
-
Excel VBA ユーザーフォームの...
-
文字の整列(printf)
-
perlで配列の要素が空なのを知...
-
perl 配列の要素数について
-
Strawberry Perl for Windows ...
-
VBA 二次元配列の1つ目を増...
-
チェックボックスのperlでの値...
-
perl 初等プログラミングについて
-
DBIを使ってSelect文 複数のカ...
-
複数のキーで配列をソートする...
-
Excel(VBA)で配列の要素数を...
-
newで個別に生成した配列にNULL...
おすすめ情報