Descrizione :
Un mio generatore avanzato di numeri interi casuali, con un funzionamento stile "Slot-Machine".
+ Articolo :
Anzitutto un'immagine del generatore in funzione, per rendere rapidamente l'idea di cosa andiamo a costruire e di come dovrà girare :
Il progetto è di tipo Windows Forms, e le Classi essenziali alla compilazione sono le seguenti :
- Casella.vb : Controllo UserControl ( Controllo Utente ).
- Ruota.vb : Controllo UserControl ( Controllo Utente ).
- ModuloPublics.vb : Modulo.
- FormMain.vb : Form ( Form di avvio ).
1. Casella.vb :
E' l'elemento base. Ogni Ruota può contenere N Oggetti Casella.
Nel presente progetto ho limitato N in modo opportuno :
- N minimo = 2 ( per ovvi motivi ).
- N massimo = 10 ( da 0 a 9 ).
La struttura di Casella è semplice :
- lbl_valore : Label.
--> Codice per Casella.vb :
Public Class Casella 'Dimensioni Fisse Private m_w As Integer = 170 Private m_h As Integer = 170 Private m_valore As Integer Public Property valore() As Integer Get Return m_valore End Get Set(ByVal value As Integer) m_valore = value Me.lbl_valore.Text = m_valore End Set End Property Protected Overrides Sub SetBoundsCore(ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer, ByVal specified As System.Windows.Forms.BoundsSpecified) MyBase.SetBoundsCore(x, y, m_w, m_h, specified) End Sub End Class
2. Ruota.vb :
La Ruota è la Classe centrale del progetto. Provvede a caricare le caselle, a farle girare e a generare i valori casuali. Così come per Casella.vb, le dimensioni di Ruota non possono essere decise a casaccio, perciò per semplicità anche in questo caso sono bloccate.
- lbl_numruota : Label.
- pnl_ruota : Panel.
- tmr_ruota : Timer ( Interval = 20 ).
--> Codice per Ruota.vb :
Public Class Ruota 'Membri Interni N.A. Private m_w As Integer = 200 'Dimensioni Fisse Private m_h As Integer = 200 'Dimensioni Fisse Private m_tmrTicks As Integer = 0 Private m_speedMin As Integer = 80 Private m_speedMax As Integer = 120 Private m_speed As Integer = 0 Private m_scarto As Integer = 0 'Membri Interni Property Private m_numCaselleRuota As Integer = 10 Private m_inGiocoRuota As Boolean = False Private m_esitoRuota As Integer = 0 Private m_numRuota As Integer = 0 Private m_velocitàRuota As Integer = 20 Public Property NumCaselleRuota() As Integer Get Return m_numCaselleRuota End Get Set(ByVal value As Integer) If value < 2 Then m_numCaselleRuota = 2 Else m_numCaselleRuota = value End If Me.ResetRuota() End Set End Property Public ReadOnly Property InGiocoRuota() As Boolean Get Return m_inGiocoRuota End Get End Property Public ReadOnly Property EsitoRuota() As Integer Get Return m_esitoRuota End Get End Property Public Property NumRuota() As Integer Get Return m_numRuota End Get Set(ByVal value As Integer) m_numRuota = value Me.lbl_numruota.Text = m_numRuota End Set End Property Public Property VelocitàRuota() As Integer Get Return m_velocitàRuota End Get Set(ByVal value As Integer) If value <= 0 Then m_velocitàRuota = 20 Else m_velocitàRuota = value End If Me.tmr_ruota.Interval = m_velocitàRuota End Set End Property Protected Overrides Sub SetBoundsCore(ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer, ByVal specified As System.Windows.Forms.BoundsSpecified) MyBase.SetBoundsCore(x, y, m_w, m_h, specified) End Sub Private Sub ResetRuota() Me.pnl_ruota.BackColor = Color.Black Me.pnl_ruota.Controls.Clear() For i As Integer = 1 To m_numCaselleRuota Dim C As New Casella C.valore = i - 1 Me.pnl_ruota.Controls.Add(C) C.Left = 10 C.Top = (1 - i) * C.Height Next End Sub Public Sub Start() 'Normalizzazione valori per SeedX Random Dim nr As Integer = m_numRuota * 99 Dim ttcks As Integer = Convert.ToInt32(m_tmrTicks.ToString.PadRight(3, "9")) Dim er As Integer = m_esitoRuota * 99 Dim mox As Integer = Cursor.Position.X Dim moy As Integer = Cursor.Position.Y Dim sxs As Integer = nr + er + ttcks + mox + moy m_speed = RandomizzaIntero(m_speedMin, m_speedMax, sxs) m_inGiocoRuota = True Me.pnl_ruota.BackColor = Color.Black Me.tmr_ruota.Enabled = True End Sub Private Sub tmr_ruota_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmr_ruota.Tick If m_tmrTicks = 999 Then m_tmrTicks = 1 Else m_tmrTicks += 1 End If Dim sxt As Integer = Convert.ToInt32(m_tmrTicks.ToString.PadRight(3, "9")) For Each C As Casella In Me.pnl_ruota.Controls C.Top = C.Top + m_speed Next For Each C As Casella In Me.pnl_ruota.Controls If C.Top > C.Height Then C.Top = C.Top - m_numCaselleRuota * C.Height Try 'Aggiungere qui un suono per slot casella 'My.Computer.Audio.Play(suonoSlot, AudioPlayMode.Background) Catch ex As Exception End Try End If Next If m_inGiocoRuota = True Then m_speed -= RandomizzaIntero(0, 1, sxt) Else m_scarto -= 1 If m_scarto = 0 Then Me.tmr_ruota.Enabled = False End If End If If m_speed <= 0 And m_inGiocoRuota = True Then m_scarto = Integer.MaxValue m_inGiocoRuota = False Me.pnl_ruota.BackColor = Color.LimeGreen For Each C As Casella In Me.pnl_ruota.Controls If Math.Abs(C.Top) < m_scarto Then m_scarto = Math.Abs(C.Top) Next For Each C As Casella In Me.pnl_ruota.Controls If Math.Abs(C.Top) = m_scarto Then m_esitoRuota = C.valore If C.Top > 0 Then m_speed = -1 ElseIf C.Top < 0 Then m_speed = 1 Else 'C.Top = 0 m_speed = 0 End If Exit For End If Next End If End Sub End Class
NOTA : Per rendere il tutto più "realistico" ho pensato alla possibilità di associare un suono ad ogni "[I]giro di slot[/I]". Il punto esatto in cui farlo è nel metodo [B]Private Sub tmr_ruota_Tick()[/B] di Ruota.vb, in corrispondenza del blocco Try/Catch, in cui ho commentato la riga di esecuzione del file suono :
Try 'Aggiungere qui un suono per slot casella 'My.Computer.Audio.Play(suonoSlot, AudioPlayMode.Background) Catch ex As Exception End Try
3. ModuloPublics.vb :
Contiene dichiarazioni di utilità generale a livello di Progetto.
--> Codice per ModuloPublics.vb :
Module ModuloPublics Public percorso As String = Application.StartupPath & "\" Public suonoSlot As String = percorso & "slot.wav" Public reportFile As String = percorso & "GnrtrRndmSlt_Report.txt" Public ruote As New List(Of Ruota) Public msg As System.Text.StringBuilder Public esitoReport As System.Text.StringBuilder Public Function RandomizzaIntero(ByVal Min As Integer, ByVal Max As Integer, ByVal seedX As Integer) As Integer If seedX < 0 Then seedX = -seedX Dim gen As New System.Random(System.DateTime.Now.Millisecond + seedX) Return gen.Next(Min, Max + 1) End Function Public Sub CreaAccodaReport(ByVal esito As String) My.Computer.FileSystem.WriteAllText(reportFile, esito & Environment.NewLine, True) End Sub End Module
4. FormMain.vb :
- num_numcaselle : NumericUpDown.
- cmb_velocitàruota : ComboBox ( 2 Items a Design : {Normale, Veloce} ).
- cmd_start : Button.
- tmr_check : Timer ( Interval = 500 ).
--> Codice per FormMain :
'************************************************** 'GENERATORE RANDOM SLOT - MarcoGG - 2011 ********** 'VB 2010 FW 4.0 *********************************** '************************************************** Public Class FormMain Private Sub FormMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load cmb_velocitàruota.Text = cmb_velocitàruota.Items(0) For Each R As Control In Me.Controls If TypeOf R Is Ruota Then ruote.Add(R) Next 'Ordinamento Ruote per righe e colonne, da sinistra a destra e dall'alto in basso ruote = ruote.OrderBy(Function(R) R.Top).ThenBy(Function(R) R.Left).ToList 'Assegnazione For Each R As Ruota In ruote R.NumCaselleRuota = num_numcaselle.Value R.NumRuota = ruote.IndexOf(R) + 1 Next End Sub Private Sub cmd_start_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd_start.Click msg = New System.Text.StringBuilder esitoReport = New System.Text.StringBuilder For Each R As Ruota In ruote R.Start() Next cmd_start.Enabled = False num_numcaselle.Enabled = False cmb_velocitàruota.Enabled = False tmr_check.Enabled = True End Sub Private Sub tmr_check_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmr_check.Tick For Each R As Ruota In ruote If R.InGiocoRuota = True Then Exit Sub Next tmr_check.Enabled = False For Each R As Ruota In ruote msg.Append("RUOTA " & R.NumRuota & " : " & R.EsitoRuota & Environment.NewLine) esitoReport.Append(R.EsitoRuota.ToString) Next MessageBox.Show(msg.ToString, "OK", MessageBoxButtons.OK, MessageBoxIcon.Information) CreaAccodaReport(esitoReport.ToString) cmd_start.Enabled = True num_numcaselle.Enabled = True cmb_velocitàruota.Enabled = True End Sub Private Sub cmb_velocitàruota_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmb_velocitàruota.SelectedIndexChanged '0.Normale - Risultato in circa 9 sec. '1.Veloce - Risultato in circa 4 sec. Dim V As Integer = 20 - cmb_velocitàruota.SelectedIndex * 10 For Each R As Ruota In ruote R.VelocitàRuota = V Next End Sub Private Sub num_numcaselle_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles num_numcaselle.ValueChanged For Each R As Ruota In ruote R.NumCaselleRuota = num_numcaselle.Value Next End Sub End Class
--> Alcune Note di Utilizzo :
I ) Una volta create le classi, basta eseguire una compilazione per trovare [B]Ruota[/B] tra i controlli WinForms utilizzabili. A questo punto si possono aggiungere tutte le ruote che si desiderano alla propria FormMain ( personalmente ho fatto un test con 16 Ruote senza problemi ).
Non è assolutamente necessario aggiungere Ruote da codice. Basta usare il Designer.
A tutto il resto pensa il MIO codice.
II ) Quando FormMain è pronta... START ! :D
III ) Quando tutte le Ruote avranno fornito il loro esito, apparirà una MessageBox di riepilogo.
Come ultima "chicca", verrà creato e aggiornato ad ogni Start, un semplice report txt : "GnrtrRndmSlt_Report.txt".
IV ) Possibili applicazioni ? L'unico limite è la fantasia ! :-)
+ Fine Articolo.
0 commenti:
Posta un commento