スロットの絵柄をループ処理で

タグの編集
投稿者 モウヘイ  (高校生) 投稿日時 2009/3/30 06:07:49
こんばんは、またまたお世話になります。スロットの絵柄を乱数を使わずにx,y,zのそれぞれを順に増やして0に戻すといったループで処理を行いたいのですが、どうすればいいでしょうか?できれば同じ処理がある所はまとめるようなシンプルな書き方にしたいのですが。アドバイスよろしくお願いします。↓は乱数を使ったときのものです。  
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Randomize()
        x = Int(11 * Rnd())
               Select Case x
            Case 0
                PictureBox1.Image = PictureBox4.Image
            Case 1
                PictureBox1.Image = PictureBox5.Image
                       ・
                 ・
                 ・ 
            Case 9
                PictureBox1.Image = PictureBox13.Image
        End Select
    End Sub

    Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
               Randomize()
        y = Int(11 * Rnd())

        Select Case y
            Case 0
                PictureBox2.Image = PictureBox4.Image
            Case 1
                PictureBox2.Image = PictureBox5.Image
                ・
                ・
                ・         
               
       Case 9
                PictureBox2.Image = PictureBox13.Image

        End Select
    End Sub


    Private Sub Timer3_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer3.Tick
               Randomize()
        z = Int(11 * Rnd())
        Select Case z
            Case 0
                PictureBox3.Image = PictureBox4.Image
                 ・
                 ・
                 ・
            Case 9
                PictureBox3.Image = PictureBox13.Image
        End Select
    End Sub

投稿者 neptune  (社会人) 投稿日時 2009/3/30 07:49:55
私の基準で言うと、
>シンプルな書き方にしたいのですが
の必要なし。です。

無理やりやってもわかりにくくなりそう。

他の識者の意見もお待ちください。
投稿者   (社会人) 投稿日時 2009/3/30 15:56:29
1ドラムのデータ(絵柄)slotの配列を作成
2絵柄を格納するのにImageListコントロールを使う
3各絵柄(要素)の表示は剰余を使う
4ドラムを表示する関数を作る

というのはどうでしょうか?


投稿者 あにす  (社会人) 投稿日時 2009/3/30 18:29:37
無理やりシンプルにしようとしてわかりにくくなった例
Public Class Form1
    Const min As Integer = 0
    Const max As Integer = 9
    Const drumSize As Integer = 100
    Dim imageList1 As New ImageList()

    Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load
        imageList1.ImageSize = New Size(drumSize, drumSize)

        '画像が無いので自分で描いてるだけ 
        For i As Integer = min To max
            Dim img As New Bitmap(drumSize, drumSize)

            Using g As Graphics = Graphics.FromImage(img)
                'サイズは適当に収まるように設定 
                Dim fnt As New Font(Me.Font.FontFamily.Name, drumSize * 0.8)
                g.DrawString(i.ToString(), fnt, Brushes.Black, 0, 0)
            End Using

            Me.imageList1.Images.Add(img)
        Next

        'ドラムを作成して配置、スタート 
        For i As Integer = 0 To 3 - 1
            Dim drum As New Drum(500, Me.imageList1)
            Me.Controls.Add(drum)
            drum.Location = New Point(i * drum.Width, 0)
            drum.DrumStart()
        Next
    End Sub
End Class

Class Drum
    Inherits PictureBox

    WithEvents timer_ As New Timer()
    Dim imgList As ImageList
    Dim index As Integer = 0 - 1

    ''' <summary> 
    ''' ドラムを初期化 
    ''' </summary> 
    ''' <param name="interval">ドラムの回転間隔</param> 
    ''' <param name="imgList">ドラムの図柄リスト</param> 
    Sub New(ByVal interval As IntegerByVal imgList As ImageList)
        Me.imgList = imgList
        timer_.Interval = interval
        Me.Size = New Size(100, 100)
        timer_Tick(timer_, EventArgs.Empty)
    End Sub

    ''' <summary> 
    ''' ドラムを回す 
    ''' </summary> 
    Public Sub DrumStart()
        timer_.Start()
    End Sub

    ''' <summary> 
    ''' ドラムを止める 
    ''' </summary> 
    ''' <remarks></remarks> 
    Public Sub DrumStop()
        timer_.Stop()
    End Sub

    Private Sub timer_Tick(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles timer_.Tick
        If index = imgList.Images.Count - 1 Then
            index = 0
        Else
            index += 1
        End If

        Me.Image = imgList.Images(index)
    End Sub
End Class


ごめんなさい面白そうなんで書いてみただけです。
投稿者 (削除されました)  () 投稿日時 2009/3/30 18:36:07
(削除されました)
投稿者 (削除されました)  () 投稿日時 2009/3/30 18:37:57
(削除されました)
投稿者   (社会人) 投稿日時 2009/3/30 18:54:42
簡単に作ってみました。
Public Class Form1
    Dim iti As Integer
    Dim slot() As Integer = New Integer() {4, 3, 2, 1, 3, 0, 2, 4, 1} 'ImageList1の画像サイズは「80,80」


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        PictureBox1.Image = New Bitmap(80, 240)
        iti = 0
        drawslot(PictureBox1, iti)

    End Sub
    Private Sub drawslot(ByRef pb As PictureBox, ByVal p As Integer)
        Dim i As Integer
        Dim g As Graphics = Graphics.FromImage(pb.Image)

        For i = 0 To 2
            g.DrawImage(ImageList1.Images(slot((p + i) Mod 9)), 0, 160 - i * 80)
        Next

        g.Dispose()
        pb.Invalidate()

    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        iti = (iti + 1) Mod 9
        drawslot(PictureBox1, iti)

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Timer1.Enabled = True

    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Timer1.Enabled = False

    End Sub
End Class
投稿者 よねKEN  (社会人) 投稿日時 2009/3/30 18:58:35
#上の方の2つの(削除)は私が削除したものです。質問のコードを読み間違えて
#見当はずれなことを書いていたので削除しましたm(_ _)m

> できれば同じ処理がある所はまとめるようなシンプルな書き方にしたいのですが。
こちらについてのみコメントします。

改善すべきポイントはいくつかありますが、一遍にやろうとすると大変ですから、
まずは似た機能を関数化するところから始めましょう。

メソッドの作り方の基本的なところは以下を参照してください。
「第11回 メソッドを作る」
http://homepage1.nifty.com/rucio/main/dotnet/shokyu/standard11.htm

○オリジナルのソースから以下を抜粋して関数化の流れを書いて見ます。

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Randomize()
        x = Int(11 * Rnd())
               Select Case x
            Case 0
                PictureBox1.Image = PictureBox4.Image
            Case 1
                PictureBox1.Image = PictureBox5.Image
                       ・
                 ・
                 ・ 
            Case 9
                PictureBox1.Image = PictureBox13.Image
        End Select
    End Sub

○ステップ1
似たような処理はとりあえず、引数、戻り値なしのメソッドとして切り出す。
以下のような感じになります。

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        SetSlotImage()
    End Sub

Private Sub SetSlotImage()
        Randomize()
        x = Int(11 * Rnd())
               Select Case x
            Case 0
                PictureBox1.Image = PictureBox4.Image
            Case 1
                PictureBox1.Image = PictureBox5.Image
                       ・
                 ・
                 ・ 
            Case 9
                PictureBox1.Image = PictureBox13.Image
        End Select
End Sub

○ステップ2
この処理はTimer1、Timer2、Timer3での処理でほとんどが同じです。
違うのは、乱数用の変数とスロットの画像のセットする対象のピクチャーボックスが違うところです。
3つの乱数用の変数x,y,zはこのままでは扱いにくいので配列にします。
x,y,zは削除して代わりに以下の宣言を追加します。

private currentSlotImageIndex(2) As Integer

x →currentSlotImageIndex(0)、y →currentSlotImageIndex(1)、z →currentSlotImageIndex(2)が対応します。
そして、SetSlotImageメソッドを改造して、どのリール(あの回転している部分の名称。言葉が正しいかはあまり自信なし)の番号を0~2で指定できるようにします。
対象(=target)のピクチャーボックスを指定できるように修正します。

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        SetSlotImage(0, PictureBox1)
    End Sub

Private Sub SetSlotImage(ByVal slotIndex As Integer, ByVal target As PictureBox)
        Randomize()
        currentSlotImageIndex(slotIndex) = Int(11 * Rnd())
               Select Case currentSlotImageIndex(slotIndex)
            Case 0
                target.Image = PictureBox4.Image
            Case 1
                target.Image = PictureBox5.Image
                       ・
                 ・
                 ・ 
            Case 9
                target.Image = PictureBox13.Image
        End Select
End Sub

○ステップ3
Timer2_Tick、Timer3_Tickの処理を同様に
SetSlotImage(1, PictureBox2)、SetSlotImage(2, PictureBox3)
と書き換えることで共通化ができます。

これである程度共通化されました。しかし、まだ中途半端感のある実装ですね。
続きは考えてみてください。

また他のの改善点として気になるのは、PictureBox4.Image~PictureBox13.Imageです。
これらはPictureBox1~3に表示するイメージが準備してあるのだと思いますが、
PictureBoxを使う必要はないのではないでしょうか。
拓さんのご指摘にあるImageListコントロールを使ってもよいでしょうし、
Imageクラスの配列やリスト(コレクション)に格納しておくのでもよいでしょう。

そのためにはまずは以下の講座を熟読してみるのがよいのではないでしょうか。

「第27回 配列」
http://homepage1.nifty.com/rucio/main/dotnet/shokyu/standard27.htm
「第28回 コレクション」
http://homepage1.nifty.com/rucio/main/dotnet/shokyu/standard28.htm 
投稿者   (社会人) 投稿日時 2009/3/30 19:12:03
ちなみに絵柄を3つから4つに表示を変更するときには下記のようになります。

ublic Class Form1
    Dim iti As Integer
    Dim slot() As Integer = New Integer() {4, 3, 2, 1, 3, 0, 2, 4, 1} 'ImageList1の画像サイズは「80,80」


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        PictureBox1.Image = New Bitmap(80, 320)
        iti = 0
        drawslot(PictureBox1, iti)

    End Sub
    Private Sub drawslot(ByRef pb As PictureBox, ByVal p As Integer)
        Dim i As Integer
        Dim g As Graphics = Graphics.FromImage(pb.Image)

        For i = 0 To 3
            g.DrawImage(ImageList1.Images(slot((p + i) Mod 9)), 0, 240 - i * 80)
        Next

        g.Dispose()
        pb.Invalidate()

    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        iti = (iti + 1) Mod 9
        drawslot(PictureBox1, iti)

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Timer1.Enabled = True

    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Timer1.Enabled = False

    End Sub
End Class
投稿者 モウヘイ  (高校生) 投稿日時 2009/3/31 01:39:09
多くのことをアドバイスしていただき、皆様、本当にありがとうございます!これらを参考に、もう一度しっかりと学習し、プログラム作成に役立てたいと思います。