sabato 29 settembre 2012

Il ciclo For

Nei precedenti articoli sono stati discussi l'uso del ciclo while e do. Tuttavia esiste un altro modo per creare un ciclo di struzioni mediante l'anello for, il quale è particolarmente adatto per i contatori e per eseguire una serie di istruzioni in sequenza. La sintassi comune del ciclo for è la seguente:
for (inizializzazione; controllo; azione) { istruzioni; }
l'inizializzazione è una variabile che imposta le condizioni iniziali dell'anello for (ad esempio impostare il contatore a 0). L'espressione controllo, viene verificata ogni volta prima di eseguire il ciclo, così come accadeva nel ciclo while. Se il controllo è falso, il programma si sposta all'istruzione successiva al ciclo, se vero, il programma esegue le istruzioni contenute nel ciclo. Non appena il controllo viene verificato falso, il ciclo si interrompe.

Un esempio di conteggio

Il seguente programma conta in avanti, alla rovescia, per multipli di tre. Inoltre può stampare un conteggio multiplo di una griglia formata da righe e colonne. Tutto questo viene realizzato mediante cicli for.
// Contatore
//Dimostra il ciclo for
#include <iostream>
using namespace std;
int main()
{
cout << “Conto in avanti:\n”
for (int i=0; i <=10; i++) cout << i << “ ”;

cout << “Conto alla rovescia:\n”
for (int i=10; i >=0; -i) cout << i << “ ”;

cout << “Conto multipli di tre:\n”
for (int i=0; i <=30; i+=3) cout << i << “ ”;

cout << “Conto con cicli annidati:\n”
const int RIG = 5
const int COL = 6
for (int i=0; i < RIG; ++i){
           for (int k =0; k < COL; ++j){
           cout << i << “,”<< k << “ “ ;
          } cout << endl;
    }
}

giovedì 27 settembre 2012

Uso degli operatori logici

Una espressione semplice può essere valutata attraverso l'uso degli operatori logici tramite il valore di vero o falso. Tuttavia è possibile combinare gli operatori logici per creare espressioni più complesse. La sintassi degli operatori logici è la seguente:
! NOT logico !espressione
&& AND logico espressione1 && espressione2
|| OR logico espressione1 || espressione2
Una semplice espressione logica complessa può essere scritta in modo seguente:
string sNome;
string sPassword;
cout << “Inserisci nome”;
cin >> sNome;
cout << “Inserisci password”;
cin >> sPassword;
if ( sNome == “Pippo” && sPassword == “Noccioline”)
{ cout << “Ciao Super-pippo”; }
if ( sNome == “ospite” || sPassword == “ospite”)
{ cout << “Benvenuto ospite”; }

In questo breve  frammento di programma, vengono riconosciuti come validi utenti Pippo e ospite, nel primo caso è necessario conoscere la passweord per essere ritenuti un valido utente, nel secondo caso la parola ospite può essere digitata come nome utente o come password.

martedì 25 settembre 2012

Generare un numero casuale II

Un modo estremamente semplice per costruire un generatore di numeri pseudocasuali dotato di maggiore entropia, è il seguente.

srand(time(0)); // seme numero casuale
 int primi[10]= {11,23,7,19,2,13,31,5,3,29};
for (int c=0;c < 10;c++){
dado = (rand()* primi[c]) %6 + 1;
}

La nostra funzione rand() restituisce un valore intero, il quale viene moltiplicato con un valore proveniente da un vettore di numeri interi primi disposti casualmente. Il valore prodotto viene sottoposto all'operazione modulo la quale ci restituisce un valore numerico nella scala di valori scelta. Poichè la sequenza di valori nel vettore è stata scelta casualmente dal programmatore essa introduce un elemento di disordine alla funzione peseudocasuale. E' possibile definire più vettori o utilizzare intervaslli numerici diversi all'interno di uno stesso vettore per aumentare la casualità di altre funzioni utilizzate nel programma che necessitino di generare numeri casuali.

lunedì 24 settembre 2012

Generare un numero casuale

Generare un numero casualmente, per creare imprevisti, aggiunge eccitazione ad un gioco. Il cambio di strategia esercitato da un simulatore degli scacchi o l'improvvisa apparizione di una creatura nemica in un FPS, introduce nel giocatore il fattore sorpresa.
Per richiamare la funzione rand(), per prima cosa è necessario include un nuovo file libreria nel programma.
#include<cstlib>
Questo file contiene tra le altre cose, una funzione che permette di generare numeri casuali. Una volta incluso il file, siamo liberi di richiamare la funzione che contiene rand(), la quale viene inserita nella funzione main().
int numerocasuale = rand();
Utilizzando questa funzione viene generato un numero casuale assegnato alla variabile intera numerocasuale, questo valore viene generato come ritorno dalla funzione. Questa funzione come si capisce dalle due parentesi chiuse non ha bisogno di argomenti per essere richiamata.

Generare un seme per il generatore numerico

I computer a differenza di un dado fisico lanciato varie volte, possono generare solo numeri pseudocasuali basati su una formula. Un modo di pensare è che la funzione rand() legge da un grande libro di numeri casuali predeterminati. Ma la funzione rand() inizia sempre da un punto diverso la lettura di questo libro. Per modificare il punto di inizio della funzione vien utilizzato l'orologio interno del calcolatore utilizzando la libreria ctime. Pertanto viene determinato il seme mediante la funzione: 
srand(time(0)); 
Questa funzione è corretta in quanto time(0) restituisce un numero basandosi sull'ora corrente, la quale costituisce il seme per il valore casuale.

Calcolare un numero casuale in un intervallo

Dopo aver generato un valore intero mediante la funzione srand(), il valore casuale determinato è compreso tra 0 e 32677, per limitare questo intervallo si utilizza quindi l'operazione matematica modulo.
int dado = (numerocasuale % 6)+1;
In questo caso simuliamo un dado a 6 facce che può assumere un valore numerico casuale compreso tra 1 e 6, il risultato che volevamo ottenere vien ottenuto sommando 1 al valore dell'operazione modulo.

venerdì 21 settembre 2012

Uso delle istruzioni break & continue

Le istruzioni break e continue possono fornire un maggiore controllo dei cicli di istruzioni.
Di seguito viene illustrato un breve esempio delle due istruzioni.

#include <iostream>

using namespace std;
//Saltatre
int main(int argc, char *argv[])
{
    int conto=0;
    while(true){
                conto++;
                if(conto > 10) break;
                if (conto == 3) continue; //prosegue il ciclo
                cout << conto << endl;
                }
    system("PAUSE");
    return EXIT_SUCCESS;
}

In questo ciclo l'istruzione break viene usata per interrompere il ciclo non appena la nostra variabile conto raggiunge il valore di 10, iterando quindi il ciclo dieci volte prima di interrompersi. Il nostro contatore visualizza il valore della variabile intera conto tutte le volte, tranne quando la variabile assume valore tre. In questo caso il ciclo vien riportato all'inizio senza eseguire tutte le istruzioni poste dopo l'istruzione continue. Nel nostro caso la visulaizzazione su schermo della variabile.

mercoledì 19 settembre 2012

Utilizzo del ciclo Do - While

Nel caso il ciclo di istruzioni da eseguire nel programma deve essere eseguito almeno per una volta, viene introdotta una modifica al ciclo while, con l'introduzione dell'istruzione do nella sintassi, in questo modo:

do { istruzioni; } 
                      while (espressione);
Un semplice esempio viene illustrato dal seguente programma.
 int a=0;
do { 
         printf(" numero ciclo %d",a);
          a++; } while(a<2);
In questo caso il ciclo viene ripetuto due volte, sino a quando la condizione di a sia equivalente al valore 2, il ciclo si interrompe.

martedì 18 settembre 2012

Generatore di labirinti

Il seguente codice è un semplice programma che permette di generare casualmente dei labirinti composti da caratteri e stamparli su schermo.
Il programma è stato commentato per renderne più facile la comprensione.
 
#include <iostream>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<time.h>

#define MAX 81  // 40 * 2 + 1
#define CELLA 1600  // 40^2
#define MURO 1
#define VIA 0

using namespace std;

void iniz_labi(int labi[MAX][MAX]);
void labi_generator(int indiceks, int labi[MAX][MAX], int retrotraccia_x[CELLA], int retrotraccia_y[CELLA], int x, int y, int n, int visitato);
void stampa_labi(int labi[MAX][MAX], int labi_taglia);
int e_chiuso(int labi[MAX][MAX], int x, int y);

int main(void)
{
    srand((unsigned)time(NULL));

    int taglia, indiceks = 0;
    int labi[MAX][MAX], retrotraccia_x[CELLA], retrotraccia_y[CELLA];
    cout << "CREATORE LABIRINTO\n\n";
    cout << "input  (0 ~ 40): ";
    cin >> taglia;
    cout << endl;
   

    iniz_labi(labi);

    retrotraccia_x[indiceks] = 1;
    retrotraccia_y[indiceks] = 1;

    labi_generator(indiceks, labi, retrotraccia_x, retrotraccia_y, 1, 1, taglia, 1);
    stampa_labi(labi, taglia);

    getch();
    return EXIT_SUCCESS;
}
// inizializzazione labirinto vuoto e pieno
void iniz_labi(int labi[MAX][MAX])
{
     for(int a = 0; a < MAX; a++)
     {
         for(int b = 0; b < MAX; b++)
         {
             if(a % 2 == 0 || b % 2 == 0)
                 labi[a][b] = MURO;
             else
                 labi[a][b] = VIA;
         }
     }
}
// generazione aperture casuali nel percorso
void labi_generator(int indiceks, int labi[MAX][MAX], int retrotraccia_x[CELLA], int retrotraccia_y[CELLA], int x, int y, int n, int visitato)
{
    if(visitato < n * n)
    {
        int vicino_valido = -1;
        int vicino_x[4], vicino_y[4], passo[4];

        int x_prossimo;
        int y_prossimo;

        if(x - 2 > 0 && e_chiuso(labi, x - 2, y))  // sopra
        {
            vicino_valido++;
            vicino_x[vicino_valido]=x - 2;;
            vicino_y[vicino_valido]=y;
            passo[vicino_valido]=1;
        }

        if(y - 2 > 0 && e_chiuso(labi, x, y - 2))  // a sinistra
        {
            vicino_valido++;
            vicino_x[vicino_valido]=x;
            vicino_y[vicino_valido]=y - 2;
            passo[vicino_valido]=2;
        }

        if(y + 2 < n * 2 + 1 && e_chiuso(labi, x, y + 2))  // a destra
        {
            vicino_valido++;
            vicino_x[vicino_valido]=x;
            vicino_y[vicino_valido]=y + 2;
            passo[vicino_valido]=3;

        }

        if(x + 2 < n * 2 + 1 && e_chiuso(labi, x + 2, y))  // basso
        {
            vicino_valido++;
            vicino_x[vicino_valido]=x+2;
            vicino_y[vicino_valido]=y;
            passo[vicino_valido]=4;
        }

        if(vicino_valido == -1)
        {
            // traccia lasciata ed arretramento
            x_prossimo = retrotraccia_x[indiceks];
            y_prossimo = retrotraccia_y[indiceks];
            indiceks--;
        }

        if(vicino_valido!=-1)
        {
            // traccia lasciata ed arretramento
            int casualizzare = vicino_valido + 1, random = rand()%casualizzare;
            x_prossimo = vicino_x[random];
            y_prossimo = vicino_y[random];
            indiceks++;
            retrotraccia_x[indiceks] = x_prossimo;
            retrotraccia_y[indiceks] = y_prossimo;

            int rpasso = passo[random];

            if(rpasso == 1)
                labi[x_prossimo+1][y_prossimo] = VIA;
            else if(rpasso == 2)
                labi[x_prossimo][y_prossimo + 1] = VIA;
            else if(rpasso == 3)
                labi[x_prossimo][y_prossimo - 1] = VIA;
            else if(rpasso == 4)
                labi[x_prossimo - 1][y_prossimo] = VIA;
            visitato++;
        }

        // richiamo a se stessa
        labi_generator(indiceks, labi, retrotraccia_x, retrotraccia_y, x_prossimo, y_prossimo, n, visitato);
    }
}

// determina se cella chiusa
int e_chiuso(int labi[MAX][MAX], int x, int y)
{
    if(labi[x - 1][y]  == MURO && labi[x][y - 1] == MURO
       && labi[x][y + 1] == MURO && labi[x + 1][y] == MURO ) return 1;

    return 0;
}

// visualizzazione labirinto
void stampa_labi(int labi[MAX][MAX], int labi_taglia)
{
     for(int a = 0; a < labi_taglia * 2 + 1; a++)
     {
         for(int b = 0; b < labi_taglia * 2 + 1; b++)
         {
             if(labi[a][b] == MURO)
                 cout << "@";
             else
                 cout <<" ";
         }
         printf("\n");
     }
}

lunedì 17 settembre 2012

Uso del ciclo While

L'istruzione while permette di creare una sezione di codice che si ripete sino a quando la condizione in espressione è vera; il programma esegue l'istruzione e torna ad analizzare l'espressione. Questo ciclo si ripete sino quando l'espressione non diviene falsa, a quel punto il ciclo termina ed il programma prosegue sull'istruzione successiva.
Qui viene mostrata la forma generica del ciclo while:
while(espressione) istruzione;

Presentare il programma Ti piace

// Ti piace
// Dimostra il ciclo while
#include <iostream>
using namespace std;
int main()
{
char cAncora = ‘s’;
while (cAncora == ‘s’)
{
cout << “\n**Hai giocato ad un piacevole gioco**”;
cout << “\nTi piace? (s/n): “;
cin >> cAncora;
}
cout << “\nOk, addio.”;
return 0;
}

domenica 16 settembre 2012

Racconto della Biblioteca di Babele

Una semplice modifica al programma mostrato in precedenza, in questo caso il risultato non viene stampato su schermo, ma viene salvato in modo semplice all'interno di un file di testo in una cartella temporanea.
Il codice del programma.
 
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
 char *r, stringa[32] = "abcdefghijklmnopqrstuvwxyz.; !?";
 srand(time(0)); // seme numero casuale
 ofstream out("/tmp/out.txt");
    out << "RACCONTO DELLA BIBLIOTECA DI BABELE\n";
   
for (int c=0;c < 20;c++){
    cout << c << endl;
 for (int b=0; b < 40; b++){
     for (int a =0; a < 40; a++){      
              out << stringa[rand()%32];
              } out << endl;
     } out << "\n\n";
 }
out.close();       
system("PAUSE");
return 0;
}


Il racconto della biblioteca di Babele si compone di 20 pagine distanziate tra loro con un paio di righe vuote; ogni pagina è composta da 40 righe per 40 caratteri.

Uso dell'istruzione Switch

E' possibile utilizzare l'istruzione switch per creare ramificazioni multiple nel codice. Viene mostrata una generica forma dell'istruzione:
switch(scelta)
{
case valore1: istruzione1; break;
case valore2: istruzione2; break;
case valore3: istruzione3; break;
case valoreN: istruzioneN; break;
default: istruzioneDefault;
}
L'istruzione verifica che il valore di scelta con tutti i possibili valori (1,2,3, N) in ordine. Se scelta non equivale a nessun valore, viene eseguita l'istruzione di default; altrimenti se equivale a uno dei valori nella lista, il programma esegue le istruzioni corrispondenti. Il programma abbandona l'istruzione switch non appena esegue l'istruzione break. L'uso di break o default sono opzionali, ma in questo modo il programma continuerà a controllare i successivi rami dell'istruzione switch sino al termine. Solitamente break viene utilizzato alla fine di ogni ramo case. E anche se default non è obbligatorio, ci permette di tenere sotto controllo tutti i valori possibili di scelta.
Qui viene dato un esempio che mostra l'idea. Supponiamo che scelta equivalga a valore2. Il programma verifica che il valore di scelta equivalga a valore1, non è così, quindi prosegue sull'istruzione. Di seguito verifica che scelta equivale a valore2, sono identici, per cui viene eseguita istruzione2, sino a che il programma non trova il break, ed esce dalla struttura dello switch.

Presentare il programma Menu Scelta

Il programma Menu scelta presenta all'utente una lista di tre livelli di difficoltà del programma e gli chiede di effettuare una scelta. Se l'utente inserisce il numero corrispondente ad una delle scelte in lista, viene visualizzato un messaggio di conferma. Se l'utente effettua qualche altra scelta, viene comunicato che si tratta di un valore non valido.
Il codice del semplice programma:
//Menu Scelta
//Dimostrazione istruzione switch
#include<iostream>
using namespace std;
int main()
{
int iScelta=0;
cout << “Livelli difficolta'\n\n”;
cout << “1 – Facile\n 2 – Normale\n 3 – Difficile\n”;
cout << “Scegli: ”; cin >> iScelta;
switch (iScelta){
case 1: cout << “Hai scelto Facile.\n”;
case 2: cout << “Hai scelto Normale.\n”;
case 3: cout << “Hai scelto Difficile.\n”;
default: cout << “Scelta non valida.\n”;
}
system(“PAUSE”);
return EXIT_SUCCESS;
}

sabato 15 settembre 2012

Interpretare un valore come vero o falso

Qualsiasi valore può essere interpretato come vero o falso. Se il valore di esso è diverso da 0, sarà interpretato come true, nel caso invece valga zero, sarò interpretato come false.

if(punteggio) cout << “Bene, hai un punteggio diverso da 0\n”;

Nel caso abbiamo attribuito al valore punteggio un valore diverso da 0 questa scritta viene visualizzata a schermo.

Uso degli operatori relazionali

Ma l'uso più comune dell'istruzione if è mediante l'uso degli operatori relazionali, i quali permettono di comparare un valore ad un altro, così come sarà mostrato negli esempi successivi. Per prima cosa vediamo se il punteggio ottenuto è maggiore di 10.

if (punteggio > 10) cout << “Hai un punteggio maggiore di 10. Bravo!\n”;

Se vogliamo gratificare il giocatore con un messaggio per indicare che ha raggiunto il punteggio massimo, ad esempio 100, possiamo scrivere.

if (punteggio == 100) cout <<” Ottimo, hai ottenuto il punteggio massimo: 100!\n”;

Nel caso si vogliano racchiudere più istruzioni nel blocco dell'istruzione if è necessario scrivere.

if (punteggio == 100) {… istruzioni }

Creare due ramificazioni

Avete visto la prima parte dell'istruzione if, e come lavora. Se il punteggio ottenuto è maggiore di 10 viene visualizzato il messaggio “Bravo. Hai ottenuto un punteggio maggiore di 10”.

if(punteggio > 10) cout << “Bravo. Hai ottenuto un punteggio maggiore di 10\n”;

Tuttavia possiamo creare un bivio tramite l'istruzione else, che permette di esplorare un nuovo ramo se la condizione è falsa. Viene mostrato il messaggio, “Hai un punteggio minore di 10. Non fa nulla. ”.

else cout << “\nHai ottenuto un punteggio minore di 10. Non fa nulla.\n”;

Fate molta attenzione nel caso di istruzioni if annidate tra loro, e l'attribuzione della clausola else.

venerdì 14 settembre 2012

Blocchi condizionali, ramificazioni e cicli ad anello

I programmi sinora scritti hanno una struttura lineare, ogni istruzione esegue un ordine dal'alto in basso. Comunque per creare giochi interessanti, è necessario scrivere programmi che eseguono o (evitano) sezioni di codice basandosi su certe condizioni. Questo è il principale argomento di questi post. Specificatamente:
  • Comprendere il Vero (e come viene stabilito da C++)
  • Utilizzare l'istruzione if nelle sezioni di codice per ramificarlo
  • Utilizzare l'istruzione switch per selezionare una sezione di codice da eseguire
  • Utilizzare while e do nei cicli per ripetere sezioni del codice
  • Generare numeri casuali

Comprendere il Vero

La verità può essere solo bianca o nera, almeno per quanto riguarda il C++. Si possono rappresentare vero oppure falso con le rispettive parole chiave true o false. Puoi immagazzinare il valore Booleano in una variabile di tipo bool , come visto nel capitolo 1. Qui un veloce riepilogo:
bool fatti = true, finzioni = false;
Questo codice rappresenta due variabili bool, fatti e finzioni. Fatti è vera e finzioni è falsa. Comunque la variabile è dichiarata tramite la parola chiave, un modo comodo per interpretarlo. Al contrario ogni valore può essere interpretato numerico come vero oppure falso. Tuttavia la maggior parte dei confronti di vero o falso riguarda la comparazione di cose. I confronti solo spesso fatti utilizzando gli operatori relazionali inclusi nel linguaggio.
==                               equivalente        vera solo se i due operatori sono identici
!=                                diverso da         vera solo se i due operatori sono diversi
>                                 maggiore di        vera solo se il primo operatore è maggiore del secondo
<                                 minore di            vera solo se il primo operatore è minore del secondo
>=                               maggiore uguale  vera solo se il primo operatore è maggiore o equivalente al secondo
<=                               minore uguale     vera solo se il primo operatore è minore o equivalente al secondo

Utilizzare l'istruzione if

Bene, ora è tempo di mettere al lavoro i concetti di vero o falso. E' possibile utilizzare l'istruzione if per controllare il vero ed eseguire del codice basato su di essa. Un semplice esempio dell'istruzione if:
if (espressione) istruzione;
Se l'espressione è vera, l'istruzione viene eseguita. Altrimenti l'espressione viene saltata e il programma procede alle istruzioni successive al blocco if.

Verificare il vero ed il falso

E' possibile scrivere una espressione if con una affermazione vera. Poiché vero è sempre true, il programma eseguirà sempre questa istruzione.
if (true) cout << “Questo viene sempre scritto a display\n”;

Allo stesso modo si può testare un'affermazione sempre falsa, poiché false non è true, il programma non eseguirà mai questa istruzione.

if(false) cout << “Questo non viene mai scritto a display\n”;

giovedì 13 settembre 2012

Sovraccarico delle Funzioni

Nel C++ è possibile definire funzioni con nomi identici ma che effettuano diverse azioni. Le funzioni devono differire nella lista dei parametri (e/o i loro attributi const). Un esempio vien elencato sotto:
#include <stdio.h>
void mostra(int valore)
{
printf("Intero: %d\n", valore);
}

void mostra(double valore)
{
printf("Virgola mobile: %lf\n", valore);
}

void mostra(char const *valore)
{
printf("Stringa: %s\n", valore);
}

int main()
{
mostra(18);
mostra(3.1415);
mostra("Ciao Mondo!\n");
system ("PAUSE");
return 0;
}

Nel programma soprascritto la funzione mostra viene definita, e modificando solo la lista parametri, si aspetta un int, double o char *, rispettivamente. Le funzioni hanno nome identico ma che differiscono per la lista parametri sono chiamate overloaded “sovraccariche”. L'atto di definire queste funzioni è chiamato 'function overloading', 'sovraccarico di funzione'.
Il compilatore C++ implementa il sovraccarico della funzione mostra in modo abbastanza semplice. Tutte le funzioni condividono lo stesso nome (in questo esempio mostra), il compilatore ( e di conseguenza il linker) usa nomi diversi. La conversione del nome nel file sorgente è chiamato 'compressione del nome'. Il compilatore C++ può convertire il prototipo void mostra(int) nel nome interno VmostraI, mentre un'analoga funzione char*, può essere chiamata VmostraCP. I nomi veri sono usati internamente dipendono dal compilatore e non sono rilevanti per il programmatore, eccetto quando vengono mostrati (es. la lista del contenuto di una libreria).
Alcuni punti da rispettare nel caso del sovraccarico di funzione:
  • Non usare l'overloading per funzioni che svolgono compiti concettualmente diversi. Nel caso della funzione mostra essi sono correlati tra loro (stampa informazione a schermo).
  • C++ non permette di creare funzioni che differiscono solo per il valore restituito, il quale può essere ignorato dal programmatore. Ad esempio l'istruzione printf(“Ciao...”); non attribuisce alcun particolare valore di ritorno della funzione.
  • E' possibile sovraccaricare una funzione che differisca solo per il valore di const, in questo caso le classi possono avere funzioni con identica lista parametri ma differiscono per il valore di const attribuito. In questo caso solo una delle funzioni può avere un valore const.

mercoledì 12 settembre 2012

Presentare Fortuna Trovata

Si tratta del progetto finale di questa prima parte di articoli, un semplice gioco di avventura nel quale il giocatore introduce alcune informazioni (compreso il proprio nome), nel quale il computer utilizza per modificare la storia di base.
// Il codice di Fortuna Trovata

#include <string>
#include <iostream>

using std::cin;
using std::cout;
using std::endl;
using std::string;
Per prima cosa sono inizializzate le funzioni da utilizzare nel corso del programma.
int main(int argc, char *argv[])
{
const int PEZZI_ORO = 900;
int iAvventurieri, iNemici, iSopravvissuti, iUccisi;
string sComandante;
Vengono definite le variabili nella funzione Main() che ci permetteranno di immagazzinare i dati forniti dall'utente del programma.

//prendere informazioni
cout << "Benvenuti a Fortuna trovata" << endl;
cout << "Fornisci le seguenti informazioni per personalizzare l'avventura" << endl;
cout << "Inserisci un numero:";
cin >> iAvventurieri;
cout << "Inserisci un numero minore del precedente:";
cin >> iUccisi;
iSopravvissuti = iAvventurieri - iUccisi;
iNemici = iAvventurieri *2;
cout << "Scrivi il tuo nome" << endl;
cin >> sComandante;
Vengono richiesti agli utenti i dati necessari al funzionamento del programma ed immagazzinati nelle variabili.
//narrare la storia
cout << "Un coraggioso gruppo di " << iAvventurieri << " avventurieri affronta una missione";
cout << "- La ricerca dell'Antico tesoro dei Nani - ";
cout << "Il gruppo e' guidato dal legendario eroe " << sComandante <<endl;
cout << "Lungo la via una squadra di " << iNemici << " orchetti attacca il gruppo di avventurieri. \n Ma sotto la guida del "
<< sComandante << " i nemici sono tutti sconfitti.\n";
cout << "Alcuni avventurieri, " << iUccisi << " cadono valorosamente.\n";
cout << "Lasciando " << iSopravvissuti << " sopravvissuti nel gruppo.\n";
cout << "Gli avventurieri stavano perdendo le speranze." << endl <<
"Ma mentre stavano seppellendo gli altri, hanno trovato la Fortuna sepolta." << endl;
cout << "Cosi' gli avventurieri divisero i " << PEZZI_ORO << " pezzi d'oro ritrovati.\n";
cout << "Il comandante " << sComandante << " ricevette il resto della divisione " << (PEZZI_ORO % iSopravvissuti) <<
" per pareggiare i conti.\n";
system("PAUSE");
return EXIT_SUCCESS;
}

Infine il programma stampa la storia personalizzata a seconda dei dati inseriti dall'utente.

martedì 11 settembre 2012

Utilizzo delle costanti

Per definire una costante nel programma che attribuisca il valore al nemico si utilizza la sintassi:
const int VALORE_NEMICO = 100;
Viene utilizzata la parola chiave const che ne modifica la definizione. Ora è possibile utilizzare come se si trattasse di un valore numerico. In questo caso il nome è stato scritto solo con lettere maiuscole, questa è una convenzione, la quale indica al programmatore che il valore che si sta utilizzando è una costante.
E' possibile quindi calcolare il punteggio del nostro gioco tramite la semplice moltiplicazione:
int punteggio = nemici_uccisi * VALORE_NEMICO.
L'utilizzo delle costanti rende il codice molto chiaro agli occhi del programmatore.

Utilizzo degli Enumeratori

Una enumerazione è una serie di interi privi di segno, chiamati enumeratori. Solitamente sono indicati in ordine crescente di valore, per esempio: 
enum liv_dif { NOVIZIO, FACILE, NORMALE, DIFFICILE, IMBATTIBILE };
Questa definizione crea una enumerazione chiamata livello. Per default i valori degli enumeratori iniziano per 0 ed aumentano di uno. Così, NOVIZIO vale 0, FACILE è 1, NORMALE è 2 ecc...
Successivamente viene creata una nuova variabile con questo tipo di enumerazione.
liv_dif miaDifficolta = FACILE;
La variabile miaDifficolta viene impostata su FACILE (equivale ad 1). Questa variabile è un tipo di liv_dif, pertanto può avere solo valore che sia stato in precedenza definito dall'enumeratore, quindi i valori compresi tra 0 e 4. Tuttavia è possibile inizializzare una enumerazione in modo diverso:
enum tipo_nave { CACCIA = 25, BOMBARDIERE, INCROCIATORE = 50, DISTRUTTORE = 100};
In questo caso la dichiarazione assegna un valore 25 a CACCIA, valore 26 a BOMBARDIERE, valore 50 ad INCROCIATORE e infine 100 a DISTRUTTORE 

lunedì 10 settembre 2012

Effettuare operazioni con le variabili

Dopo aver ottenuto i valori delle variabili, è possibile che questi siano manipolati durante il corpo del gioco. Ad esempio incrementare il punteggio, calcolare un bonus, calcolare la vita dei nemici. Utilizzando gli operatori matematici è possibile fare tutto questo. Di seguito il programma d'esempio viene modificato:

#include <iostream>
using namespace std;
int iPunteggio = 0, iVite =3;
float fDistanza = 13.2;
bool bScudi_attivi = true;

void stampa();

void stampa(){
//visualizzazione variabili
cout << "Vite:" << iVite << endl;
cout << "Punteggio:" << iPunteggio << endl;
cout << "Distanza:" << fDistanza << "Km" << endl;
cout << "Scudi attivi:"; if (bScudi_attivi == true) cout << "ON"; else cout << "OFF"; cout << endl;
}

int main(int argc, char *argv[])
{
stampa();
iPunteggio += 30;
fDistanza -= (8/2.2);
iVite++;
stampa();
system("PAUSE");
return EXIT_SUCCESS;
}

Il programma utilizza gli operatori matematici incremento e combinati per manipolare le variabili. La funzione stampa() viene richiamata due volte per visualizzare i dati.

domenica 9 settembre 2012

La Biblioteca di Babele

Questo semplice programma, stampa sullo schermo una pagina di un libro della famosa  "Biblioteca di Babele", come descritta dal racconto di Borges. Come si può notare nella generazione della pagina viene utilizzata la funzione pseudocasuale rand(). Il programma genera in pochi istanti una pagina tratta da un libro della biblioteca, con frasi di 40 caratteri, e 40 righe per pagina.

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
 char r, stringa[33] = "abcdefghijklmnopqrstuvwxyz.; !?.";
 srand(time(0)); // seme numero casuale
 cout << "PAGINA DELLA BIBLIOTECA DI BABELE\n";

for (int b=0; b < 40; b++){
    for (int a =0; a < 40; a++){      
        cout << stringa[rand()%33];
        } cout << endl;
    }
cin >> r;
return 0;
}

Dichiarare ed inizializzare Variabili

Una variabile rappresenta un particolare elemento di memoria del computer che è stato da te dedicato alla conservazione, recupero e manipolazione dei dati. Se si vuol tenere traccia del punteggio del giocatore, si può creare una variabile a tale scopo, in modo da poterlo mostrare alla bisogna. E' inoltre possibile tenere conto del numero dei colpi sparati a un nemico alieno colpito nel cielo. Un semplice programma che svolge questo mestiere è il seguente:
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
int iPunteggio = 0;
float fDistanza = 13.2;
bool bScudi_attivi = true;
cout << "Punteggio:" << iPunteggio << endl;
cout << "Distanza:" << fDistanza << "Km" << endl;
cout << "Scudi attivi:"; if (bScudi_attivi == true) cout << "ON"; else cout << "OFF";
cout << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
Le tre variabili sono inizializzate all'inizio del programma, dopodiché vengono visualizzate su schermo utilizzando la funzione cout vista in precedenza.

Comprendere le tipologie fondamentali

Ogni variabile che può essere creata deve appartenere ad un tipo il quale rappresenta la tipologia di informazione che può essere immagazzinata. Comunica al compilatore quanta memoria deve essere messa da parte per la variabile e definisce in modo legale cosa la variabile possa fare. Le tipologie fondamentali includono bool per valori di logica booleana che può essere (vero o falso), char per il singolo carattere, int per i valori interi, float per i valori a virgola mobile a precisione singola, double per valori a virgola mobile a doppia precisione.

Comprendere i modificatori di Tipo

E' possibile utilizzare un modificatore per alterare un tipo. short è un modificatore che può ridurre il valore che una variabile può trattenere in memoria. Long è un modificatore che aumenta la capacità della variabile. Entrambi possono modificare un valore intero. Mentre long può modificare anche il valore double.
Signed e unisgned sono modificatori che lavorano solo con gli interi. Indicano che la variabile deve avere solo valore positivo o anche negativo. Il modulo non viene alterato da questi modificatori, di norma le variabili interi sono con segno (signed).

Comprendere quale tipologia utilizzare

Solitamente vi sono parecchie scelte nelle tipologie fondamentali. Ma quale utilizzare? Bene, se si ha bisogno in un valore intero, è meglio utilizzare int. Tuttavia se il valore massimo della variabile supera i limiti e non si ha bisogno del segno, è meglio specificare unsigned int. I requisiti di memoria del programma possono non essere una preoccupazione su PC per programmi relativamente piccoli, ma possono creare un problema su sistemi console o portatili. Nel caso si abbia bisogno di un valore numerico a virgola mobile float rappresenta la scelta migliore.

sabato 8 settembre 2012

Programma Il gioco continua...

Nel seguente programma sono introdotti alcuni elementi che consentono una maggiore interattività rispetto al precedente. La funzione cin ci permette di inviare un input via tastiera che modifica il comportamento del programma. In questo caso il numero di volte che viene scritta sullo schermo la frase “Il gioco continua...”.



#include <cstdlib>
#include <iostream>


using std::cout;
using std::cin;
using std::endl;


int domanda();
int main(int argc, char *argv[])
{ cout << "Il gioco inizia." << endl;
do
{ cout << "Il gioco continua..." << endl;
} while (domanda() ==1);
cout << "Game over!" << endl;
system("PAUSE");
return EXIT_SUCCESS;
}


int domanda()
{
char risposta = 'y';
cout << "Vuoi continuare?(y/n)" << endl;
cin >> risposta;
if (risposta == 'y') return 1; else return 0;
}
Inoltre viene dichiarata una nuova funzione diversa da main(), chiamata domanda(), la quale richiede al giocatore di inserire un input tramite tastiera.

venerdì 7 settembre 2012

Utilizzare la Direttiva using

Il programma include la direttiva using per accedere agli elementi del namespace std.
using namespace std;
Il namespace come detto prima rappresenta un'area di codice, quindi la linea indica l'accesso diretto agli elementi di std deve essere modificata come un numero di telefono locale. Questo permette di utilizzare cout e endl privi di qualsiasi prefisso. Può non rivelarsi un grande vantaggio a prima vista, ma quando in un programma vi sono centinaia di riferimenti a questi oggetti, vi risparmia una grande fatica.

Introdurre modifiche al programma Inizia il gioco

E' possibile ottenere gli stessi risultati modificando il programma in questo modo:
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char *argv[])
{
cout << "Inizia il gioco" << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
Questo tipo di dichiarazione consente di localizzare le funzioni che saranno utilizzate nel programma, appartenenti al namespace std. Lasciando da parte molta roba che non abbiamo intenzione di utilizzare.

Comprendere quale utilizzare

Esistono due modi per localizzare gli elementi del namespace nel tuo programma. Quale tecnica utilizzare?
Un purista del linguaggio direbbe di evitare l'impiego della direttiva using nei programmi ed inserire sempre il prefisso della funzione di ogni elemento. La mia opinione è che si tratta di una operazione ridondante, come chiamare un amico usando sempre il nome, cognome ed indirizzo. Si tratta di una formalità eccessiva.

giovedì 6 settembre 2012

Mostrare del testo come Output Standard

La prima linea del corpo della funzione main() mostra Inizia il gioco, seguito da un a capo, nella finestra di console.
cout << "Inizia il gioco" << endl;
“Inizia il gioco” è una stringa, una serie di caratteri stampabili.
Cout è un oggetto, definito dile file iostream, il quale viene usato per inviare dati al flusso di output standard. Nella maggior parte dei programmi (incluso questo), l'output standard è solitamente una finestra di console sullo schermo del computer.
Viene usato l'operatore output (<<) per inviare la stringa a cout. Si può pensare a questo operatore come un imbuto che trasferisce qualsiasi cosa sia scritta sul lato aperto verso il lato appuntito, così la stringa viene spinta sullo schermo.
Viene utilizzato il prefisso std per dire al compilatore che cout fa parte della libreria standard, il quale viene dichiarato come namespace. Il namespace è un'are di codice che identifica un gruppo di appartenenza della funzione. Il prefisso del namespace (::) è l'operatore di risoluzione.
Infine viene inviato allo standard output la funzione endl. Anche questa definita da iostream è un oggetto del namespace std. Utilizzare questa funzione è come se qualcuno premesse il tasto di ritorno a capo sullo schermo. Se vi fosse scritta un'altra stringa verrebbe scritta sotto la precedente.

Terminatore di istruzione

Come si può notare, la prima linea della funzione termina con un punto e virgola (;). Questa linea è una istruzione, il componente di base che controlla il flusso eseguito. Tutte le istruzioni devono terminare con un punto e virgola, altrimenti il compilatore segnalerà un errore del programma senza compilarlo.

Funzione di sistema

Nella riga successiva viene richiamata una funzione di sistema la quale provvede a congelare la finestra di console sino a quando non viene premuto un tasto da parte dell'operatore. Altrimenti la finestra di console si sarebbe richiusa non appena il programma fosse stato eseguito.

Restituire un valore da main()

Nell'ultima istruzione della funzione, vine restituito il valore Exit_Success al sistema operativo.
Una possibile alternativa è :
return 0;
Restituire questo valore da main() è un modo per indicare che il programma si è concluso senza problemi. Il sistema operativo non deve fare nulla con il valore restituito semplicemente perché il requisito standard di C++, è la restituzione di un valore intero da main(). In generale si opta per la restituzione del valore 0.

mercoledì 5 settembre 2012

La funzione main()

Includere altri file

La linea successiva del programma è la direttiva del pro-processore. Le quali iniziano con il carattere #.
#include<iostream>
Il pre-processore viene eseguito prima che il compilatore faccia il suo lavoro, e sostituisce il testo con varie direttive. In questo caso la linea coinvolge la direttiva #include, la quale comunica al pre-processore di ricercare un altro file.
Il file incluso iostream, è parte della libreria standard, il quale contiene tutto il codice per mostrare output nello schermo. I due caratteri minore di (<) e maggiore di (>) comunicano al compliatore di effettuare la ricerca nella directory dove sono contenute le sue librerie. Un file incluso in questo modo viene chiamato file intestazione.

Definire la Funzione main()

Nelle righe successive del programma viene scritta l'intestazione della funzione chiamata main().
int main(int argc, char *argv[])
Una funzione è un gruppo di codice del programma che può fare un lavoro e restituire un valore. In questo caso si tratta di un intero segnalato dalla scritta int. Tutte le funzioni hanno un paio di parentesi nel loro nome.
Tutti i programmi scritti in C++ devono avere una funzione chiamata main(), la quale è il punto d'inizio del programma. L'azione comincia da qui.
Le linee seguenti segnano l'inizio della funzione.
{
e l'ultima riga segna la fine della funzione.
}
Tutte le funzioni devono essere delimitate dalle parentesi graffe, e qualsiasi cosa sia scritta tra loro è parte della funzione. Il codice tra due parentesi graffe viene chiamato blocco e solitamente mostra una unità di codice. Il blocco che rappresenta l'intera funzione viene chiamato corpo della funzione.

martedì 4 settembre 2012

Primi passi nel C++

Gestire gli errori

Quando ho descritto il processo per la creazione di un file eseguibile dal codice sorgente, ho tralasciato di menzionare gli errori. Errare è umano e i programmatori sono tra essi. Anche il miglior programmatore scrive codice che genera errori la prima (o sesta) volta. I programma tori devono correggere errori sin dall'inizio. Qui vi è una breve lista di errori di base nel quale incapperete mentre programmate in C++:
  • Errori di Compilazione. Questi avvengono durante la compilazione del codice. Come risultato un file oggetto non viene prodotto. Spesso si tratta di errori di Sintassi. Significa che il compilatore non capisce qualcosa, magari è dovuto ad un solo carattere errato. Il compilatore può dare anche degli avvertimenti. Ma solitamente questi vanno trattati come se fossero degli errori, ripararli e ricompilare.
  • Errori di Collegamento. Avvengono durante il processo di collegamento e può segnalare che un riferimento del programma non viene trovato. Questi errori sono risolti correggendo il collegamento alla risorsa e ricompilando il programma.
  • Errori di Esecuzione. Avvengono durante l'esecuzione del programma, se esso compie un'azione illegale, può interrompersi istantaneamente. E' una forma di errore più subdola è l'errore di Logica, il quale fa comportare il programma in modo non previsto. Se avete mai giocato a qualcosa nel quale il personaggio cammina per aria (se non può farlo), questo è un errore logico in azione.

Comprendere lo standard ISO

Lo standard ISO per il C++ è una definizione che descrive esattamente come lavora il linguaggio. Definisce un gruppo di file chiamato, libreria standard, che contiene i blocchi di costruzione per le funzioni comuni nella programmazione, come I/O, dare Input, ottenere Output. Le librerie standard rendono la vita facile per i programmatori e forniscono il codice fondamentale per salvarli dal dover reinventare la ruota. IN questo libro saranno usate le librerie standard.
Gli esempi di questo libro sono stati scritti utilizzando Dev C++. Questo compilatore è molto fedele allo standard ISO, così dovete essere abili nel compilare, collegare, ed eseguire i programmi utilizzando altri compilatori moderni per Windows o qualsiasi altro sistema operativo che rispetti lo standard ISO dei compilatori.


Indizio


Lo standard ISO è spesso chiamato anche standard ANSI o ANSI/ISO. Questi nomi diversi sono dovuti agli acronimi delle organizzazioni che hanno rivisto e stabilito gli standard. Il modo più comune per riferirsi a codice C++ conforme allo standard ISO è Standard C++.

Scrivere il primo programma in C++

Bene, basta teoria. E' tempo di applicarsi e scrivere il primo programma in C++. Piuttosto semplice, basta seguire l'anatomia di base del programma. Dimostra anche come visualizzare del testo nella console video.

Presentare il programma Inizia il gioco

Il primo compito classico del programmatore alle prese con un nuovo linguaggio, è Hello World, il quale mostra la scritta Hello World sullo schermo. Il programma Inizia il gioco ne è solo una versione modificata e mostra la scritta Inizia il gioco sullo schermo.
Di seguito viene mostrato il codice del programma.
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << "Inizia il gioco" << endl;
system("PAUSE");
return EXIT_SUCCESS;
}


Per commentare il codice

Potete inserire due righe di commento all'inizio del programma.
// Inizia il gioco
// Primo programma in C++
Le righe di commento sono ignorate dal compilatore, in quanto riservate agli esseri umani. Possono aiutare altri programmatori a comprendere le vostre azioni, ma possono aiutare anche voi. Sono un promemoria per quello che si è fatto se ciò non è chiaro alla prima occhiata. I caratteri (//) sono riservati a caratteri successivi nella riga di testo, pertanto è possibile scrivere del codice C++ prima di essi.

Uso degli spazi bianchi

La linea successiva del programma è una linea vuota. Il compilatore ignora gli spazi vuoti, le tabulazioni, e gli a capo. Come i commenti, anche gli spazi servono solo agli umani. Un uso corretto delle spaziature rende il codice comprensibile. E' possibile utilizzare gli spazi per separare delle sezioni di codice appartenenti ad un unico gruppo.

Creare un file eseguibile

Il file che tu esegui per lanciare un programma, che si tratti di un gioco o di altra applicazione, è un file eseguibile. Esistono alcuni passi da seguire per la creazione di un file eseguibile dal codice sorgente C++ (un insieme di istruzioni in C++).
Il processo è il seguente:
  1. Il programmatore usa un editore per scrivere il codice sorgente C++, questo file ha solitamente una estensione .cpp. L'editore è come un programma di scrittura, permette ai programmatori di creare, modificare e salvare il codice sorgente.
  2. Dopo che il programmatore ha salvato il codice sorgente, invoca il compilatore C++, una applicazione che legge il codice sorgente e lo traduce in file oggetto. I file oggetto hanno solitamente estensione .obj.
  3. Successivamente un linker collega il file oggetto alle necessarie risorse esterne, e quindi crea un file eseguibile, il quale ha solitamente estensione .exe. A questo punto l'utente o il giocatore può eseguire il programma lanciando l'eseguibile.
Per aiutare il programmatore in questo processo, solitamente viene utilizzato un unico programma di sviluppo chiamato IDE (Integrated Development Environment- Ambiente di Sviluppo Integrato). Il quale IDE combina editore, compilatore e linker, insieme ad altre funzioni. IDE commerciali più popolari sono per Windows, il Visual Studio .NET o C++ Builder Studio. Dev C++ è uno strumento IDE eccellente e gratuito, open source.