02. Strike and balls

Consegna

Implementare un programma che gioca a strike and balls.

Il programma deve indovinare il numero di quattro cifre che noi abbiamo scelto. Il numero può iniziare per zero e tutte le cifre devono essere diverse tra loro.

Ad ogni mano il programma effettua un lancio al quale bisogna rispondere indicando quanti strike e quanti balls ha realizzato.

Strike: cifra giusta al posto giusto

Balls: cifra giusta al posto sbagliato

Esempio di esecuzione

Il programma quando è avviato mostra i seguenti messaggi:


Annotare su un foglio un numero di 4 cifre tutte diverse tra loro 

(il numero puo' iniziare con 0).

Confrontarlo con il numero visualizzato dal programma e indicare gli Strike e i Balls totalizzati.

Strike: cifra giusta al posto giusto 

Balls: cifra giusta al posto sbagliato 

Lancio 1: 0123

Quanti Strike? 1

Quanti Balls? 0 

Lancio 2: 0456

...

Strategia

Con quattro cifre, banalmente, si possono realizzare 10000 numeri differenti (da 0 a 9999).

Di questi non possono essere considerati validi i numeri con più cifre uguali.

Nel caso un numero abbia meno di 4 cifre (ad esempio 27) deve essere normalizzato a 4 cifre anteponendo degli zero (nell'esempio 0027).

Allochiamo l'array

    int SpazioCampionario[10000];

Nella posizione i dell'array carichiamo il valore VALIDO se il numero i è compatibile con il gioco (cifre tutte differenti) mentre carichiamo il valore INVALIDO se il numero i ha più cifre uguali.

Ogni volta che effettuiamo un lancio memorizziamo il risultato nell'array Lanci. Eseguiamo quindi le seguenti operazioni:


Lanci[NLanci][0]=<Numero estratto>;

Lanci[NLanci][1]=<Numero di Strike>;

Lanci[NLanci][2]=<Numero di Balls>;

Nlanci++;

Riduciamo lo SpazioCampionario impostando ad INVALIDO gli elementi il cui indice corrisponde ad un numero incompatibile con il nuovo lancio effettuato.

Supponiamo, ad esempio, che il lancio x=1234 abbia dato come esito 2 Strike e 1 Balls.

Il numero i=4567 è compatibile con x se e solo se dal confronto di x e i risultano esattamente 2 Strike e 1 Balls: in questo esempio risultano 0 Strike e 1 Balls da cui discende che i è incompatibile, dovrà perciò essere impostato SpazioCampionario[4567]=INVALIDO.

Progettazione


#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#define VALIDO 1

#define INVALIDO 0

int SpazioCampionario[10000];

int Lanci[100][3];

int NLanci;

// Riceve in input due numeri interi positivi; li confronta cifra 

// a cifra e restituisce il numero di cifre uguali nella stessa

// posizione (Strike)

// Es. 341 e 271 hanno in comune le cifre 0 e 1 (2 Strike)

int Strike(int x, int y)

{

    int s;

    return s;

}

// Riceve in input due numeri interi positivi; li confronta cifra 

// a cifra  e restituisce il numero di cifre uguali ma in diversa

// posizione (Balls)

// Es. 341 e 1270 hanno in comune le cifre 0 e 1 in posizioni

// diverse (2 Balls) 

int Balls(int x, int y)

{

    int b;

    return b;

}

// Inizializza l'array SpazioCampionario. Imposta a VALIDO le celle

// corrispondenti ad un indice composto da 4 cifre differenti e ad

// INVALIDO le altre celle.

// N.B. 123 è normalizzato a 0123 e quindi si considera composto

// da 4 cifre differenti.

void Inizializza()

{

    

    return;

}

// Per ciascun elemento SpazioCampionario[i]==VALIDO verifica

// se l'indice i è compatibile con tutti i lanci effettuati.

// Se ad esempio in corrispondenza del lancio x si sono avuti

// 2 Strike e 1 Balls, allora i è compatibile se risulta

// Strike(i, x)==2 e Balls(i, x)==1.

// Se un indice i non è compatibile, allora è posto 

// SpazioCampionario[i]=INVALIDO

void Riduci()

{

    

    return;

}

// Seleziona in modo casuale un indice i dello SpazioCampionario

// tale che SpazioCampionario[i]==VALIDO

// Se un tale indice non esiste restituisce -1

int Lancio()

{

    int x;

    

    return x;

}

int main()

{

    int x, s, b;

    int n;

    printf("Annotare su un foglio un numero di 4 cifre tutte diverse tra loro \n(il numero puo' iniziare con 0).\n");

    printf("Confrontarlo con il numero visualizzato dal programma e indicare \ngli Strike e i Balls totalizzati.\n");

    printf("Strike: cifra giusta al posto giusto\n");

    printf("Balls: cifra giusta al posto sbagliato\n\n");

    Inizializza();

    do {

        Riduci();

        x = Lancio();

        if (x == -1){

            printf("Nessuna soluzione possibile\n");

            return -1;

        }

        printf("\nLancio N. %d: %.4d\n", NLanci+1, x);

        printf("Quanti Strike? "); scanf("%d", &s);

        printf("Quanti Balls? "); scanf("%d", &b);

        Lanci[NLanci][0]=x;

        Lanci[NLanci][1] = s;

        Lanci[NLanci][2] = b;

        NLanci++;

    } while (s!=4);

    printf("\nGioco risolto in %d lanci\n", NLanci);

    return 0;

}


Test

Deve essere effettuato il test di ciascuna funzione separatamente, utilizzando il modulo relativo già predisposto (ovviamente dopo aver implementato la funzione stessa).


Modulo Strike


#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#define VALIDO 1

#define INVALIDO 0

int SpazioCampionario[10000];

int Lanci[100][3];

int NLanci;

// Riceve in input due numeri interi positivi; li confronta cifra 

// a cifra e restituisce il numero di cifre uguali nella stessa

// posizione (Strike)

// Es. 341 e 271 hanno in comune le cifre 0 e 1 (2 Strike)

int Strike(int x, int y)

{

    int s;

    return s;

}

int main()

{

    int x;

    x = Strike(341, 271);

    printf("0341 <> 0271 attesi 2 Strike - esito %x\n", x); 

    x = Strike(1341, 241);

    printf("1341 <> 0241 attesi 2 Strike - esito %x\n", x); 

    x = Strike(7890, 8741);

    printf("7890 <> 8741 attesi 0 Strike - esito %x\n", x); 

    return 0;

}

Modulo Balls


#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#define VALIDO 1

#define INVALIDO 0

int SpazioCampionario[10000];

int Lanci[100][3];

int NLanci;

// Riceve in input due numeri interi positivi; li confronta cifra 

// a cifra  e restituisce il numero di cifre uguali ma in diversa

// posizione (Balls)

// Es. 341 e 1270 hanno in comune le cifre 0 e 1 in posizioni

// diverse (2 Balls) 

int Balls(int x, int y){

    int b;

    return b;

}

int main()

{

    int x;

    x = Balls(341, 271);

    printf("0341 <> 0271 attesi 0 Balls - esito %x\n", x); 

    x = Balls(9341, 241);

    printf("9341 <> 0241 attesi 0 Balls - esito %x\n", x); 

    x = Balls(7890, 8741);

    printf("7890 <> 8741 attesi 2 Balls - esito %x\n", x); 

    x = Balls(895, 8740);

    printf("0895 <> 8740 attesi 2 Balls - esito %x\n", x); 

    return 0;

}

Modulo Inizializza


#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#define VALIDO 1

#define INVALIDO 0

int SpazioCampionario[10000];

int Lanci[100][3];

int NLanci;

// Inizializza l'array SpazioCampionario. Imposta a VALIDO le celle

// corrispondenti ad un indice composto da 4 cifre differenti e ad

// INVALIDO le altre celle.

// N.B. 123 è normalizzato a 0123 e quindi si considera composto

// da 4 cifre differenti.

void Inizializza()

{

    return;

}

int main()

{

    int i;

    Inizializza();

    printf("Tutti i numeri visualizzati devono avere almeno 3 cifre.\n");

    printf("Tutte le cifre di uno stesso numero devono essere differenti tra loro.\n\n");

    for (i=0; i<10000; i++)

         if (SpazioCampionario[i]==VALIDO)

             printf("%d ", i);

    printf("\n\nTutti i numeri visualizzati devono rispettare almeno uno delle seguenti proprieta':\n");

    printf("   Devono essere composti da meno di 3 cifre\n");

    printf("   Devono avere almeno 2 cifre uguali (N.B. xyz<=>0xyz)\n\n");

    for (i=0; i<10000; i++)

         if (SpazioCampionario[i]==INVALIDO)

             printf("%d ", i);

    return 0;

}

Modulo Lancio


#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#define VALIDO 1

#define INVALIDO 0

int SpazioCampionario[10000];

int Lanci[100][3];

int NLanci;

// Seleziona in modo casuale un indice i dello SpazioCampionario

// tale che SpazioCampionario[i]==VALIDO

// Se un tale indice non esiste restituisce -1

int Lancio()

{

    int x;

    

    return x;

}

int main()

{

    int i, x;

    for (i=0; i<8000; i++) {

         SpazioCampionario[i]=INVALIDO;

    }

    for (i=8000; i<10000; i++) {

         SpazioCampionario[i]=VALIDO;  

    }

    x=Lancio();

    printf("Il valore visualizzato deve essere compreso tra 8000 e 9999: %d\n", x);

    for (i=0; i<100; i++) {

         SpazioCampionario[i]=VALIDO;

    }

    for (i=100; i<10000; i++) {

         SpazioCampionario[i]=INVALIDO;  

    }

    x=Lancio();

    printf("Il valore visualizzato deve essere compreso tra 0 e 99: %d\n", x);

    for (i=0; i<10; i++) {

         SpazioCampionario[i]=VALIDO;

    }

    for (i=10; i<1000; i++) {

         SpazioCampionario[i]=INVALIDO;  

    }

    for (i=1000; i<1010; i++) {

         SpazioCampionario[i]=VALIDO;

    }

    for (i=1010; i<10000; i++) {

         SpazioCampionario[i]=INVALIDO;  

    }

    x=Lancio();

    printf("Il valore visualizzato deve essere compreso tra 0 e 9 oppure tra 1000 e 1010: %d\n", x);

    return 0;

}

Modulo Integrazione


Implementare la funzione Riduci() avvalendosi delle funzioni Strike() e Balls().

Inserire nel modulo di integrazione anche le funzioni Inizializza().

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#define VALIDO 1

#define INVALIDO 0

int SpazioCampionario[10000];

int Lanci[100][3];

int NLanci;

// Riceve in input due numeri interi positivi; li confronta cifra 

// a cifra e restituisce il numero di cifre uguali nella stessa

// posizione (Strike)

// Es. 341 e 271 hanno in comune le cifre 0 e 1 (2 Strike)

int Strike(int x, int y)

{

    int s;

    return s;

}

// Riceve in input due numeri interi positivi; li confronta cifra 

// a cifra  e restituisce il numero di cifre uguali ma in diversa

// posizione (Balls)

// Es. 341 e 1270 hanno in comune le cifre 0 e 1 in posizioni

// diverse (2 Balls) 

int Balls(int x, int y)

{

    int b;

    return b;

}

// Inizializza l'array SpazioCampionario. Imposta a VALIDO le celle

// corrispondenti ad un indice composto da 4 cifre differenti e ad

// INVALIDO le altre celle.

// N.B. 123 è normalizzato a 0123 e quindi si considera composto

// da 4 cifre differenti.

void Inizializza()

{

    

    return;

}

// Per ciascun elemento SpazioCampionario[i]==VALIDO verifica

// se l'indice i è compatibile con tutti i lanci effettuati

// memorizzati nell'array Lanci (il numero di lanci è 

// memorizzato nella variabile NLanci).

// Se ad esempio in corrispondenza del lancio x si sono avuti

// 2 Strike e 1 Balls, allora i è compatibile se risulta

// Strike(i, x)==2 e Balls(i, x)==1.

// Se un indice i non è compatibile, allora è posto 

// SpazioCampionario[i]=INVALIDO

void Riduci()

{

    

    return;

}

int main()

{

    int n, i;

    NLanci=0;

    Inizializza();

    Lanci[NLanci][0]=1234;

    Lanci[NLanci][1] = 0;

    Lanci[NLanci][2] = 0;

    NLanci++;

    Riduci();

    n=0;

    for(i=0; i<10000; i++)

         if (SpazioCampionario[i]==VALIDO)

              n++;

    printf("Numero atteso D(6,4)=6!/2!=360 - esito: %d\n", n);

    Lanci[NLanci][0]=1256;

    Lanci[NLanci][1] = 0;

    Lanci[NLanci][2] = 0;

    NLanci++;

    Riduci();

    n=0;

    for(i=0; i<10000; i++)

         if (SpazioCampionario[i]==VALIDO)

              n++;

    printf("Numero atteso 4!=24 - esito: %d\n", n);

    return 0;

}