Problema passaggio per indirizzo

di il
6 risposte

Problema passaggio per indirizzo

Salve, sto riscontrando un fastidioso problema che non riesco a risolvere. Praticamente ho una matrice 5 x 5 nella quale ci sono delle I, precisamente 5 sulla prima riga, 4 sulla seconda, 3 sulla terza e così via. Ogni giocatore può decidere di eliminare un numero arbitrario di I su qualsiasi riga, il giocatore che cancellerà l'ultima I perde. Ho creato quindi 5 variabili per stabilire quante I sono disponibili su ogni riga, ogni variabile inizializzata al numero di I presenti sulla riga. Questo mi permette di effettuare tutti i possibili controlli sugli inserimenti dell'utente, ma il passaggio per indirizzo funziona solo per la variabile che indica le i disponibili sulla prima riga, per le altre no e non capisco perchè.. riporto il codice (ancora incompleto).
/* Inclusione delle librerie */
/*****************************/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

/********************************/
/* Dichiarazione delle funzioni */
/********************************/

void disegna_grafico(char[5][5]);
int inizia_partita(char[5][5],
		   int*,
		   int*,
		   int*,
		   int*,
		   int*,
	  	   int,
	  	   int);
void popola_matrice(char[5][5]);
int gestione_vittoria(char[5][5]);

/* Definizione della funzione main */

int main ()
{	
	/* Definizione delle variabili locali alla funzione */
	char campo[5][5];			/* Output: Matrice 3x3 del tris*/

	int valido = 0;				/* Lavoro: Variabile flag per determinare la fine della partita */
	
	int disponibile0 = 5,
	    disponibile1 = 4,
	    disponibile2 = 3,
	    disponibile3 = 2,
	    disponibile4 = 1;
	
	int inizio = 0;				/* Lavoro: Variabile che gestisce casualmente l'inizio della partita */

	/* Popola la matrice tris con degli spazi */
	popola_matrice(campo);

	printf("Disegno il campo da gioco...\n");
	
	/* Si richiama la funzione che stampa a video la matrice tris */
	disegna_grafico(campo);

	/* Si gestisce in modo casuale quale giocatore deve iniziare */
        srand(time(NULL));
        inizio = rand() % 2;

        printf("\nSta per iniziare la partita, tenetevi pronti!\n");

        if(inizio == 0)
                printf("\nIl Giocatore1 è il primo ad iniziare.\n\n");
        else
                printf("\nIl Giocatore2 è il primo ad iniziare.\n\n");

        /* Se il risultato della funzione rand() è 0, allora inizia il giocatore X */
        do
        {
                valido = inizia_partita(campo,&disponibile0,&disponibile1,&disponibile2,&disponibile3,&disponibile4,valido,inizio);
		inizio = (inizio + 1) % 2;
        }
        while(valido != 1);

	return (0);
}

/* Definizione della funzione disegna_grafico */

void disegna_grafico(char campo[5][5])
{
	int i,					/* Lavoro: Variabile che scorre le righe della matrice */
	    j;					/* Lavoro: Variabile che scorre le colonne della matrice */


	printf("\n    0  1  2  3  4 \n");
	
	for(i=0;
	    i<5;
            i++)
       	{
		printf("\n");
		printf("%d)",i);
		for(j=0;
		    j<5;
		    j++)
		{
			printf("  %c",campo[i][j]);
		}
		
	}

	printf("\n\n");
}

/* Definizione della funzione popola_matrice */

void popola_matrice(char campo[5][5])		/* Output: Matrice 3x3 del tris */
{	
	int i,					/* Lavoro: Variabile che scorre le righe della matrice */
	    j;					/* Lavoro: Variabile che scorre le colonne della matrice */
	
	/* Si popola la matrice con degli spazi vuoti */
	for(i=0;i<5;i++) 
		for(j=0;j<5;j++)
		{
			campo[i][j]   = ' ';
			campo[i][0]   = 'I';
			campo[i-1][1] = 'I';
			campo[i-2][2] = 'I';
			campo[i-3][3] = 'I';
			campo[i-4][4] = 'I';
		}
}

/* Definizione della funzione inizia_partita */
			              
int inizia_partita(char campo[5][5],		/* Output: Matrice 5x5 del tris */
	  	   int *disponibile0,
 		   int *disponibile1,
		   int *disponibile2,
		   int *disponibile3,
		   int *disponibile4,
		   int valido,			/* Lavoro: Variabile flag per determinare la fine della partita */
	  	   int inizio)			/* Lavoro: Variabile che gestisce casualmente l'inizio della partita */
{
	int prosegui = 1;			/* Lavoro: Variabile flag che gestisce se terminare o meno il programma */

	int esito_lettura;			/* Lavoro: Variabile che assume il valore di ritorno della funzione scanf */

	int  posizionex,			/* Input: Conversione in intero della variabile di input stringax */
	     posizioney;			/* Input: Conversione in intero della variabile di input stringay */
	
	int i;
	int ciclo;

	char giocatore[11];			/* Lavoro: Assume il valore X o O, in base a quale giocatore effettua il turno */

	/* Associo alla variabile simbolo il valore X o O, a seconda del risultato della variabile inizio */
	if(inizio == 0)
		strcpy(giocatore, "Giocatore1");
	else
		strcpy(giocatore, "Giocatore2");

	do
	{
		do
		{
			printf("%s inserire la riga dalla quale si desidera eliminare la I: ",giocatore);
			esito_lettura = scanf("%d",
					      &posizionex);
			/* Se non è stato inserito un numero valido, si richiede l'inserimento */
			if(esito_lettura != 1 || (posizionex > 4 || posizionex < 0))
           	        {
             	        	printf("\nInput non accettabile!\n\n");
               	       		while (getchar() != '\n');
				prosegui = 0;
               	       	}
			else if((posizionex == 0 && *disponibile0 == 0) ||
				(posizionex == 1 && *disponibile1 == 0) ||
			        (posizionex == 2 && *disponibile2 == 0) ||
				(posizionex == 3 && *disponibile3 == 0) ||
				(posizionex == 4 && *disponibile4 == 0))
			{
				printf("\nTutte le I di questa riga sono state cancellate! Scegliere una riga valida.\n\n");
				while(getchar() != '\n');
				prosegui = 0;
			}
			else
			{
				prosegui = 1;
				while(getchar() != '\n');
			}
		}
		while(prosegui != 1);
	        do		
		{
		
			printf("Quante I desidera eliminare? ");
			esito_lettura = scanf("%d",
			      		      &ciclo);
			if(esito_lettura != 1 || 
			  (ciclo > 5 || ciclo < 1) || 
                          (posizionex == 1 && ciclo > 4) || 
                          (posizionex == 2 && ciclo > 3) || 
               	          (posizionex == 3 && ciclo > 2) || 
                       	  (posizionex == 4 && ciclo != 1))
			{
				printf("\nInput non accettabile!\n\n");	
				while(getchar() != '\n');
				prosegui = 0;
			} 
			else if((posizionex == 0 && (ciclo > *disponibile0)) || 
		        	  (posizionex == 1 && (ciclo > *disponibile1)) || 
				  (posizionex == 2 && (ciclo > *disponibile2)) || 
  				  (posizionex == 3 && (ciclo > *disponibile3)) || 
		  		  (posizionex == 4 && (ciclo > *disponibile4)))
			{
				printf("\nInput non accettabile!\n\n");
				while(getchar() != '\n');
				prosegui = 0;
			}
			else
			{
				if(posizionex == 0)
					*disponibile0 -= ciclo;
				else if(posizionex == 1)
					*disponibile1 -= ciclo;
				else if(posizionex == 2)
					*disponibile2 -= ciclo;
				else if(posizionex ==  3)
					*disponibile3 -= ciclo;
				else
					*disponibile4 -= ciclo;
				prosegui = 1;
				while (getchar() != '\n');
			}
			printf("%d\n",*disponibile0);
			printf("%d\n",*disponibile1);
			printf("%d\n",*disponibile2);
			printf("%d\n",*disponibile3);
			printf("%d\n",*disponibile4);
		}
		while(prosegui != 1);	
		for(i = 0; i < ciclo; i++)
		{
			do
			{
				do
				{
					printf("%s quale I desidera eliminare dalla riga %d? ",giocatore,posizionex);
					esito_lettura = scanf("%d",	
							      &posizioney);
					/* Se non è stato inserito un numero valido, si richiede l'inserimento */
					if(esito_lettura != 1 || 
					  (posizioney > 4 || posizioney < 0) ||
        	     	   	          (posizionex == 4 && posizioney != 0) || 
					  (posizionex == 3 && (posizioney > 1 || posizioney < 0)) ||
					  (posizionex == 2 && (posizioney > 2 || posizioney < 0)) ||
					  (posizionex == 1 && (posizioney > 3 || posizioney < 0)))
        		       		{
						printf("\nInput non accettabile!\n\n");
						while (getchar() != '\n');
              	       				prosegui = 0;
					}
					else
					{
						prosegui = 1;
						
					}
				}
				while(prosegui != 1);
				/* Si impedisce all'utente di sovrascrivere le caselle della matrice già occupate */
				if(campo[posizionex][posizioney] == '-')
				{
					printf("\nQuesta posizione è già stata cancellata! Inserisci una posizione valida.\n\n");
					while(getchar() != '\n');
					prosegui = 0;
				}
				else
				{
					prosegui = 1;
					while(getchar() != '\n');
					campo[posizionex][posizioney] = '-';
				}
			}		
			while(prosegui != 1);
		}
	}
	while(prosegui != 1);	
	disegna_grafico(campo);
	/* Controlla se il giocatore X ha vinto, se sì... */
	if(gestione_vittoria(campo) == 1)
		/*...imposta valido = 1,così da non chiedere altri inserimenti */
		valido = 1; 
	
	return(valido);
}

/* Definizione della funzione gestione_vittoria */

int gestione_vittoria(char campo[5][5])		/* Lavoro: Variabile che tiene conto di quanti inserimenti sono stati effettuati */
{
	int i;					/* Lavoro: Indice che scorre le righe e le colonne della matrice */
	int uscita = 0;				/* Lavoro: Variabile che tiene conto delle condizioni per terminare la partita */
	int vittoria = 0;			/* Lavoro: Variabile che gestisce la vittoria di un giocatore,vale 0 se nessuno ha vinto, 1 viceversa */

	/* Controllo tutte le possibili situazioni di vittoria */
	return(uscita);
}


Non capisco perchè il valore della variabile disponibile0 è corretto, cioè è inizializzata a 5, e nel momento in cui l'utente decidere di levare un tot di I dalla riga 0, questo tot viene decrementato dalla variabile, invece le altre variabili hanno valori assurdi... eppure non dovrebbero riportare i loro indirizzi di memoria, ma il loro valore aggiornato ad ogni ciclo.

6 Risposte

  • Re: Problema passaggio per indirizzo

    Non sono riuscito a replicare il tuo problema, i valori sono corretti ad una prima esecuzione.

    Comunque non capisco perché utilizzi cinque variabili diverse e non un vettore di cinque int (molto più comodo in molte situazioni), ad esempio

    int disponibile[5];
  • Re: Problema passaggio per indirizzo

    oregon ha scritto:


    Non sono riuscito a replicare il tuo problema, i valori sono corretti ad una prima esecuzione.

    Comunque non capisco perché utilizzi cinque variabili diverse e non un vettore di cinque int (molto più comodo in molte situazioni), ad esempio

    int disponibile[5];
    Sinceramente non ci avevo pensato, grazie per il consiglio! In ogni caso non capisco tu non hai il mio stesso errore.. adesso facendolo con un vettore ho le prime 3 posizioni corrette e le altre completamente a caso come prima.. il fatto che non è solo questione di printf, ma è proprio che il loro valore è sballato, infatti i controlli su quelle caselle non funzionano. Da cosa può dipendere? Sto usando Ubuntu e compilo con "gcc -ansi -Wall -O nomefile.c -o nomefile".
  • Re: Problema passaggio per indirizzo

    Tu hai mostrato che il programma inizia con Giocatore2, a me parte con Giocatore1.

    Mostra il codice con il vettore di interi e la sequenza esatta di cosa fai dalla partenza del programma in poi.
  • Re: Problema passaggio per indirizzo

    L'inizio della partita è gestito in modo casuale, per questo a te inizia con il Giocatore1 e a me con il Giocatore1, comunque il codice aggiornato è questo:
    /*****************************/
    /* Inclusione delle librerie */
    /*****************************/
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    
    /********************************/
    /* Dichiarazione delle funzioni */
    /********************************/
    
    void disegna_grafico(char[5][5]);
    int inizia_partita(char[5][5],
    	 	   int*,
    	  	   int,
    	  	   int);
    void popola_matrice(char[5][5]);
    int gestione_vittoria(char[5][5],
    		      char,
    		      int);
    
    /* Definizione della funzione main */
    
    int main ()
    {	
    	/* Definizione delle variabili locali alla funzione */
    	char campo[5][5];			/* Output: Matrice 3x3 del tris*/
    
    	int valido = 0;				/* Lavoro: Variabile flag per determinare la fine della partita */
    	
    	int disponibile[6] = {15,5,4,3,2,1};
    	
    	int inizio = 0;				/* Lavoro: Variabile che gestisce casualmente l'inizio della partita */
    
    	/* Popola la matrice tris con degli spazi */
    	popola_matrice(campo);
    
    	printf("Disegno il campo da gioco...\n");
    	
    	/* Si richiama la funzione che stampa a video la matrice tris */
    	disegna_grafico(campo);
    
    	/* Si gestisce in modo casuale quale giocatore deve iniziare */
            srand(time(NULL));
            inizio = rand() % 2;
    
            printf("\nSta per iniziare la partita, tenetevi pronti!\n");
    
            if(inizio == 0)
                    printf("\nIl Giocatore1 è il primo ad iniziare.\n\n");
            else
                    printf("\nIl Giocatore2 è il primo ad iniziare.\n\n");
    
            /* Se il risultato della funzione rand() è 0, allora inizia il giocatore X */
            do
            {
                    valido = inizia_partita(campo,disponibile,valido,inizio);
    		inizio = (inizio + 1) % 2;
            }
            while(valido != 1);
    
    	return (0);
    }
    
    /* Definizione della funzione disegna_grafico */
    
    void disegna_grafico(char campo[5][5])
    {
    	int i,					/* Lavoro: Variabile che scorre le righe della matrice */
    	    j;					/* Lavoro: Variabile che scorre le colonne della matrice */
    
    
    	printf("\n    0  1  2  3  4 \n");
    	
    	for(i=0;
    	    i<5;
                i++)
           	{
    		printf("\n");
    		printf("%d)",i);
    		for(j=0;
    		    j<5;
    		    j++)
    		{
    			printf("  %c",campo[i][j]);
    		}
    		
    	}
    
    	printf("\n\n");
    }
    
    /* Definizione della funzione popola_matrice */
    
    void popola_matrice(char campo[5][5])		/* Output: Matrice 3x3 del tris */
    {	
    	int i,					/* Lavoro: Variabile che scorre le righe della matrice */
    	    j;					/* Lavoro: Variabile che scorre le colonne della matrice */
    	
    	/* Si popola la matrice con degli spazi vuoti */
    	for(i=0;i<5;i++) 
    		for(j=0;j<5;j++)
    		{
    			campo[i][j]   = ' ';
    			campo[i][0]   = 'I';
    			campo[i-1][1] = 'I';
    			campo[i-2][2] = 'I';
    			campo[i-3][3] = 'I';
    			campo[i-4][4] = 'I';
    		}
    }
    
    /* Definizione della funzione inizia_partita */
    			              
    int inizia_partita(char campo[5][5],
    		   int *disponibile,
    		   int valido,			/* Lavoro: Variabile flag per determinare la fine della partita */
    	  	   int inizio)			/* Lavoro: Variabile che gestisce casualmente l'inizio della partita */
    {
    	int prosegui = 1;			/* Lavoro: Variabile flag che gestisce se terminare o meno il programma */
    
    	int esito_lettura;			/* Lavoro: Variabile che assume il valore di ritorno della funzione scanf */
    
    	int posizionex,			/* Input: Conversione in intero della variabile di input stringax */
    	    posizioney;			/* Input: Conversione in intero della variabile di input stringay */
    	
    	int i;
    	int ciclo;
    
    	char giocatore[11];			/* Lavoro: Assume il valore X o O, in base a quale giocatore effettua il turno */
    
    	/* Associo alla variabile simbolo il valore X o O, a seconda del risultato della variabile inizio */
    	if(inizio == 0)
    		strcpy(giocatore, "Giocatore1");
    	else
    		strcpy(giocatore, "Giocatore2");
    
    	do
    	{
    		do
    		{
    			printf("%s inserire la riga dalla quale si desidera eliminare la I: ",giocatore);
    			esito_lettura = scanf("%d",
    					      &posizionex);
    			/* Se non è stato inserito un numero valido, si richiede l'inserimento */
    			if(esito_lettura != 1 || (posizionex > 4 || posizionex < 0))
               	        {
                 	        	printf("\nInput non accettabile!\n\n");
                   	       		while (getchar() != '\n');
    				prosegui = 0;
                   	       	}
    			else if((posizionex == 0 && disponibile[1] == 0) ||
    				(posizionex == 1 && disponibile[2] == 0) ||
    			        (posizionex == 2 && disponibile[3] == 0) ||
    				(posizionex == 3 && disponibile[4] == 0) ||
    				(posizionex == 4 && disponibile[5] == 0))
    			{
    				printf("\nTutte le I di questa riga sono state cancellate! Scegliere una riga valida.\n\n");
    				while(getchar() != '\n');
    				prosegui = 0;
    			}
    			else
    			{
    				prosegui = 1;
    				while(getchar() != '\n');
    			}
    		}
    		while(prosegui != 1);
    	        do		
    		{
    		
    			printf("Quante I desidera eliminare? ");
    			esito_lettura = scanf("%d",
    			      		      &ciclo);
    			if(esito_lettura != 1 || 
    			  (ciclo > 5 || ciclo < 1) || 
                              (posizionex == 1 && ciclo > 4) || 
                              (posizionex == 2 && ciclo > 3) || 
                   	          (posizionex == 3 && ciclo > 2) || 
                           	  (posizionex == 4 && ciclo != 1))
    			{
    				printf("\nInput non accettabile!\n\n");	
    				while(getchar() != '\n');
    				prosegui = 0;
    			} 
    			else if((posizionex == 0 && (ciclo > disponibile[1])) || 
    		        	  (posizionex == 1 && (ciclo > disponibile[2])) || 
    				  (posizionex == 2 && (ciclo > disponibile[3])) || 
      				  (posizionex == 3 && (ciclo > disponibile[4])) || 
    		  		  (posizionex == 4 && (ciclo > disponibile[5])))
    			{
    				printf("\nInput non accettabile!\n\n");
    				while(getchar() != '\n');
    				prosegui = 0;
    			}
    			else
    			{
    				if(posizionex == 0)
    					disponibile[1] -= ciclo;
    				else if(posizionex == 1)
    					disponibile[2] -= ciclo;
    				else if(posizionex == 2)
    					disponibile[3] -= ciclo;
    				else if(posizionex ==  3)
    					disponibile[4] -= ciclo;
    				else
    					disponibile[5] -= ciclo;
    				prosegui = 1;
    				while (getchar() != '\n');
    				disponibile[0] -= ciclo;
    			}
    			printf("%d\n",disponibile[0]);
    			printf("%d\n",disponibile[1]);
    			printf("%d\n",disponibile[2]);
    			printf("%d\n",disponibile[3]);
    			printf("%d\n",disponibile[4]);
    			printf("%d\n",disponibile[5]);
    		}
    		while(prosegui != 1);	
    		for(i = 0; i < ciclo; i++)
    		{
    			do
    			{
    				do
    				{
    					printf("%s quale I desidera eliminare dalla riga %d? ",giocatore,posizionex);
    					esito_lettura = scanf("%d",	
    							      &posizioney);
    					/* Se non è stato inserito un numero valido, si richiede l'inserimento */
    					if(esito_lettura != 1 || 
    					  (posizioney > 4 || posizioney < 0) ||
            	     	   	          (posizionex == 4 && posizioney != 0) || 
    					  (posizionex == 3 && (posizioney > 1 || posizioney < 0)) ||
    					  (posizionex == 2 && (posizioney > 2 || posizioney < 0)) ||
    					  (posizionex == 1 && (posizioney > 3 || posizioney < 0)))
            		       		{
    						printf("\nInput non accettabile!\n\n");
    						while (getchar() != '\n');
                  	       				prosegui = 0;
    					}
    					else
    					{
    						prosegui = 1;
    						
    					}
    				}
    				while(prosegui != 1);
    				/* Si impedisce all'utente di sovrascrivere le caselle della matrice già occupate */
    				if(campo[posizionex][posizioney] == '-')
    				{
    					printf("\nQuesta posizione è già stata cancellata! Inserisci una posizione valida.\n\n");
    					while(getchar() != '\n');
    					prosegui = 0;
    				}
    				else
    				{
    					prosegui = 1;
    					while(getchar() != '\n');
    					campo[posizionex][posizioney] = '-';
    				}
    			}		
    			while(prosegui != 1);
    		}
    	}
    	while(prosegui != 1);	
    	disegna_grafico(campo);
    	/* Controlla se il giocatore X ha vinto, se sì... */
    	if(gestione_vittoria(campo,giocatore,*disponibile) == 1)
    		/*...imposta valido = 1,così da non chiedere altri inserimenti */
    		valido = 1; 
    	
    	return(valido);
    }
    
    /* Definizione della funzione gestione_vittoria */
    
    int gestione_vittoria(char campo[5][5],
    		      char giocatore,
    		      int disponibile)		/* Lavoro: Variabile che tiene conto di quanti inserimenti sono stati effettuati */
    {
    	int i;					/* Lavoro: Indice che scorre le righe e le colonne della matrice */
    	int uscita = 0;				/* Lavoro: Variabile che tiene conto delle condizioni per terminare la partita */
    	int vittoria = 0;			/* Lavoro: Variabile che gestisce la vittoria di un giocatore,vale 0 se nessuno ha vinto, 1 viceversa */
    
    
    	printf("%d\n\n",disponibile);
    	
    	if(disponibile == 0)
    	{   
    		printf("\nIl %s ha vinto!\n",giocatore);
    		printf("\nLa partita è terminata...\n");
    		uscita = 1;
    	}
    
    	/* Controllo tutte le possibili situazioni di vittoria */
    	return(uscita);
    }
    Devo ancora sistemare la funziona per gestire la vittoria, ma per il momento non è una priorità.
    https://imgur.com/kahhgk

    https://imgur.com/a/n9aMGa
  • Re: Problema passaggio per indirizzo

    A me continua a non dare grossi problemi (a parte qualche errore in compilazione) ...

    Cosa rappresenta disponibile[0] ?

    Perché non usi le variabili come indici al posto di tutte quelle if quando tratti il vettore disponibile[] ? Altrimenti che scopo ha il vettore ?
  • Re: Problema passaggio per indirizzo

    Sisi quegli errori li ho risolti, erano dovuti alla funzione gestisci_vittoria che non ancora completavo. Comunque disponibile[0] rappresenta il totale di tutti gli spazi ancora disponibili, quando questa sarà 0 allora l'ultimo giocatore che ha cancellato una I perde.
    In che senso variabili come indici? Pensavo che il vettore servisse solo per non allocare 6 variabili. Comunque continuo a non capire perchè a me non va. Praticamente è come se nella posizione 4 e 5 del vettore io non allocassi nulla, infatti sia se le inizializzo, sia se non lo faccio, i valori del vettore in quelle posizioni sono sempre 73 e 18761...
Devi accedere o registrarti per scrivere nel forum
6 risposte