Jump to content

Recommended Posts

Posted

Boas...

Estou aqui a tentar adaptar uma função para o que pretendo fazer, mas não consigo resolver uma parte.

A função verifica o tabuleiro do jogo do galo a ver se existe algum dos caracteres , X ou O, dispostos de forma a fazer os 3 em linha!

Como aloquei memória para a matriz usando a forma matrix[y + x * w], em que w é o número de colunas, estou a ter dificuldades em detectar vitória quando estão os caracteres dispostos na vertical.

Para o caso dos caracteres na horizontal, tenho o seguinte:

if(ptabuleiro[i * 11 + 1] != '_' &&
	ptabuleiro[i * 11 + 1] == ptabuleiro[i * 11 + DOIS] &&
	ptabuleiro[i * 11 + 1] == ptabuleiro[i * 11 + TRES]){
   printf("Mark 1\n");
   return ptabuleiro[i * 11 + 1] == psim ? -1 : 1;
}

O DOIS e o TRES é apenas para dizer que na verdade o 2 tem que ser um 5 e o TRES tem que ser um 9, porque a matriz não é 3 * 3 mas sim 3 * 12.

Isto porque eu quero que o desenho da matriz seja assim:

_01_|_05_|_09_

_12_|_16_|_20_

_23_|_27_|_31_

E portanto quando o jogador insere 2 para o X, na verdade na matriz será um 5. E quando o jogador insere um 3, na verdade é um 9!

Agora, não consigo fazer a verificação para as linhas verticais! Como hei-de fazer?

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Posted

estás a misturar dados com apresentação
o que quero dizer é que é má implementação usar a matriz dessa forma somente devido à apresentação, porque nao é da responsabilidade dela saber como vais apresentar-la

no entanto, se pretendes então ter assim, o que deverias fazer seria:

#define MATRIX_SCANLINE 11
#define MATRIX_OFFSETS(col) (col == 0 ? 1 : (col == 1 ? 5 : 9))
#define MATRIX_CELL(m, x, y) (& (m)[(y) * MATRIX_SCANLINE + MATRIX_OFFSETS(x)])

int checkHorizontal(char * matrix) {
    return    MATRIX_CELL(matrix, 0, 0) == MATRIX_CELL(matrix, 1, 0) == MATRIX_CELL(matrix, 2, 0)
           || MATRIX_CELL(matrix, 0, 1) == MATRIX_CELL(matrix, 1, 1) == MATRIX_CELL(matrix, 2, 1)
           || MATRIX_CELL(matrix, 0, 2) == MATRIX_CELL(matrix, 1, 2) == MATRIX_CELL(matrix, 2, 2);
}

int checkVertical(char * matrix) {
    return    MATRIX_CELL(matrix, 0, 0) == MATRIX_CELL(matrix, 0, 1) == MATRIX_CELL(matrix, 0, 2)
           || MATRIX_CELL(matrix, 1, 0) == MATRIX_CELL(matrix, 1, 1) == MATRIX_CELL(matrix, 1, 2)
           || MATRIX_CELL(matrix, 2, 0) == MATRIX_CELL(matrix, 2, 1) == MATRIX_CELL(matrix, 2, 2);
}

int checkDiagonals(char * matrix) {
    return    MATRIX_CELL(matrix, 0, 0) == MATRIX_CELL(matrix, 1, 1) == MATRIX_CELL(matrix, 2, 2)
           || MATRIX_CELL(matrix, 2, 0) == MATRIX_CELL(matrix, 1, 1) == MATRIX_CELL(matrix, 0, 2);
}

int checkWin(char * matrix) {
    return    checkHorizontal(matrix)
           || checkVertical(matrix)
           || checkDiagonals(matrix);
}
  • Vote 1
IRC : sim, é algo que ainda existe >> #p@p
Posted (edited)
1 hora atrás, PsySc0rpi0n disse:

E sem aqueles defines esquisitos?

Os "defines esquisitos" são macros e são uma parte importante da linguagem C. Podes passá-los a funções.

Edited by thoga31
Correcção do erro ortográfico

Knowledge is free!

Posted
13 hours ago, thoga31 said:

Os "defines esquisitos" são macros e são uma parte importante da linguagem C. Podes passá-los a funções.

Sim, eu sei que são macros, para para mim não é fácil entendê-las! Até porque para usar isto agora desta maneira, tinha que alterar o meu código todo!

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Posted (edited)

Equivalem a um if -> else

#define MATRIX_OFFSETS(col) (col == 0 ? 1 : (col == 1 ? 5 : 9))

se col == 0 entao 1 senao

se col == 1 entao 5 senao 9

podes transformar isto numa função, int matrix_offsets(int col), que te devolve o índice da matriz onde tens o valor. 

Mas concordo com o Hippo, nem devias usar isso assim. É sempre desejável separar o mais possível a funcionalidade da interface.

Edited by Flinger
Posted (edited)

😄 tinha-me passado despercebida 

#define MATRIX_CELL(m, x, y) (& (m)[(y) * MATRIX_SCANLINE + MATRIX_OFFSETS(x)])

aqui acedes directamente à posição da matriz.

Uma matriz não passa de um array, onde gravas cada linha a seguir à outra. Ora se tens uma matriz X por Y, para aceder à posição [1][0] andas X posições para a frente. Neste caso, MATRIX_SCANLINE posições.

Para acederes à posição [1][1] andas MATRIX_SCANLINE posições + 1. para aceder à posição [2] [1] acedes ao elemento [MATRIX_SCANLINE * 2 +1], etc.

 Expandindo a macro, com MATRIX_CELL(matrix, 2, 2) ficas com 

(& (matrix)[(2) * MATRIX_SCANLINE + MATRIX_OFFSETS(2)]), 

(& (matrix)[(2) * 11 + 9]), 

o que é equivalente a matrix[2][9]

Edited by Flinger
  • Vote 1
Posted
Em 27/09/2016 às 14:37, Flinger disse:

Não corri o código mas parece-me que como está estás a comparar apontadores e não os valores.

sim, é isso, se bem que a remoção do & retira a funcinoalidade de atribuição de um valor ao resultado da macro function

tenho uma solução engraçada (que até acho já ter demonstrado num tópico semelhante à uns anos) mas tinha renitência em apresentar-la por ser ainda mais complexa,que resolve ainda outro bug

mas aqui vai :

#define SPACE   ' '
#define PLAYER1 'O'
#define PLAYER2 'X'
 
#define SCANLINE 11
#define OFFSETS(col) (col == 0 ? 1 : (col == 1 ? 5 : 9))
#define CELL(m, x, y) ((m)[(y) * SCANLINE + OFFSETS(x)])

int checkHorizontal(char * m) {
    return    ((CELL(m, 0, 0) + CELL(m, 1, 0) + CELL(m, 2, 0) == CELL(m, 0, 0) * 3) && (CELL(m, 0, 0) != SPACE))
           || ((CELL(m, 0, 1) + CELL(m, 1, 1) + CELL(m, 2, 1) == CELL(m, 0, 1) * 3) && (CELL(m, 0, 1) != SPACE))
           || ((CELL(m, 0, 2) + CELL(m, 1, 2) + CELL(m, 2, 2) == CELL(m, 0, 2) * 3) && (CELL(m, 0, 2) != SPACE));
}

int checkVertical(char * m) {
    return    ((CELL(m, 0, 0) + CELL(m, 0, 1) + CELL(m, 0, 2) == CELL(m, 0, 0) * 3) && (CELL(m, 0, 0) != SPACE))
           || ((CELL(m, 1, 0) + CELL(m, 1, 1) + CELL(m, 1, 2) == CELL(m, 1, 0) * 3) && (CELL(m, 1, 0) != SPACE))
           || ((CELL(m, 2, 0) + CELL(m, 2, 1) + CELL(m, 2, 2) == CELL(m, 2, 0) * 3) && (CELL(m, 2, 0) != SPACE));
}

int checkDiagonals(char * m) {
    return    ((CELL(m, 0, 0) + CELL(m, 1, 1) + CELL(m, 2, 2) == CELL(m, 0, 0) * 3) && (CELL(m, 0, 0) != SPACE))
           || ((CELL(m, 2, 0) + CELL(m, 1, 1) + CELL(m, 0, 2) == CELL(m, 0, 0) * 3) && (CELL(m, 2, 0) != SPACE));
}

int checkWin(char * m) {
    return    checkHorizontal(m)
           || checkVertical(m)
           || checkDiagonals(m);
}

int validCheck() {
  return    PLAYER1 != PLAYER2 + SPACE
         && PLAYER2 != PLAYER1 + SPACE;
}

int main(void) {
  char m[SCANLINE * 3];
  memset(m, ' ', SCANLINE * 3);

  if (!validCheck()) {
    printf("invalid check code for the selected tokens");
  }

  return 0;
}
  • Vote 1
IRC : sim, é algo que ainda existe >> #p@p
Posted (edited)

I love your way of coding :]

Porque é que o array vai de index 4 a 4? Têm a ver com algum problema que envolva conversões de array de chars para array de inteiros e vice-versa?

Acrescento isto na função validCheck:

bool validCheck() {
  for(int i = 0; i < 3; i++)
  {
  	if(PLAYER1 == PLAYER2 * i + SPACE * (2 - i)
    || PLAYER2 == PLAYER1 * i + SPACE * (2 - i))return false;
  }
  return true;
}
Edited by seuqram
Posted

Isso é tudo muito lindo, mas não me estou a ver a alterar o que já tenho para incluir isto tudo!

Queria mesmo era usar a forma como eu estava a fazer originalmente para poder continuar com o que tenho! Senão assim, já sei que a coisa morre por aqui!

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Posted (edited)

Não conseguiste com o código do Hippo? É só substituíres as macros pela tua estrutura. partindo do princípio que também definiste "UM" como 1, para manter a coerência

int checkVertical(char * matrix) {
    return    pTabuleiro[0 * 12 + UM] == pTabuleiro[1 * 12 + UM] == pTabuleiro[2 * 12 + UM] != '_'
           || pTabuleiro[0 * 12 + DOIS] == pTabuleiro[1 * 12 + DOIS] == pTabuleiro[2 * 12 + DOIS] != '_'
           || pTabuleiro[0 * 12 + TRES] == pTabuleiro[1 * 12 + TRES] == pTabuleiro[2 * 12 + TRES] != '_'
}
Edited by Flinger
Adicionada verificação se não estão em branco
Posted (edited)

Ok, mas e porquê 12??? Eu tenho usado 11. Não percebi bem o 12. E com esse código, o loop que ue tenho não faz sentido. Mas preciso dele para as horizontais, certo?

Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Posted (edited)

Desculpa é 11... Fiz de cabeça, pareceu-me que tinha visto que o comprimento da linha era 12.

Para a horizontal podes fazer igual a este, mas fixando a linha. Não faz muito sentido fazeres um loop para 3 posições, até porque o compilador vai provavelmente optimizar o código retirando o loop.

Edited by Flinger
Posted

E ainda outro pormenor. Isso vai retornar 0 ou 1. No entanto eu estava a devovler o -1 e o 1 que usava para identificar o jogador e devolvia 0 para o caso de empate e devolvia -2 caso ainda houvesse posições vazias!

Com esse código terei que reformular a função para manter as mesmas funcionalidades.

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Posted (edited)

ou então refazes estas funções, como:

int checkVertical(char * matrix) {
    int res=    pTabuleiro[0 * 12 + UM] == pTabuleiro[1 * 12 + UM] == pTabuleiro[2 * 12 + UM] != '_'
           || pTabuleiro[0 * 12 + DOIS] == pTabuleiro[1 * 12 + DOIS] == pTabuleiro[2 * 12 + DOIS] != '_'
           || pTabuleiro[0 * 12 + TRES] == pTabuleiro[1 * 12 + TRES] == pTabuleiro[2 * 12 + TRES] != '_'
	
	if (!res) return -1;
	else return 1;

}
Edited by Flinger
Posted

Ok, vou ver se consigo pôr isso a funcionar! Mas só depois de fazer um trabalho que aqui tenho! Sim, eu estou no meu trabalho! E fazer um programa par ajogar o ic tac toe não é o meu trabalho! xD

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Posted (edited)

prontos ... se tens esses requisitos todos:

int checkHorizontal(char * m) {
    // para todas as linhas
    for (int line = 1; line < 3; ++line) {
        // verificar linha "line"
        if (   pTabuleiro[line * 11 + UM] == pTabuleiro[line * 11 + DOIS]
            && pTabuleiro[line * 11 + UM] == pTabuleiro[line * 11 + TRES]
            && pTabuleiro[line * 11 + UM] != '_')
            // retornar o valor associado ao vencedor
            return pTabuleiro[line * 11 + UM] == 'O' : -1 : 1;
    }

    return 0;
}

int checkVertical(char * m) {
    // para todas as colunas
    for (int column = UM; column <= TRES; ) {
        // verificar coluna "column"
        if (   pTabuleiro[0 * 11 + column] == pTabuleiro[1 * 11 + column]
            && pTabuleiro[0 * 11 + column] == pTabuleiro[2 * 11 + column]
            && pTabuleiro[0 * 11 + column] != '_')
            // retornar o valor associado ao vencedor
            return pTabuleiro[0 * 11 + column] == 'O' : -1 : 1;

        // incremneto do ciclo de coluna
        column = column == UM
                  ? DOIS
                  : (column == DOIS
                        ? TRES
                        : TRES + 1);
    }

    return 0;
}

int checkDiagonals(char * m) {
      // verificar diagonal principal
      if (   pTabuleiro[0 * 11 + UM] == pTabuleiro[1 * 11 + DOIS]
          && pTabuleiro[0 * 11 + UM] == pTabuleiro[2 * 11 + TRES]
          && pTabuleiro[0 * 11 + UM] != '_')
          // retornar o valor associado ao vencedor
          return pTabuleiro[0 * 11 + column] == 'O' : -1 : 1;

      // verificar diagonal secundaria
      if (   pTabuleiro[2 * 11 + UM] == pTabuleiro[1 * 11 + DOIS]
          && pTabuleiro[2 * 11 + UM] == pTabuleiro[0 * 11 + TRES]
          && pTabuleiro[2 * 11 + UM] != '_')
          // retornar o valor associado ao vencedor
          return pTabuleiro[0 * 11 + column] == 'O' : -1 : 1;

      return 0;
}

int checkWin(char * m) {
    // verificar vencedor
    int check =    checkHorizontal(m)
                || checkVertical(m)
                || checkDiagonals(m);
    if (check)
        return check;

    // verificar se existem espaços vazios
    for (int line; line < 3; ++line) {
        for (int column; column <= TRES; ) {
            // verificar se a célula iterada se encontra vazia
            if (pTabuleiro[line * 11 + column] == '_')
                return -2;

            // incremneto do ciclo de coluna
            column = column == UM
                      ? DOIS
                      : (column == DOIS
                            ? TRES
                            : TRES + 1);
        }
    }

    // empate ...
    return 0;
}
Edited by HappyHippyHippo
removed unacessary code
IRC : sim, é algo que ainda existe >> #p@p

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.