09/12/2023 - MattINfo ha scritto:
Ho letto il primo punto relativo all'utilizzo di un puntatore e sarei molto curioso di sapere la tua soluzione
Nel seguente caso
Gioco sposta(Gioco c, int n)
{
...
return c;
}
int main()
{
...
campo = sposta(campo, num);
...
}
quando viene richiamata la funzione sposta(), una copia di campo viene creata e passata come argomento alla funzione; quest'ultima modificherà la suddetta copia per poi ritornarla al main(), dove la variabile campo verrà aggiornata con un'assegnazione.
Con un'impostazione del genere invece
void sposta(Gioco *c, int n)
{
...
return;
}
int main()
{
...
sposta(&campo, num);
...
}
si risparmia la memoria per allocare la copia, e si evitano due copie della struct (quella per inizializzare la copia e quella per aggiornare l'oggetto campo). Ovviamente in casi del genere la differenza in termini di prestazioni è nulla, ma sono comunque questioni di cui bisogna tener conto.
09/12/2023 - MattINfo ha scritto:
Sarei anche interessato alle altre questioni di cui parlavi.
Alcune osservazioni:
- una struct deve indicare qualcosa di ben preciso e il suo utilizzo deve comportare una qualche utilità, come una semplificazione del codice o una sua maggiore chiarezza e leggibilità. E nel caso specifico io sinceramente non avrei utilizzato le struct;
- se rifletti sul significato canonico di x e y, dovresti scrivere
c.x = j;
c.y = i;
e non
c.x = i;
c.y = j;
- nella funzione vincente() ti dimentichi di incrementare la variabile tmp.
Poi la variabile check è inutile, in quanto se la condizione dell'if è rispettata la funzione può direttamente ritornare 0.
Apro una breve parentesi: in C gli array statici (multidimensionali e non) occupano uno spazio di memoria contiguo, il che significa che un array multidimensionale può essere tranquillamente trattato come un array monodimensionale.
Al netto di quanto appena detto per la funzione vincente() farei qualcosa del genere:
int vincente(int v[16])
{
for(unsigned int i = 0; i < 15; ++i)
{
if(v[i] != i + 1)
{
return 0;
}
}
return 1;
}
int main()
{
...
while(!vincente(*campo.campo))
{
...
}
- passiamo alla funzione controlla().
Nella condizione dell'if più interno rischi di andare a leggere zone di memoria che non competono alla matrice; per esempio se n si trova in posizione i=0 e j=2, il primo controllo
pc->campo[i - 1][j] == 0
si trasforma in
pc->campo[-1][2] == 0
così come se n si trova in posizione i=1 e j=3, il secondo controllo
pc->campo[i][j + 1] == 0
si trasforma in
pc->campo[1][4] == 0
Quindi prima di accedere a pc->campo[i-1][j] devi assicurarti che i sia diverso da 0, così come prima di accedere a pc->campo[i][j+1] devi assicurarti che j sia diverso da 3, e così via…
Anche in questo caso la variabile check è inutile, infatti se l'if più interno è rispettato la funzione può tornare direttamente 1.
E ancora, invece di ricercare n nella matrice, dal momento che conosci la posizione dello 0 tramite x e y, non converrebbe maggiormente verificare se n è adiacente allo 0?!
Infine nel momento in cui identifichi la posizione sia di n che dello 0, puoi anche scambiarli di posto, in modo che la funzione sposta() la elimini proprio.
Al netto di quanto appena detto per la funzione controlla() farei qualcosa del genere:
int controlla(Gioco *pc, int n)
{
if(pc->i != 0 && pc->campo[pc->i - 1][pc->j] == n)
{
pc->campo[pc->i--][pc->j] = n;
pc->campo[pc->i][pc->j] = 0;
return 1;
}
if(pc->j != 3 && pc->campo[pc->i][pc->j + 1] == n)
{
pc->campo[pc->i][pc->j++] = n;
pc->campo[pc->i][pc->j] = 0;
return 1;
}
if(pc->i != 3 && pc->campo[pc->i + 1][pc->j] == n)
{
pc->campo[pc->i++][pc->j] = n;
pc->campo[pc->i][pc->j] = 0;
return 1;
}
if(pc->j != 0 && pc->campo[pc->i][pc->j - 1] == n)
{
pc->campo[pc->i][pc->j--] = n;
pc->campo[pc->i][pc->j] = 0;
return 1;
}
return 0;
}
(ho utilizzato i e j al posto di y e x per evitare fraintendimenti)
09/12/2023 - MattINfo ha scritto:
essendo un programma fatto per il principale divertimento di programmare
Nel precedente post avevo chiesto se fossi interessato, perché spesso capita di avere a che fare con persone a cui basta un programma pseudo-funzionante da portare al prof, e quindi volevo evitare di perdere tempo.
In ogni caso per il momento credo di aver già messo abbastanza carne al fuoco!