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.