Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Giochi in Flash con Actionscript 3: Mastermind

Molti giochi di un tempo, con carta e penna, sono stati trasposti in versioni per PC: in questo articolo vedremo come creare Mastermind in Flash con Actionscrpt 3
Molti giochi di un tempo, con carta e penna, sono stati trasposti in versioni per PC: in questo articolo vedremo come creare Mastermind in Flash con Actionscrpt 3
Link copiato negli appunti

Molti giochi di un tempo, con carta e penna, sono stati trasposti in versioni per PC: in questo articolo vedremo come creare Mastermind in Actionscript 3.

Mastermind è il nome con cui è più conosciuto un gioco di logica e deduzione che veniva giocato già molto tempo fa; le regole del gioco sono molto semplici: innanzitutto la versione "cartacea" prevede due giocatori. A turno un giocatore realizza un "codice" (che può essere di diversa lunghezza e composto da simboli o da colori, a seconda della variante di gioco) mentre l'altro giocatore dovrà indovinarlo entro un certo numero di tentativi; ad ogni tentativo del giocatore "B", il giocatore "A" dovrà indicare quanti sono i simboli posizionati correttamente e quanti invece sono i simboli esatti ma in posizione sbagliata.

Se il giocatore "B" indovina entro un certo numero di tentativi vince la partita, altrimenti a vincere è il giocatore "A".

Facciamo un esempio pratico per quanto riguarda i "suggerimenti" che il giocatore "A" deve fornire al giocatore "B": nel caso in cui il codice fosse composto da pedine colorate, se il codice del giocatore "A" fosse:

Rosso Verde Blu Rosso Blu

E il giocatore "B" ipotizzasse

Rosso Blu Viola Rosso Giallo

Avremo come responso 2 completamente corretti (la pedina rossa in posizione 1 e la pedina rossa in posizione 4) e 1 parzialmente corretto (la pedina blu, per cui è giusto il colore ma non la posizione).

Nella versione da tavolo di Mastermind questo responso viene fornito con delle pedine bianche e nere, dove la bianca corrisponde a posizione e colore corretti mentre la nera indica un colore corretto ma in posizione errata.

Le regole delle versioni per PC di questo gioco sono praticamente identiche alla versione da tavolo, con l'ovvia eccezione che il giocatore "A" viene sostituito dal computer, che si occupa di generare il codice e di dare indicazioni all'utente sulle pedine posizionate correttamente nelle varie ipotesi di codice.

Nella versione in Flash che andremo a creare sfrutteremo delle pedine con 5 possibili colori e il codice sarà formato da 5 pedine, per un totale di 3125 possibili combinazioni.

Preparazione dello stage

Per prima cosa imposteremo lo stage, dove creeremo una semplice schermata introduttiva per il gioco e soprattutto realizzeremo il movieclip delle pedine, che conterrà diversi fotogrammi (precisamente 6, il primo rappresentate lo spazio vuoto e i restanti i diversi colori delle pedine).

Apriamo Flash CS3 e creiamo un nuovo file Actionscript 3 (File -> Nuovo -> File Actionscript 3), quindi inseriamo un nuovo simbolo di tipo MovieClip (Inserisci -> Nuovo simbolo, oppure la scorciatoia Ctrl+F8). Impostiamo come identificativo pedina e spuntiamo l'opzione Esporta per Actionscript.

Figura 1. Creazione del movieclip pedina
Screenshot del pannello

Flash ci porterà all'interno del movieclip, dove potremo disegnare i diversi fotogrammi. È possibile creare i simboli di proprio gradimento e renderli più o meno elaborati graficamente, questo non influirà praticamente per nulla sul codice Actionscript, comunque è consigliato non superare le dimensioni di 25x25 pixel per le pedine, in caso contrario potrebbe essere necessario variare alcune distanze impostate nel codice della classe, che vedremo in seguito.

In figura è possibile vedere la linea temporale del movieclip dopo la creazione dei 6 fotogrammi.

Figura 2. La linea temporale del movieclip pedina
Screenshot della timeline

Possiamo tornare allo stage principale per impostare la schermata introduttiva; non inseriamo istanze della clip nell'area di lavoro, poiché tutte le operazioni di creazione e gestione dell'area di gioco saranno gestite dalla classe Actionscript.

Inseriamo un nuovo fotogramma nella linea temporale del filmato principale, portiamoci sul primo frame e inseriamo alcuni elementi: nell'esempio sono stati creati un titolo, un breve testo di istruzioni e un pulsante (con nome istanza gioca), inoltre è stato impostato uno sfondo grigio; ovviamente è possibile personalizzare a piacimento questi aspetti. In figura è possibile vedere la schermata introduttiva dell'esempio.

Figura 3. La schermata introduttiva del gioco
Screenshot dello stage

Il codice presente sul fotogramma è il seguente:

stop()
gioca.addEventListener(MouseEvent.CLICK,avvia_gioco)
function avvia_gioco(evt:MouseEvent):void{
  gotoAndStop(2)
}

In questo modo quando l'utente premerà il pulsante gioca la linea temporale verrà portata al secondo fotogramma, dove inseriamo invece il codice:

nuova_partita()

La funzione nuova_partita sarà sita all'interno della classe Actionscript; concludiamo la preparazione dello stage andando ad inserire nel pannello Proprietà la Document Class "mastermind".

Figura 4. Impostazione della classe documento dal file FLA
Screenshot del pannello

Prima di proseguire è necessario ancora un elemento: dobbiamo dar modo all'utente di indicare al gioco quando la sua ipotesi di codice è completa, per cui creeremo un piccolo pulsante di cui andremo a creare poi dinamicamente le istanze tramite Actionscript. Inseriamo quindi un nuovo simbolo (Inserisci -> Nuovo simbolo) di tipo Pulsante, diamogli identificativo fatto e impostiamo anche per questo l'esportazione per Actionscript.

In figura è possibile vedere un esempio del pulsante da creare; anche in questo caso non posizioniamo istanze del pulsante sullo stage.

Figura 5. Esempio di composizione del pulsante fatto
Screenshot del pulsante

Nota: è importante che sia le pedine che il pulsante siano posizionati allo stesso modo rispetto al centro della clip, ovvero se per il pulsante abbiamo il centro nell'angolo in alto a sinistra (come in figura) così dovrà essere anche per le pedine. In caso contrario noteremo un disallineamento tra la riga di pedine e il rispettivo pulsante.

Una volta completata questa operazione possiamo considerare conclusa la preparazione dello stage: passiamo alla parte Actionscript con la scrittura della classe mastermind.

Preparazione della classe

Per prima cosa creiamo un nuovo file Actionscript (File->Nuovo->File Actionscript) e salviamolo come mastermind.as nella stessa cartella del file FLA.

Per prima cosa è necessario importare i package che utilizzeremo all'interno della classe: in questo gioco saranno flash.display.*, flash.events.* e flash.text.*.

Il primo sarà necessario per creare i movieclip, il secondo per gestire gli input dell'utente e il terzo per creare i campi di testo che useremo per dare indicazioni al giocatore.

Nel codice possiamo anche dichiarare la classe, dopo la sequenza di import.

package{
  import flash.display.*
  import flash.events.*
  import flash.text.*
  
  public class mastermind extends MovieClip{

A questo punto possiamo passare alla dichiarazione delle costanti e delle variabili che utilizzeremo nel gioco. Caratteristica delle costanti è quella di mantenere inalterato il loro valore in tutta la classe, sono quindi l'ideale per le impostazioni di gioco come ad esempio la lunghezza del codice, il numero di colori, il numero massimo di tentativi e alcune impostazioni riguardo la distanza tra le pedine e tra ogni riga di tentativi. Nel nostro esempio imposteremo anche due costanti relativi alla distanza dal punto 0,0 (l'angolo in alto a sinistra) dello stage, per indicare al player dove iniziare a disegnare la prima riga.

// dichiarazione delle costanti
private static const pedine:uint = 5; // quante pedine
private static const colori:uint = 5; // quanti colori
private static const tentativi_max:uint = 10; // massimo di tentativi
private static const dist_orizz:Number = 30; // distanza orizzontale dal punto 0,0
private static const dist_vert:Number = 60; // distanza verticale dal punto 0,0
private static const spazio_pedine:Number = 30; // spazio tra le pedine
private static const spazio_righe:Number = 30; // spazio tra le righe

Grazie a questo vasto numero di costanti potremo facilmente configurare l'aspetto del gioco, in particolare qualora le pedine fossero più grosse di 25x25 pixel basterà cambiare i valori di spazio_pedine e spazio_righe per adattare il layout del gioco di conseguenza.

Una volta definite le costanti possiamo passare alle variabili; principalmente durante la partita vorremo sapere quale sia la soluzione esatta (quindi quella generata dal computer) e a quale turno si trovi l'utente (per stabilire se ha ancora tentativi o se ha perso), avremo inoltre tre variabili relative alla riga di pedine attualmente attiva, all'istanza del pulsante fatto (che porremo di fianco alla riga), al campo di testo che verrà posizionato accanto al pulsante (che conterrà il responso della combinazione inserita) e un array che conterrà i riferimenti a tutti gli oggetti grafici inseriti sullo stage, che ci tornerà utile per eliminarli qualora l'utente volesse iniziare una nuova partita. In totale quindi sei variabili.

// dichiarazione delle variabili
private var soluzione:Array; // soluzione
private var numero_turno:uint; // numero di tentativi
// riferimenti agli oggetti
private var riga_corrente:Array; // riferimento alle pedine della riga attuale
private var pulsante_corrente:fatto // riferimento al pulsante corrente
private var testo_corrente:TextField; // campo di testo corrente
private var tutti_oggetti:Array; // riferimento a tutti gli oggetti

A questo punto abbiamo a disposizione le costanti e le variabili necessarie ad impostare l'area di gioco: vediamo come creare la funzione principale della classe, nel nostro caso nuova_partita, che si occuperà semplicemente di generare il codice casuale da far indovinare all'utente e richiamerà in seguito la funzione di costruzione della riga di spazi.

public function nuova_partita():void{
  tutti_oggetti = new Array()
  soluzione = new Array()
  for(var n:uint = 0 ; n<pedine; n++){
    var casuale:uint = uint(Math.floor(Math.random()*colori)+1);
    soluzione.push(casuale)
  }
  numero_turno = 0
  creaRiga()
}

Vediamo che ad ogni partita verranno reimpostati gli array tutti_oggetti e soluzione, quindi tramite un ciclo for (basato sul valore di pedine) ci occupiamo di creare una soluzione casuale, dove ogni elemento avrà un valore casuale basato sul numero di colori disponibili (memorizzato nella variabile colori). Al termine della funzione avremo all'interno dell'array soluzione l'intero codice e potremo quindi costruire la prima riga per richiedere al giocatore di inserire il suo primo tentativo.

Per ora, per evitare confusione, interrompiamo qui l'articolo e rimandiamo a settimana prossima per la seconda parte.

Creazione di una riga

La funzione creaRiga si occuperà di creare per ogni riga un numero di istanze del movieclip pedina pari al valore della variabile pedine, rendendole cliccabili da parte dall'utente e andando a creare anche il pulsante di conferma e il campo di testo per il responso.

Ogni pedina avrà una variabile numero per identificare la sua posizione nella riga, mentre all'interno dell'array riga_corrente inseriremo ogni volta un oggetto composto da due valori: il riferimento all'istanza creata e il colore scelto (inizialmente 0, dato che sarà mostrato lo spazio vuoto).

Il codice di questa funzione è piuttosto lungo, ma anche molto semplice:

private function creaRiga():void{
  riga_corrente = new Array()
  
  for(var p:uint = 0; p<pedine; p++){
    var pedina_attuale:pedina = new pedina() // creiamo la pedina
    pedina_attuale.x = p*spazio_pedine+dist_orizz; // la posizioniamo orizzontalmente
    pedina_attuale.y = numero_turno*spazio_righe+dist_vert // e verticalmente
    pedina_attuale.gotoAndStop(1) // la portiamo al primo fotogramma (lo spazio vuoto)
    pedina_attuale.addEventListener(MouseEvent.CLICK,pedina_cliccata) // la rendiamo cliccabile
    pedina_attuale.buttonMode = true // facciamo in modo che il cursore diventi "manina" su di essa
    pedina_attuale.numero = p // le associamo una variabile "numero"
    addChild(pedina_attuale) // la mostriamo sullo stage
    tutti_oggetti.push(pedina_attuale) // aggiungiamo un riferimento alla pedina nell'array tutti_oggetti
    riga_corrente.push({pedina:pedina_attuale,colore:0}) // inseriamo due valori nell'array riga_corrente
  }
  
  if(pulsante_corrente == null){ // se non abbiamo ancora creato il pulsante
    pulsante_corrente = new fatto() // ne creiamo un'istanza
    pulsante_corrente.x = pedine*spazio_pedine+dist_orizz+10 // lo posizioniamo in orizzontale
    pulsante_corrente.addEventListener(MouseEvent.CLICK,analizza) // lo rendiamo cliccabile
    pulsante_corrente.buttonMode = true // facciamo in modo che il cursore diventi "manina" su di esso
    addChild(pulsante_corrente) // lo mostriamo sullo stage
    tutti_oggetti.push(pulsante_corrente) // aggiungiamo un riferimento al pulsante nell'array tutti_oggetti
  }
  pulsante_corrente.y = numero_turno*spazio_righe+dist_vert // posizioniamo il pulsante all'altezza della riga
  
  testo_corrente = new TextField() // creiamo il campo di testo
  testo_corrente.x = pedine*spazio_pedine+dist_orizz+pulsante_corrente.width+10 // lo posizioniamo in orizzontale
  testo_corrente.y = numero_turno*spazio_righe+dist_vert // e in verticale
  testo_corrente.width = 300 // lo rendiamo largo 300 pixel
  testo_corrente.text = "Inserisci il tuo codice, quindi premi il pulsante FATTO"; // vi inseriamo il testo
  addChild(testo_corrente); // lo mostriamo sullo stage
  tutti_oggetti.push(testo_corrente); // aggiungiamo un riferimento al campo di testo nell'array tutti_oggetti
}

Unico appunto "supplementare" sulla creazione del pulsante, dove possiamo notare che alcuni comandi sono all'interno di un controllo if mentre il posizionamento verticale è esterno ad esso. Questo perché in tutto il filmato noi utilizzeremo un solo pulsante (che creiamo appunto all'interno dell'if), mentre nei turni successivi ci limiteremo a spostarlo verticalmente. In pratica la creazione del pulsante avviene quando il gioco imposta la prima riga (e pulsante_corrente ha ancora valore null), mentre nelle righe successive avviene solo lo spostamento (infatti pulsante_corrente non risulterà più null e i comandi all'interno dell'if non verranno eseguiti).

Qualora volessimo testare il filmato per vedere il risultato occupiamoci di commentare momentaneamente le righe relative ai listener per gli eventi CLICK, altrimenti il player ci restituirà un errore; una volta compilate queste due righe avviando la prova filmato dovremmo avere un risultato simile a quello in figura.

Figura 6. La prima riga con gli spazi vuoti, il pulsante e il campo di testo
Screenshot del filmato

Gestione degli input dell'utente

Nella precedente funzione abbiamo associato al click su ogni pedina il richiamo della funzione pedina_cliccata. Il sistema che utilizzeremo è molto semplice: ad ogni click su una pedina il giocatore le cambierà colore (l'ordine dei colori è quello dei fotogrammi del movieclip pedina), quindi ogni volta che la funzione pedina_cliccata sarà richiamata dovremo innanzitutto identificare quale pedina è stata cliccata dall'utente, quindi mandarla avanti di un fotogramma (a meno che non si trovi già al sul ultimo colore, nel qual caso la riporteremo allo stato di spazio vuoto ovvero al primo frame); contemporaneamente al cambio di fotogramma effettueremo anche il cambio di valore all'interno dell'array riga_corrente.

private function pedina_cliccata(evt:MouseEvent):void {
  // ricaviamo la pedina cliccata
  var pedina_attuale:Object = riga_corrente[evt.currentTarget.numero];
  var colore_attuale:uint = pedina_attuale.colore; // ricaviamo il colore della pedina
  if (colore_attuale < colori) { //se il colore non è l'ultimo
    pedina_attuale.colore = colore_attuale+1 // cambiamo il valore nell'array
  } else {
    pedina_attuale.colore = 0; // reimpostiamo nell'array il colore a zero
  }
  // cambiamo il fotogramma della pedina
  pedina_attuale.pedina.gotoAndStop(pedina_attuale.colore+1);
}

Grazie alla proprietà currentTarget, passata con l'evento, siamo in grado di ricavare la pedina cliccata e di conseguenza il valore della sua variabile numero, che utilizziamo per creare un riferimento all'elemento appropriato dell'array riga_corrente. Tale riferimento è la variabile pedina_attuale, che infatti usiamo nel prosieguo del codice per impostare il nuovo colore. Notiamo come pedina_attuale.pedina indichi il riferimento all'istanza del movieclip, riferimento che avevamo inserito nell'array all'interno del ciclo for visto nella funzione nuova_partita.

Decommentiamo all'interno di nuova_partita la riga relativa all'evento MouseEvent.CLICK su una pedina, testiamo il filmato e proviamo a cliccare ripetutamente su una o più pedine: il risultato sarà simile a quello in figura.

Figura 7. Le pedine risultano ora colorabili
Screenshot del filmato

Controllare il codice inserito dal giocatore

Passiamo alla funzione che si occuperà di confrontare il codice inserito dal giocatore con la soluzione generata dal computer. Di questo si occuperà la funzione analizza, che viene richiamata quando il giocatore preme il pulsante "Fatto". Questa funzione dovrà calcolare le pedine interamente corrette (posizione e colore) e quelle parzialmente corrette (solo il colore). Intanto vediamo il codice della funzione:

private function analizza(evt:MouseEvent):void{
  var pedine_corrette:uint = 0; // variabile per le pedine corrette
  var colori_corretti:uint = 0; // variabile per i colori corretti
  var colori_soluzione:Array = new Array(); // array per il controllo colori
  var colori_attuali:Array = new Array(); // array per il controllo colori
  for(var n:uint=0; n<colori; n++){
    colori_soluzione.push(0)
    colori_attuali.push(0)
  }
  // controlliamo le pedine
  for(var i:uint=0;i<pedine;i++) {
    // se la pedina corrisponde alla soluzione
    if (riga_corrente[i].colore == soluzione[i]) {
      pedine_corrette++; // aumentiamo le pedine corrette
    } else {
      // la pedina non corrisponde, ma memorizziamo il colore
      colori_soluzione[soluzione[i]-1]++
      colori_attuali[riga_corrente[i].colore-1]++
    }
    // disattiviamo la pedina
    riga_corrente[i].pedina.removeEventListener(MouseEvent.CLICK,pedina_cliccata);
    riga_corrente[i].pedina.buttonMode = false;
  }
  // ricaviamo il numero di colori esatti
  for(i=0;i<colori;i++) {
    colori_corretti += Math.min(colori_soluzione[i],colori_attuali[i]);
  }
  // mostriamo il responso
  testo_corrente.text = "Pedine correte: "+pedine_corrette+", Colori corretti: "+colori_corretti;
  // incrementiamo i turni
  numero_turno++;
  // se tutte le pedine sono corrette
  if (pedine_corrette == pedine) {
    vittoria(); // il giocatore vince
  } else {
    if (numero_turno == tentativi_max) { // se i tentativi sono esauriti
      sconfitta() // il giocatore perde
    } else { // se invece ci sono ancora tentativi
      creaRiga(); // creiamo una nuova riga
    }
  }
}

Il controllo delle pedine corrette è semplicissimo: con un ciclo for controlliamo le corrispondenze tra i colori della riga attuale e quelli della soluzione e quando troviamo un'uguaglianza andiamo ad aumentare il valore della variabile pedine_corrette.

Altro passaggio molto semplice è la disattivazione delle pedine di ogni riga: in questo modo evitiamo che il giocatore possa ricliccare sulle righe diverse da quella attualmente in gioco.

La parte più difficile è sul confronto dei colori: se il confronto tra i colori delle pedine nella stessa posizione non da buon esito memorizziamo comunque il colore nell'array colori_attuali, così come facciamo per l'array colori_soluzione.

Praticamente alla fine del ciclo avremo due array contenenti il numero di colori usati nella soluzione (e nella riga) al di fuori delle corrispondenze esatte.

Supponiamo ad esempio che il codice da indovinare sia

Rosso Blu Rosso Verde Giallo

E che il giocatore ipotizzi

Giallo Blu Verde Rosso Giallo

Avremo 2 corrispondenze esatte (seconda pedina blu e quinta gialla), quindi i rimanenti colori del codice utente sono 1 giallo, 1 verde e 1 rosso (l'array sarà quindi 1,1,0,1,0) mentre per la soluzione avremo 2 rossi e 1 verde (l'array sarà quindi 2,1,0,0,0). Possiamo quindi ricavare il numero minore tra ogni elemento dei due array per sapere quanti colori sono esatti ma in posizione errata: nel confronto tra i valori di rosso (1 e 2) il minimo è 1, nel confronto tra i verdi (1 e 1) abbiamo ancora 1, mentre nei rimanenti tre confronti abbiamo sempre 0 (blu 0 e 0, verde 1 e 0 e viola 0 e 0). Quindi i colori corretti (ma in posizione errata) sono 2, così come le pedine completamente corrette. Il valore completamente errato è invece il primo giallo (infatti l'unico giallo presente nella soluzione è il quinto).

Per ricavare il valore minimo tra gli elementi dei due array abbiamo sfruttato il comando Math.min, che restituisce appunto il più basso tra i due valori passati come parametri; al termine del secondo ciclo for (che controlla appunto i colori) avremo le variabili pedine_corrette e colori_corretti pronte per essere inserite nel campo di testo.

Le ultime operazioni della funzione si occupano di controllare se tutte le pedine sono corrette (in questo caso viene richiamata la funzione vittoria) o, nel caso non lo fossero, se i turni sono stati esauriti (nel qual caso viene richiamata la funzione sconfitta) oppure no (in questo caso verrà creata una nuova riga con la funzione creaRiga).

Volendo possiamo commentare momentaneamente i richiami alle funzioni di vittoria e sconfitta, decommentare la riga relativa all'evento CLICK per il pulsante fatto e testare il filmato: il risultato sarà simile a quello in figura.

Figura 8. Una sequenza di gioco
Screenshot del filmato

Funzioni di vittoria e di sconfitta

Non ci resta che preparare le funzioni di vittoria e di sconfitta, che saranno peraltro molto simili tra loro. Scopo di queste funzioni sarà di creare una nuova riga di testo sotto all'ultima riga di pedine, mostrando il testo appropriato; anche il pulsante fatto verrà spostato sulla nuova riga e cambieremo la sua azione in modo che al click su di esso il giocatore venga riportato al primo fotogramma così da poter eventualmente iniziare una nuova partita.

La differenza principale tra le due funzioni sarà che sconfitta andrà a mostrare al giocatore quale fosse il codice esatto.

private function vittoria():void{
  // spostiamo il pulsante
  pulsante_corrente.y = numero_turno*spazio_righe+dist_vert;
  // cambiamo azione al pulsante
  pulsante_corrente.removeEventListener(MouseEvent.CLICK,analizza);
  pulsante_corrente.addEventListener(MouseEvent.CLICK,pulisci);
  
  // creiamo il nuovo testo con il messaggio di vittoria
  testo_corrente = new TextField();
  testo_corrente.x = pedine*spazio_pedine+dist_orizz+pulsante_corrente.width+10
  testo_corrente.y = numero_turno*spazio_righe+dist_vert
  testo_corrente.width = 300;
  testo_corrente.text = "Hai vinto!";
  addChild(testo_corrente);
  tutti_oggetti.push(testo_corrente);
}

private function sconfitta():void{
  // spostiamo il pulsante
  pulsante_corrente.y = numero_turno*spazio_righe+dist_vert;
  // cambiamo azione al pulsante
  pulsante_corrente.removeEventListener(MouseEvent.CLICK,analizza);
  pulsante_corrente.addEventListener(MouseEvent.CLICK,pulisci);
  
  // creiamo il nuovo testo con il messaggio di sconfitta
  testo_corrente = new TextField();
  testo_corrente.x = pedine*spazio_pedine+dist_orizz+pulsante_corrente.width+10
  testo_corrente.y = numero_turno*spazio_righe+dist_vert
  testo_corrente.width = 300;
  testo_corrente.text = "Hai perso!";
  addChild(testo_corrente);
  tutti_oggetti.push(testo_corrente);
  
  riga_corrente = new Array();
  for(var i:uint=0;i<pedine;i++) {
    var pedina_attuale:pedina = new pedina();
    pedina_attuale.x = i*spazio_pedine+dist_orizz;
    pedina_attuale.y = numero_turno*spazio_righe+dist_vert;
    pedina_attuale.gotoAndStop(soluzione[i]+1);
    addChild(pedina_attuale);
    tutti_oggetti.push(pedina_attuale);
  }
}

Possiamo notare nei due codici come l'evento MouseEvent.CLICK venga riassociato in modo che al click sul pulsante fatto dopo la vittoria o la sconfitta sia richiamata la funzione pulisci. Questa funzione semplicemente sfrutterà l'array tutti_oggetti per ripulire completamente lo stage, resettare le variabili di gioco e rimandare la linea temporale al primo fotogramma.

private function pulisci(evt:MouseEvent):void{
  // rimuoviamo tutti gli elementi creati dinamicamente
  for(var clip in tutti_oggetti) {
    removeChild(tutti_oggetti[clip]);
  }
  // reimpostiamo i riferimenti a "null"
  tutti_oggetti = null;
  testo_corrente = null;
  pulsante_corrente = null;
  riga_corrente = null;
  // rimandiamo la linea temporale al primo fotogramma
  MovieClip(root).gotoAndStop(1);
}

A questo punto possiamo decommentare le righe di richiamo a queste due funzioni e testare il filmato; nel caso di vittoria del giocatore avremo un risultato simile a quello di figura 9, altrimenti la situazione sarà quella di figura 10 dove notiamo il codice rivelato dal gioco a fine partita.

Figura 9. Vittoria del giocatore
Screenshot del filmato
Figura 10. Sconfitta del giocatore
Screenshot del filmato

Conclusione

Il fatto di aver basato praticamente tutte le funzioni su costanti e variabili ci permette di creare rapidamente delle versioni più o meno complesse, ad esempio in figura possiamo vedere una versione con 8 pedine (è bastato cambiare la costante pedine).

Figura 11. Una versione con 8 pedine
Screenshot del filmato

Analogamente potremmo variare il numero di colori per rendere ancor più difficile (o più semplice) il gioco, tutto agendo semplicemente su una riga di codice (anche se nel caso di un cambio di colori dovremmo aggiungere anche i relativi fotogrammi al movieclip pedina).

La programmazione di questo gioco non ha presentato particolari difficoltà, l'unico aspetto non proprio basilare era il sistema di calcolo dei colori sbagliati, tutto il resto è gestito con comandi abbastanza semplici di Actionscript 3; proprio il fatto che quasi tutti gli elementi siano controllati da codice ci consentirebbe di variare piuttosto comodamente la grafica del gioco (ovviamente entro alcuni limiti). Potremmo facilmente usare anche il gioco all'interno ad esempio di un'avventura grafica, inserendo questo Mastermind come enigma secondario per aprire una porta o guadagnare determinati premi, questo grazie principalmente alla versatilità che abbiamo fornito al gioco.


Ti consigliamo anche