Appunti di Programmazione

Creative Commons License

Creiamo un gioco semplice

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:

Schema celle collegate

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:

Semafori

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.

Layout delle celle

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.

Il gioco finito

Download sorgente "Gioco.zip" ( 143KB )