Like it?
Sviluppare Snake in C
Scritto da carloVentrella  in  Programmazione >>  C  il 2012-06-10

Vediamo come realizzare il celebre gioco di snake in C: è un algoritmo non particolarmente complesso e, se compreso bene, molto semplice da realizzare.

Snake

Prima di visualizzare il codice vi spiego il lato teorico del codice analizzando le varie sezioni in cui è suddiviso:

  • OrganizzaHeader: funzione che scrive il titolo del gioco, il punteggio e il timer di partenza;
  • disegnaQuadro: disegna il quadro di gioco;
  • disegnaSnake: disegna il serpente di lunghezza quattro al centro del quadro di gioco;
  • aggiornaPunteggio: aggiorna il punteggio di gioco ogni qualvolta il serpente mangia del cibo
  • generaCibo: funzione che inserisce  il cibo sulla base della funzione random() che genera numeri casuali;
  • start: è la funzione che gestisce un timer di 3 secondi, alla scadenza di questi viene richiamata la funzione muovi();
  • muovi: è la porzione di codice principale che gestisce il movimento del serpente, e quindi controlla se mangia del cibo o se mangia la sua stessa coda, o supera il limite del quadro di gioco.

A questo punto non ci rimane che spiegare come ho gestito il serpente e, quindi, il suo movimento: ho utilizzato due array che contengono le coordinate x ed y delle singole parti del serpente a partire da snake_row[0] e snake_cols[0] che corrispondono alla testa.

Il serpente è disegnato attraverso un ciclo (disegnaSnake()) che inserisce un' asterisco nelle posizioni contenute nei due array. Il movimento avviene quindi cancellando l'asterisco 'coda' ,aggiungendo l'asterisco 'testa'  e facendo slittare il contenuto dei due array in modo tale che ogni parte del serpente assuma le coordinate della parte precedente. L'unica parte che non 'slitta' in questo modo è la testa che assumere i valori in base al tasto precedentemente premuto.

Movimento Snake

Vediamo ora il codice:

 
#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();
 
// 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;
 
main()
{
 
    organizzaHeader();
    disegnaQuadro();
 
    disegnaSnake();
 
    generaCibo();
    int tasto = getch();
    if (tasto == 13) // ha premuto invio
    {
       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");
                return 0;
            }
        }
 
 
        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");
            return 0;
        }
 
        // 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");
    }
}
void generaCibo(void)
{
    cibo_cols = random(11,68);
    cibo_row = random(6,23);
 
    GotoXY(cibo_cols,cibo_row);
    SetColor(4);
    printf("o");
 
}
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;
}
void aggiorna_punteggio(int score) // da controllare
{
    // 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("*");
    }
}
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("@");
    }
}
 
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);
}
void  GotoXY(int x, int  y) {
COORD CursorPos = {x, y};
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hConsole, CursorPos);
}
void SetColor(short Color)
{
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); // oppure system("COLOR E9");
SetConsoleTextAttribute(hCon,Color);
}
 


Tags:   C   algoritmo   snake   movimento   setColor    GotoXY   gioco
Commenti(0)

    Non ci sono commenti.

Sono Carlo Ventrella, studente e appassionato di programmazione, particolarmente interessato allo sviluppo di applicazioni e script per il web. Linguaggi attualmente conosciuti: C,Java, Javascript, css, css3, php e html5.

Carlo Ventrella
Sito realizzato da Carlo Ventrella | Feb 2012

Feedback

La tua opinione è indispensabile per migliorare il sito!

Critica Consiglio


CAPTCHA Image

Collabora

Ciao! Come sicuramente avrai notato il sito è ancora 'spoglio' e lo si deve al fatto che è nato da poco e la manodopera diciamo che...scarseggia! Il sito al momeno è gestito da una sola persona ed è per questo motivo che nuovi collaboratori sarebbero ben accetti! La collaborazione parte dalla gestione di una o più categorie fino all'inserimento di un semplice articolo che secondo voi potrebbe suscitare particolare interesse. Se volete aiutarmi potete anche solo mandarmi un feedback nel quale mi dite cosa vi piace o cosa pensate che debba essere migliorato. Ve ne sarei molto grato!
Grazie.

Feedback

Cosa ne pensi di questo articolo?