1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

[C] Jogo do Galo - Revisão

Discussão em 'Programação' iniciada por diutsu, 1 de Janeiro de 2009. (Respostas: 5; Visualizações: 2781)

  1. diutsu

    diutsu [email protected] Member

    Boas,

    Iniciei-me há pouco tempo, na programação, tendo decidido começar por C.

    Gostaria que vissem o meu primeiro "trabalho" e me dessem depois as vossas opiniões, visto que como estou a aprender isto por mim próprio, não tenho ninguém para me criticar (para o bem e para o mal).

    Bom, aqui está o código:

    Código:
    
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    #define DIM 3
    
    void mostra(char m[DIM][DIM]);
    void inic_random();
    void jogada(char ch, int njogadores);
    void cpu(char ch);
    void jogador(char ch);
    int ganhou(char ch);
    void jogo();
    void inic_mapa();
    
    char mapa[DIM][DIM];/*[linha] [coluna]*/
    main() /* permite começar um jogo novo sempre que se acabe o anterior*/
    {
         int escolha;
        printf(" Bem vindo ao jogo do galo !!!");
        do
        {
            printf("\n\n ******************************");
            printf("\n Queres comecar um novo jogo?");
            printf("\n 1: Novo jogo");
            printf("\n 0: Sair");
            printf("\n Escolha: ");
            scanf("%d", &escolha);
            getchar();
            if (escolha == 1)
            {
                jogo();
            }
        }
        while (escolha);
        printf("Adeus");
    }
    
    void jogo() /* função responsável por ver quantos jogadores vão jogar, mudar os turnos, e assinalar o fim de um jogo*/
    {
        int njogadas = 0;
        int njogadores = 0;
        char ch='o';
        inic_random();
        inic_mapa();
        while(njogadores > 2 || njogadores < 1)
        {
        printf("\n Quantos jogadores? ");
        scanf("%d", &njogadores);
        }
        printf("\n Jogo para %d jogador(es)", njogadores);
        mostra(mapa);
        do
        {
            ch = (ch == 'o' ? 'x' : 'o');
            jogada(ch, njogadores);
            njogadas++;
            mostra(mapa);
        }
        while(njogadas <9 && !ganhou(ch));
        
        if (ganhou(ch))
        {
            if (njogares = 1 && ch 'o')
            {
                printf("\n*****************************");
                printf("\nO cpu ganhou! Se eu fosse a ti tinha vergonha!");
            }
            else
            {
                njogadores = (ch == 'o') + 1;
                printf("\n*****************************");
                printf("\nParabens jogador %d! Ganhaste!", njogadores);
            }
        }
        else
        {
            if(njogadas = 9)
            {
                printf("\nBom, isto foi um empate");
            }
        }
        getchar();
    }
    
    void inic_mapa ()  /*inicia o campo do jogo, com todas as casas com espaço*/
    {
         int x,y;
         for (x = 0; x<DIM; x++)
         {
             for (y = 0; y<DIM; y++)
             {
                 mapa[x][y] = ' '; /*[linha] [coluna]*/
             }
         }
    }
    
    void inic_random() /* permite a função aleat */
    {
        long ultime;
        time (&ultime);
        srand ((unsigned) ultime);
    }
    
    int aleat(min, max)        /* esta função gera um número aleatório entre min e max*/  
    {
        return rand()%(max)+min;
    }
    
    void mostra (char m[DIM][DIM]) /* mostra o jogo */
    {
        int x,y;
        printf("\n------------------\n");
        for (y = 0; y < DIM; y++)
        {
            for (x = 0; x < DIM; x++)
            {
                printf (" %d %c %c",DIM*(y)+x, m[y][x], x == DIM-1? ' ' : '|');
            }
            printf("\n----------------\n");
        }
    }
    
    void jogada(char ch, int njogadores) /* escolhe quem vai fazer a jogada se e um jogador ou o computador*/
    {
           if (ch == 'x')
        { 
            jogador(ch);
        }
        if (ch == 'o')      /* So para cpu vs jogador*/
        {
            if (njogadores == 1)
            {
                cpu(ch);
            }
            if (njogadores == 2)
            {
                jogador(ch);
            }
        }
    }
    
    void jogador(char ch) /* pede um número ao jogador, converte esse número para uma das casas e joga o caracter na casa correspondente*/
    {
        int casa, posx, posy, jogador;
        if (ch == 'x')
        {
            jogador = 1;
        }
        if (ch == 'o')
        {
            jogador = 2;
        }
        printf("Jogador %d: \n", jogador);
            do
            {
                printf("Escolha a casa que vai jogar, \ncasa: ");
                scanf("%d",&casa);
                posx = casa%3;
                posy = casa/3;
                if (mapa [posy][posx] != ' ') 
                {
                    printf("Casa ja ocupada, tente outra casa\n");
                }
            }
            while(mapa [posy][posx] != ' ');
            mapa [posy][posx] = ch;
            getchar();
            /*ver se o jogador ja ganhou*/
    }
    
    void cpu(char ch) /* Escolhe uma casa aleatóriamente, na vez do computador jogar, verifica se essa casa está livre*/
    {
        int posx, posy;
        printf("CPU");
        do
        {
            posx = aleat(1,3);
            posy = aleat(1,3);
        }
        while(mapa [posy-1][posx-1] != ' ');
        mapa [posy-1][posx-1] = ch;
    }
    
    int ganhou(char ch) /* Verifica se o jogador com o caracter ch ganhou o jogo*/
    {
        int x;
        int resultado = 0;
        for(x=0;x<DIM;x++)
        {
            if(mapa[x][0] == mapa[x][1] && mapa[x][1] ==  mapa[x][2] && mapa [x][2]== ch)/*verifica as linha*/
            {   
                resultado = 1;
            }
            if(mapa[0][x] == mapa[1][x] && mapa[1][x] ==  mapa[2][x] && mapa[1][x] == ch)/*verifica as colunas*/
            {
    
                resultado = 1;
            }
    
        }
        if(mapa[0][0] == mapa[1][1] && mapa[1][1] == mapa[2][2] && mapa[2][2] == ch)
            resultado = 1;
        if(mapa[0][2] == mapa[1][1] && mapa[1][1] == mapa[2][0] && mapa[2][0] == ch)
            resultado = 1;
        return resultado;
    }
    
    Só um pequeno à parte, o computador faz jogadas aleatórias, acho que IA é um pouco avançado para mim, não acham?

    Critiquem há vontade. :P
     
  2. Baderous

    Baderous Banido

    1 - Não há necessidade de declarar mapa como variável global. As variáveis globais trazem mais problemas do que aqueles que resolvem (se é que resolvem algum). Podes declarar essa variável dentro da main.
    2 - Deves sempre indicar o tipo de retorno e de parâmetros da main: http://www.portugal-a-programar.org/...html#msg236498
    3 - A escolha da opção no menu inicial deve ser feita com um switch e não com um if.
    4 - Deve-se testar os valores devolvidos pelos scanfs.

    Assim muito rápido, é isto.
     
  3. diutsu

    diutsu [email protected] Member

    Obrigado pela resposta.

    Ja estive a resolver o que tu disseste, mas tenho um problema, se quanto aos pontos 2, 3 e 4 percebo o que tu disseste e já os resolvi, quanto ao ponto 1 não percebo o que queres dizer.
    1.Porque é que dizes que as variáveis globais trazem mais problemas que aqueles que resolvem?
    2.Eu não posso declarar mapa dentro da função main, porque todas as funções precisam de mapa.
    Podia passar mapa como parametro para as outras funções, mas visto que as funções jogador e cpu interagem com mapa, essa alteração não teria efeito, uma vez que não iria alterar mapa, na função main.
    Um "return mapa" também não seria possivel, pelo menos sem uma grande revisão do código primeiro.

    Por isso a minha pergunta: Porque é que dizes que as variáveis globais trazem mais problemas que aqueles que resolvem?
    De qualquer maneira vou já pensando como é que conseguirei não usar mapa como variável global.
     
  4. Baderous

    Baderous Banido

    Não vou estar agora a falar de todas as desvantagens de usar variáveis globais (até porque não as sei todas), mas por exemplo, imagina estes 2 ficheiros:

    # teste1.c

    Código:
    #include <stdio.h>
    
    int c = 0;
    
    #include "teste2.c"
    
    int main(void) {
        troca();
        printf("%d\n",c);
        int c=3;
        printf("%d\n",c);
        return 0;
    }
    # teste2.c

    Código:
    void troca(void) { c=100;}
    O resultado de executar a main é:
    Código:
    100
    3
    Ora, como é que olhando apenas para o código de teste1.c sabes que a variável c vai tomar o valor 100? Não sabes, nem tens nenhuma referência no código de teste1.c que te diga que essa variável é alterada antes do 1º printf. Supostamente, deveria ser 0, mas aparece com o valor 100. Ficas com o trabalho extra de ir verificar a função troca() e constatar que realmente está a ser atribuído o valor 100 a c. No entanto, se fizesses:
    Código:
    troca(&c);
    e alterasses a função troca para:
    Código:
    void troca(int * c) {*c=100;}
    já saberias que a variável c teria sido utilizada na função troca e que, por isso, poderia ter o seu valor alterado. Esta solução vem responder à tua pergunta de não usar mapa como variável global. Tens de o passar por referência, isto é, passar o seu endereço de memória para que, efectivamente, mapa seja alterado (se passares como valor, o que é alterado é uma cópia da variável mapa que é criada aquando da chamada de uma função que a receba como parâmetro, cópia essa que é destruída no fim da execução da função).

    O outro problema que surge no código acima é a declaração de uma variável local também chamada c, a qual é inicializada com o valor 3 (e não há conflito com a variável global, pois estas 2 variáveis residem em zonas diferentes da memória). Este problema vai fazer com que uma variável que, supostamente deveria ser 100 (e já com o problema que referi atrás), passe a ter o valor 3. Grande confusão!

    São apenas alguns pontos negativos quanto às variáveis globais. É claro que se podem usar, tal como se podem usar goto's (o kernel do linux tem goto's), mas para os usar, é preciso saber usar, é preciso ter disciplina e método no seu uso, e isso só se ganha com experiência. http://en.wikipedia.org/wiki/Global_variable
     
  5. diutsu

    diutsu [email protected] Member

    Obrigado por essa resposta.
    Era essa parte do "&mapa" que me estava a faltar, o que não é de espantar uma vez eu ainda estou 3 capítulos antes do capitulo onde é abordado esse modo de passar parâmetros, e também 2 capítulos antes dos apontadores. Vou agora saltar para para esse capítulo, para poder resolver o meu problema desse modo, voltando depois ao seguimento de onde estou agora.

    EDIT: Segundo o que estive a ler, assim muito rápido, não é para usar "&mapa", mas sim apenas "mapa", visto que mapa é um vector
    Código:
    char mapa [DIM][DIM];
     
    Última edição: 2 de Janeiro de 2009
  6. diutsu

    diutsu [email protected] Member

    Bom, já estive a fazer isso, mas mesmo assim não dá certo.

    Neste momento tenho isto:
    Código:
    
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    #define DIM 3
    
    void mostra(char m[DIM][DIM]);
    void inic_random();
    void cpu(char ch, char **mapa);
    void jogador(char ch, char **mapa);
    int ganhou(char ch, char **mapa);
    void jogo();
    void inic_mapa(char **mapa);
    
    int main(void) /* permite começar um jogo novo sempre que se acabe o anterior*/
    {
           
        int escolha;
        printf(" Bem vindo ao jogo do galo !!!");
        do
        {
            printf("\n\n ******************************");
            printf("\n Queres comecar um novo jogo?");
            printf("\n 1: Novo jogo");
            printf("\n 0: Sair");
            printf("\n Escolha: ");
            scanf("%d", &escolha);
            getchar();
            switch (escolha)
            {
            case '1' : jogo(); break;
            default : printf("Opção não disponivel. Tenta outra");
            }
        }
        while (escolha);
        printf("Adeus");
    }
    
    void jogo() /* função responsável por ver quantos jogadores vão jogar, mudar os turnos, e assinalar o fim de um jogo*/
    {
        char mapa[DIM][DIM];/*[linha] [coluna]*/
        int njogadas = 0;
        int njogadores = 0;
        char ch='o';
        inic_random();
        inic_mapa(mapa);
        while(njogadores > 2 || njogadores < 1)
        {
            printf("\n Quantos jogadores? ");
            scanf("%d", &njogadores);
        }
        printf("\n Jogo para %d jogador(es)", njogadores);
        mostra(mapa);
        do
        {
            ch = (ch == 'o' ? 'x' : 'o');
            if (ch == 'x')
            { 
                jogador(ch,mapa);
            }
            if (ch == 'o')      /* So para cpu vs jogador*/
            {
                if (njogadores == 1)
                {
                    cpu(ch,mapa);
                }
                if (njogadores == 2)
                {
                    jogador(ch,mapa);
                }
            }
            njogadas++;
            mostra(mapa);
        }
        while(njogadas <9 && !ganhou(ch,mapa));
        
        if (ganhou(ch, mapa))
        {
            if (njogadores = 1 && ch == 'o')
            {
                printf("\n*****************************");
                printf("\nO cpu ganhou! Se eu fosse a ti tinha vergonha!");
            }
            else
            {
                njogadores = (ch == 'o') + 1;
                printf("\n*****************************");
                printf("\nParabens jogador %d! Ganhaste!", njogadores);
            }
        }
        else
        {
            if(njogadas = 9)
            {
                printf("\nBom, isto foi um empate");
            }
        }
        getchar();
    }
    
    void inic_mapa (char **mapa)  /*inicia o campo do jogo, com todas as casas com espaço*/
    {
         int x,y;
         for (x = 0; x<DIM; x++)
         {
             for (y = 0; y<DIM; y++)
             {
                 mapa[x][y] = ' '; /*[linha] [coluna]*/
             }
         }
    }
    
    void inic_random() /* permite a função aleat */
    {
        long ultime;
        time (&ultime);
        srand ((unsigned) ultime);
    }
    
    int aleat(min, max)        /* esta função gera um número aleatório entre min e max*/  
    {
        return rand()%(max)+min;
    }
    
    void mostra (char m[DIM][DIM]) /* mostra o jogo */
    {
        int x,y;
        printf("\n------------------\n");
        for (y = 0; y < DIM; y++)
        {
            for (x = 0; x < DIM; x++)
            {
                printf (" %d %c %c",DIM*(y)+x, m[y][x], x == DIM-1? ' ' : '|');
            }
            printf("\n----------------\n");
        }
    }
    
    
    void jogador(char ch, char **mapa) /* pede um número ao jogador, converte esse número para uma das casas e joga o caracter na casa correspondente*/
    {
        int casa, posx, posy, jogador;
        if (ch == 'x')
        {
            jogador = 1;
        }
        if (ch == 'o')
        {
            jogador = 2;
        }
        printf("Jogador %d: \n", jogador);
        do
        {
            do
            {
                printf("Escolha a casa que vai jogar, \ncasa: ");
                scanf("%d",&casa);
            }
            while(casa < 0 || casa > 8);
            posx = casa%3;
            posy = casa/3;
            if (mapa [posy][posx] != ' ') 
            {
                printf("Casa ja ocupada, tente outra casa\n");
            }
        }
        while(mapa [posy][posx] != ' ');
        mapa [posy][posx] = ch;
        getchar();
    }
    
    void cpu(char ch, char **mapa) /* Escolhe uma casa aleatóriamente, na vez do computador jogar, verifica se essa casa está livre*/
    {
        int posx, posy;
        printf("CPU");
        do
        {
            posx = aleat(1,3);
            posy = aleat(1,3);
        }
        while(mapa [posy-1][posx-1] != ' ');
        mapa [posy-1][posx-1] = ch;
    }
    
    int ganhou(char ch, char **mapa) /* Verifica se o jogador com o caracter ch ganhou o jogo*/
    {
        int x;
        int resultado = 0;
        for(x=0;x<DIM;x++)
        {
            if(mapa[x][0] == mapa[x][1] && mapa[x][1] ==  mapa[x][2] && mapa [x][2]== ch)/*verifica as linha*/
            {   
                resultado = 1;
            }
            if(mapa[0][x] == mapa[1][x] && mapa[1][x] ==  mapa[2][x] && mapa[1][x] == ch)/*verifica as colunas*/
            {
                resultado = 1;
            }
    
        }
        if(mapa[0][0] == mapa[1][1] && mapa[1][1] == mapa[2][2] && mapa[2][2] == ch)
            resultado = 1;
        if(mapa[0][2] == mapa[1][1] && mapa[1][1] == mapa[2][0] && mapa[2][0] == ch)
            resultado = 1;
        return resultado;
    }
    
    Nota: Deixou de existir a função jogada, o seu conteúdo ficou dentro da função jogo.
    Esta era função jogada:
    Código:
    void jogada(char ch, int njogadores)
    {
           if (ch == 'x')
        { 
            jogador(ch);
        }
        if (ch == 'o')      /* So para cpu vs jogador*/
        {
            if (njogadores == 1)
            {
                cpu(ch);
            }
            if (njogadores == 2)
            {
                jogador(ch);
            }
        }
    }
    
    Continuando, quando tento compilar o código dá-me isto:
    A pergunta é porquê e como é que faço para resolver isto?
     

Partilhar esta Página