C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: シャッフル


(過去ログ 67 を表示中)

[トピック内 18 記事 (1 - 18 表示)]  << 0 >>

■38363 / inTopicNo.1)  シャッフル
  
□投稿者/ ウヌ (1回)-(2009/07/12(Sun) 10:50:17)

分類:[VB.NET/VB2005 以降] 

2009/07/12(Sun) 12:36:26 編集(投稿者)

  Dim i As Integer = 0
Dim Labels(10) As Label
Dim arbefore As New ArrayList
Dim arafter As New ArrayList

  Do
arafter.Add(arbefore(Int(Rnd() * (10 - i))))
arbefore.Remove(Int(Rnd(0) * (10 - i)))
i += 1
Loop While i <= 9

Label1.Text = arafter(0)
Label2.Text = arafter(1)
Label3.Text = arafter(2)
Label4.Text = arafter(3)
Label5.Text = arafter(4)
Label6.Text = arafter(5)
Label7.Text = arafter(6)
Label8.Text = arafter(7)
Label9.Text = arafter(8)
Label10.Text = arafter(9)

i = 0
arbefore.Add(1)
arbefore.Add(2)
arbefore.Add(3)
arbefore.Add(4)
arbefore.Add(5)
arbefore.Add(6)
arbefore.Add(7)
arbefore.Add(8)
arbefore.Add(9)
arbefore.Add(10)
arafter.Clear()

とプログラムしても、Label1〜Label10にかぶった数字が出てしまいます。1〜10までランダムにそしてどれも異なるようにするにはどうすればいいのでしょうか?

VB2005、XPです。

追加:全文を

Public Class Form1
Dim i As Integer = 0
Dim arbefore As New ArrayList
Dim arafter As New ArrayList

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
arbefore.Add(1)
arbefore.Add(2)
arbefore.Add(3)
arbefore.Add(4)
arbefore.Add(5)
arbefore.Add(6)
arbefore.Add(7)
arbefore.Add(8)
arbefore.Add(9)
arbefore.Add(10)
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Label1.Text = Int(Rnd() * 10) + 1
Label2.Text = Int(Rnd() * 10) + 1
Label3.Text = Int(Rnd() * 10) + 1
Label4.Text = Int(Rnd() * 10) + 1
Label5.Text = Int(Rnd() * 10) + 1
Label6.Text = Int(Rnd() * 10) + 1
Label7.Text = Int(Rnd() * 10) + 1
Label8.Text = Int(Rnd() * 10) + 1
Label9.Text = Int(Rnd() * 10) + 1
Label10.Text = Int(Rnd() * 10) + 1
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Do
arafter.Add(arbefore(Int(Rnd() * (10 - i))))
arbefore.Remove(Int(Rnd(0) * (10 - i)))
i += 1
Loop While i <= 9

Label1.Text = arafter(0)
Label2.Text = arafter(1)
Label3.Text = arafter(2)
Label4.Text = arafter(3)
Label5.Text = arafter(4)
Label6.Text = arafter(5)
Label7.Text = arafter(6)
Label8.Text = arafter(7)
Label9.Text = arafter(8)
Label10.Text = arafter(9)

i = 0
arbefore.Add(1)
arbefore.Add(2)
arbefore.Add(3)
arbefore.Add(4)
arbefore.Add(5)
arbefore.Add(6)
arbefore.Add(7)
arbefore.Add(8)
arbefore.Add(9)
arbefore.Add(10)
arafter.Clear()
End Sub
End Class


Button1で普通の乱数を、Button2で重複しない乱数を作成したいと思っています。Labelsは消し忘れです。

もちろん自作です。
引用返信 編集キー/
■38366 / inTopicNo.2)  Re[1]: シャッフル
□投稿者/ επιστημη (2054回)-(2009/07/12(Sun) 11:31:44)
επιστημη さんの Web サイト
> 1〜10までランダムにそしてどれも異なるようにするにはどうすればいいのでしょうか?

1〜10 の入った配列を乱数でかき混ぜてはいかがでしょうか。

引用返信 編集キー/
■38367 / inTopicNo.3)  Re[1]: シャッフル
□投稿者/ ぽぴ王子 (444回)-(2009/07/12(Sun) 12:10:21)
ぽぴ王子 さんの Web サイト
No38363 (ウヌ さん) に返信
>   Dim i As Integer = 0
>     Dim Labels(10) As Label
>     Dim arbefore As New ArrayList
>     Dim arafter As New ArrayList
> 
>   Do
>         arafter.Add(arbefore(Int(Rnd() * (10 - i))))
>         arbefore.Remove(Int(Rnd(0) * (10 - i)))
>             i += 1
>     Loop While i <= 9
> 
>     Label1.Text = arafter(0)
>     Label2.Text = arafter(1)
>     Label3.Text = arafter(2)
>     Label4.Text = arafter(3)
>     Label5.Text = arafter(4)
>     Label6.Text = arafter(5)
>     Label7.Text = arafter(6)
>     Label8.Text = arafter(7)
>     Label9.Text = arafter(8)
>     Label10.Text = arafter(9)
> 
>     i = 0
>     arbefore.Add(1)
>     arbefore.Add(2)
>     arbefore.Add(3)
>     arbefore.Add(4)
>     arbefore.Add(5)
>     arbefore.Add(6)
>     arbefore.Add(7)
>     arbefore.Add(8)
>     arbefore.Add(9)
>     arbefore.Add(10)
>     arafter.Clear()
> 
> とプログラムしても、Label1〜Label10にかぶった数字が出てしまいます。1〜10までランダムにそしてどれも異なるようにするにはどうすればいいのでしょうか?
> 
> VB2005、XPです。

このコードを見ても「何をしたいのか」がわかりません。
・Labeles は何のために宣言しているの?
・arbefore を宣言して、値が入っていないのに Remove するとエラーになりませんか?
・Label1〜Label10 に値を設定した後で arbefore.Add する理由は?

ご自分で書いたコードが「何をしているか」を理解していますか?
それこそ、ご自分で書いたコードですか?

課題で出たから仕方なく、のような状態であれば、まずは質問する前に自分でコードの流れを考えてみるのがいいと思います。

引用返信 編集キー/
■38368 / inTopicNo.4)  Re[2]: シャッフル
□投稿者/ やじゅ (1092回)-(2009/07/12(Sun) 12:42:55)
やじゅ さんの Web サイト
> ■No38363 (ウヌ さん) に返信

Tips7:トランプのシャッフル
http://www.interq.or.jp/www-user/komurak/tips/tranp.html
引用返信 編集キー/
■38369 / inTopicNo.5)  Re[3]: シャッフル
□投稿者/ ウヌ (2回)-(2009/07/12(Sun) 13:06:28)
No38368 (やじゅ さん) に返信
>>■No38363 (ウヌ さん) に返信
>
> Tips7:トランプのシャッフル
> http://www.interq.or.jp/www-user/komurak/tips/tranp.html

このサイトも見たんですが、それでも分からなかったのです。それに、そのまま実行すると青線ひかれます。
引用返信 編集キー/
■38370 / inTopicNo.6)  Re[4]: シャッフル
□投稿者/ επιστημη (2055回)-(2009/07/12(Sun) 14:40:38)
επιστημη さんの Web サイト
>>http://www.interq.or.jp/www-user/komurak/tips/tranp.html
> このサイトも見たんですが、それでも分からなかったのです。

なにが/どこがわからんかを語らんと「わかるまで読め」と返されて終わりになりますよ。

引用返信 編集キー/
■38373 / inTopicNo.7)  Re[2]: シャッフル
□投稿者/ 倉田 有大 (673回)-(2009/07/12(Sun) 18:18:36)
2009/07/12(Sun) 18:18:51 編集(投稿者)
No38366 (επιστημη さん) に返信
>>1〜10までランダムにそしてどれも異なるようにするにはどうすればいいのでしょうか?
> 
> 1〜10 の入った配列を乱数でかき混ぜてはいかがでしょうか。

もう、これが答えとしか思えないんですが。

int list[10];
for(int i = 0; i < 10;i++)
{
   list[i] = i;
}
Random rnd = new Random();
for(int i = 0; < 100; i++)
{
   int index1 = rnd.Next(10);
   int index2 = rnd.Next(10);
   int tmp = list[index1];
   list[index1] = list[index2];
   list[index2] = tmp;
}

ビルドしてません。適当手書き。

引用返信 編集キー/
■38374 / inTopicNo.8)  Re[5]: シャッフル
□投稿者/ 倉田 有大 (674回)-(2009/07/12(Sun) 18:20:51)
トランプのシャッフルのほうが実装が綺麗ですね。
お好みにーって感じです。
引用返信 編集キー/
■38376 / inTopicNo.9)  Re[4]: シャッフル
□投稿者/ やじゅ (1093回)-(2009/07/12(Sun) 19:22:45)
やじゅ さんの Web サイト
2009/07/12(Sun) 19:48:07 編集(投稿者)
No38369 (ウヌ さん) に返信
>>Tips7:トランプのシャッフル
>>http://www.interq.or.jp/www-user/komurak/tips/tranp.html
> 
> このサイトも見たんですが、それでも分からなかったのです。それに、そのまま実行すると青線ひかれます。

青線が引かれる原因の箇所である、iの型をLong→Integerに変更すればいいです。

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim colBefore As Collection
        Dim colAfter As Collection
        Dim i As Integer  'Long→Integerに変更

        colBefore = New Collection
        colAfter = New Collection

	'colBefore にセットされる値
	'1,2,3,4,5,6,7,8,9,10,11,12,13
        For i = 1 To 13
            colBefore.Add(CStr(i))
        Next

	'colBefore が無くなるまで繰り返す
        Do Until colBefore.Count = 0
	  '1回目 1〜13 の中から乱数値を取得 例 i=5   	
	  '2回目 1〜12 の中から乱数値を取得 例 i=9   	
	  '3回目 1〜11 の中から乱数値を取得 例 i=3   	
            i = Int(Rnd(1) * (colBefore.Count - 1)) + 1

	  '1回目 colAfterに乱数値を登録 例 i=5
	  '2回目 colAfterに乱数値を登録 例 i=9
	  '3回目 colAfterに乱数値を登録 例 i=3
            colAfter.Add(colBefore.Item(i))

	  '既にcolAfterに登録した乱数値を削除(同じ乱数値を出さないため)
	  '1回目 colBeforeを1つ削除(乱数値) 例 i=5
	  '2回目 colBeforeを1つ削除(乱数値) 例 i=9
	  '3回目 colBeforeを1つ削除(乱数値) 例 i=3
            colBefore.Remove(i)
        Loop

	'colAfterにシャッフルされた値がセットされたので、全て表示   	
        For i = 1 To 13
            Debug.Print(colAfter.Item(i))
        Next

   End Sub

引用返信 編集キー/
■38377 / inTopicNo.10)  Re[1]: シャッフル
□投稿者/ もりお (9回)-(2009/07/12(Sun) 19:44:55)
2009/07/12(Sun) 20:34:34 編集(投稿者)
No38363 (ウヌ さん) に返信

この辺りにブレークポイントを仕掛けて
after にどの値が追加されて、before からどの値が削除されたのか
本来、どの値が削除されるべきなのか確認してみてはいかがでしょうか。
>     Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
>         Do
>             arafter.Add(arbefore(Int(Rnd() * (10 - i))))
>             arbefore.Remove(Int(Rnd(0) * (10 - i)))
>             i += 1
>         Loop While i <= 9
> 
>         Label1.Text = arafter(0)


引用返信 編集キー/
■38380 / inTopicNo.11)  Re[2]: シャッフル
□投稿者/ ウヌ (3回)-(2009/07/12(Sun) 23:31:48)
2009/07/12(Sun) 23:33:03 編集(投稿者)
■回答していただいた皆さんに返信
> 2009/07/12(Sun) 20:34:34 編集(投稿者)
>
多くの回答大変ありがたく思っています。自分としてはこの投稿が初めてだったということもあり。

ですが、明日学校なので申し訳ありませんが少し考える時間をいただきたいです。じっくり考えてお礼をしようと思います。本当にありがとうございます。

もうひとつ、使い方をまだちゃんと理解していないので、その点ご理解をお願いしますm(_ _)m
引用返信 編集キー/
■38387 / inTopicNo.12)  Re[5]: シャッフル
□投稿者/ επιστημη (2056回)-(2009/07/13(Mon) 13:26:17)
επιστημη さんの Web サイト
> >>http://www.interq.or.jp/www-user/komurak/tips/tranp.html
>>このサイトも見たんですが、それでも分からなかったのです。

ではコレ↓ならいかがでしょう。
http://blogs.wankuma.com/episteme/archive/2009/07/13/177448.aspx

引用返信 編集キー/
■38565 / inTopicNo.13)  Re[5]: シャッフル
□投稿者/ ウヌ (4回)-(2009/07/19(Sun) 05:28:18)
No38376 (やじゅ さん) に返信
> 2009/07/12(Sun) 19:48:07 編集(投稿者)
>
> ■No38369 (ウヌ さん) に返信
> >>Tips7:トランプのシャッフル
> >>http://www.interq.or.jp/www-user/komurak/tips/tranp.html
>>
>>このサイトも見たんですが、それでも分からなかったのです。それに、そのまま実行すると青線ひかれます。
>
> 青線が引かれる原因の箇所である、iの型をLong→Integerに変更すればいいです。
>
> Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
> Dim colBefore As Collection
> Dim colAfter As Collection
> Dim i As Integer 'Long→Integerに変更
>
> colBefore = New Collection
> colAfter = New Collection
>
> 'colBefore にセットされる値
> '1,2,3,4,5,6,7,8,9,10,11,12,13
> For i = 1 To 13
> colBefore.Add(CStr(i))
> Next
>
> 'colBefore が無くなるまで繰り返す
> Do Until colBefore.Count = 0
>   '1回目 1〜13 の中から乱数値を取得 例 i=5   
>   '2回目 1〜12 の中から乱数値を取得 例 i=9   
>   '3回目 1〜11 の中から乱数値を取得 例 i=3   
> i = Int(Rnd(1) * (colBefore.Count - 1)) + 1
>
>   '1回目 colAfterに乱数値を登録 例 i=5
>   '2回目 colAfterに乱数値を登録 例 i=9
>   '3回目 colAfterに乱数値を登録 例 i=3
> colAfter.Add(colBefore.Item(i))
>
>   '既にcolAfterに登録した乱数値を削除(同じ乱数値を出さないため)
>   '1回目 colBeforeを1つ削除(乱数値) 例 i=5
>   '2回目 colBeforeを1つ削除(乱数値) 例 i=9
>   '3回目 colBeforeを1つ削除(乱数値) 例 i=3
> colBefore.Remove(i)
> Loop
>
> 'colAfterにシャッフルされた値がセットされたので、全て表示   
> For i = 1 To 13
> Debug.Print(colAfter.Item(i))
> Next
>
> End Sub
>

じっくり読ませていただきました。そして、自分なりに、13ではなく10個の数字を数列化しました。確かに、重複なく数字が並ぶようになりました。

しかし、いつも10が最後になってしまいます。Collectionはインデックスが0からみたいなので、修正しようとしましたが、

Dim colBefore As Collection
Dim colAfter As Collection
Dim i As Integer 'Long→Integerに変更

colBefore = New Collection
colAfter = New Collection

'colBefore にセットされる値
'1,2,3,4,5,6,7,8,9,10
For i = 0 To 9
colBefore.Add(CStr(i))
Next

'colBefore が無くなるまで繰り返す
Do Until colBefore.Count = 0
'1回目 1〜10 の中から乱数値を取得 例 i=5   
'2回目 1〜9 の中から乱数値を取得 例 i=9   
'3回目 1〜8 の中から乱数値を取得 例 i=3   
i = Int(Rnd() * (colBefore.Count - 1))

'1回目 colAfterに乱数値を登録 例 i=5
'2回目 colAfterに乱数値を登録 例 i=9
'3回目 colAfterに乱数値を登録 例 i=3
colAfter.Add(colBefore.Item(i))

'既にcolAfterに登録した乱数値を削除(同じ乱数値を出さないため)
'1回目 colBeforeを1つ削除(乱数値) 例 i=5
'2回目 colBeforeを1つ削除(乱数値) 例 i=9
'3回目 colBeforeを1つ削除(乱数値) 例 i=3
colBefore.Remove(i)
Loop

'colAfterにシャッフルされた値がセットされたので、全て表示   
For i = 0 To 9
Debug.Print(colAfter.Item(i))
Next

どうしても、colAfter.Add(colBefore.Item(i))の行でエラーが起こります。たびたび申し訳ありませんが、回答よろしくお願いします。
引用返信 編集キー/
■38566 / inTopicNo.14)  Re[3]: シャッフル
□投稿者/ 倉田 有大 (677回)-(2009/07/19(Sun) 05:42:16)
エラーメッセージぐらいは書きましょうー
引用返信 編集キー/
■38573 / inTopicNo.15)  Re[6]: シャッフル
□投稿者/ やじゅ (1116回)-(2009/07/19(Sun) 13:34:03)
やじゅ さんの Web サイト
2009/07/19(Sun) 13:47:37 編集(投稿者)
No38565 (ウヌ さん) に返信
> じっくり読ませていただきました。そして、自分なりに、13ではなく10個の数字を数列化しました。確かに、重複なく数字が並ぶようになりました。
> しかし、いつも10が最後になってしまいます。Collectionはインデックスが0からみたいなので、修正しようとしましたが、

あら、ほんとですねw 気が付きませんでした、そのサイトの方がわざとそうしたのかバグなのか・・・ 教えてあげた方がいいかもね。
i = Int(Rnd(1) * (colBefore.Count - 1)) + 1 → i = Int(Rnd(1) * colBefore.Count) + 1 にする必要がありますね。

> どうしても、colAfter.Add(colBefore.Item(i))の行でエラーが起こります。たびたび申し訳ありませんが、回答よろしくお願いします。

コレクション インデックスのサイズは、1 以上である必要があります。
colBefore.Item(i)のiの値に0がセットされると、このエラーとなります。

修正ソース

        Dim colBefore As Collection
        Dim colAfter As Collection
        Dim i As Integer

        colBefore = New Collection
        colAfter = New Collection

        '値は0〜9だけど、コレクション インデックスは、1〜10だよ。
        For i = 0 To 9
            colBefore.Add(CStr(i))
        Next

        Do Until colBefore.Count = 0
            'コレクション インデックスのサイズは、1 以上だから、最後に+1して、1〜10とする。        
            i = Int(Rnd(1) * colBefore.Count) + 1
            colAfter.Add(colBefore.Item(i))
            colBefore.Remove(i)
        Loop
        
        'コレクション インデックスのサイズは、1 以上だから、1〜10とする。でも値は、0〜9だよ。
        For i = 1 To 10
            Debug.Print(colAfter.Item(i))
        Next


επιστημηさんが、別のシャッフルの方法について、下記のBlogを書かれております。
http://blogs.wankuma.com/episteme/archive/2009/07/13/177448.aspx
上記の内容を理解されたら、別のシャッフルの方法についても勉強してみてくださいね。

引用返信 編集キー/
■38575 / inTopicNo.16)  Re[4]: シャッフル
□投稿者/ επιστημη (2062回)-(2009/07/19(Sun) 15:01:16)
επιστημη さんの Web サイト
VB.NETで書きなおしてみた。

Imports System.Collections.Generic

Module Program
  Sub Main()
    Dim colBefore As New List(Of Integer)
    Dim colAfter As New List(Of Integer)

    For i = 0 To 9
      colBefore.Add(i)
    Next

    Dim rnd As New System.Random
    Do Until colBefore.Count = 0
      dim i as Integer = rnd.Next(colBefore.Count)
      colAfter.Add(colBefore(i))
      colBefore.RemoveAt(i)
    Loop

    For Each item As Integer In colAfter
      Console.Write("{0} ", item)
    Next
  End Sub
End Module


引用返信 編集キー/
■38590 / inTopicNo.17)  Re[7]: シャッフル
□投稿者/ 倉田 有大 (682回)-(2009/07/20(Mon) 07:07:25)
> コレクション インデックスのサイズは、1 以上である必要があります。
> colBefore.Item(i)のiの値に0がセットされると、このエラーとなります。

うお、まじですかい!
VBはそうだったか。もう忘れた^^;
引用返信 編集キー/
■38826 / inTopicNo.18)  Re[7]: シャッフル
□投稿者/ ウヌ (5回)-(2009/07/25(Sat) 17:16:40)
Dim colBefore As Collection
Dim colAfter As Collection
Dim i As Integer

colBefore = New Collection
colAfter = New Collection

'値は0〜9だけど、コレクション インデックスは、1〜10だよ。
For i = 0 To 9
colBefore.Add(CStr(i))
Next

Do Until colBefore.Count = 0
'コレクション インデックスのサイズは、1 以上だから、最後に+1して、1〜10とする。
i = Int(Rnd(1) * colBefore.Count) + 1
colAfter.Add(colBefore.Item(i) + 1) '"+1"を付け足しました
colBefore.Remove(i)
Loop

'コレクション インデックスのサイズは、1 以上だから、1〜10とする。でも値は、0〜9だよ。
For i = 1 To 10
Debug.Print(colAfter.Item(i))
Next

やじゅさんが書かれたコードでそのままデバッグしてみたところ、0〜9までがランダムになったので、一部書き換えました。

全面解決しましたので、お礼を申しあげます。ほかのかたがたもありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -