Il prossimo esercizio in laboratorio che faremo sarà snake. Uno dei modi per realizzarlo è fare tutto da soli... un altro è quello di vedere cosa hanno fatto gli altri. Su internet si trovano tantissimi esempi di snake!

Il vostro compito è quello di:

  • Analizzare il codice e comprenderne il funzionamento
  • Fare il tracing dell'applicazione
  • Descrivere in italiano il funzionamento dell'applicazione
  • Evidenziare le parti difficili e poco comprensibili

Il codice è preso da: http://www.ketek.it/programmare-snake-in-c/

Scarica il sorgente

	  
#include <stdio.h>
#include <windows.h>
#include <windows.h>
#include <TIME.H>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include <unistd.h>
 
// dimensioni quadro di gioco
#define MAX_WIDTH 60
#define MAX_HEIGHT 20
// limiti: 10 - 69, 5 - 24
 
// tasti di movimento(ascii)
#define UP 119
#define DW 115
#define LF 97
#define RH 100
 
// prototipi di funzioni
void organizzaHeader(void);
void disegnaQuadro(void);
void disegnaSnake(void);
void aggiorna_punteggio(int);
void generaCibo(void);
int random(int,int);
void start(void);
void game_started(int);
void muovi();

// questa funzione mi permette di spostarmi alle coordinate x,y
void  GotoXY(int x, int  y) {
    COORD CursorPos = {x, y};
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hConsole, CursorPos);
}
// questa funzione mi permette di usare i colori
void SetColor(short Color)
{
    HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); // oppure system("COLOR E9");
    SetConsoleTextAttribute(hCon,Color);
}
 
// variabili globali del serpente
int snake_cols[100] = {MAX_WIDTH/2 +3, MAX_WIDTH/2 +2,MAX_WIDTH/2 +1,MAX_WIDTH/2};
int snake_row[100] = {MAX_HEIGHT/2 + 5,MAX_HEIGHT/2 + 5,MAX_HEIGHT/2 + 5,MAX_HEIGHT/2 + 5};
int snake_lenght = 4;
 
// coordinate del cibo
int cibo_cols = 0;
int cibo_row = 0;
 
// punteggio
int score = 0;
 
int main() {
    // preparo il gioco
    organizzaHeader();
    disegnaQuadro();
    disegnaSnake();
    generaCibo();
    int tasto = getch();
 
    // se si preme invio...inizia il gioco
    if (tasto == 13) {
        start();
    }
 
    // evito messaggi sul quadro di gioco
    SetColor(15);
    GotoXY(0,27);
}

void start(void) {
    int x;
    for (x = 3; x>=0; x--) {
        SetColor(12);
        GotoXY(20,2);
        printf("%d",x);
        Sleep(1000);
    }
    muovi();
}

void muovi() {
    int cibo = 1; // c'è cibo nel quadro
    int i;
    int dr = 0, dc = +1;
    int tasto=0;
    do {
        SetColor(2);
        // genero cibo se non ce n'è
        if (cibo == 0) {
            generaCibo();
            cibo = 1;
        }
        // controllo se la testa si è mangiata il corpo
        for (i=snake_lenght-1; i>0; i--) {
            if (snake_row[0] == snake_row[i] && snake_cols[0] == snake_cols[i]) {
                SetColor(12);
                GotoXY(0,27);
                printf("GAME OVER");                
            }
        }
        if (kbhit()) {
            tasto=getch();
            if (tasto == UP){ dr = -1; dc = 0; }
            if (tasto == DW){ dr = +1; dc = 0; }
            if (tasto == LF){ dr = 0; dc = -1; }
            if (tasto == RH){ dr = 0; dc = +1; }
        }
        // movimento
        // cancello coda
        GotoXY(snake_cols[snake_lenght-1],snake_row[snake_lenght-1]);
        printf(" ");
        // aggiungo testa
        GotoXY(snake_cols[0]+dc,snake_row[0]+dr);
        SetColor(2);
        printf("*");
        // slitto array
        for(i=snake_lenght-1; i>0; i--) {
            snake_row[i] = snake_row[i-1];
            snake_cols[i] = snake_cols[i-1];
        }
        snake_row[0]  += dr;
        snake_cols[0] += dc;
        //controllo dei limiti del quadro
        if (snake_cols[0] == 69 || snake_cols[0] == 10 || snake_row[0] == 24 || snake_row[0] == 5) {
            GotoXY(snake_cols[0],snake_row[0]);
            SetColor(12);
            printf("*");
            GotoXY(MAX_WIDTH/2+5,MAX_HEIGHT+6);
            printf("GAME OVER");            
        }
        
        // controllo se il serpente si mangia il cibo
        if (snake_cols[0] == cibo_cols && snake_row[0] == cibo_row) {
            // aggiungo coda al serpente
            snake_lenght++;
            snake_cols[snake_lenght-1] = snake_cols[snake_lenght-2];
            snake_row[snake_lenght-1] = snake_row[snake_lenght-2];
            // score +1
            GotoXY(MAX_WIDTH/2 + 34, 2);
            score += 10;
            SetColor(14);
            printf("%d", score);
            cibo = 0;
        }
        Sleep(70);
    }
    while(tasto != 27);
    if (tasto == 27) {
        SetColor(14);
        printf("STOP");
    }
}

// genero il cibo
void generaCibo(void)
{
    cibo_cols = random(11,68);
    cibo_row = random(6,23);
    GotoXY(cibo_cols,cibo_row);
    SetColor(4);
    printf("o");
}

// genero numeri casuali per il cibo
int random(int min, int max) {
    int random, diff = max - min;
    srand(time(NULL)); //inizializza il generatore
    random = rand() % diff; //genera un numero casuale fra 0 e 5
    random+= min; //otteniamo un valore fra 1 e 6
    return random;
}

// man mano che lo snake mangia il cibo bisogna incrementare il punteggio
void aggiorna_punteggio(int score) {
    // punteggio
    GotoXY(MAX_WIDTH/2 + 20, 2);
    SetColor(15);
    printf("Score: %d", score);
}

void disegnaSnake(void) {
    int x;
    SetColor(2);
    for (x = snake_lenght-1; x>=0; x--) {
        GotoXY(snake_cols[x],snake_row[x]);
        printf("*");
    }
}

// disegno il piano di gioco
void disegnaQuadro(void) {
    GotoXY(0,5);
    SetColor(6);
    int x = 0, y = 0;
    for (x=0; x<MAX_HEIGHT; x++) {
        printf("          @");
        for(y = 1; y < MAX_WIDTH -1; y++) {
            if (x == 0 || x == MAX_HEIGHT-1) {
                printf("@");
            }
            else {
                printf(" ");
            }
        }
        printf("@\n");
    }
}

// con questa funzione organizzo l'header
void organizzaHeader(void) {
    // start
    GotoXY(10+3,2);
    printf("Start: ");
    SetColor(12);
    printf("0");
    SetColor(15);
    // titolo
    GotoXY(MAX_WIDTH/2+6, 2);
    SetColor(10);
    printf("SNAKE");
    // punteggio
    GotoXY(MAX_WIDTH/2 + 27, 2);
    SetColor(15);
    printf("Score: ");
    SetColor(12);
    printf("0");
    SetColor(15);
}