Problema de compliçao em C, array bidimensional - C - Portugal-a-Programar
Problema de compliçao em C, array bidimensional
By _SirO_,
May 3, 2006 in C
Boas! estou com um problema numa funçao, obtenho o erro de compilaçao "invalid use of array with unspecified bounds", o que eu pretendia na funçao era inicializar uma matriz com um espaço em cada posiçao....
char jogo[3][3];
inicializa_jogo(jogo);
while(N!=9)
escreve_tabuleiro(jogo);
jogada_pess(jogo,&N);
jogada_pc(jogo,&N);
void inicializa_jogo(char jogo[][])
{    int i,j;
jogo[i][j]=' ';
EDIT: Usa a ferramenta GeSHi, assim o código fica mais legível
O teu problema é que não podes definir um função como definiste, ou seja, com char jogo[][] como parametro. Como noutros posts, já não me lembro muito de C, mas sugiro o seguinte :
void inicializa_jogo (char * jogo)
memset (jogo, ' ', 3*3*sizeof(char));
Isto irá limpar o array e colocar o espaço em todas as posições. A chamada a esta função é exactamente a mesma como tens inicializa_jogo(jogo).
Um array do estilo char xpto[9][10] faz com que a variavel xpto seja um ponteiro para o inicio do array que declaraste. Ou seja, no limite, se quisesses fazer as coisas à mão, podias navegar pelo array da seguinte forma;
for (int i = 0; i < 9; i+=3*sizeof(char))
char* elemento = xpto + i;
e em cada iteração, estarias a aceder à posição 0, 1 e 2 do array de chars que criaste.
Expliquem-me como deve de ser ? Se não, digam qualquer coisa que tento melhor.
obrigado por essa funçao memset, nao conhecia, mas esta funçao
também nao pode ser definida assim.... penso eu, é que sendo o array bidimensional, penso que nao podemos aceder aos endereços de memoria assim tao facilmente.... quer dizer, imaginando que pretendo a posiçao [1][2], como é que faço, em aritmetica de ponteiros?
Btw, ja descobri porque e que nao compilava, o erro estava onde disseste, tinha que indicar tambem as dimensoes do array.
void inicializa_jogo(char jogo[3][3])
Podes aceder da forma que disse, porque quando tu crias o array bidimensional, ele aloca-te o espaço em memória consecutivamente.
Se quiseres, nunca fiz isto, mas se olhares para o assembler que é gerado para aceder a uma posição, por exemplo [1][2] do array, vais ver que ele irá fazer a aritmética simples, de 1*tamanho do array(neste caso 3) + 2.
O C alloca-te a memória consecutiva, senão tinha que manter uma tabela de endereço para saber onde estava cada elemento do array, o que é contra-produtivo, lento e ocupa mais espaço que o array em si.
no topo do programa, defines algo do tipo:
typedef int MATRIZ[3][3];
no teu código,ficaria:
inicializa_jogo(m);
escreve_tabuleiro(m);
jogada_pess(m,&N);
jogada_pc(m,&N);
void inicializa_jogo(MATRIZ m)
m[i][j]=' ';
ps: fiz isto à pressa, apenas alterei o óbvio.
utilizando assim a matriz, funciona.
experimenta 😄
Ok, obrigado pelo esclarecimento, isto de compreender bem, ponteiros/etc, é uma grande ajuda.
Já acabei um programa, o jogo do galo, está porreiro por acaso, mas agora tenho um problema, nunca consigo ganhar.... :S
Bem, acho que é sinal que está bem feito....
@ untouchables
Por acaso também me ocorreu fazer uma coisa dessas.... mas só sabia fazer em Pascal, em C ainda sou muito tenrinho.... 😄
lol não consegues ganhar? então está muito bem feito 😄 não tens executável, para o pessoal ver como ficou?
http://www.leirifotec.com/galo.exe (19KB)
e o código também
http://www.leirifotec.com/galo.c
bem, não consegui ganhar, mas também não perdi nenhuma vez 😄 está engraçado, parabéns!
Acho que devias acrescentar a opção de jogar novamente ao código-fonte.
Tambem joguei três vezes, não ganhei mas tambem não perdi. 😄
Bem vindo ao forum _SirO_
Só agora ví o tópico. Vou te dar uns conselhos.
Não é boa política usar variáveis globais (eu sou alérgico a isso ). Deve-se sempre evitar, só em situações extremas é que se deve usar.
O teu problema podia ser resolvido de duas maneiras.
Pegando no teu código, como passar uma variável Matriz[N][M]?
Bem, para quem não sabe isto é um array de N vectores de dimensão M. E vectores são apontadores para uma memória pré-reservada.
Quando tens arrays de arrays, isto quer dizer que tens apontadores de apontadores. Neste momento vocês devem ter ficado confusos ou não.
Isto é complicado de explicar para quem não percebe que um array/vector é um apontador. Mas quando acedes a Matriz[2][3] o que acontece é isto:
1.º - Vais à variável Matriz buscar o valor do endereço para onde está a apontar {por exemplo a posição 2451 (n.º fictício)}
2.º - Incrementas 2 unidades para chegares à posição Martiz[2] { neste momento estás apontar para a posição 2453}
3.º - Nessa posição está outro endereço de memória (o 2.º apontador) { por exemplo 6215}
4.º - Incrementas 3 unidades e tens o endereço de memória da Matriz[2][3]
Confuso? Tanto trabalho que o compilador tem de fazer só para termos isto Matriz[N][M]!
Pois é, como o meu professor disse: A memória é linear, não existe matrizes de memórias!
Por isso é que nenhum programador com um determinado grau ou qualificação faz isso do Matriz[N][M].
Depois do sermão fica o modo de resolução. Como Matriz[N][M] é um apontador de apontadores, então fica do seguinte modo:
void teste(char **Matriz)
char Matriz[3][3];
teste(Matriz);
Na boa política é fazeres isto assim:
char Matriz[3*3];
Depois para acederes à linha X e coluna Y, fazes assim:
Matriz[Y + X * numero de colunas]
Depois vou verificar o IA do teu programa e comento. 😄
O programa tem um bug!! LOL
Estava eu preste a ganhar logo à primeira jogada quando ele substituiu o meu X por um O. LOL
Assim não vale, isso é batota!
Deixo aqui a sequência das minhas jogadas:
eu: 1,3
PC: 2,2
eu: 3,3
PC: 1,3
eu: 3,1
PC: 2,1
eu: 3,2 (sepostamente a jogada da vitória)
PC: 3,3 ? ??????
Nota: Conheço todos os segredos do jogo do Galo (são poucos), porque já fiz um programa de IA do jogo do galo, onde estudei todas as jogadas!
brink@ero essas combinações não funcionam comigo... o PC não chega a substituir o caracter.
reparei num "defeito"... o pc está mais preocupado com o facto de eu nao ganhar do que ele ganhar. exemplo:
1,3 (neste momento ele ja tem 2 elementos seuigos, mas nao vou fazer com que ele nao ganhe)
3,1(neste momento, ele podia ter ganho, mas tapou a minha jogada)
só nofim disto é que ele irá ganhar, não aproveita a situação à primeira...
no fim destas 3 jogadas, se ainda fizer "3,2", ele ainda não vai acabar o jogo
lol isto esta feito um bocado à pedreiro, tens razao, tenho que alterar a IA para o gajo dar prioridade a ganhar, em vez de dar prioridade a nao deixar ganhar.
Quanto á questao de ponteiro de ponteiro, eu sabia isso, apenas nao tenho pratica e portanto fiz como sabia
No que diz respeito a variavel global, ela nao e bem global ou é? quer dizer, ela esta declarada em cada cabeçalho de cada funçao, apenas resolvi manter o nome, mas podia ter alterado para outro.....
O que sugeres? que cada funçao retorne um valor que por sua vez vai ser usado em vez de ter tantas funçoes void?
EDIT: fazendo a modificação de
void escreve_tabuleiro(char jogo[3][3]); para void escreve_tabuleiro(char **jogo);
compila, com avisos, "incompatible pointer tipe" e assim que tento correr dá erro.... 😄
EDIT 2: AI revista. está mais lixado 😄
Mais um "grande" update....
http://www.leirifotec.com/galo.exe
Um dia destes comercializo isto....
Qual ânsia pelo Windows Vista qual quê, o pessoal está é todo à espera da ultima versao do meu jogo do galo.... ?
Quanto á questao de ponteiro de ponteiro, eu sabia isso, apenas nao tenho pratica e portanto fiz como sabia 😄
EDIT 2: AI revista. está mais lixado
Não, eu comentei aquilo antes de ver o código. Não tens nenhuma variável global.
Sobre o erro, não sei. Foi compilar o teu código no VC++.
Deu-me um erro:
error C2065: 'memset' : undeclared identifier
Fui a net e ví isto:
fonte: http://www.opengroup.org/onlinepubs/007908799/xsh/memset.html
Depois compilou sem nenhum erro.
O VC++ não aceita isto, à tarde tento isso no linux. Mas tenho quase a certeza que dava assim. Agora estou confuso 😄
Sobre a nova versão, já corrigiste o erro 😁
Mas mesmo assim consigo vencer :P :P
Já experimentei no linux ?
Erro meu, afinal ele não aceita char **matriz, para uma inicialização matriz[3][3]. Confundi com outra inicialização em que construia matrizes com memória dinâmica.
Nessa situação fazia isto: char ** matriz na inicialização, depois é que reservava o espaço. Erro meu