Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

Miketo

Criação de Matriz com tamanho variavel

Mensagens Recomendadas

Miketo

Boas pessoal.

A minha duvida penso que é algo muito básico, mas como já não utilizo C++ há um tempinho tou um bocado enferrujado, e com uns vícios de outras linguagens, pelo que peço que me dêem umas dicas para eu desenferrujar e começar a programar que nem um louco  :D

Ora, o que eu tenho de fazer é o jogo da memória, bastante simples, sem aplicar openGl nem nada. Apenas e so com os caracteres e a consola.

Pensei em fazer três níveis para o jogo, fácil, médio e difícil, em que para cada nível, vai variar o tamanha do tabuleiro (matriz), que será 4x4, 6x6 e 8x8.

Comecei por criar um menu em que o utilizador escolhe se quer jogar, ver os records ou escolher o nível.

Quando escolhe a opção nível, chama uma função que pede ao utilizador que escolha a opção 1,2 ou 3, relativa ao nível que quer. Muito simples até aqui.

Eu criei o seguinte ciclo que tem a ver com o menu inicial:

switch (op){
	case 1:{// Jogar
		break;
	}
	case 2:{ // Nivel
		niv=nivel();
		break;
	}
	case 3:{// Records
		break;
	}
	case 4:{// Sair
		break;
	}
	default:// Nao faz nada
	break;
};
}

A variável niv esta inicializada logo no inicio do programa.

Se a opçao for o nivel, neste caso a opção 2, o que eu quero que o programa faça é que chame a função nivel e coloque em niv o valor deste.

A funcao nivel é a seguinte:

int nivel(){

int n;

cout << "Escolha o nivel de jogo:" << endl;
cout << "1 - Facil" << endl << "2 - Medio" << endl << "3 - Dificil" << endl;
cin >> n;

return n;
}

Até aqui corre tudo bem.

Agora quando quero criar a matriz relativa a cada nível que me surgiram os problemas.

Criei a seguinte função, que recebe o valor do nível, e de acordo com esse valor, gera uma matriz com as dimensões geradas. Mas quando compilo da erro.

int tabuleiro(int niv){

int dim=0; // dimensoes do tabuleiro 

switch (niv){
	case 1:{
		dim=4;
		break;
	}
	case 2:{
		dim=6;
		break;
	}
	case 3:{
		dim=8;
		break;
	}
	default:
	break;
};
int tab[dim][dim];

return tab;

}

O erro que da, penso que tem a ver com o tipo de variável int e o int da matriz :-[

Podem ajudar-me a fazer a função como deve ser?

Agradecia imenso.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
TheDark

Em C++ só podes declarar arrays com dimensões conhecidas em tempo de compilação. Para o que pretendes, ou utilizas 3 arrays diferentes com os tamanhos que pretendes (desaconselhado), ou crias os arrays dinamicamente.

Algo assim:

int **tab = new int*[dim];
for (int i = 0; i< dim; ++i) { tab[i] = new int[dim]; }

No final, não te esqueças de libertar a memória!

Tens aí outros problemas:

- a função tabuleiro devolve int, e estás a tentar devolver um array de int de duas dimensões. Por si isto já é um problema que impede a compilação. Com a modificação que sugeri, a função terá que retornar int**;

- o que acontece se na função nivel o utilizador inserir 10? Ou 'a'?


Desaparecido.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Miketo

Obrigado pela sugestão, mas tenho uma dúvida.

Com o código que sugeriste, não vou criar um vector unidimensional em vez de uma matriz quadrada?

Quanto à pergunta que fizeste, eu ainda nao introduzi protecções no código. O que irei fazer é criar um ciclo que caso o jogador introduzir uma opção diferente vai repetir a questão até o utilizador introduzir a correcta ou escolher sair(opção que tb ainda não implementei).

Mas primeiro quero meter as funções a funcionar bem. Depois as protecções sao simples de introduzir.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Baderous

Obrigado pela sugestão, mas tenho uma dúvida.

Com o código que sugeriste, não vou criar um vector unidimensional em vez de uma matriz quadrada?

Na 1ª instrução é criado um vector unidimensional de apontadores para inteiros. Depois na 2ª instrução é percorrido esse vector e, para cada apontador, é criado um vector unidimensional, pelo que no fim ficarás com um vector de vectores, ou seja, uma matriz.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Miketo

:wallbash: baaah.. ca buuuurro...

Gera uma matriz sim senhor. É da falta de prática  :thumbsup:

E assim a função já não dá erro.

Muito obrigado.

Vou continuar a fazer o jogo. Se tiver mais dúvidas volto a perguntar  :P

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Miketo

Ok... a criação da matriz funciona e tudo muito bem.

Agora vem outro problema...

Quero introduzir valores na matriz... neste caso vou começar por inteiros.

Para tal, criei um (neste casos dois, um dentro do outro) ciclo for, para ir metendo em casa indice da matriz, um valor.

O que acontece é que o compilador compila bem, sem qualquer erro, e depois ao executar, quando entra no ciclo, da um erro "Segmentation Fault".

Pesquisei e vi que tem a ver com a alocação de memoria.

Mas se eu defini a matriz com uma determinada dimensão, não seria suposto já ter esse problema resolvido?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
merlin3000

Mostra o código onde estás a fazer a alocação e os ciclos se poderes, torna-se mais fácil de saber onde está o erro.

Mas já agora vê se nenhum dos ciclos está a ultapassar o tamanho dos vectores.


Criar é Divertido

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Miketo

Fica aqui o código. Espero que me possam ajudar, que sinceramente não consegui descobrir o erro, e nao quero ter de optar pela opção de criar 3 matrizes, uma para cada opção... queria algo mais "evoluído".

Penso que nenhum dos ciclos sai do tamanho dos vectores, ate porque estão definidos exactamente como o ciclo que aloca a memória....

E não liguem a variáveis tipo simb e assim... são variáveis de controlo que uso para ver como o programa corre e que serão usadas para coisas que ainda não implementei.

int** tabuleiro(int niv){

int dim=0; // dimensoes do tabuleiro 
int simb;

switch (niv){
	case 1:{
		dim=4;
		break;
	}
	case 2:{
		dim=6;
		break;
	}
	case 3:{
		dim=8;
		break;
	}
	default:
	break;
};

int **tab = new int*[dim];
for (int i=0; i< dim; ++i){ 
	tab[i] = new int[dim];
};

/* initialize random seed: */
srand ( time(NULL) );

simb= (dim*dim)/2; // pares

cout << simb << endl;

// É neste ciclo que dá erro, pois sem ele o programa corre sem problemas
for (int i=0; i<dim ; ++i){
	for(int j=0; i<dim; ++j){

		tab[i][j]= 1; // 1 é um exemplo que dá erro, 
		//mas a ideia é usar o rand para criar numeros aleatorios

	}
}
for (int i=0; i<dim ; ++i){
	for(int j=0; i<dim; ++j){
		cout << tab[i][j] << " ";
	}
                cout << endl;
}

return tab;
}

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Miketo

Realmente isso estava mal sim. Mas após corrigir esse erro, continua a dar a mesma coisa... segmentation error.... Não consigo entender...

Eu penso que tem a ver com o facto de usar ponteiros e já não estar muito lembrado de como se usam correctamente... mas eu aqui até coloquei a introdução de valores na matriz e a sua impressão no ecrã dentro da função para ver se era disso, e dá erro na mesma... por isso sinceramente... não tou a ver  :thumbsup:

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
merlin3000

ok acabei de fazer um teste rápido e isso funciona. De certeza que alteras-te o i para j nos dois for's? É que tens isso mal tanto na atribuição do valor 1 e na impressão para o ecrã.


Criar é Divertido

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Miketo

Funciona?

Fogo... Ok... eu vou tentar fazer isso isolado ... pode ser que seja algo que tenha no resto do código que esteja a fazer conflito. Já agora ajuda-me numa coisa... para depois usar a matriz fora da funcao... como é que a tenho de definir? é int **tab por exemplo?

Nao fujas que vou ja ja testar  :thumbsup:

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Miketo

Ok... fiz um ficheiro novo só com esta função e correu bem.

Até experimentei em criar uma variável no main que recebe a matriz e depois a imprimir no ecrã e da tudo bem....

Mas no programa que tinha feito nao da. Da sempre aquele erro...Será que tem algo a ver com nao libertar memoria?

É so preciso usar o delete tab né? Meto isso dentro da funcao ou no main?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Miketo

E agora por teimosia voltei a experimentar no programa antigo e já dá... Eu reiniciei o Geany... não sei se foi disso ou não  :-[

No entanto mantenho a pergunta de libertar memória.. convém fazer isso né? Onde ponho o delete?

Obrigado pela ajuda. Já me desenrascaram bastante  :)

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
falk0n
É so preciso usar o delete tab né? Meto isso dentro da funcao ou no main?

Deves fazer delete a cada posição do array uma vez que é um array bidimensional; e depois delete ao tab

Boas programações

Nuno Martins

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
TheDark

Pensa assim: para todo e cada new que fazes, tem que existir algures um delete correspondente, e para todo e cada new[] que fazes, tem que existir algures um delete[] correspondente.


Desaparecido.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Miketo

Sim. Compreendi. E até já tenho o jogo a funcionar!  :)

Só me falta arranjar uma maneira de ordenar o Top 10 ... mas já tenho isto a bombar.

De momento só tenho um problema.

Eu fiz o jogo no ubuntu, e agora queria verificar se funciona no windows tambem, mas não sei que programa usar no windows. O visual studio é uma caca que dá-me erros por tudo e por nada. Experimentei o Dev C++. Têm algum conselho ?

Já agora, gostaria de partilhar o código que fiz com o pessoal aqui do fórum, para poder ajudar alguém e para caso alguém mais experiente que eu vir algo que possa ser melhorado me possa ajudar, mas o código está dividido em main e num file.h. Como o partilho aqui?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.