Con questo tutorial mi propongo di programmare un piccolo gioco di tipo rompicapo, la cui semplicità può fornire uno spunto per applicazioni più complesse.
Il gioco ha regole semplici:
si tratta di una griglia di 3x3 caselle, in ognuna delle quali si trova una delle 2 immagini possibili.
Cliccando 2 volte con il mouse su una di queste caselle essa vedrà cambiare il suo contenuto da un'immagine all'altra, e così pure le caselle vicine secondo questo schema:
In linea generale cliccando una qualunque casella vengono pure variate anche quelle che sono in linea sia orizzontalmente che verticalmente con la casella scelta.
Lo scopo del gioco è quello di avere tutte le caselle con la stessa immagine, in questo caso un semaforo Rosso.
Con un qualunque programma di elaborazioni immagini, disegniamo due oggetti diversi, magari complementari fra loro, con dimensioni di 100x100 pixels, tipo questi:
Grazie a Diego Borghini per i disegni
A questo punto avviamo Visual Basic .Net e selezioniamo File->Nuovo Progetto, scegliamo "Applicazione Windows" e digitiamo "Semafori" come nome per la nostra applicazione.
Premiamo F7 per visionare il codice e inseriamo le seguenti linee:
Public Class Form1 Private WithEvents btnExit As New System.Windows.Forms.Button Private WithEvents Cella11 As New System.Windows.Forms.PictureBox Private WithEvents Cella12 As New System.Windows.Forms.PictureBox Private WithEvents Cella13 As New System.Windows.Forms.PictureBox Private WithEvents Cella21 As New System.Windows.Forms.PictureBox Private WithEvents Cella22 As New System.Windows.Forms.PictureBox Private WithEvents Cella23 As New System.Windows.Forms.PictureBox Private WithEvents Cella31 As New System.Windows.Forms.PictureBox Private WithEvents Cella32 As New System.Windows.Forms.PictureBox Private WithEvents Cella33 As New System.Windows.Forms.PictureBox Dim ck11 As Boolean = True Dim ck12 As Boolean = False Dim ck13 As Boolean = False Dim ck21 As Boolean = False Dim ck22 As Boolean = False Dim ck23 As Boolean = True Dim ck31 As Boolean = True Dim ck32 As Boolean = False Dim ck33 As Boolean = False End Class
In questo modo abbiamo inizializzato un pulsante Exit, 9 PictureBox e 9 variabili di tipo booleano per controllare il tipo di immagine che contengono.
La figura seguente mostra i nomi delle PictureBox in relazione alla posizione che occupano nella griglia.
In "Esplora Soluzioni" clicchiamo con il tasto DX del mouse sul nome del progetto (Semafori) e scegliamo "Proprietà" dal menù che appare. Scegliamo il Tab "Risorse" e clicchiamo nel menù; a discesa in alto dove sta scritto "Stringhe", per poi selezionare "Immagini".
Quindi usiamo il mouse sul menù a discesa che si trova immediatamente a DX, "Aggiungi Risorsa" e scegliamo la voce "Aggiungi File Esistente".
A questo punto cerchiamo e carichiamo nelle risorse del progetto i due file immagine che rappresentano i nostri semafori.
Le due immagini vengono caricate nella finestra contraddistinta dal Tab "Risorse".
Torniamo al codice del programma. Selezioniamo l'evento Form1_Load e digitiamo le seguenti istruzioni:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Me.Name = "frmGioco" Me.Text = "Semafori" Me.Size = New Size(500, 600) With btnExit .Size = New Size(100, 40) .Location = New Point(200, 500) .Text = "Exit" End With With Cella11 .Size = New Size(100, 100) .Location = New Point(50, 50) .BorderStyle = BorderStyle.FixedSingle End With With Cella12 .Size = New Size(100, 100) .Location = New Point(200, 50) .BorderStyle = BorderStyle.FixedSingle End With With Cella13 .Size = New Size(100, 100) .Location = New Point(350, 50) .BorderStyle = BorderStyle.FixedSingle End With With Cella21 .Size = New Size(100, 100) .Location = New Point(50, 200) .BorderStyle = BorderStyle.FixedSingle End With With Cella22 .Size = New Size(100, 100) .Location = New Point(200, 200) .BorderStyle = BorderStyle.FixedSingle End With With Cella23 .Size = New Size(100, 100) .Location = New Point(350, 200) .BorderStyle = BorderStyle.FixedSingle End With With Cella31 .Size = New Size(100, 100) .Location = New Point(50, 350) .BorderStyle = BorderStyle.FixedSingle End With With Cella32 .Size = New Size(100, 100) .Location = New Point(200, 350) .BorderStyle = BorderStyle.FixedSingle End With With Cella33 .Size = New Size(100, 100) .Location = New Point(350, 350) .BorderStyle = BorderStyle.FixedSingle End With Me.Controls.Add(btnExit) Me.Controls.Add(Cella11) Me.Controls.Add(Cella12) Me.Controls.Add(Cella13) Me.Controls.Add(Cella21) Me.Controls.Add(Cella22) Me.Controls.Add(Cella23) Me.Controls.Add(Cella31) Me.Controls.Add(Cella32) Me.Controls.Add(Cella33) CambiaStatoCelle(ck11, Cella11) CambiaStatoCelle(ck12, Cella12) CambiaStatoCelle(ck13, Cella13) CambiaStatoCelle(ck21, Cella21) CambiaStatoCelle(ck22, Cella22) CambiaStatoCelle(ck23, Cella23) CambiaStatoCelle(ck31, Cella31) CambiaStatoCelle(ck32, Cella32) CambiaStatoCelle(ck33, Cella33) End Sub
In questo modo imponiamo a VB di impostare tutti i controlli durante la fase di caricamento e visualizzazione della form.
Vengono cioè definiti nome, dimensioni, posizione di ogni singolo controllo: Form1, btnExit e le Celle, quindi aggiunti alla Form.
Adesso scriviamo una nuova Sub:
Private Sub CambiaStatoCelle(ByVal n1 As Boolean, ByVal oggetto As System.Windows.Forms.PictureBox) If n1 = True Then oggetto.Image = My.Resources.Verde_2_Luci Else oggetto.Image = My.Resources.Rosso_2_Luci End If If ck11 = False And ck12 = False And ck13 = False And ck21 = False And ck22 = False And ck23 = False And _ ck31 = False And ck32 = False And ck33 = False Then MessageBox.Show("Hai Vinto!") End If End Sub
Questa Sub fa in modo che, passandole come argomento una variabile booleana e una PictureBox, l'immagine contenuta venga cambiata. Inoltre verifica se tutte le PictureBox contengono un Semaforo Rosso; in caso affermativo stampa un messaggio di vittoria.
Adesso aggiungiamo gli eventi DoubleClick per ognuna delle 9 PictureBox del nostro gioco.
Private Sub Cella11_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Cella11.DoubleClick ck11 = Not ck11 CambiaStatoCelle(ck11, Cella11) ck12 = Not ck12 CambiaStatoCelle(ck12, Cella12) ck13 = Not ck13 CambiaStatoCelle(ck13, Cella13) ck21 = Not ck21 CambiaStatoCelle(ck21, Cella21) ck31 = Not ck31 CambiaStatoCelle(ck31, Cella31) End Sub
Cliccando sulla cella (1,1), contraddistinta dal nome Cella11, il suo contenuto e quello delle Cella12, Cella13, Cella21 e Cella31, vengono anch'esse variate.
Per fare questo si cambia lo stato delle variabili booleana collegate con le celle ck11, ck12, ck13, ck21, ck31 e si richiama la Sub CambiaStato passandole i rispettivi parametri.
Deve essere fatta la stessa cosa su tutte le celle.
Private Sub Cella12_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Cella12.DoubleClick ck11 = Not ck11 CambiaStatoCelle(ck11, Cella11) ck12 = Not ck12 CambiaStatoCelle(ck12, Cella12) ck13 = Not ck13 CambiaStatoCelle(ck13, Cella13) ck22 = Not ck22 CambiaStatoCelle(ck22, Cella22) ck32 = Not ck32 CambiaStatoCelle(ck32, Cella32) End Sub Private Sub Cella13_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Cella13.DoubleClick ck11 = Not ck11 CambiaStatoCelle(ck11, Cella11) ck12 = Not ck12 CambiaStatoCelle(ck12, Cella12) ck13 = Not ck13 CambiaStatoCelle(ck13, Cella13) ck23 = Not ck23 CambiaStatoCelle(ck23, Cella23) ck33 = Not ck33 CambiaStatoCelle(ck33, Cella33) End Sub Private Sub Cella21_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Cella21.DoubleClick ck11 = Not ck11 CambiaStatoCelle(ck11, Cella11) ck22 = Not ck22 CambiaStatoCelle(ck22, Cella22) ck23 = Not ck23 CambiaStatoCelle(ck23, Cella23) ck21 = Not ck21 CambiaStatoCelle(ck21, Cella21) ck31 = Not ck31 CambiaStatoCelle(ck31, Cella31) End Sub Private Sub Cella22_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Cella22.DoubleClick ck12 = Not ck12 CambiaStatoCelle(ck12, Cella12) ck21 = Not ck21 CambiaStatoCelle(ck21, Cella21) ck22 = Not ck22 CambiaStatoCelle(ck22, Cella22) ck23 = Not ck23 CambiaStatoCelle(ck23, Cella23) ck32 = Not ck32 CambiaStatoCelle(ck32, Cella32) End Sub Private Sub Cella23_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Cella23.DoubleClick ck13 = Not ck13 CambiaStatoCelle(ck13, Cella13) ck21 = Not ck21 CambiaStatoCelle(ck21, Cella21) ck22 = Not ck22 CambiaStatoCelle(ck22, Cella22) ck23 = Not ck23 CambiaStatoCelle(ck23, Cella23) ck33 = Not ck33 CambiaStatoCelle(ck33, Cella33) End Sub Private Sub Cella31_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Cella31.DoubleClick ck11 = Not ck11 CambiaStatoCelle(ck11, Cella11) ck21 = Not ck21 CambiaStatoCelle(ck21, Cella21) ck31 = Not ck31 CambiaStatoCelle(ck31, Cella31) ck32 = Not ck32 CambiaStatoCelle(ck32, Cella32) ck33 = Not ck33 CambiaStatoCelle(ck33, Cella33) End Sub Private Sub Cella32_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Cella32.DoubleClick ck12 = Not ck12 CambiaStatoCelle(ck12, Cella12) ck22 = Not ck22 CambiaStatoCelle(ck22, Cella22) ck31 = Not ck31 CambiaStatoCelle(ck31, Cella31) ck32 = Not ck32 CambiaStatoCelle(ck32, Cella32) ck33 = Not ck33 CambiaStatoCelle(ck33, Cella33) End Sub Private Sub Cella33_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Cella33.DoubleClick ck13 = Not ck13 CambiaStatoCelle(ck13, Cella13) ck23 = Not ck23 CambiaStatoCelle(ck23, Cella23) ck31 = Not ck31 CambiaStatoCelle(ck31, Cella31) ck32 = Not ck32 CambiaStatoCelle(ck32, Cella32) ck33 = Not ck33 CambiaStatoCelle(ck33, Cella33) End Sub
Aggiungiamo il codice relativo al pulsante Exit:
Private Sub btnExit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnExit.Click Me.Close() End Sub
Il programma è finito e può essere usato.