Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Attento: nel main, usi x1, y1, x2 e y2 come indici senza averli inizializzati (perchè l'inizializzazione l'hai messa nella funzione cammino)!
Inoltre, nella funzione passo_casuale, effettui tutti gli incrementi senza premettere l'opportuno operatore: tu scrivi y1++, ma avendo passato il parametro by reference dovresti scrivere (*y1)++
Detto questo, è normale che ti escano passi uguali, visto che il tuo programma viene eseguito dal calcolatore in pochissimo tempo e dunque ad ogni ripetizione passa ad srand() un valore di tempo sostanzialmente uguale a quello passatogli prima.
Una semplice soluzione a scopo didattico sarebbe quella di passare alla funzione cammino anche l'indice del for, e ri-scrivere la riga 59 così:
Codice sorgente - presumibilmente Plain Text
srand((((int)time(NULL)) / 314) + i * 27183);
(Notare che i due numeri che ho scelto sono assolutamente arbitrari: io ho preso multipli di pi-greco e del valore di Nepero, ma tu puoi usare quelli che vuoi )
E inoltre potresti riscrivere le due righe 71-72 così:
Codice sorgente - presumibilmente Plain Text
pass1 = (rand() + *x1) % 4;
pass2 = (rand() + 314 * (*x2)) % 4;
Non è una soluzione perfetta (avrai ancora delle ripetizioni, ineluttabilmente), ma almeno ti garantirà dei risultati un po' più interessanti
Detto questo, per la gestione grafica della scacchiera ti basta, in sede di determinazione del prossimo passo, nell'ordine:
- Svuotare la casella dove prima si trovava la pedina
- Determinare la sua nuova posizione
- Inserire il suo segnaposto (un trattino, se ben ricordo) nella nuova posizione
Non è difficile: sono tre-quattro righe di codice implementabili nella funzione passo_casuale
Ho seguito i tuoi suggerimenti sulla sistemazione delle srand(), e effettivamente qualcosa è cambiato ma rimane sempre strano: ora le 10 esecuzioni restituiscono diversi numeri totali di passi eseguiti, ma quando eseguo nuovamente l'intero algoritmo i risultati sono identici a prima (praticamente le 10 esecuzioni restituiscono sempre gli stessi numeri di passi totali, sempre nello stesso ordine); poi, il numero di passi totali prima che le due pedine si incontrino è sempre un numero basso, tra l'1 e il 10, anche questo mi pare un po' improbabile dato che le due pedina si muovono su una scacchiera di 30 caselle x 30, tecnicamente ce ne vorrebbero di passi prima di farle incontrare.. Infine scusami se posso sembrare un po' tardo, ma questo "aggiornamento" delle posizioni delle pedine non riesco proprio a implementarlo
Purtroppo, dei risultati veramente casuali non li avrai mai (almeno, non ponendo come seme della randomizzazione qualcosa di legato all'orario)... per quanto riguarda il numero di passi, il problema principale è un errore nel tuo codice che non avevo visto prima (*), ma considera che molto dipende anche da dove hai posto le due pedine: le hai infatti sistemate in due caselle che sfruttando il comportamento del tuo programma rispetto ai movimenti "oltre i bordi" sono reciprocamente facili da raggiungere, quindi è molto probabile che qualche ripetizione riporti un numero di passi molto basso.
(*) Il while nella funzione cammino ha una condizione che non va bene: ponendo (x1 != x2 && y1 != y2) sostanzialmente il ciclo si ferma non appena le due pedine sono sulla stessa riga o sulla stessa colonna, anche se magari su due caselle diverse. La condizione che serve a te è, a parole, "finchè non è vero contemporaneamente che x1 = x2 e y1 = y2", la quale in codice C si traduce in
Codice sorgente - presumibilmente Plain Text
while(!(x1 == x2 && y1 == y2))
O, applicando il teorema di De Morgan:
Codice sorgente - presumibilmente Plain Text
while(x1 != x2 || y1 != y2)
Andiamo ora all'aggiornamento della posizione delle pedine: onestamente, che tu non riesca ad implementarlo non ci credo, perchè è veramente semplice... più probabile piuttosto che tu non abbia capito la mia proposta (che ho in effetti esposto un po' maccheronicamente)
Quello che ti proponevo io è di sostituire alle righe
Codice sorgente - presumibilmente Plain Text
(*y1) = 0;
p1 = scacchiera[*x1][*y1];
Ed affini, le righe:
Codice sorgente - presumibilmente Plain Text
scacchiera[*x1][*y1] = ' ';
(*y1) = 0;
scacchiera[*x1][*y1] = '_';
p1 = scacchiera[*x1][*y1];
Così da spostare opportunamente il "segnaposto"
Nel tuo programma non è essenziale, perchè di fatto tu quella matrice non la stampi mai... ma, nel caso ti venisse voglia di stamparla, questo sarebbe un metodo semplice per aggiornarla
Ultima modifica effettuata da Template il 19/02/2016 alle 13:47
Purtroppo, dei risultati veramente casuali non li avrai mai (almeno, non ponendo come seme della randomizzazione qualcosa di legato all'orario)... per quanto riguarda il numero di passi, il problema principale è un errore nel tuo codice che non avevo visto prima (*), ma considera che molto dipende anche da dove hai posto le due pedine: le hai infatti sistemate in due caselle che sfruttando il comportamento del tuo programma rispetto ai movimenti "oltre i bordi" sono reciprocamente facili da raggiungere, quindi è molto probabile che qualche ripetizione riporti un numero di passi molto basso.
(*) Il while nella funzione cammino ha una condizione che non va bene: ponendo (x1 != x2 && y1 != y2) sostanzialmente il ciclo si ferma non appena le due pedine sono sulla stessa riga o sulla stessa colonna, anche se magari su due caselle diverse. La condizione che serve a te è, a parole, "finchè non è vero contemporaneamente che x1 = x2 e y1 = y2", la quale in codice C si traduce in
Codice sorgente - presumibilmente Plain Text
while(!(x1 == x2 && y1 == y2))
O, applicando il teorema di De Morgan:
Codice sorgente - presumibilmente Plain Text
while(x1 != x2 || y1 != y2)
Andiamo ora all'aggiornamento della posizione delle pedine: onestamente, che tu non riesca ad implementarlo non ci credo, perchè è veramente semplice... più probabile piuttosto che tu non abbia capito la mia proposta (che ho in effetti esposto un po' maccheronicamente)
Quello che ti proponevo io è di sostituire alle righe
Codice sorgente - presumibilmente Plain Text
(*y1) = 0;
p1 = scacchiera[*x1][*y1];
Ed affini, le righe:
Codice sorgente - presumibilmente Plain Text
scacchiera[*x1][*y1] = ' ';
(*y1) = 0;
scacchiera[*x1][*y1] = '_';
p1 = scacchiera[*x1][*y1];
Così da spostare opportunamente il "segnaposto"
Nel tuo programma non è essenziale, perchè di fatto tu quella matrice non la stampi mai... ma, nel caso ti venisse voglia di stamparla, questo sarebbe un metodo semplice per aggiornarla
Non so come ho fatto a non rendermi conto dell'errore del while.. sono pessimo! Non giudicarmi per questo
Dopo averlo corretto i risultati sono decisamente più adeguati allo scopo dell'algoritmo, ora non mi resta che rendere più efficienti le funzioni di randomizzazione (perché come hai detto tu se il seed è in base all'orario per ottenere risultati diversi devo eseguire il programma ogni tot minuti) e magari ottimizzare un po', alleggerendo un po' il codice. Riguardo l'aggiornamento delle posizioni, effettivamente non avevo capito molto bene.. mea culpa! Dopo il tuo ultimo post ho afferrato il concetto per bene. Detto questo, ti ringrazio tanto perché mi hai dato un enorme aiuto e te ne sono infinitamente grato!
Se per caso avessi qualche altro suggerimento per ottimizzare, sarò felice di ascoltarti (tranquillo non ti sto chiedendo nient altro, hai già fatto tanto )
Vorrei postare la mia versione dell'esercizio, non so se sia etico, possa sembrare scortese, o addirittura è fuori dal regolamento del forum, solo stamani, leggendo il problema alle sette del mattino, ho pasticciato col codice per vedere il problema e capire come funzionasse, quindi mi dispiace che si stato tempo perso.
Se la cosa sembra scortese, basta accennarlo e provvederò a eliminare il codice da questo messaggio.
Come ho interpretato io le richieste della traccia, mi soffermo sul punto TENTARE di eseguire una mossa, perché lo preso come essenziale.
Codice sorgente - presumibilmente C++
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
/* Per visuallizzare la scacchiera impostare le dimensione della finestra
del prompt a 200 x 200 e massimizzatela */
int passo_casuale(char[][30],int*,int*,int*,int*);
Mi fa piacere che tu non intenda fermarti solo perchè "il programma fa il suo lavoro": è un atteggiamento che, secondo me, nel tempo può portare a capire veramente come si programma bene
Detto questo, per prima cosa - visto che lo chiedi - fossi in te toglierei quell'orribile definizione della matrice, sostituendola con la molto più ordinata versione:
Codice sorgente - presumibilmente C/C++
char scacchiera[30][30];
for (i = 0; i < 30; i++)
for (j = 0; j < 30; j++)
scacchiera[i][j] = ' ';
scacchiera[0][0] = '_';
scacchiera[29][29] = '-';
Inoltre, se proprio vuoi continuare a utilizzare il tempo del sistema come seme per srand(), ne effettuerei un casting esplicito al tipo int, che per correttezza ci starebbe proprio (e che, se ci fai caso, silenziosamente ti ho già "proposto" nel codice di un post precedente)
Per il resto, non è che ci sia molto da dire: in termini di correttezza, il codice va bene, e di fatto il suo lavoro lo fa in maniera abbastanza pulita... per curiosità, sei autodidatta?
Chiedo perchè l'attenzione alla leggibilità del codice ed una sua scrittura in generale così pulita (se eccettuiamo i pochi errori che ti ho segnalato - che in generale possono capitare - il codice in sè era già buono in partenza) sono caratteri che quasi mai ho ritrovato negli autodidatti
Per il resto, non è che ci sia molto da dire: in termini di correttezza, il codice va bene, e di fatto il suo lavoro lo fa in maniera abbastanza pulita... per curiosità, sei autodidatta?
Chiedo perchè l'attenzione alla leggibilità del codice ed una sua scrittura in generale così pulita (se eccettuiamo i pochi errori che ti ho segnalato - che in generale possono capitare - il codice in sè era già buono in partenza) sono caratteri che quasi mai ho ritrovato negli autodidatti
Ti ringrazio, ricevere belle parole da un esperto fa sempre piacere
Comunque no, non sono autodidatta, sto seguendo un corso universitario di scienze informatiche, sono al primo anno e per ora sono solo un modesto aspirante programmatore
"Esperto", suvvia... diciamo più che altro un "cugino un po' più grande": sono al secondo anno di ingegneria informatica (anche se in effetti quando sono entrato all'università programmavo già da 5-6 anni ).
Comunque, complimenti anche al tuo professore: non tutti si premurano di insegnare all'allievo l'importanza di un codice pulito ed efficace
Ultima modifica effettuata da Template il 19/02/2016 alle 15:09
Vorrei postare la mia versione dell'esercizio, non so se sia etico, possa sembrare scortese, o addirittura è fuori dal regolamento del forum, solo stamani, leggendo il problema alle sette del mattino, ho pasticciato col codice per vedere il problema e capire come funzionasse, quindi mi dispiace che si stato tempo perso.
Se la cosa sembra scortese, basta accennarlo e provvederò a eliminare il codice da questo messaggio.
Come ho interpretato io le richieste della traccia, mi soffermo sul punto TENTARE di eseguire una mossa, perché lo preso come essenziale.
Grazie per aver postato anche la tua versione, alla fine ho ovviato diversamente ma un confronto fa sempre bene. Comunque a occhio la tua function passo_casuale non fa un lavoro poi così diverso dalla mia, solo che tu usi uno switch che magari esteticamente rende anche meglio e io invece utilizzo solo degli if annidati, ma fondamentalmente è quello.. se mi sto sbagliando probabilmente dipende anche da interpretazioni leggermente diverse che abbiamo dato alla traccia