Oppure

Loading
09/12/09 19:24
Luca90
Ciao a tutti!Scusatemi, sto cercando di scrivere il gioco Life con C; ora, dovendo contare i "vivi" della matrice, sorge il problema degli estremi: quando si arriva ai limiti della matrice, come potrei fare per contare i vivi dall'altro lato della matrice? Come se fosse una griglia sferica? Avevo pensato a cicli while a catena, però mi son incartato...Potreste darmi qualche dritta?
aaa
09/12/09 20:27
TheKaneB
ciao, ci sono varie soluzioni al problema... una che mi viene in mente è questa:
#include <stdio.h>

#define MAX_X 5
#define MAX_Y 8

int myMatrix[MAX_X][MAX_Y];

#define		SIDE_NONE  	0
#define		SIDE_RIGHT	1
#define		SIDE_LEFT	2
#define		SIDE_UP		4
#define		SIDE_DOWN	8
// La negazione di 0 corrisponde alla parola con tutti i bit settati a 1
// Non uso la forma 0xFFFFFFFF per evitare assunzioni sulla lunghezza della parola macchina
#define		SIDE_ALL	(~0)

// Versione NON ottimizzata
int getX(int side, int x)
{
    int _x = x;

    // Attenzione: Considero la X crescente verso destra e la Y crescente verso il basso (convenzione comune in computer graphics)
    if (side & SIDE_LEFT) 	_x -= 1;
    if (side & SIDE_RIGHT)	_x += 1;

    // Mi riporto nel campo dei numeri positivi
    while (_x < 0) { _x += MAX_X; }

    // Rientro nel campo dei valori ammissibili per x e y
    _x %= MAX_X;
}

int getY(int side, int y)
{
    int _y = y;

    if (side & SIDE_UP)		_y -= 1;	
    if (side & SIDE_DOWN)	_y += 1;

    while (_y < 0) { _y += MAX_Y; }

    _y %= MAX_Y;
}

int getValue(int side, int x, int y)
{
    int sphericalX = getX(side, x);
    int sphericalY = getY(side, y);
    
    return myMatrix[sphericalX][sphericalY];
}

void setValue(int side, int x, int y, int value)
{
    int sphericalX = getX(side, x);
    int sphericalY = getY(side, y);
    
    myMatrix[sphericalX][sphericalY] = value;
}

int main(int argc, char **argv)
{
    // Inizializzo myMatrix
    // [...] codice "a piacere"
    int i,j;
    printf(">>>\n");
    for (j = 0; j < MAX_Y; j++)
    {
	printf("|");
	for (i = 0; i < MAX_X; i++)
	{
	    myMatrix[i][j] = i + MAX_X * j;
	    printf("%d\t", myMatrix[i][j]);
	}
	printf("|\n");
    }
    printf(">>>\n");
    // [...] FINE codice "a piacere"

    int a = getValue(SIDE_NONE, 12, -3);
    int b = getValue(SIDE_RIGHT, 11, -3);

    if (a == b) printf("Yeah!\n");

    // Ottengo il valore della casella in alto a sinistra rispetto alle coordinate 0,0, cioè ottengo lo spigolo opposto della matrice
    a = getValue(SIDE_LEFT + SIDE_UP, 0, 0);
    b = getValue(SIDE_NONE, MAX_X - 1, MAX_Y - 1);

    if (a == b) printf("Oh Yeah 2 - la vendetta\n");

    return 0;
}


L'ho scritta di getto, quindi non mi aspetto che funzioni a primo colpo, ma tentare una compilazione con annesso debugging richiedeva troppo sforzo fisico e mentale XD
Il codice è self explanatory, l'ho volutamente mantenuto semplice senza ottimizzare nulla (ci sarebbe molto da migliorare se ti servono tempi di calcolo brevi).

Buono studio ;)
aaa
09/12/09 20:29
TheKaneB
ps: per verificare se hai capito la tecnica... potresti spiegarmi come mai SIDE_NONE e SIDE_ALL hanno esattamente lo stesso effetto, cioè di restituire la cella voluta?

Ciao!
aaa
10/12/09 15:50
Luca90
Prima di tutto ti ringrazio per aver perso tempo con la mia richiesta:)e mi scuso se non ti ho risposto subito, ma non ho potuto..comunque, non riesco a rispondere alla tua domanda di "assert":k:,perchè non ho capito cosa fa la tilde quando definisci SIDE_ALL.Perchè ((Non so come scrive la tilde)0)?
aaa
10/12/09 15:53
Luca90
Ah ma è 0 negato???? La negazione non si scrive tipo (!0)?
aaa
10/12/09 16:21
TheKaneB
la negazione di un booleano si fa con !, la negazione bitwise (cioè per ogni singolo bit) si fa con la tilde ~ (su windows premi ALT e digita 126 sul tastierino numerico, poi rilascia ALT).

aaa
10/12/09 16:26
TheKaneB
ah ovviamente ho fatto in modo che con get value tu possa interrogare le celle adiacenti senza intervenire sugli indici, così semplifichi il calcolo delle regole di Life. Lo stesso risultato si può ottenere togliendo il SIDE e agendo direttamente su x e y, tanto funziona comunque in coordinate toroidali.

Già, perchè pensandoci meglio, non è equivalende ad una sfera, ma ad un toroide! cioè una figura a forma di ciambella :)
aaa
11/12/09 11:33
Luca90
Sono arrivato alla fine a questo codice, ma su linux dopo la prima printf mi da Segmentation fault..Che tipo di errore è?

#include <stdio.h>
#define X 80
#define Y 30

//clear the screen from not wanted chars
void blackScreen(char screen[Y][X],int max_x, int max_y){
	int i,j;
	for(i=0; i<max_y;i++){
		for(j=0; j<max_x; ++j){
			screen[i][j]=' ';
		}
	}
}

// print the screen
void printScreen(char screen[Y][X],int max_x, int max_y){
	int i, j;
	for(i=0;i<max_y;++i){
		printf("\n");
		for(j=0;j<max_x;++j){
			printf("%c",screen[i][j]);
		}
	}		
}

//copy a screen to the new one
void copyScreen(char target[Y][X],char source[Y][X],int max_x, int max_y){
	int i,j;
	for(i=0; i<max_y; ++i){
		for(j=0; j<max_x; ++j){
			target[i][j]=source[i][j];	
		}
	}
}

// new generation of population
void epoch(char new[Y][X],char old[Y][X],int max_x, int max_y){
	int i,j;
	for(i=0; i<max_y; ++i){
		for(j=0; j<max_x; ++j){
			switch(contaVicini(old[i][j], max_x, max_y)){
				case 2:
					new[i][j]=old[i][j];
					break;
				case 3: 
					new[i][j]= '+';
					break;
				default:
					new[i][j]= ' ';
					break;
			}	
		}	
	}	
}
//count the neighbor
int contaVicini(char screen[Y][X],int x,int y, int max_x, int max_y){
	int i,j,cont=0,flag=0;
		
		//Eccezioni per i quattro angoli; conta manualmente gli 8 vicini, pensando la matrice come una sfera
		if(y == 0){
			
			//Angolo: AltoSx
			if(x == 0){
				while(flag <= 3){
					if(screen[y][max_x]=='+')++cont;
					if(screen[y][1]=='+')++cont;
					++flag;
					if(screen[y+1][0]=='+')++cont;
					if(screen[y+1][1]=='+')++cont;
					if(screen[y+1][max_x]=='+')++cont;
					++flag;
					if(screen[max_y][0]=='+')++cont;
					if(screen[max_y][1]=='+')++cont;
					if(screen[max_y][max_x]=='+')++cont;
					++flag;
				}	
				
			}
			
			//Angolo: AltoDx
			if(x == max_x){
				while(flag <= 3){
					if(screen[y][max_x-1]=='+')++cont;
					if(screen[y][0]=='+')++cont;
					++flag;
					if(screen[y+1][max_x]=='+')++cont;
					if(screen[y+1][max_x-1]=='+')++cont;
					if(screen[y+1][0]=='+')++cont;
					++flag;
					if(screen[max_y][max_x]=='+')++cont;
					if(screen[max_y][max_x-1]=='+')++cont;
					if(screen[max_y][0]=='+')++cont;
					++flag;
				}	
				
			}
		}
		
		if(y == max_y){
		
			//Angolo: BassoSx
			if(x == 0){
				while(flag <= 3){
					if(screen[y][max_x]=='+')++cont;
					if(screen[y][1]=='+')++cont;
					++flag;
					if(screen[0][0]=='+')++cont;
					if(screen[0][1]=='+')++cont;
					if(screen[0][max_x]=='+')++cont;
					++flag;
					if(screen[max_y-1][0]=='+')++cont;
					if(screen[max_y-1][1]=='+')++cont;
					if(screen[max_y-1][max_x]=='+')++cont;
					++flag;
				}
			}
			
			//Angolo: BassoDx
			if(x==max_x){
				while(flag <= 3){
					if(screen[y][max_x-1]=='+')++cont;
					if(screen[y][0]=='+')++cont;
					++flag;
					if(screen[y-1][max_x]=='+')++cont;
					if(screen[y-1][max_x-1]=='+')++cont;
					if(screen[y-1][0]=='+')++cont;
					++flag;
					if(screen[0][max_x]=='+')++cont;
					if(screen[0][max_x-1]=='+')++cont;
					if(screen[0][0]=='+')++cont;
					++flag;
				}	
				
			}	
				
		}
		
	//Eccezioni per le righe estreme: matrice vista come una sfera
	
	//Riga 0
	if(y == 0){
		if(x != (0 & max_x)){
			while(flag <= 3){
					if(screen[y][x-1]=='+')++cont;
					if(screen[y][x+1]=='+')++cont;
					++flag;
					if(screen[max_y][x]=='+')++cont;
					if(screen[max_y][x-1]=='+')++cont;
					if(screen[max_y][x+1]=='+')++cont;
					++flag;
					if(screen[y+1][x]=='+')++cont;
					if(screen[y+1][x-1]=='+')++cont;
					if(screen[y+1][x+1]=='+')++cont;
					++flag;
			}		
		}
	}
	
	//Riga max_y
	if(y == max_y){
		if(x != (0 & max_x)){
			while(flag <= 3){
						if(screen[y][x-1]=='+')++cont;
						if(screen[y][x+1]=='+')++cont;
						++flag;
						if(screen[0][x]=='+')++cont;
						if(screen[0][x-1]=='+')++cont;
						if(screen[0][x+1]=='+')++cont;
						++flag;
						if(screen[y-1][x]=='+')++cont;
						if(screen[y-1][x-1]=='+')++cont;
						if(screen[y-1][x+1]=='+')++cont;
						++flag;
			}
		}
	}
	
	//Colonna 0
	if(x == 0){
		if(y != (0 & max_y)){
			while(flag <= 3){
					if(screen[y][max_x]=='+')++cont;
					if(screen[y][x+1]=='+')++cont;
					++flag;
					if(screen[y-1][max_x]=='+')++cont;
					if(screen[y-1][0]=='+')++cont;
					if(screen[y-1][1]=='+')++cont;
					++flag;
					if(screen[y+1][max_x]=='+')++cont;
					if(screen[y+1][0]=='+')++cont;
					if(screen[y+1][1]=='+')++cont;
					++flag;
			}
		}
	}
	
	
	//Colonna max_x
	if(x == max_x){
		if(y != (0 & max_y)){
			while(flag <= 3){
					if(screen[y][max_x-1]=='+')++cont;
					if(screen[y][0]=='+')++cont;
					++flag;
					if(screen[y-1][max_x]=='+')++cont;
					if(screen[y-1][max_x-1]=='+')++cont;
					if(screen[y-1][0]=='+')++cont;
					++flag;
					if(screen[y+1][max_x]=='+')++cont;
					if(screen[y+1][max_x-1]=='+')++cont;
					if(screen[y+1][0]=='+')++cont;
					++flag;
			}
		}
	}
	
	//Tutto il resto	
		for(i=y-1; i<y+2;++i){
			for(j=x-1; j<x+2; ++j){
				if(screen[i][j]=='+'){
					++cont;
				}
			}
		}

return cont;
}


int main(){
int x,y;

	printf("Inserisci i valori di Y (verticale) - MAX 30\n>");
	scanf("%d", &y);	
		while(y>Y){
			printf("Errore. Valore eccessivo. Reimmettere MAX 30\n> ");
			scanf("%d", &y);
		}
	printf("Inserisci i valori di X (orizzontale) - MAX 80\n>");
	scanf("%d", &x);
		while(x>X){
			printf("Errore. Valore eccessivo. Reimmettere MAX 80\n> ");
			scanf("%d", &x);
		}


	char newScreen[Y][X];

	char screen[Y][X]={
	"   +                                       ",
	"                                           ",
	"                              +            ",
	"                            + +            ",
	"               ++         ++             ++",
	"              +    +      ++             ++",
	"   ++        +       +    ++               ",
	"   ++        +    +  + +    + +            ",
	"             +       +        +            ",
	"              +    +                       ",
	"               ++                          ",
	};

/*
	char screen[Y][X]={
	"                                      ",
	"        +  +                          ",
	"       +                              ",
	"       +   +                          ",
	"       ++++                           ",
	"                                      ",
	"                                      ",
	};
*/

int a=-1;

while(a!=0){
printScreen(screen, x,y);
printf("Print Ok --------------------------------------------------------------------------------------\n");
epoch(newScreen, screen, x,y); 
printf("Epoch Ok ---------------------------------------------------------------------------------------\n");
copyScreen(screen, newScreen, x,y);
}

	
	
	

	
return 0;
}

aaa