Jump to content

Recommended Posts

Posted

Olá pessoal estou com um grande problema, preciso fazer com que meu programa em C execute duas funções ao mesmo tempo.

--> para ser mais específico estou criando um jogo de labirinto onde o personagem(um caractere) se movimenta sozinho tentando achar o caminho mais curto ate a saída percorrendo um labirinto(matriz de char), só que em determinado ponto eu quero duplicar este personagem para isso criei uma nova função de execução e preciso fazer com que ela seja executada ao mesmo tempo que o main fazendo assim meus personagens andarem por caminhos diferentes no meu labirinto.

Posted

o que pretendes é possível, mas não imaginas a quantidade de problemas que originam ao tentar resolver o problema através desse método.

o melhor seria apresentares o código que tens para apresentar uma segunda solução possível que passará por uma generalização do processo de decisão do movimento de uma personagem

IRC : sim, é algo que ainda existe >> #p@p
Posted

Aqui esta o código, fiz uns comentários para tentar explica-lo

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

int m,n,i,j;

float x,y,menor1,menor2,menorC=80,menorB=80,menorE=80,menorD=80;
//a variavel abaixo e o mapa do labirinto

char labirinto [20][32]={
'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1',
'@',' ','1','1','1',' ','1','1',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','1','1',
'1',' ','1','1','1',' ','1','1',' ','1','1','1',' ','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1',' ',' ','1',
'1',' ','1','1','1',' ',' ',' ',' ','1','1','1',' ',' ','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1',' ','1',
'1',' ','1','1','1','1','1','1','1','1','1','1',' ',' ','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1',' ','1',
'1',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','1','1',' ','1',
'1','1','1','1','1','1','1','1','1','1','1','1','1',' ','1','1','1','1','1',' ','1','1','1','1','1','1','1',' ','1','1',' ','1',
'1',' ','1','1','1','1','1','1','1','1','1','1','1',' ','1','1','1','1','1',' ',' ','1','1','1','1','1','1',' ','1','1',' ','1',
'1',' ',' ',' ',' ','1','1','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1',' ','1',
'1','1','1','1',' ','1','1','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1',' ','1',
'1','1','1','1',' ','1','1','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1',' ','1',
'1',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1',' ','1',
'1',' ','1','1','1','1','1','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1',' ','1',
'1',' ','1','1','1','1','1','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1',' ','1',
'1',' ','1','1','1','1','1','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ','1','1',' ','1',
'1',' ','1','1','1','1','1','1','1','1','1','1','1',' ','1','1','1','1','1','1',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','1',
'1',' ','1','1','1','1','1','1','1','1','1','1','1',' ','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1',' ','1',
'1',' ',' ',' ',' ',' ',' ',' ',' ',' ','1','1','1',' ','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1',' ','1',
'1','1','1','1','1','1','1','1','1',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','1','1','1',' ','1',
'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1',' ','1'};
_flushall();

void movimenta2(int m, int n);

int main()
{

m=1;
n=0;
//fiz uma rotina, onde só terminará o game quando encontrar a saída

float adj [20][32];
for(i=0;i<20;i++){
for(j=0;j<32;j++){
	 adj[i][j]=0;//zerando a matriz de adjacência
}//for interno
}//for externo


for(i=0;i<20;i++){
for(j=0;j<32;j++){
	if(labirinto[i][j]!='1'){
		adj[i][j]=((i+j)+2);
	}else if(labirinto[i][j]=='@'){//atribuindo os devidos valores a matriz de adajcência
		adj[i][j]=0;
	}   else{
			adj[i][j]=-1;
		}
}//for interno
}//for externo

while(1)
{
for(i=0;i<20;i++){
for(j=0;j<32;j++){
printf("%c",labirinto[i][j]);
}
printf("\n");

}
//Como fiz utilizando variaveis do tipo char, a cada comando do teclado
//preciso alterar o local novo e do antigo, se a condicao for aceita
//o corpo só se movera se o programa achar o ' ' (espaco).

if (adj[m+1][n]!= -1 && labirinto[m+1][n]!='1'){//se for possivel andar para baixo ele calcula a distância

x=adj[m][n];
y=adj[m+1][n];
menor1=y-x;

x=adj[m+1][n];
y=adj[19][30];
menor2=y-x;

menorB=menor2-menor1;
}

if ( adj[m-1][n]!= -1 && labirinto[m-1][n]!='1'){//se for possivel andar para cima ele calcula a distância

x=adj[m][n];
y=adj[m-1][n];
menor1=y-x;

x=adj[m-1][n];
y=adj[19][30];
menor2=y-x;

menorC=menor2-menor1;
}

if ( adj[m][n+1]!=-1 && labirinto[m][n+1]!='1') {//se for possivel andar para a direita ele calcula a distância

x=adj[m][n];
y=adj[m][n+1];
menor1=y-x;

x=adj[m][n+1];
y=adj[19][30];
menor2=y-x;

menorD=menor2-menor1;
}


if ( adj[m][n-1]!= -1 && labirinto[m][n-1]!='1' ) {//se for possivel andar para a esquerda ele calcula a distância


x=adj[m][n];
y=adj[m][n-1];
menor1=y-x;

x=adj[m][n-1];
y=adj[19][30];
menor2=y-x;

menorE=menor2-menor1;
}
//faz as devidas comparações a fim de decidir para onde vai ce movimentar

if(menorC<menorD&&menorC<menorB&&menorC<menorE){
m = m - 1;

if(labirinto[m][n] == ' '){
		labirinto [m][n]= '@';
		labirinto [m+1][n]=' ';
	}
}

if(menorD<menorC&&menorD<menorB&&menorD<menorE){
  n = n + 1;
if(labirinto[m][n] == ' '){
		labirinto [m][n]= '@';
		labirinto [m][n-1]=' ';
	}
}

if(menorE<menorC&&menorE<menorB&&menorE<menorD){
n = n - 1;
if(labirinto[m][n] == ' '){
		labirinto [m][n]= '@';
		labirinto [m][n+1]=' ';
	}
}

if(menorB<menorC&&menorB<menorE&&menorB<menorD){

m = m + 1;

if(labirinto[m][n] == ' '){
		labirinto [m][n]= '@';
		labirinto [m-1][n]=' ';
	}
}
/*Aqui esta um dos meus problemas, ha pontos em que a distancia é giual tanto para um lado quanto para o outro
então nesses if's digo que quando ele encontrar direita e baixo iguais opte pela direita e quando encontrar direita
e esquerda igualis opte pela direita por isso quero criar uma função para quando encontrar dois pontos mandar um caratere
por um lado e outro por outro lado.
*/

if(menorD==menorB){

movimenta2(m,n);

	m = m + 1;

	if(labirinto[m][n] == ' '&& adj[m][n]!= -1){
		labirinto [m][n]= '@';
		labirinto [m-1][n]=' ';
	}

}

if(menorD==menorE){

movimenta2(m,n);

n = n + 1;

if(labirinto[m][n] == ' '&& adj[m][n]!= -1){
		labirinto [m][n]= '@';
		labirinto [m][n-1]=' ';
	}

}

getch();


if(labirinto [19][30] == '@')//quando chega a saida acaba

break;

system("cls");

}

system("cls");
for(i=0;i<20;i++){
for(j=0;j<32;j++){
printf("%c",labirinto[i][j]);
}
printf("\n");

}

printf("PARABENS, VOCE CONSEGEUIU ESCAPAR!!!!!!!\n");

getch();

return 0;
}


/*a função e práticamente igual o código de cima mas muda as opções de movimento quando encontra distâncias iguais*/
void movimenta2(int m,int n){

//fiz uma rotina, onde só terminará o game quando encontrar a saída
float adj [20][32];
for(i=0;i<20;i++){
for(j=0;j<32;j++){
	 adj[i][j]=0;
}//for interno
}//for externo


for(i=0;i<20;i++){
for(j=0;j<32;j++){
	if(labirinto[i][j]!='1'){
		adj[i][j]=((i+j)+2);
	}else if(labirinto[i][j]=='@'){
		adj[i][j]=0;
	}   else{
			adj[i][j]=-1;
		}
}//for interno
}//for externo

while(1)
{
for(i=0;i<20;i++){
for(j=0;j<32;j++){
printf("%c",labirinto[i][j]);
}
printf("\n");

}

if (adj[m+1][n]!= -1 ){

x=adj[m][n];
y=adj[m+1][n];
menor1=y-x;

x=adj[m+1][n];
y=adj[19][13];
menor2=y-x;

menorB=menor2-menor1;
}

if ( adj[m-1][n]!= -1 ){

x=adj[m][n];
y=adj[m-1][n];
menor1=x-y;

x=adj[m-1][n];
y=adj[19][13];
menor2=y-x;

menorC=menor2-menor1;
}

if ( adj[m][n+1]!=-1 ) {

x=adj[m][n];
y=adj[m][n+1];
menor1=y-x;

x=adj[m][n+1];
y=adj[19][13];
menor2=y-x;

menorD=menor2-menor1;
}


if ( adj[m][n-1]!= -1 ) {


x=adj[m][n];
y=adj[m][n-1];
menor1=x-y;

x=adj[m][n-1];
y=adj[19][13];
menor2=y-x;

menorE=menor2-menor1;
}


if(menorC<menorD&&menorC<menorB&&menorC<menorE){
m = m - 1;

if(labirinto[m][n] == ' '){
		labirinto [m][n]= '@';
		labirinto [m+1][n]=' ';
	}
}

if(menorD<menorC&&menorD<menorB&&menorD<menorE){
  n = n + 1;
if(labirinto[m][n] == ' '){
		labirinto [m][n]= '@';
		labirinto [m][n-1]=' ';
	}
}

if(menorE<menorC&&menorE<menorB&&menorE<menorD){
n = n - 1;
if(labirinto[m][n] == ' '){
		labirinto [m][n]= '@';
		labirinto [m][n+1]=' ';
	}
}

if(menorB<menorC&&menorB<menorE&&menorB<menorD){

m = m + 1;

if(labirinto[m][n] == ' '){
		labirinto [m][n]= '@';
		labirinto [m-1][n]=' ';
	}
}


if(menorD==menorB){


	n=n+1;

	if(labirinto[m][n] == ' '&& adj[m][n]!= -1){
		labirinto [m][n]= '@';
		labirinto [n-1][n]=' ';
	}

}

if(menorD==menorE){

n = n - 1;

if(labirinto[m][n] == ' '&& adj[m][n]!= -1){
		labirinto [m][n]= '@';
		labirinto [m][n+1]=' ';
	}
}


getch();

if(labirinto [19][30] == '@')
break;
system("cls");

}

system("cls");
for(i=0;i<20;i++){
for(j=0;j<32;j++){
printf("%c",labirinto[i][j]);
}
printf("\n");

}


printf("PARABENS, VOCE CONSEGEUIU ESCAPAR!!!!!!!\n");

getch();
}

sim o calculo do movimento deve ser feito assim com base no algoritmo de busca "A*".

Posted

Usa libdispatch. Aquilo que dizem ser complexo passa a ser praticamente trivial.

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Posted (edited)

Rui estou sim tentando fazer uma busca, só que uma busca em um grafo,por isso no código uso a matriz de adjacência.

KTachyon, poderia falar um pouco mais sobre libdispatch ?

Edited by JJMUniz
Posted (edited)

KTachyon, poderia falar um pouco mais sobre libdispatch ?

Deverá ser fácil de interpretar

#import <dispatch/dispatch.h>

int main(int argc, const char * argv[])
{
   dispatch_group_t group = dispatch_group_create();
   dispatch_queue_t queue = dispatch_queue_create("qualquer coisa", DISPATCH_QUEUE_CONCURRENT);

   for (int i = 0; i < 5; i++)
       dispatch_group_async(group, queue, ^{ printf("hello world concorrente #%d\n", i); });

   dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

   printf("e foram felizes para sempre\n");

   return 0;
}

Só para facilitar, imagina que tens os dois procedimentos que queres executar em simultâneo ao chamares as funções func1 e func2:

#import <dispatch/dispatch.h>

int main(int argc, const char * argv[])
{
   dispatch_group_t group = dispatch_group_create();
   dispatch_queue_t queue = dispatch_queue_create("qualquer coisa", DISPATCH_QUEUE_CONCURRENT);

   dispatch_group_async(group, queue, ^{ func1(); });
   dispatch_group_async(group, queue, ^{ func2(); });

   dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

   printf("e foram felizes para sempre\n");

   return 0;
}
Edited by KTachyon

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Posted

Precisas de ter o libdispatch para o poderes importar e, se queres fazer uso de blocks (^{}), tens que utilizar um compilador que os suporte, como o Clang.

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Posted

@KTachyon

Por muito tentadora que me pareça essa lib, é algo que vem do IOS, e embora exista um port para Linux, não sei até que ponto eu me atiraria para algo nesse estado, visto que nem sequer posso utilizar o gcc. Além disso, o que faz nesse exemplo base não é complicado de implementar usando as threads por meios mais normais. Acredito que tenha outras potencialidades, mas para algo tão simples eu não me daria ao trabalho de mudar de compilador.

Se pode ser feito sem recurso a paralelismo, ainda melhor.

Posted

É open source (e os blocks são uma extensão do C). Não vem do iOS, mas sim do Mac OS X. Segundo o que sei, está integrada no FreeBSD. Já tem uns 6 anos, e antes de criticares por "ser Apple", agradecia que fosses ler um pouco mais sobre o assunto.

O problema com gestão de threads é ser pesada. Isso é um problema que o pessoal normalmente resolve com thread pools, mas o problema é que a criação das thread pools depende dos recursos do sistema. Se tiveres uma thread pool demasiado pequena não consegues aproveitar os recursos do sistema, se tiveres uma thread pool demasiado grande, perdes performance com mudanças de contexto. Para além disso, tens que conseguir gerir o código que vais executar em cada uma das threads. Não há uma forma de simplesmente despejares código para uma thread específica e esperar que ela execute.

Com libdispatch não precisas de saber quantas threads tens disponíveis, podes despejar o código que queres, quando queres, em runtime. O sistema escala para os recursos do sistema que estão disponíveis e é extremamente leve. Para além disso, em muitos casos em que precisarias de utilizar locks e semáforos para gerir a utilização concorrente de recursos, com GCD consegues gerir os acessos sem a necessidade de locks, forçando os acessos sequenciais ao recurso num getter/setter.

Isto é apenas um peek. Existem muito mais funcionalidades que tornam a libdispatch a framework ideal para gerir concorrência.

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Posted (edited)

O meu problema com isso não é ser Apple, é não ser POSIX. O grande problema dos ports é a falta de compatibilidade com muitas plataformas. Falas em FreeBSD, e o as grandes distribuições Linux?

Pelo que vi pela net, vejo grandes potencialidades à biblioteca, mas em todo o lado (Excepto Apple) me parece mais um Workinprogress do que propriamente um produto terminado. E posso-te desde já dar mais uma razão. Se vejo problemas em compilar isso para uma qualquer distro Linux, imagino agora para um arm, onde normalmente pouco mais tenho do que uma toolchain com o gcc.

No entanto reconheço que possivelmente a minha realidade me levou a torcer o nariz ao uso da Lib, depois da primeira pesquisa (inicialmente até fiquei empolgado pois parece-me bastante útil). Além do mais parti do princípio que seria para usar Linux, quando no tópico não existe nenhuma alusão a esse facto. Existem ports para Windows, mas, mais uma vez, me parece mais um Workinprogress do que algo terminado.

Por estas dificuldades e interrogações todas, dificilmente usaria essa solução para resolver algo bem mais simples como este problema.

Edited by Flinger
Posted

A sugestão é não utilizares concorrência, se bem que penso que ainda não deu para perceber exactamente o que pretendes fazer. Eu começava por limpar o código, uma vez que tens aí uma série de repetições de código que deviam estar encapsuladas em funções.

Em resposta ao Flinger:

- A libdispatch não é un work in progress. A API tem é crescido.

- A instalação em Linux é tão simples como apt-get install libdispatch-dev

- Estranhamente, tenho andado a compilar para ARM com o Clang...

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Posted

Em resposta ao Flinger:

- A libdispatch não é un work in progress. A API tem é crescido.

- A instalação em Linux é tão simples como apt-get install libdispatch-dev

- Estranhamente, tenho andado a compilar para ARM com o Clang...

Então, se assim é, só me resta retirar o que disse. Não foi essa a ideia com que fiquei ao fazer uma pesquisa rápida pela net.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.