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;
}
Sito: 7ecnologie
Sezione: 08. C language
Capitolo: 98. Esercizi
Paragrafo: 12. Progettazione guidata
Approfondimento: 02. Strike and balls
Indice dei capitoli: 00. Risorse - 01 Ambiente di sviluppo - 02. Introduzione al C - 03. Le librerie - 04. Tutorial - 05. Esercizi svolti - 98. Esercizi
Indice dei paragrafi: 01. Introduttivi - 02. Quesiti strutturati - 03. Interpretazione del codice - 04. Diagrammi di flusso - 05. Array - 06. Tipi numerici - 07. Programmazione strutturata - 08. Caratteri e stringhe - 09. File - 10. Numeri casuali - 11. Riepilogativi - 12. Progettazione guidata
Indice degli approfondimenti: 01. Corsa con i numeri - 02. Strike and balls - 03. Raggi cosmici