Corso di Visual Basic: | ||||||||
Diciassettesima lezione - Campo Minato: gli ultimi accorgimenti (a cura di
Giorgio Abraini) Nell'ultima lezione vi avevo lasciato con la routine che gestisce il click sui pulsanti: quando viene premuto un pulsante, bisogna innanzitutto verificare se esso nasconde una mina oppure no, e per questo bisogna controllare la sua proprietà Tag. Se essa è maggiore di 0, significa che sotto di esso non ci sono mine e bisogna mostrare al giocatore quante mine circondano quel pulsante. E' quello che fa la prima diramazione della If tramite l'aggiornamento della proprietà Caption. Se il Tag non è maggiore di 0, potrebbe essere uguale a -1: in tal caso, il pulsante nasconde una mina e lo facciamo capire all'utente visualizzando una "M" sul pulsante; il vero Campo Minato mostra l'icona della mina, ma noi per semplicità ci accontentiamo di modificare opportunamente la Caption dei pulsanti. Trovata la mina, il gioco deve terminare e quindi interrompiamo il conteggio dei secondi disabilitando il Timer e mostrando al giocatore la posizione di tutte le mine: per questo motivo con un ciclo aggiorniamo la Caption di tutti i pulsanti con le mine, e non solo di quella trovata dal giocatore. La variabile contatore utilizzata nel ciclo è x, che di per sé dovrebbe essere usata per calcolare la riga in cui si trova il pulsante premuto: volendo essere diligenti, avremmo dovuto dichiarare un'altra variabile apposita, ma dato che l'utilizzo di x viene comodo e non crea problemi con le altre diramazioni della If, possiamo benissimo utilizzarla risparmiando così qualche byte. La terza diramazione della If serve per l'ultimo caso, quello in cui
Quando ciò si verifica, Campo Minato mostra tutta la "frontiera" dei pulsanti che si trovano nelle vicinanze di una mina. Per ottenere lo stesso risultato, noi dovremmo usare una funzione ricorsiva (cioè una funzione che chiama se stessa un numero indefinito di volte) con opportuni controlli per evitare di bloccare l'applicazione, e siccome tutto ciò potrebbe rivelarsi complesso, per ora ci accontentiamo di mostrare il numero di mine vicine ai pulsanti che circondano quello premuto. Ora il nostro Campo Minato è quasi pronto: possiamo già fare una prima partita, avviate il progetto, selezionate "Nuova" dal menù "Partita" e premete i pulsanti; ricordate di selezionare il menù, perché altrimenti i pulsanti non sono ancora inizializzati (o, se preferite, il campo non è ancora minato). Ora che avete giocato la vostra prima partita, provate a farne un'altra: noterete che le Caption dei pulsanti rimangono invariate. Infatti ingenuamente ci siamo dimenticati di inizializzare anche quelle: per la prima partita non ce n'era bisogno, perché in fase di progettazione avevamo eliminato le proprietà Caption, ma per le partite successive dobbiamo ripristinare le condizioni iniziali. Pertanto aggiungiamo queste semplici righe nella routine mnuNew_click (all'inizio o anche alla fine, come preferite):
Ora possiamo giocare quante partite vogliamo, ma non abbiamo ancora finito: innanzitutto dobbiamo scrivere un bel "Unload me" in mnuExit_click; e poi sarebbe bene congratularsi col giocatore quando vince la partita: E' intuitivo che una partita a campo minato viene vinta quando il giocatore "scopre" tutti i pulsanti tranne quelli che nascondono le mine (nel nostro caso 13 pulsanti); avremo quindi bisogno di un contatore che tenga traccia di quanti pulsanti sono stati scoperti. Il luogo più naturale in cui fare questi conti è la routine Mina_Click:
La variabile ContaMine andrebbe logicamente dichiarata a livello di modulo, nella sezione delle dichiarazioni generali del Form; tuttavia si potrebbe anche dichiararla nella medesima routine Mina_Click usando la parola chiave Static. La variabile MaxContaMine, invece, va necessariamente dichiarata a livello di modulo, perché non è utilizzata solo da Mina_Click: essa infatti deve essere inizializzata al valore 13 (il numero massimo di pulsanti scopribili) all'avvio dell'applicazione, cioè in Form_Load; dal momento che abbiamo un solo livello di gioco (e non tre come il vero Campo Minato), potremmo fare direttamente:
ma questo non è un buon metodo, perché limita la possibilità di ulteriori aggiornamenti ed espansioni dell'applicazione: se infatti un giorno volessimo aumentare il numero di pulsanti, dovremmo cambiare manualmente tutte le occorrenze del valore 13; per non parlare del caso in cui volessimo aggiungere un livello di gioco. Invece utilizzando una variabile apposita, dovremmo preoccuparci soltanto di modificarla in fase di inizializzazione. Ricordate inoltre che l'utilizzo di una variabile apposita rende più chiaro e leggibile il codice, anche a voi stessi. Ricordate anche di inserire l'istruzione:
nella routine mnuNew_Click, perché in ogni nuova partita il contatore deve partire da 0. Per quanto riguarda la prima If che abbiamo inserito, c'è da dire che il contatore va aggiornato solo se il pulsante è stato premuto per la prima volta (altrimenti uno potrebbe "vincere" premendo per 13 volte lo stesso pulsante!), ovvero se la sua Caption è ancora una stringa nulla. Il controllo non viene effettuato confrontando la Caption con "", ma esaminando la lunghezza della Caption stessa: questo perché le operazioni con i numeri (la funzione Len restituisce appunto la lunghezza della stringa, cioè un numero) sono più veloci di quelle con le stringhe. La seconda If è così ovvia che se non l'avete capita dovreste ricominciare il corso daccapo... L'aggiornamento del contatore però non deve essere fatto solo per il pulsante premuto, ma per qualunque pulsante sia stato "scoperto": in altri termini dobbiamo aggiornare il contatore anche quando si preme un pulsante che non è circondato da mine, perché in questo caso il gioco visualizzerà il numero di mine vicine ai pulsanti che circondano quello premuto. Quindi le istruzioni:
vanno inserite nella prima e nella terza diramazione della If contenuta nella routine Mina_Click, che pertanto è diventata così:
Non resta che aggiornare l'etichetta lblMine: a che serve? Serve a tenere il conto delle mine non ancora trovate; come saprete, cliccando col tasto destro su uno dei pulsanti del vero Campo Minato, su di esso apparirà una bandiera ad indicare che in quella posizione c'è (o pensiamo che ci sia) una mina, e quel pulsante diventerà insensibile al clic sinistro, almeno finchè su di esso resterà la bandierina. Noi al posto della bandiera visualizzeremo una "x", ma non è questo il punto: la cosa importante è capire come intercettare il clic col tasto destro, ed è una cosa che impareremo più avanti. Per concludere questa lezione, vorrei tornare al punto da cui siamo partiti: la matrice di controlli. Dovreste esservi resi ormai conto dell'utilità dei vettori e delle matrici di variabili: con una sola dichiarazione avete a disposizione numerose variabili dello stesso tipo, collegate tra loro da un nesso logico, da una medesima funzione, da un medesimo scopo; potete modificarle tutte insieme con un semplice ciclo sfruttando la possibilità di accedere ad esse attraverso un indice. Per una matrice di controlli i vantaggi sono gli stessi: i pulsanti del nostro campo minato svolgono tutti la stessa funzione, cioè visualizzano quante mine ci sono nelle vicinanze o interrompono il gioco se nascondono una mina; grazie al fatto che appartengono a una matrice, possiamo accedere ad ognuno di essi tramite un indice che, nel caso dell'evento click, ci viene fornito direttamente da Visual Basic, con la conseguenza che possiamo scrivere il codice solo una volta, perché una sola è la routine Mina_Click; se non avessimo usato una matrice di pulsanti, avremmo dovuto crearne 16 diversi e indipendenti, e ripetere le istruzioni della routine per l'evento click di ognuno dei 16 pulsanti: immaginate se avessimo usato 480 pulsanti, come nel terzo livello del vero Campo Minato! Le matrici di controlli semplificano tutto questo. |
Archivio: | ||||
Lezioni | Commenta questa lezione | Invia la tua guida | Avviso
per le nuove lezioni | Proponi
un argomento |
Visual Basic Italia©
copyright 2000 - tutti i diritti riservati |