Diamo i numeri... esperimento Natalizio con la classe System.Random (Storico)

Nelle ultime due settimane, c'è stata una insistente richiesta di aiuto da parte di un iscritto che non riusciva ad usare la classe Random per produrre numeri casuali non ripetuti, ora, se questa necessità è imposta dall'esigenza di implementare un algoritmo per cifratura, generazione di password o simili progetti, questo non è assolutamente l'esempio più adatto, anche se può dare qualche idea, se invece il problema è simulare dei dadi, oppure estrarre i numeri della tombola, ecco un metodo semplice e, almeno per me, funzionale.

Il buon Diego ha promesso di postare un metodo con la massima efficienza, ma intanto vediamo qual'è l'ABC.

La prima cosa da fare è creare un progetto Winforms con un singolo form che chiameremo FrmMain, Per il nostro primo esperimento trascineremo dalla toolbar i seguenti oggetti:

  • Una groupbox che chiameremo grbDadi, il cui Text vale "Giochiamo a Dadi"
  • Un button che chiameremo btnTira, il cui Text Vale "Tira Dadi"
  • Due textbox che chiameremo txtDado1  e txtDado2 il cui Text è vuoto

Porremo i tre controlli dentro la groupbox che sposteremo nell'angolo in alto a sinistra della form e ancoreremo in modo standard Top/Left

A questo punto scriviamo la funzione di generazione numeri random

 public partial class FrmMain : Form
 {
  System.Random mObjRandom ;
 
  public int GetRandomNumber(int Low, int High)
  {
   return mObjRandom.Next(Low, High + 1);
  }...
 }

  public FrmMain()
  {
   InitializeComponent();
   mObjRandom = new System.Random(((int)(System.DateTime.Now.Ticks % System.Int32.MaxValue)));
   ...
  }

Inizializziamo il generatore di numeri nel costruttore della form, la funzione .Next ci restituirà il numero casuale a richiesta.
Per  simulare i dadi, scriviamo una routine sull'evento click del bottone btnTira.

  private void btnTira_Click(object sender, EventArgs e)
  {
   int dado;
   dado = GetRandomNumber(1, 6);
   this.txtDado1.Text = dado.ToString("#");
   dado = GetRandomNumber(1, 6);
   this.txtDado2.Text = dado.ToString("#");
  }

Generiamo due numeri casuali e li mettiamo nelle textbox, ecco i nostri dadi virtuali.

Ed ora, volendo dare i numeri fino in fondo, allarghiamo la form e trasciniamovi i seguenti controlli:

  • Una groupbox che chiameremo grbTombola la cui proprietà Text sarà inizializzata a "Giochiamo a Tombola"
  • Due button che chiameremo btnTombola e btnReset la cui proprietà Text sarà inizializzata a "Estrai" e "Reset"
  • tre label che chiameremo lblEstratti, lblCicli, lblTabellone le cui proprietà text saranno rispettivamente: "Estratti", "Cicli", "Tabellone"
  • una Textbox che chiameremo txtCicli
  • Due ListView che chiameremo lvEstratti e lvTabellone iniziamo la property View a Tile e la TileSize a 40x32 pixel

Dimensioniamo le listview in modo che contengano 9 file di 10 caselle, circa 428x322 pixel e poniamole una a fianco all'altra nella Groupbox
Poniamo le label da sopra e da un lato della listview corrispondente e i bottoni la label e la text ciclo in alto sopra alle listview.

Aggiungiamo alla form le seguenti variabili a livello di classe:

  int[] mTombola;
  int[] mEstratti;
  int contaestratti;

Aggiungiamo al costruttore la loro inizializzazione

  public FrmMain()
  {
   InitializeComponent();
   mObjRandom = new System.Random(((int)(System.DateTime.Now.Ticks % System.Int32.MaxValue)));
   mTombola = new int[90];
   mEstratti = new int[90];
   ResetTombola();
   this.Icon = Properties.Resources.btn361;
  }

Vediamo la funzione di reset per la tombola.

  private void ResetTombola()
  {
   contaestratti = 0;
   for (int i = 0; i < 90; i++)
   {
    mTombola[i] = 0;
    mEstratti[i] = 0;
   }
   this.lvEstratti.Items.Clear();
   this.lvTabellone.Items.Clear();
   for (int i = 0; i < 90; i++)
   {
    this.lvEstratti.Items.Add("  ");
    this.lvTabellone.Items.Add("__");
   }
  }

Azzeriamo il contatore degli estratti e i due array di supporto azzeriamo e rigeneriamo le listview.

Ed ora aggiungiamo una funzione per la visualizzazione degli estratti e del tabellone

  private void ShowTombola()
  {
   StringBuilder sb = new StringBuilder();
   for (int i = 0; i < contaestratti; i++)
   {
    this.lvEstratti.Items[i].Text = this.mEstratti[i].ToString("0#");
   }
   for (int i = 0; i < 90; i++)
   {
    if( this.mTombola[i] != 0 )
    {
     this.lvTabellone.Items[i].Text = this.mTombola[i].ToString("0#");
    }
   }
  }

Come possiamo vedere, i due array di supporto contengono i numeri estratti in ordine di estrazione e i numeri estratti nell'ordine naturale, in modo da poter sapere l'ordine di estrazione e visualizzare il tabellone per il gioco.

Ed ora le funzioni click dei due bottoni.

  private void btnReset_Click(object sender, EventArgs e)
  {
   ResetTombola();
  }

  private void btnTombola_Click(object sender, EventArgs e)
  {
   int estratto;
   int pieni = 0;
   for (int i = 0; i < this.mTombola.Length; i++)
   {
    if (this.mTombola[i] != 0) pieni++;
   }
   if (pieni < 90)
   {
    int ciclo = 0;
    while (true)
    {
     estratto = GetRandomNumber(1, 90);
     if (this.mTombola[estratto-1] == 0) break;
     ciclo++;
    }
    this.txtCicli.Text = ciclo.ToString("00#");
    this.mTombola[estratto-1] = estratto;
    this.mEstratti[contaestratti] = estratto;
    contaestratti++;
    ShowTombola();
   }
   else
   {
    MessageBox.Show("Tutti i numeri sono stati estratti resettare la tombola");
   }
  }

Ed ecco la funzione che genera i numeri casuali senza doppioni, per una funzionalità semplice come la tombola possiamo utilizzare un metodo semplice, ovvero un ciclo che esclude i numeri doppi. Ovviamente, per applicazioni con numeri complessi e con un numero più alto di numeri generati, non è molto adatta. Abbiamo inserito una piccola funzione di controllo che conta i tentativi per ogni estrazione, le prove fatte indicano che le ripetizioni salvo alcuni casi non sono molte. ed ora, se volete evitare sacchettino e pedine numerate, avete il vostro generatore di tombola computerizzato.

Il progetto completo in versione sorgente con il programma di setup può essere scaricato qui

Tags:

Print | posted on lunedì 24 marzo 2008 21.10

Feedback

No comments posted yet.

Your comment:





 
Please add 1 and 8 and type the answer here:

Copyright © Sabrina C.

Design by Bartosz Brzezinski

Design by Phil Haack Based On A Design By Bartosz Brzezinski