Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Cammino casuale di una pedina su scacchiera
Forum - C/C++ - Cammino casuale di una pedina su scacchiera

Pagine: [ 1 2 3 ] Precedente | Prossimo
Avatar
eclix (Normal User)
Newbie


Messaggi: 13
Iscritto: 20/05/2012

Segnala al moderatore
Postato alle 15:42
Domenica, 20/05/2012
Salve a tutti. Sto incontrando alcune difficoltà nell'implementazione di un algoritmo. Come da titolo, l'esercizio è riferito al cammino casuale di due pedine su una scacchiera (la traccia dell'esercizio è nel codice). Quello che non riesco a fare è tenere traccia del cammino della pedina, ed inoltre mi capita che a volte il cammino termina quando le due pedine si incontrano, mentre altre volte no. Qualcuno riesce a farmi capire qual è l'errore che faccio?? 8-|

Codice sorgente - presumibilmente Python

  1. /**Si vuole sviluppare un algoritmo del cammino casuale di una pedina. Un cammino si svolge su una scacchiera in cui ogni casella
  2. rappresenta una possibile posizione del cammino della pedina. Stando in una casella, una pedina può muoversi solo nella casella
  3. a destra, nella casella a sinistra, nella casella sopra o nella casella sotto. La scelta di una tra queste quattro caselle deve
  4. essere fatta a caso (generando per esempio un numero intero in {0,1,2,3}).
  5. Ogni movimento da una casella all’altra è detto passo del cammino. L’algoritmo usa un array 2D nxn, con n=30, per simulare la scacchiera.
  6. Ci sono due pedine sulla scacchiera, e all’inizio una si trova nella casella in alto a sinistra e l’altra nella casella in basso a destra.
  7. A ogni movimento di una pedina, segue il movimento dell’altra pedina. Fare attenzione al movimento di una pedina quando si trova sul bordo
  8. della scacchiera. L’algoritmo procede finché accade che le due pedine tentano di muoversi sulla stessa casella della scacchiera; in tal caso
  9. l’algoritmo termina (cammino terminato), restituendo il numero di passi effettuati. Organizzare l’algoritmo come una function che restituisce
  10. il numero di passi (lunghezza) del cammino. Scrivere un main che per 100 volte chiama la function e visualizza la lunghezza di ogni cammino
  11. effettuati.**/


Ultima modifica effettuata da eclix il 11/06/2012 alle 19:43
PM Quote
Avatar
subazu (Normal User)
Rookie


Messaggi: 35
Iscritto: 06/08/2011

Segnala al moderatore
Postato alle 15:58
Lunedì, 21/05/2012
23: Perché passi singolarmente tutti quei valori quando puoi passare direttamente le 2 struct "ped_1" e "ped_2"? con una semplice modifica puoi inserire anche il carattere che rappresenta la pedina nella struttura

Come mai disegni il movimento delle pedine a video se non è richiesto nella consegna?


Ultima modifica effettuata da subazu il 21/05/2012 alle 16:40


PM Quote
Avatar
eclix (Normal User)
Newbie


Messaggi: 13
Iscritto: 20/05/2012

Segnala al moderatore
Postato alle 9:59
Martedì, 22/05/2012
Cioè cosa dovrei fare esattamente? È da poco che ho cominciato a programmare in C, non sono una cima :D.

Scusa come faccio a stabilire se il cammino termina una volta che le due pedine si incontrano senza vederlo prima?

PM Quote
Avatar
subazu (Normal User)
Rookie


Messaggi: 35
Iscritto: 06/08/2011

Segnala al moderatore
Postato alle 17:59
Martedì, 22/05/2012
intanto puoi modificare il prototipo della funzione da così:
Codice sorgente - presumibilmente C++

  1. int function_mia (char [][N], int *, int *, char, int *, int *, char);


a così
Codice sorgente - presumibilmente C/C++

  1. int function_mia (struct pedina*, struct pedina*);


apportando però prima delle modifiche alla struttura
1 dargli un nome (struct pedina{....} al posto di struct {})
2 inserirci una variabile di tipo char nella struttura

in modo che poi all'interno della funzione tu possa usare le variabili utilizzando questa sintassi:
Codice sorgente - presumibilmente C/C++

  1. void funzioneProva(struct pedina *p){
  2.   *p.x = 10;
  3.   *p.y = 15;
  4.   *p.simbolo = 'x';
  5. }



PM Quote
Avatar
eclix (Normal User)
Newbie


Messaggi: 13
Iscritto: 20/05/2012

Segnala al moderatore
Postato alle 19:17
Venerdì, 25/05/2012
Ma funzioneProva sarebbe una nuova funzione per poter gestire ogni singola pedina?? Non riesco a capire! :-|

PM Quote
Avatar
subazu (Normal User)
Rookie


Messaggi: 35
Iscritto: 06/08/2011

Segnala al moderatore
Postato alle 21:16
Venerdì, 25/05/2012
Non mi sono spiegato bene, la funzione "function_mia" ha come prototipo:
Codice sorgente - presumibilmente C++

  1. int function_mia (char [][N], int *, int *, char, int *, int *, char);


Passare così tanti parametri alla funzione può essere solo che fonte di errore, no?
Non sarebbe più comodo passare le "pedine" alla funzione, invece che ogni loro capo?
così è come invochi tu la tua funzione:
Codice sorgente - presumibilmente Plain Text

  1. conta_passi=function_mia(walk, &ped_1.x, &ped_1.y, pawn1, &ped_2.x, &ped_2.y, pawn2);


così è come dovresti invocarla
Codice sorgente - presumibilmente Plain Text

  1. conta_passi=function_mia(walk, &ped_1, &ped_2);


Questo è solo un consiglio che è però necessario seguire per programmare correttamente, anche non seguendolo il programma funzionerà, ma la sua fluidità logica ne risente.

Per il tuo problema principale invece devi ripensare un attimo a cosa devi fare.
Intanto in informatica i concetti: "scrivere", "leggere" e sopratutto "vedere" sono sempre relativi.

Per vedere se due pedine sono nello stesso posto basta confrontarne le coordinate
Codice sorgente - presumibilmente C/C++

  1. if ((p1.x == p2.x) && (p1.y == p2.y)) {
  2.    //le pedine sono nello stesso posto
  3. }
  4. else{
  5.   //le pedine sono in posti diversi
  6. }


La parte logica del programma deve essere, indipendente da ciò che vedi a video.
Non so se è chiaro ma la parte video (i caratteri del terminale per intenderci) sono l'ultima cosa a cui devi pensare, prima devi pensare alle variabili, ai loro valori, e a come gestirle.

Il problema è chiaro, devi:
1posizionare** le pedine
2fino a che non si scontrano
   1muovi una delle pedine (prima una, il ciclo dopo l'altra)
3fine.

**anche posizionare in questo caso è relativo, infatti non devi posizionare proprio niente da nessuna parte, questo perché a te interessano solo le coordinate delle pedine (tralascia il comparto video per ora, lo risolviamo in seguito).


PM Quote
Avatar
eclix (Normal User)
Newbie


Messaggi: 13
Iscritto: 20/05/2012

Segnala al moderatore
Postato alle 1:48
Sabato, 26/05/2012
allora... ho aggiustato un pochino il codice apportando delle modifiche mie e dei vari suggerimenti che mi hai dato aggiungendo man mano anche dei commenti per ogni riga.
Ti posto ora l'intero codice in modo tale che tu abbia una panoramica più chiara di cosa abbia potuto combinare XD
Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #define N 30
  5. #define SU 0
  6. #define GIU 1
  7. #define DESTRA 2
  8. #define SINISTRA 3
  9. //struttura
  10. struct pedina {
  11.     int x;
  12.     int y;
  13.     char simb;
  14.     };
  15. // viene definito un nuovo tipo 'Pedina'
  16. typedef struct pedina Pedina;
  17. //prototipi delle function
  18. void build_chess(char [][N]);
  19. void show_chess(char v[][N]);
  20. void movimento_casuale(char [][30],Pedina*,int);
  21. int function_mia (char [][N], Pedina *, Pedina *);
  22.  
  23. void main ()
  24.  
  25. {
  26.  
  27.     Pedina p1={0,0,''}, p2={29,29,'y'}; /* le pedine p1 e p2 sono variabili di tipo struttura alle quali vengono assegnate,
  28.     per ciascuna pedina, le proprie coordinate (1° campo e 2° campo) e il corrispettivo simbolo (3° campo)*/
  29.     char walk[N][N]; //dichiarazione della matrice (scacchiera 30x30)
  30.     int conta_passi;// variabile utilizzata per chiamare la function che dovrebbe restituire il numero dei passi delle pedine
  31.     build_chess(walk); //chiamata alla void function che costruisce la scacchiera
  32.     walk[p1.x][p1.y]=p1.simb; //postazione iniziale della pedina1
  33.     walk[p2.x][p2.y]=p2.simb; //postazione iniziale della pedina2
  34.     printf("\n");
  35.     show_chess(walk); //chiamata alla procedura per la visualizzazione su schermo della scacchiera
  36.     system("pause");
  37.     system("cls"); //pulisce lo schermo
  38.     conta_passi=function_mia(walk, &p1, &p2);
  39.     printf("Cammino terminato!\nNumero di passi eseguiti: %d", conta_passi);
  40.  
  41. }
  42.  
  43.  
  44.  
  45. /*La void function seguente esegue lo spostamento della pedina in base alla direzione ottenuta attraverso la chiamata alla rand.
  46. Per ciascun caso (case) viene stabilito l'intervallo delle coordinate entro le quali la pedina può eseguire lo spostamento, evitando, in tal modo,
  47. che essa possa uscire fuori dai bordi della scacchiera*/
  48.  
  49. void movimento_casuale(char walk[][30], Pedina *pawn,int direz)
  50. {
  51.  
  52.     switch(direz)
  53.     {
  54.         case SU:            if((*pawn).x==0)
  55.                         {walk[(*pawn).x][(*pawn).y]='.'; walk[++(*pawn).x][(*pawn).y]=(*pawn).simb;}
  56.                         else
  57.                         {walk[(*pawn).x][(*pawn).y]='.'; walk[--(*pawn).x][(*pawn).y]=(*pawn).simb;}          break;//pedina verso nord
  58.  
  59.                 case GIU:       if((*pawn).x==N-1)
  60.                         {walk[(*pawn).x][(*pawn).y]='.'; walk[--(*pawn).x][(*pawn).y]=(*pawn).simb;}
  61.                                 else
  62.                                 {walk[(*pawn).x][(*pawn).y]='.'; walk[++(*pawn).x][(*pawn).y]=(*pawn).simb;}          break;//pedina verso sud
  63.  
  64.                 case SINISTRA:  if((*pawn).y==0)
  65.                         {walk[(*pawn).x][(*pawn).y]='.'; walk[(*pawn).x][++(*pawn).y]=(*pawn).simb;}
  66.                                 else
  67.                                 {walk[(*pawn).x][(*pawn).y]='.'; walk[(*pawn).x][--(*pawn).y]=(*pawn).simb;}          break;//pedina verso ovest
  68.  
  69.                 case DESTRA:    if((*pawn).y==N-1)
  70.                         {walk[(*pawn).x][(*pawn).y]='.'; walk[(*pawn).x][--(*pawn).y]=(*pawn).simb;}
  71.                         else
  72.                         {walk[(*pawn).x][(*pawn).y]='.'; walk[(*pawn).x][++(*pawn).y]=(*pawn).simb;}          break;//pedina verso est
  73.         }
  74.  
  75. }
  76. int function_mia (char walk[][N], Pedina *p1, Pedina *p2)
  77. {
  78.     int direz, passi=0;
  79.     //il ciclo while termina una volta che entrambe le pedine si trovano sulla stessa casella
  80.     while (walk[(*p1).x][(*p1).y]!=walk[(*p2).x][(*p2).y]){
  81.         srand((unsigned)time(0));
  82.  
  83.         direz=rand()%4;
  84.         movimento_casuale(walk, p1,direz); //chiamata alla function per effettuare il cammino della pedina 1
  85.         show_chess(walk); //stampa a video del movimento della pedina 1
  86.  
  87.         system("cls");
  88.         direz=rand()%4;
  89.         movimento_casuale(walk, p2,direz); //chiamata alla function per effettuare il cammino della pedina 2
  90.         show_chess(walk); //stampa a video del movimento della pedina 2
  91.  
  92.         system("cls");
  93.         passi++; //incremento della variabile 'passi' fintanto che non termina il ciclo while (pedine nella stessa casella)
  94.  
  95. }return passi;
  96. }



Situazione migliorata o peggiorata? XD
Ah... ti ringrazio per l'aiuto e l'impegno che mi stai prestando... :)

Ultima modifica effettuata da eclix il 14/06/2012 alle 19:32
PM Quote
Avatar
subazu (Normal User)
Rookie


Messaggi: 35
Iscritto: 06/08/2011

Segnala al moderatore
Postato alle 22:08
Domenica, 27/05/2012
Ecco, io direi molto bene, già solo con 2 modifiche alla struttura tutto il programma ne giova.
Un altro modo per passare i parametri alle funzioni è per reference, e si fa così
Codice sorgente - presumibilmente C/C++

  1. int function_mia (char [][N], Pedina &, Pedina &);


con questo tipo di parametri puoi accedere ai campi della struttura con una sintassi semplificata, da così
Codice sorgente - presumibilmente Plain Text

  1. (*pawn).x=0;


a così
Codice sorgente - presumibilmente Plain Text

  1. pawn.x=0;



Il prossimo passo è fare il restyling del main, anche se non è corretto che ti imposti io l'intero programma, in questo caso ti risparmio un sacco di teoria, ovvio che hai l'obbligo di mettere in discussione i miei metodi dove non ti garbano, e ricevere delle spiegazioni :k:

Prima di tutto io diminuirei al minimo le istruzioni base dal main, non so se hai mai sentito del principio "divide et impera", bene tienilo sempre a mente.
Atomizzare il codice, spezzettare e dividere in unità più piccole tutto ciò che si può porta ad un sacco di vantaggi
- leggibilità maggiore
- meno errori
- facilita la correzione e gli upgrade
- rende più facile scovare i bug
- ecc.
Per programmi così piccoli non dovrebbe essere necessario tutto questo rigore, ma prima si impara a programmare così, prima si è in grado di capire quando non è necessario farlo.
io ad esempio farei così;
Codice sorgente - presumibilmente C++

  1. void main (){
  2.     //variabili
  3.     Pedina p1, p2; //pedine
  4.     int conta_passi; //contatore
  5.     int nPed= TRUE ; //true se ped1, false se ped2
  6.     //inizializzazione
  7.     initialize(p1,p2); //imposta i valori iniziali alle pedine
  8.  
  9.     while (! ((p1.x == p2.x) && (p1.y == p2.y))){ //se due pedine non hanno coordinate uguali
  10.         system("cls"); //pulisce lo schermo
  11.         show_chess(p1,p2); //disegno le 2 pedine
  12.         //muovo a turno una delle pedine
  13.         if (nPed) {
  14.             //muovo la pedina 1
  15.             movimento_casuale(p1);
  16.             nPed = ! nPed; //cambio la pedina che verrà mossa il giro dopo
  17.         }
  18.         else{
  19.             //muovo la pedina 2
  20.             movimento_casuale(p2);
  21.             nPed = ! nPed;
  22.         }
  23.         conta_passi++; //incremento il numero di mosse
  24.         }
  25.     }
  26.     printf("Cammino terminato!\nNumero di passi eseguiti: %d", conta_passi);
  27. }


Se hai qualche dubbio chiedi, anche se leggendo solo i commenti il codice si spiega da solo.
Devi intanto capire come funziona, per le altre implementazioni ci penserai dopo, sono comunque tutte molto semplici (non ti spaventare se non vedi la matrice perché in realtà non ti serve)
Credo che questo sia una impostazione abbastanza carina, il codice non è testato e potrebbero esserci degli errori di SINTASSI.

Ultima modifica effettuata da subazu il 27/05/2012 alle 22:14


PM Quote
Avatar
eclix (Normal User)
Newbie


Messaggi: 13
Iscritto: 20/05/2012

Segnala al moderatore
Postato alle 22:35
Lunedì, 28/05/2012
allora... per quanto riguarda il primo punto, cioè il passaggio dei parametri alle funzioni, ho provato a farlo nel modo che mi hai suggerito, ma il compilatore continua a darmi un errore del tipo:
"expected ';', ',' or ')' before '&' token".
non credo di aver commesso errori di sintassi dato che non ho fatto altro che mettere & al posto di *.

Poi, per quanto riguarda il restyling del main, quel ciclo while dovrei inserirlo nella funzione "function_mia" visto che nella traccia è richiesto di organizzare l'algoritmo come una function che restituisce il numero dei passi effettuati?

Ma togliendo la scacchiera la funzione "show_chess" deve essere cambiata suppongo, giusto?

la spostamento che esegue la pedina con la chiamata alla rand perché non compare? Si trova all'interno della funzione movimento_casuale? :-?

Scusa se ti faccio troppe domande, ma te lo chiedo semplicemente per vedere se ho effettivamente capito i cambiamenti che hai apportato. :rofl:

PM Quote
Pagine: [ 1 2 3 ] Precedente | Prossimo