PDA

View Full Version : [scacchiera] problema di logica


-Ivan-
20-02-2005, 20:22
Secondo voi c'è qualche errore nel seguente ragionamento?

Immaginatevi di avere una scacchiera 10*10, con le caselle numerate da 1 a 100, dove 1 è la prima in alto a sinistra e la 10 l'ultima in alto a destra.
C'è un damino per esempio alla casella 91, deve arrivare alla posizione 24.
Il numero di caselle di cui si deve muovere il damino per arrivare dalla 91 alla 24 lo calcolo sottraendo le decine alle decine e le unità alle unità della cella da raggiungere e da quella di posizione iniziale.
Sottraggo ovviamente il valore più grande al più piccolo.
In questo caso: (9-2)+(4-1)=10, ci sono quindi 10 movimenti da fare tra la 91 e la 24.

Ora , supponendo di avere più di una casella da raggiungere contenute in un vettore, il damino per muoversi in maniera intelligente dovrà tentare di raggiungere prima la più vicina, poi la seconda più vicina e così via.
Quindi io mi creo un nuovo vettore che chiamo distanza e ci metto i calcoli come sopra per avere il numero di mosse da fare per conquistare ogni casella.
Tutti i vettori sono di uguale lunghezza, cioè 10.

Io ora ho questi vettori non necessariamente ordinati:

caselle da conquistare (12, 14, 25, 32, 92, 93, 95, 4, 1, 13)
distanza (9 , 11, 11, 7 , 1 , 2 , 4 , 12, 9, 10)

(ho fatto i calcoli un po' in fretta spero siano giusti)

Faccio un ciclo sul vettore distanza cercando il minimo numero contenuto.
Una cosa del genere:


min=distanza[1];
for(i=1;i<=10;i++)
{
if(distanza[i]<min)
{
min=distanza[i];
obiettivo=i;
}
}


Ora obiettivo mi indica le celle su cui devo al momento lavorare.

Per spostare il damino faccio un ragionamento del tipo:
se le decinde della casella da conquistare sono minori delle decine della casella di posizione allora lo spostamento sarà verso l'alto.
Se le decine sono maggiori lo spostamento è verso il basso.
Se le unità sono minori è verso sinistra.
Se le unità sono maggiori è verso destra.
(ci sono delle eccezioni per i numeri a unità pari a 0 ma per quelli ho delle condizioni a parte, per ora mi interessa che funzioni questo).
Ogni volta che faccio uno spostamento aggiorno la variabile posizione così la volta seguente che viene chiamata la funzione tutti i calcoli sono fatti di nuovo e tutto viene aggiornato.
Ovviamente quando una casella viene conquistata imposto i vettori in modo che non vengano considerate le celle che si riferivano a quella casella.

Vedete degli errori in questa logica?
Perchè implementando il tutto, il pc già alla prima mossa mi si muove male.

Ragazzo del '99
20-02-2005, 21:15
ah... il classico problema del commesso viaggiatore :O

comunque se vuoi usare la tua strategia dovresti aggiornare il tutto quando arrivi all'obbiettivo, non prima, tanto non serve anzi probabilmente ti introduce dei casini.

-Ivan-
20-02-2005, 21:33
Qual è il problema del commesso viaggiatore?

L'obiettivo lo modifico una volta effettuato lo spostamento di casella.

tglman
20-02-2005, 22:01
Scusa la logica mi sembra giusta se puoi mi fai vedere il codice di questa parte forse riesco a capire meglio

Ciao !!

-Ivan-
21-02-2005, 16:15
Ecco qua il codice.
Questa è una funzione, le variabili non vengono usate in nessuna altra parte.



void IA()
{
int k=0;
int minimo=0;
int obiettivo=0;
int temp=0;
//decine e unità della casella da conquistare
int dc[10]={0,0,0,0,0,0,0,0,0,0};
int uc[10]={0,0,0,0,0,0,0,0,0,0};

//decine e unità della casella di posizione
int dp=0;
int up=0;

//Calcolo qual'è la casella più vicina da conquistare per il pc
for(k=1;k<=10;k++)
{
dc[k]=caselle_da_conquistare[k]/10;
uc[k]=caselle_da_conquistare[k]-(dc[k]*10);
}
dp=pos/10;
up=pos-(dp*10);

//ciclo per il riempimento del vettore distanza
for(k=1;k<=10;k++)
{
if(dc[k]>=dp)
{
temp=dc[k]-dp;
}
if(dc[k]<dp)
{
temp=dp-dc[k];
}
if(uc[k]>=up)
{
temp=temp+(uc[k]-up);
}
if(uc[k]<up)
{
temp=temp+(up-uc[k]);
}
distanza[k]=temp;
}
//Ora ho 2 vettori di uguale dimensione, uno con tutte le caselle da conquistare
//ed uno con le distanze dalla posizione attuale

minimo=distanza[1];
obiettivo=1;
for(k=1;k<=10;k++)
{
if(distanza[k]<minimo){obiettivo=k;minimo=distanza[k];}
}
//Obiettivo adesso contiene l'indice della casella che il pc
//deve tentare di conquistare al momento



//coord_xp ed yp sono le coordinate a cui viene disegnato il pedino
//del pc e 60 è la lunghezza di una casella, quindi il codice seguente
//non fa altro che spostare il pedino di una casella in una direzione


if(dc[obiettivo]<dp)
{
coord_yp=coord_yp-60;
}
if(dc[obiettivo]>dp)
{
coord_yp=coord_yp+60;
}
if(uc[obiettivo]<up)
{
coord_xp=coord_xp-60;
}
if(uc[obiettivo]>up)
{
coord_xp=coord_xp+60;
}
Sleep(150);
disegna(pc, coord_xp, coord_yp, 40, 40, 0, 0);


}


Per ora non aggiorno la posizione perchè vorrei che prima facesse bene la prima mossa.
La posizione iniziale è la casella 91.
Non ci sono nemmeno i controlli per l'ultima colonna a destra, ovvero quella della casella 10,20,30...

tglman
21-02-2005, 16:51
non ho avuto molto tempo per controllare tutto il codice ma le prime cose che mi sono balzate agli occhi sono gli indici dei cicli che iniziano da uno, facendo iniziare l'indice da uno di perdi il primo elemento del vettore (un vettore dichiarato int vett[10] a gli indici da 0 a 9 i cicli fatti da te vanno da 1 a 9).

Poi aggiusta il codice, esempio
if (a>=b)....
if(a<b)...
si puo scrivere anche
if(a>=b).....
else .....

forse questa scrittura e meno conprensibile da chi legge il codice ma è certamente più performante

-Ivan-
21-02-2005, 17:04
Originariamente inviato da tglman
non ho avuto molto tempo per controllare tutto il codice ma le prime cose che mi sono balzate agli occhi sono gli indici dei cicli che iniziano da uno, facendo iniziare l'indice da uno di perdi il primo elemento del vettore (un vettore dichiarato int vett[10] a gli indici da 0 a 9 i cicli fatti da te vanno da 1 a 9).

Poi aggiusta il codice, esempio
if (a>=b)....
if(a<b)...
si puo scrivere anche
if(a>=b).....
else .....

forse questa scrittura e meno conprensibile da chi legge il codice ma è certamente più performante

La seconda parte del codice l'ho riscritta così per vedere se erano gli else che davano errore ma purtroppo non ho risolto niente, ora la ririscrivo con gli else.
Ho paura che ci sia un errore molto camuffato da qualche parte perchè non funziona proprio, neanche se metto gli indici da 0 a 9.

tglman
21-02-2005, 19:38
Penso che questo l'hai capito:
il for lo devi scrivere cosi:

for(k=0;k<=9;k++)

Tranne la parte dove cerchi la distanza minore che va andrebbe scritta cosi:

for(k=1;k<=9;k++)

perche il primo elemento lo hai gia preso nell'inizializzazione.

non mi sembra che ci siano errori l'unica cosa che mi può destare sospetto può essere solo l'eliminazione delle distanze zero che potrebbero impedire la mossa ma nient'altro

attento comunque con l'uso dell'altro vettore, quello che usi per inizializzare il tutto...
Ciao !!!
(Bello pero il nome della funzione)

tglman
21-02-2005, 19:43
Se continua a non funzionarti fatti un log dove scrivere tutti i risultati dei calcoli che ai fatto..

Ariciao !!!

Ragazzo del '99
21-02-2005, 21:07
Ma caselle_da_conquistare è inizializzato correttamente ??

Poi ricordati che devi usare gli indici da 0 a 9 anche qui:

minimo=distanza[1];
obiettivo=1;

-Ivan-
22-02-2005, 15:30
Originariamente inviato da Ragazzo del '99
Ma caselle_da_conquistare è inizializzato correttamente ??

Poi ricordati che devi usare gli indici da 0 a 9 anche qui:

minimo=distanza[1];
obiettivo=1;


Non ci posso credere, sto sbattendo la testa da un quarto d'ora contro lo spigolo della porta.
caselle_da_conquistare era inizializzato in una funzione che mi sono dimenticao di chiamare.
Adesso funziona, è l'errore più stupido che abbia mai fatto.
Grazie a tutti adesso il pc muove correttamente..

tglman
22-02-2005, 20:33
Non ti preoccupare questi problemi li anno anche gli esperti programmatori

tglman
22-02-2005, 20:36
Lo sai che il calcolo della distanza lo potevi scrivere anche in una sola riga ...

Provaci poi ti do la soluzione .....

Inoltre altre cose possono essere ristrette come codice, il che non vuol dire che siao più veloci o performanti da eseguire ma che solo occupano meno spazio nel file sorgente (cioè non ciè non cambia niente)