Domanda studentessa sfigata in cerca di aiuto

deli88

Utente Iron
15 Marzo 2021
7
1
0
7
Ultima modifica da un moderatore:
Buongiorno, avrei bisogno di un aiutino su un esercizio in linguaggio C se possibile.
Progetto: Scacchi con soli Alfieri
Una matrice quadrata, con entrate che possono valere zero o uno, rappresenta una scacchiera dove non è presente nessuna pedina se il valore è pari a zero, mentre è presente un alfiere se il valore è pari uno. Gli alfieri possono attaccarsi come nelle regole degli scacchi, perciò esclusivamente in diagonale. Un attacco è quindi rappresentato da una coppia di alfieri che occupano due posizioni che stanno su una stessa diagonale.
Si scriva un programma che abbia le seguenti caratteristiche:
-Chieda all’utente di caricare una matrice quadrata di dimensione a scelta dell’utente e di inserire le righe della matrice che possono contenere i valori 0 o 1. La matrice rappresenta la scacchiera, le entrate pari a zero rappresentano caselle in cui non è presente nessuna pedina, mentre le entrate pari a uno rappresentano le caselle dove sono presenti gli alfieri.
-Stampi a video la matrice inserita.
-Contenga una funzione che calcoli in numero di attacchi totali possibili e stampi a video il numero ottenuto.

C:
#include <stdio.h>
#include <time.h>

int numeroAttacchi( int latomatrice, int board[latomatrice][latomatrice]){  
int attacchi = 0;
   
    for(int i = 0; i < latomatrice; i++){
   
        for(int j = 0; j < latomatrice; j++){
           
            if(board[i][j]==1){
                // i++ j--
                if(j - 1 >= 0 && i + 1 <latomatrice)      
                    if(board[i + 1][j - 1])              
                        attacchi++;
                        

                if(j - 2 >=0  && i + 2 < latomatrice)
                    if(board[i + 2][j - 2])
                        attacchi++;

                // i ++ j++
                if(j + 1 < latomatrice && i + 1 < latomatrice)
                    if(board[i + 1][j + 1])
                        attacchi++;

                
                if(j + 2 < latomatrice && i + 2 < latomatrice)
                    if(board[i + 2][j + 2])
                        attacchi++;

                // i -- j++
                if(j + 1 < latomatrice && i - 1 >= 0)
                    if(board[i - 1][j + 1])
                        attacchi++;

                
                if(j + 2 <  latomatrice && i - 2 >= 0)
                    if(board[i - 2][j + 2])
                        attacchi++;

                //i-- j--
                if(j - 1 >= 0 && i - 1 >= 0)
                    if(board[i - 1][j - 1])
                        attacchi++;

                
                if(j - 2 >= 0 && i - 2 >= 0)
                    if(board[i - 2][j - 2])
                        attacchi++;
                        
            }
        }        
    }
    return attacchi;
}

int main (){
    
    int latomatrice;
    printf("\nInserisci il lato della matrice quadrata: ");
    scanf("%d", &latomatrice);
    printf("facciamo una matrice %d x %d \n", latomatrice, latomatrice);
    
    srand(time(NULL));
    int board[latomatrice][latomatrice];
    
    for(int i = 0; i < latomatrice; i++){
    
        for(int j = 0; j < latomatrice; j++){
            board[i][j] = (rand() % 100 < 64);
    
            printf("%d ",board[i][j]);
            
        }
        printf("\n");
    }
    
    int attacchi = numeroAttacchi(latomatrice,board);    
    printf("gli attacchi totali sono %d", attacchi/2);    
    
}

MA MI Dà RISULTATI ERRATI. DOVE HO SBAGLIATO?
 
Non hai inizializzato il seme con srand srand(time(NULL));.
Comunque il tipo di casting implicito per ottenere 0/1 che stai facendo non è proprio "corretto". Se devi riempire con 0 o 1, puoi fare rand() % 2.
 
Non hai inizializzato il seme con srand srand(time(NULL));.
Comunque il tipo di casting implicito per ottenere 0/1 che stai facendo non è proprio "corretto". Se devi riempire con 0 o 1, puoi fare rand() % 2.

Non hai inizializzato il seme con srand srand(time(NULL));.
Comunque il tipo di casting implicito per ottenere 0/1 che stai facendo non è proprio "corretto". Se devi riempire con 0 o 1, puoi fare rand() % 2.
hai qualche soluzione più semplice?
magari mi sono cercata la più complicata
 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>


int main(int argc, char **argv)
{

// CHIEDO ALL'UTENTE DI CHE DIMENSIONI DEVE ESSERE LA MATRICE

int x;
printf("\nInserisci la dimensione della matrice: \n");
scanf("%d", &x);
printf("abbiamo una scacchiera %d per %d\n", x, x);

// DISEGNO LA MATRICE CON GLI ZERI IN BASE ALLE DIMENSIONI UTENTE

int matrice[x][x];
int numerazionevettori1 = 0;
//for(int i=0;i<x;i++){
int i=0;
while(i<x){
numerazionevettori1 = numerazionevettori1 +1;
printf("%d ",numerazionevettori1);
//for(int j=0;j<x;j++){
int j=0;
while(j<x){
j++;
matrice[j]= j+1;{
if(i==j){
matrice[j]=0;}
else{
matrice[j]=0;}}
printf("%d ",matrice[j]);}
i++;
printf("\n");}

// inserire le righe che possono contenere valori 0 e 1
char risposta;
printf("perfetto...scegli 2 righe dove posizionare casualmente gli alfieri \n\n");

int matrice2[x][x];
int numerazionevettori2 = 0;
//for(int i=0;i<x;i++){
i=0;
while(i<x){
numerazionevettori2 = numerazionevettori2 +1;
printf("%d ",numerazionevettori2);
//for(int j=0;j<x;j++){
int j=0;
while(j<x){
j++;
matrice[j]= j+1;{
if(i==j){
matrice[j]=0;}
else{
matrice[j]=0;}}
printf("%d ",matrice[j]);}
i++;
printf("\n");}

// aggiungiamo gli alfieri random

/*int i; // metodo per selezionare un vettore della matrice
int rigascelta;
printf("\nInserire una riga:\n");
scanf("%d",&rigascelta);
for (int j=0; j<x; j++){
int rigascelta = i;
printf("%d",matrice[j]);
}*/

/*int matrice3[x]; // metodo numeri random
int primariga;

for(primariga=0;primariga<x;primariga++){
matrice3[primariga]=rand()%2; //numeri casuali tra 1 e 100
printf("%d ", matrice3[primariga]);
} */



int primariga;
int secondariga;

printf("\n inserisci la prima riga dove vuoi aggiungere un alfiere...( da 1 a %d )\n--> ", x);
scanf("%d", &primariga);
printf("\n inserisci la seconda riga dove vuoi aggiungere un alfiere...( da 1 a %d )\n--> ", x);
scanf("%d", &secondariga);
printf("\nmettiamo gli alfieri sulla riga %d e sulla riga %d\n", primariga,secondariga);


// creiamo una matrice dove aggiungiamo gli alfieri
printf("\n gli alfieri sono posizionati sulle righe di combattimento...\n");

int matrice3[x][x];
int numerazionevettori3 = 0;
//for(int i=0;i<x;i++){
i=0;
while(i<x){
numerazionevettori3 = numerazionevettori3 +1;
printf("%d ",numerazionevettori3);
//for(int j=0;j<x;j++){
int j=0;
while(j<x){
j++;
matrice[j]= j+1;{
if(i==j){
matrice[j]=0;}
else{
matrice[j]=0;}}
printf("%d ",matrice[j]);}
i++;
printf("\n");}


}



/* for(primariga=0;primariga<x;primariga++)
matrice3[primariga] = ( rand()%2); //numeri casuali tra 0 E 1
printf("%d ", matrice3[secondariga]);
for(primariga=0;primariga<x;primariga++)
matrice3[secondariga] = (rand()%2);
printf("%d ", matrice3[secondariga]);*/

Messaggio unito automaticamente:

ma qui mi manca la funzione per gli attacchi degli alfieri
 
In C gli array (e di conseguenza anche le matrici) vanno definite con una dimensione costante in compile-time. Con int board[latomatrice][latomatrice]; stai utilizzando i VLA, che non sono proprio dei normali array. Credo che sia più corretto utilizzare malloc.

Comunque il tipo di casting implicito per ottenere 0/1 che stai facendo non è proprio "corretto". Se devi riempire con 0 o 1, puoi fare rand() % 2.
A me non disturba più di quel tanto. Per come lo sta facendo ha il 64% di probabilità di inserire un alfiere mentre per come lo faresti tu ha il 50%.

C:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>

int bishop_attacks(bool *board, int n) {
  int result = 0;

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      if (board[i * n + j]) {
        // test for down-right diagonal attacks
        for (int k = 1; i + k < n && j + k < n; k++) {
          if (board[(i + k) * n + (j + k)]) {
            // printf("[%d][%d] attack [%d][%d]\n", i, j, i + k, j + k); // debug
            result++;
            break;
          }
        }
        // test for down-left diagonal attacks
        for (int k = 1; i + k < n && 0 <= j - k; k++) {
          if (board[(i + k) * n + (j - k)]) {
            // printf("[%d][%d] attack [%d][%d]\n", i, j, i + k, j + k); // debug
            result++;
            break;
          }
        }
      }
    }
  }

  return result;
}

int main() {
  int n;
  printf("Dimensione scacchiera: ");
  scanf("%d", &n);

  int p;
  printf("Probabilità [0-100] di inserire alfieri: ");
  scanf("%d", &p);

  bool *board = malloc(n * n * sizeof(int));

  srand(time(NULL));
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      board[i * n + j] = rand() % 100 < p;
      printf("%d ", board[i * n + j]);
    }
    printf("\n");
  }

  printf("Esclusi i reciproci, si possono effettuare %d attacchi", bishop_attacks(board, n));

  free(board);
  return 0;
}
 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>


int main(int argc, char **argv)
{

// CHIEDO ALL'UTENTE DI CHE DIMENSIONI DEVE ESSERE LA MATRICE

int x;
printf("\nInserisci la dimensione della matrice: \n");
scanf("%d", &x);
printf("abbiamo una scacchiera %d per %d\n", x, x);

// DISEGNO LA MATRICE CON GLI ZERI IN BASE ALLE DIMENSIONI UTENTE

int matrice[x][x];
int numerazionevettori1 = 0;
//for(int i=0;i<x;i++){
int i=0;
while(i<x){
numerazionevettori1 = numerazionevettori1 +1;
printf("%d ",numerazionevettori1);
//for(int j=0;j<x;j++){
int j=0;
while(j<x){
j++;
matrice[j]= j+1;{
if(i==j){
matrice[j]=0;}
else{
matrice[j]=0;}}
printf("%d ",matrice[j]);}
i++;
printf("\n");}

// inserire le righe che possono contenere valori 0 e 1
char risposta;
printf("perfetto...scegli 2 righe dove posizionare casualmente gli alfieri \n\n");

int matrice2[x][x];
int numerazionevettori2 = 0;
//for(int i=0;i<x;i++){
i=0;
while(i<x){
numerazionevettori2 = numerazionevettori2 +1;
printf("%d ",numerazionevettori2);
//for(int j=0;j<x;j++){
int j=0;
while(j<x){
j++;
matrice[j]= j+1;{
if(i==j){
matrice[j]=0;}
else{
matrice[j]=0;}}
printf("%d ",matrice[j]);}
i++;
printf("\n");}

// aggiungiamo gli alfieri random

/*int i; // metodo per selezionare un vettore della matrice
int rigascelta;
printf("\nInserire una riga:\n");
scanf("%d",&rigascelta);
for (int j=0; j<x; j++){
int rigascelta = i;
printf("%d",matrice[j]);
}*/

/*int matrice3[x]; // metodo numeri random
int primariga;

for(primariga=0;primariga<x;primariga++){
matrice3[primariga]=rand()%2; //numeri casuali tra 1 e 100
printf("%d ", matrice3[primariga]);
} */



int primariga;
int secondariga;

printf("\n inserisci la prima riga dove vuoi aggiungere un alfiere...( da 1 a %d )\n--> ", x);
scanf("%d", &primariga);
printf("\n inserisci la seconda riga dove vuoi aggiungere un alfiere...( da 1 a %d )\n--> ", x);
scanf("%d", &secondariga);
printf("\nmettiamo gli alfieri sulla riga %d e sulla riga %d\n", primariga,secondariga);


// creiamo una matrice dove aggiungiamo gli alfieri
printf("\n gli alfieri sono posizionati sulle righe di combattimento...\n");

int matrice3[x][x];
int numerazionevettori3 = 0;
//for(int i=0;i<x;i++){
i=0;
while(i<x){
numerazionevettori3 = numerazionevettori3 +1;
printf("%d ",numerazionevettori3);
//for(int j=0;j<x;j++){
int j=0;
while(j<x){
j++;
matrice[j]= j+1;{
if(i==j){
matrice[j]=0;}
else{
matrice[j]=0;}}
printf("%d ",matrice[j]);}
i++;
printf("\n");}


}



/* for(primariga=0;primariga<x;primariga++)
matrice3[primariga] = ( rand()%2); //numeri casuali tra 0 E 1
printf("%d ", matrice3[secondariga]);
for(primariga=0;primariga<x;primariga++)
matrice3[secondariga] = (rand()%2);
printf("%d ", matrice3[secondariga]);*/

Messaggio unito automaticamente:

ma qui mi manca la funzione per gli attacchi degli alfieri

Per favore, ti ho editato il messaggio di prima chiedendoti di utilizzare il tag CODE, modifica il post (come noti è formattato male). Se non sai come si fa, puoi guardare qui https://xenforo.com/community/help/bb-codes/

A me non disturba più di quel tanto. Per come lo sta facendo ha il 64% di probabilità di inserire un alfiere mentre per come lo faresti tu ha il 50%.
Quello è vero, davo per scontato volesse un 50% non essendo presente alcuna richiesta esplicita nel testo dell'esercizio.
 
scusatemi....
Messaggio unito automaticamente:

più che altro spiegatemi la storia delle probabilità.

Tu generavi 100 valori, ma usando la condizione < 64 ti viene restituito true (1) 64 volte su 100. Quindi è più probabile avere un 1 rispetto a uno 0.
Nel mio caso estrai solo 0 o 1, quindi hai il 50%.

Dipende quindi se la probabilità di avere un alfiere è uguale a quella di non averlo, oppure se è giusto abbia una probabilità maggiore.
 
aspetta, piano, io devo contare gli attacchi in base ai valori zero e uno o in base effettivamente al movimento dell'alfiere?
avendo una scacchiera vuota con metti due alfieri, io avrei per ciascun alfiere almeno una trentina di mosse o sbaglio?
 
Questo pezzo di codice cerca gli alfieri
C:
for (int i = 0; i < n; i++) {
  for (int j = 0; j < n; j++) {
    if (board[i * n + j]) {
        // ...
    }
  }
}
Quindi per ogni alfiere eseguo il body di quell'if che, chiaramente, dovrà servire a contare quanti attacchi un alfiere può fare.

Un alfiere può fare al massimo 4 attacchi, perché si può muovere in 4 direzioni: top-left, top-right, bottom-left e bottom-right. Tuttavia, se io posso attaccarti muovendomi bottom-left allora tu puoi attaccarmi top-right perché siamo entrambi alfieri. Quindi nelle prossime righe di codice (all'interno del body) è sufficiente verificare se possiamo attaccare in due direzioni diverse. Io ho scelto bottom-left e bottom-right, ma altre scelte valide potrebbero essere: top-left e top-right, top-left e bottom-left oppure top-right e bottom-right. L'importante è coprire due diagonali diverse, altrimenti una rimane scoperta, verso una sola direzione, perché in una scacchiera con solo alfieri ogni attacco è bidirezionale e non ha senso contare due volte.

Questo controlla la prima diagonale, bottom-right:
C:
// test for down-right diagonal attacks                              
for (int k = 1; i + k < n && j + k < n; k++) {                       
  if (board[(i + k) * n + (j + k)]) {                                
    result++;                                                        
    break;                                                           
  }                                                                  
}
L'if serve per controllare se ho trovato un alfiere da attaccare e il break serve ad evitare di attaccare anche gli alfieri coperti dal primo alfiere che incontro. Ci muoviamo bottom-right e, per come stiamo stampando la scacchiera, [0][0] è in alto a sinistra. Muoversi bottom-right vuol dire incrementare entrambi gli indici, sia quello della riga (indice i) che quello della colonna (indice j). Se non trovo nessuno, il for si stoppa appena raggiunge un bordo della scacchiera, ovvero se l'indice di riga incrementato è uguale ad n oppure se l'indice di colonna incrementato è uguale ad n.

In modo del tutto equivalente, controlliamo bottom-left:
C:
// test for down-left diagonal attacks
for (int k = 1; i + k < n && 0 <= j - k; k++) {
  if (board[(i + k) * n + (j - k)]) {
    result++;
    break;
  }
}
L'unica cosa che cambia rispetto a prima è che invece che muoverci verso destra (i.e., incremento l'indice di colonna) ci muoviamo verso sinistra, decrementando l'indice di colonna. Ovviamente, il bordo della scacchiera sarà dall'altro lato.

Chiaro? Prova a leggere con calma.
 
  • Mi piace
Reazioni: DispatchCode