domenica 31 marzo 2013

Prato Fiorito

Beh, non tutti sanno giocare al fantastico gioco Prato Fiorito. Questa è una versione basilare, ma completamente funzionane in linea di comando programmata in C.

Non sono riuscito a farla nella libreria standard, la funzione gotoxy non è presente nella libreria conio.h ma in conio2.h. Io non sono riuscito ad installarla sul Dev quindo per utilizzare la funzione gotoxy l'ho dovuta scrivere usando delle API di windows. Un altro intoppo per la portabilità è il cambio di colore nella linea di comando, supportato solo dalla libreria 'windows.h'
ATTENZIONE: il programma funziona solo sotto Windows per le motivazioni di prima...

Credo che sia meglio fare una piccola introduzione al gioco del Prato Fiorito. Il gioco si svolge in una tabella (nel nostro caso 9x9) dove sono presenti alcuni fiori nascosti, l'obbiettivo è identificare la loro posizione senza cliccarli. Per fare ciò il gioco prevede che le caselle che non contengano un fiore, contengano un numero. Questo numero identifica il numero di fiori attorno a quella casella.

I comando per giocare a questo gioco su windows sono basilari (punti e clicchi con il mouse). A linea di comando invece è meno intuitivo. Le frecce spostano il cursore, con 'a' si segna o si toglie il segno dalla posizione come fiore, con 'b' si apre e si legge il contenuto della casella. Il senso di segnare i fiori con 'a' è quello di non premerli per errore, infatti, se una casella è segnata non si può aprire.
Passiamo ora al funzionamento. Il sistema della grafica è lo stesso identico del Tetris: scrive su una matrice quello da stampare nelle coordinate esatte. Ad ogni ciclo pulisce la console e stampa carattere a carattere il contenuto della matrice.
La gestione dell'input è abbastanza semplice, associa al codice delle frecce lo spostamento del cursore (tramite gotoxy). La posizione viene gestita semplicemente da due interi curX e curY che rappresentano ovviamente le coordinate del cursore. La funzione 'generateBoard' viene chiamata solo dopo aver aperto la prima casella, in modo tale da non perdere al primo turno. La board vera e propria vene memorizzata in una matrice (in questo caso 9x9), un fiore ha codice 0, una casella che è vicina ad n blocchi ha codice n, una casella che non è adiacente ad alcun blocco ha codice -1. Tramite questa matrice diventa veramente facile gestire l'input, quando viene aperta una casella, se è 0 il gioco termina perché è un fiore, se è un numero positivo apre la casella e visualizza il numero, se è -1 apre tutte le caselle attorno a quella con un funzione ricorsiva. Questa funzione può sembrare complicata perché è ricorsiva, in realtà è veramente semplice, ripete semplicemente la stessa operazione per tutte le caselle attorno. Non può uscire dalla matrice con gli indici perché vengono verificati con una serie di if, non può nemmeno aprire un fiore perché attorno ad una casella con codice -1 non ci sono fiori. Appena più complicata è la funzione di generazione della board, il funzionamento però è facile da comprendere leggendo i commenti. Inizialmente imposta la matrice con soli valori -1. Poi genera a caso il numero deciso di fiori, evita che due fiori si sovrappongano e che il fiore venga generato nella posizione del cursore (per evitare una sconfitta al primo turno). Ora inizia un ciclo che scorre tutte le caselle della board: se il contenuto è zero ignora la cella (un fiore ha distanza zero), se è -1 (non è un fiore) allora conta quanti fiori ci sono attorno e salva il valore nella cella. Appena viene concluso il ciclo per debug salva il contenuto della board in un file. Sarà facile capire cosa c'è dentro ogni singola cella in caso di crash o di bug...
La funzione che controlla la vittoria e quindi la fine del gioco è molto semplice, scorre tutte le caselle del modello e della board, se una casella che non è un fiore è ancora chiusa allora la partita non è terminata. Per uscire rapidamente dai due cicli ho usato un goto...
Quando il gioco si conclude mostra la board con segnate le posizioni dei fiori. Per questioni estetiche ho anche messo i colori alla linea di comando... La funzione che imposta il colore della console non l'ho scritta io  ma l'ho cercata su google... Non è difficile da comprendere, ottiene l'handle dell'stdout e chiama la funzione 'SetConsoleTextAttribute' della libreria 'wincon.h' che imposta le proprietà della linea di comando. L'intero color a parametro è definito in 'wincon.h' e può essere: FOREGROUND_XXX dove XXX può essere RED, GREEN, BLUE, INTENSITY. Eventualmente i colori possono essere uniti con l'operatore |.
Per il disegno della board ho usato un piccolo trucco che mi hanno suggerito: ho disegnato la board in un file di testo (board9x9.txt) e il suo contenuto l'ho caricato nel modello... Il file contiene anche delle informazioni sulla board, la prima linea contiene cinque numeri: la larghezza del campo di gioco, la sua altezza, la coordinata x della prima casella, la sua y, ed il numero di fiori. Non ho ancora provato, ma si potrebbe provare a modificare il file board9x9 per aggiungere altri livelli di difficoltà con più fiori e più caselle.


DOWNLOAD:
Dropbox - Google Drive

SCREEN:

Nessun commento:

Posta un commento