Scambio valori array. errore nel codice
ciao. Sto facendo un programma che permette di giocare al gioco del 15 in c.
Ci sono 4 mosse a disposizione: sopra (fai scendere la casella sopra quella vuota), sotto, destra e sinistra.
Questo è il codice (è corto, se si esclude la parte di "scrittura a schermo"):
Il problema è che fa la prima mossa giusta: sembra che scambi correttamente il contenuto delle due caselle... ma in realtà non riesce a capire quale cella diventa vuota dopo la mossa. E le mosse successive sono un disastro. (provate ad eseguire, io faccio la prima mossa un 'w').
Grazie mille.
Ci sono 4 mosse a disposizione: sopra (fai scendere la casella sopra quella vuota), sotto, destra e sinistra.
Questo è il codice (è corto, se si esclude la parte di "scrittura a schermo"):
int i,a[16],v;
char go;
//funzione scambio
int s (int n, int m)
{
int box;
box=a[n];
a[n]=a[m];
a[m]=box;
return (a[n]);
}
main()
{
for (i=1;i<16;i++)
{
a[i]=i;
}
a[16]=0;
//inizio gioco
do
{
clrscr();
//cerca casella vuota
for (i=1;i<17;i++)
{
if(a[i]==0)
{v=i;}
else {v=v;}
}
//regolamento
gotoxy (1,6);
printf ("Comandi:\nw: sopra\na: sinistra\ns: sotto\nd: destra\nee: uscire");
//tabella
gotoxy (1,1);
for (i=1;i<5;i++)
{
if (a[i]<10)
{printf ("%d",a[i]);}
else if (a[i]==10)
{printf ("A");}
else if (a[i]==11)
{printf ("B");}
else if (a[i]==12)
{printf ("C");}
else if (a[i]==13)
{printf ("D");}
else if (a[i]==14)
{printf ("E");}
else if (a[i]==15)
{printf ("F");}
else if (a[i]==0)
{printf (" ");}
}
printf ("\n");
for (i=5;i<9;i++)
{
if ((a[i]<10)&&(a[i]!=0))
{printf ("%d",a[i]);}
else if (a[i]==10)
{printf ("A");}
else if (a[i]==11)
{printf ("B");}
else if (a[i]==12)
{printf ("C");}
else if (a[i]==13)
{printf ("D");}
else if (a[i]==14)
{printf ("E");}
else if (a[i]==15)
{printf ("F");}
else if (a[i]==0)
{printf (" ");}
}
printf ("\n");
for (i=9;i<13;i++)
{
if ((a[i]<10)&&(a[i]!=0))
{printf ("%d",a[i]);}
else if (a[i]==10)
{printf ("A");}
else if (a[i]==11)
{printf ("B");}
else if (a[i]==12)
{printf ("C");}
else if (a[i]==13)
{printf ("D");}
else if (a[i]==14)
{printf ("E");}
else if (a[i]==15)
{printf ("F");}
else if (a[i]==0)
{printf (" ");}
}
printf ("\n");
for (i=13;i<17;i++)
{
if ((a[i]<10)&&(a[i]!=0))
{printf ("%d",a[i]);}
else if (a[i]==10)
{printf ("A");}
else if (a[i]==11)
{printf ("B");}
else if (a[i]==12)
{printf ("C");}
else if (a[i]==13)
{printf ("D");}
else if (a[i]==14)
{printf ("E");}
else if (a[i]==15)
{printf ("F");}
else if (a[i]==0)
{printf (" ");}
}
gotoxy (1,13);
printf ("\n\nvuota: %d",v);
go=getche();
//sopra
if (go=='w')
{
if ((v!=1)&&(v!=2)&&(v!=3)&&(v!=4))
{s(v,(v-4));}
}
//sotto
else if (go=='s')
{
if ((v!=13)&&(v!=14)&&(v!=15)&&(v!=16))
{s(v,(v+4));}
}
//destra
else if (go=='d')
{
if ((v!=4)&&(v!=8)&&(v!=12)&&(v!=16))
{s(v,(v+1));}
}
//sinistra
else if (go=='a')
{
if ((v!=1)&&(v!=5)&&(v!=9)&&(v!=13))
{s(v,(v-1));}
}
//prova 7-8
else if (go=='p')
{
if ((v!=1)&&(v!=5)&&(v!=9)&&(v!=16))
{s(7,8);}
}
//prova 1-2
else if (go=='o')
{
if ((v!=1)&&(v!=5)&&(v!=9)&&(v!=13))
{s(1,v);}
}
}while (go!='e');
getch();
}Il problema è che fa la prima mossa giusta: sembra che scambi correttamente il contenuto delle due caselle... ma in realtà non riesce a capire quale cella diventa vuota dopo la mossa. E le mosse successive sono un disastro. (provate ad eseguire, io faccio la prima mossa un 'w').
Grazie mille.
Risposte
NdM: Usa il tag code al posto del tag spoiler per inserire del codice..
L'errore principale del tuo codice è che gli indici in C partono da zero, mentre nel tuo codice parti sempre da uno. In particolare a[16] è oltre i limiti del tuo array. Con ogni probabilità stai scrivendo su di un'altra variabile.. ma potrebbe anche crashare. Mancano inoltre gli #include s all'inizio del codice e ti consiglierei di usare variabili locali al posto di quelle globali. Soprattutto per quanto riguarda i, v e go.
ok. credo di aver capito. grazie mille.
Peró potresti gentilmente spiegarmi perchè mi conviene dichiarare le variabili dentro, e non fuori, dal main? (se ho capito giusto).
ps: gli include li ho scritti nel codice, ho solo evitato di riportarli qua nel topic.
Peró potresti gentilmente spiegarmi perchè mi conviene dichiarare le variabili dentro, e non fuori, dal main? (se ho capito giusto).
ps: gli include li ho scritti nel codice, ho solo evitato di riportarli qua nel topic.
La principale ragione per preferire l'uso di variabili locali al posto di quelle globali è per rendere il codice di più facile comprensione ed evitare alcuni errori.
Il tuo programma è ancora molto piccolo ma considera il seguente caso. Supponi di avere, come nel tuo codice, un contatore di cicli globali e di avere quindi una funzione che ne fa uso:
Ad un certo punto supponi di dover fare l'operazione di f più volte in un qualche ciclo. Senza guardare il codice di f uno potrebbe essere tentato di scrivere qualcosa come:
e chiedersi perché il codice funziona in modo così strano. Questo caso è forse ancora semplice, ma prova ad immaginare cosa succede se si aumentano il numero di variabili usate come contatori e il numero di funzioni. Ogni volta che cerchi di di inserire una funzione in un'altra diventa di colpo necessario doversi guardare tutto il codice della funziona che si vuole includere e di tutte quelle da essa richiamate. Diventa insomma presto un incubo. Se invece si usano principalmente variabili locali e ogni funzione accede principalmente alle variabili che le vengono passate come argomento, tutto diventa più semplice. È infatti sufficiente sapere cosa fa una funzione per usarla.
Il tuo programma è ancora molto piccolo ma considera il seguente caso. Supponi di avere, come nel tuo codice, un contatore di cicli globali e di avere quindi una funzione che ne fa uso:
void f()
{
for (i = 0; i < N; ++i) { /* ... */ }
}
Ad un certo punto supponi di dover fare l'operazione di f più volte in un qualche ciclo. Senza guardare il codice di f uno potrebbe essere tentato di scrivere qualcosa come:
for (i = 0; i < M; ++i) { f(); }
e chiedersi perché il codice funziona in modo così strano. Questo caso è forse ancora semplice, ma prova ad immaginare cosa succede se si aumentano il numero di variabili usate come contatori e il numero di funzioni. Ogni volta che cerchi di di inserire una funzione in un'altra diventa di colpo necessario doversi guardare tutto il codice della funziona che si vuole includere e di tutte quelle da essa richiamate. Diventa insomma presto un incubo. Se invece si usano principalmente variabili locali e ogni funzione accede principalmente alle variabili che le vengono passate come argomento, tutto diventa più semplice. È infatti sufficiente sapere cosa fa una funzione per usarla.