Sobre a programação, especialmente em linguagem CTopMuitos mais exercícios!Exercícios práticos (muitos...)

Exercícios práticos (muitos...)

Como vai programar?

 

Ir directamente para exercício: 1 5 10 15 20 25 30 final

 

Exercícios

  1. Exercícios complementares.


  2. Implemente um programa que leia um inteiro n e n inteiros, determinando o maior e o menor desses n inteiros.
    Teste o seu programa interactivamente e lendo os dados de um ficheiro.
    Implemente o seu programa usando (i) uma instrução de ciclo for e (ii) uma instrução de ciclo while.
    Exemplo de dados: 4 6 8 1 3
    Resultado: 8 1


  3. Implemente um programa que imprima o número de divisores de um inteiro dado.
    Exemplo de dados: 6
    Resultado: 4 (pois 6 tem 4 divisores, 1, 2, 3 e 6).
    Nota: A condição de a dividir (ser divisor!) de b (inteiros positivos) pode ser expressa em linguagem C da forma seguinte: b%a==0.
    Implemente o programa com base na seguinte função a qual contém alguns erros. Comece por corrigí-los!
     
     //-- Retorna o num. de divisores de n (entre 1 e n).
     int ndiv(int n){
       int i,s;
       for(i=1;i<n;i++){
         if(n%i=0) s++;
       return(s);
     }
    


  4. Implemente um programa que determine se um inteiro dado é primo.
    Exemplo de dados: 23
    Resultado: Sim
    Sugestão: Utilize a função utilizada no programa do exercício anterior.


  5. Escreva um programa que leia caracteres da entrada padrão e escreva para a saída padrão os caracteres lidos de código compreendido entre 32 e 127 (extremos incluídos), passando para maiúsculas as letras minúsculas. Por exemplo
     
     As armas e 
     os 7 barões 
    
    deve ser transformado em
     
     AS ARMAS E OS 7 BARES 
    

    Notas

    1. Deve usar apenas as funções de leitura getchar() e de escrita putchar(...).
    2. O seu programa pode ter a seguinte estrutura
       
       #include <stdio.h>
       main(){ 
         int ch=getchar(); 
         while(ch!=EOF){ 
           if(ch>='a' && ch <='z') 
             ch += ... 
           if(ch>=... && ch <=...) 
             putchar(ch); 
           ch=getchar(); 
         } 
       } 
      
    3. Teste o seu programa com o comando
       
         a.out < ... 
      


  6. Implemente um programa que leia os caracteres de um ficheiro com a instrução getchar() e imprima o número total de caracteres e de letras no ficheiro.
    Exemplo de ficheiro: As 7 nuvens
    Resultado: 11 caracteres, 8 letras


  7. Usando directamente a definição
    f(0,b)=0
    f(1,b)=1
    f(n+2,b)=f(n+1,b)+f(n,b) mod b
    escreva uma função recursiva que calcule f(n,b). No main deve começar por ler nb e listar f(i,b) para 0 <= i <= n.
    Que conclui quanto à "velocidade" do seu programa?
    Quantas vezes f() é chamada, se exteriormente for chamado f(7,b)?


  8. Utilizando a seguinte função que retorna um inteiro aleatório compreendido entre a e b (inclusivé), escreva um programa que "lance" 1000 vezes um par de dados com vista a estimar a probabilidade do seguinte acontecimento: no lancamento, o total de pontos saídos é 4 ou mais. A probabilidade estimada é: (num. de vezes que saiu 4 ou mais)/1000.
     
     //-- inteiro aleatório >=a e <=b 
     int aleat(int a, int b){ 
       return(a+(rand()%(b-a+1))); 
     } 
    
    Notas.
    Leia o manual de rand() escrevendo no terminal "man rand" ou no Emacs "ESC x manual-entry" e depois, "rand".

    uma solução deste problema:

     
    main(){
      int i,d1,d2;
      double num=0;
      srand(getpid());
      for(i=0;i<LANCS;i++){
        int d1=aleat(1,6);
        int d2=aleat(1,6);
        if(d1+d2>=4)
          num++;
      }
      printf("Prob = %8.4f\n",num/LANCS);
    }
    

    -> Compare o valor obtido com a previsão "teórica".


  9. Trocas... Considere a seguinte parte de um programa em linguagem C:
      void mostra(int a[],int n){
        int i;
        for(i=0;i<m;i++)
          printf("%3d",v[i]);
        printf("\n");
      }
     
      main(){
        int v[]={8,2,6,18,4}, n=5;
        troca(v,n,0);
        mostra(v,n);
        troca(v,n,1);
        mostra(v,n);
      }
    
    Neste programa falta definir a função
        void troca(int v[],int m,int i)
    
    que deve ter como efeito trocar v[i] com v[k] onde k é o índice que contém o menor dos valores
    v[i], v[i+1],···, v[m-1]
    Por exemplo, o vector considerado atrás, depois de executar troca(v,5,2), deve ficar
    8,2,4,18,6
    1. Escreva a função troca e teste o programa; na função deve começar-se por determinar o valor de k.
    2. Modifique a função main por forma a que o programa ordene os valores do vector por ordem crescente.
      Sugestão. Basta chamar troca(?,?.?) repetidamente com um ciclo for apropriado.


  10.   Troca com o seguinte... Considere a seguinte parte de um programa em linguagem C:
      void mostra(int a[],int n){
        int i;
        for(i=0;i<m;i++)
          printf("%3d",v[i]);
        printf("\n");
      }
     
      main(){
        int v[]={8,2,6,18,4}, n=5;
        mostra(v,n);
        ordena(v,n,1);
        mostra(v,n);
      }
    
    Neste programa falta definir a função
        void ordena(int v[],int m)
    
    que deve ter como efeito ordenar o vector v[i] com m elementos por ordem crescente utilizando a seguinte observação:
    Se o vector ainda não está ordenado, existe i com v[i] > v[i+1] para um qualquer i com 0<=i<=n-2.
    Possível método: Pode por exemplo, percorrer sucessivamente o vector da esquerda para a direita, trocando v[i] com v[i+1] sempre que seja v[i]>v[i+1].
    Experimente primeiro o método para o vector dado!


  11. Endereços de correio electrónico Implemente um programa que imprima todos os endereços de correio electrónico que existem num ficheiro (lido por redireccionamento da entrada-padrão). Entende-se por "endereço de correio electrónico" uma sequência da seguinte forma
    <PAL1>@<PAL2>
    onde <PAL1> e <PAL1> são sequências máximas de 1 ou mais caracteres dos seguintes tipos:
    A,B,...,Z,a,b,...z,1,2,...,9,-,_,,.

    Exemplos:
    x2yz@com.com, ataca-te@laden.pt.

    Notas: (i) Utilize apenas getchar e putchar como funções de entrada e saída. (ii) Quando está a formar um eventual endereço, vá guardando os caracteres correspondentes num vector, (iii) Como sempre, utilize a divisão apropriada do seu programa em funções com vista a o estruturar!


  12. Pequenos exercícios de revisão
    1. Primeiro + último
      Escreva um programa que leia os inteiros positivos nb e imprima a soma do primeiro com o último dígito de n escrito na base b. Note que, em particular, pode ser n<b (um só dígito). Exemplos:
      9,2 -> 2, 118,10 -> 9, 8,10 -> 16


    2. Muitos divisores?
      Escreva um programa que leia n e imprima todos os inteiros compreendidos entre 1 e n que são "perfeitos", isto é, iguais à soma dos seus divisores próprios; um divisor d de n diz-se próprio se é inferior a n. Por exemplo, 6 é perfeito porque 6=1+2+3.

      O seu programa deve incluir uma função "int somad(int n)" que retorna a soma dos divisores próprios de n.


    3. Quando chega a n?
      Considere uma sucessão f(0), f(1),··· definida por: f(0)=f(1)=1 e f(n+2)=(f(n)+f(n+1)) mod 100 (resto da divisão por 100). Por exemplo, se f(8)=55 e f(9)=60, é f(10)=15.

      Escreva um programa que lê n e imprime o primeiro valor positivo de i não superior a 1000 tal que f(i)=n ou -1 se tal i não existe.


    4. Média...
      São lidos n (inteiro maior ou igual a 2) e n inteiros não negativos. O maior desses n inteiros é desprezado. O programa deve imprimir a média dos restantes n-1 inteiros utilizando para tal uma instrução do tipo
      printf("%3.3f",m);

      Exemplo: 4 1 5 3 2, resultado: 2.


  13. Procura...
    Em linguagem C um conjunto finito de inteiros pode ser representado por um vector de inteiros.
    1. Escreva uma função
      int pertence(int x,int v[], int n)
      que retorna 1 se x pertence ao conjunto de n elementos representado por v[] e 0 caso contrário; para aprocura deve utilizar-se uma pesquisa sequencial.
    2. Teste a função que escreveu com um programa semelhante ao seguinte:
      main(){
        int a,
          v[]={8,5,2,12,25,9,10,81,4,22}, nv=10;
        do{
          printf("Valor (negativo para acabar)? ");
          scanf("%d",&a);
          printf("%s\n",pertence(a,v,nv)?"SIM":"NAO");
        } while(a>=0);
      }
      
    3. Utilizando a função pertence escreva uma função
      int diferenca(int x[], int m, int y[], int n, int z[], int *p)
      que calcula a diferença dos conjuntos representados por (x[],m) e por (y[],n); esse diferença será representada por (z[],p)

      Como se sabe a diferença entre os conjuntos AB é o conjunto dos elementos de A que não pertencem a B.

    4. Teste a função que escreveu com um programa semelhante ao seguinte:
      #define MAX 100
      main(){
        int v[]={2,4,6,8,10,12,14,16}, nv=8,
            w[]={2,8,9,3}, nw=4,
            z[MAX], nz,
            i;
        diferenca(v,nv,w,nw,z,&nz);
        for(i=0;i<nz;i++)
          printf("%3d",z[i]);
      }
      


  14. Maior palavra.
    É lido um "string". O programa deve imprimir o comprimento da maior palavra presente nesse "string". Por exemplo, para o "string" "3 ba\bax*s!" a resposta é 3 (correspondente à palavra "bax".


  15.   Codificação de um texto com uma chave secreta n
    Escreva uma função "void roda(char s[],int n)" que tem como efeito "rodar no alfabeto" todas as letras de s (maiúsculas ou minúsculas) de n posições. Assim, se n=2, o string "ac Z" é transformado em "ce B".

    Nota. Pode usar o seguinte programa para testar a função que escreveu.

    main(){
      int n;
      char v[MAX];
      strcpy(v,"as Nuvens");
      printf("Chave? ");
      scanf("%d",&n);
      roda(v,n);
      printf("%s\n",v);
      roda(v,-n);
      printf("%s\n",v);
    }
    


  16. Esticar...
    Escreva uma função "void estica(char s[])" que, no "string s, introduz um espaço após cada caracter.
    Assim, "as nuvens" fica transformado em
    "a s   n u v e n s "
    

    Supõe-se que em s[] existe espaço suficiente para efectuar esta operação.

    Nota. Pode usar o seguinte programa para testar a função que escreveu.

    main(){
      char v[MAX];
      strcpy(v,"as nuvens");
      estica(v);
      printf("<%s>\n",v);
    }
    


  17. Ordenar palavras...
    Adapte o programa estudado de ordenação por selecção do mínimo com vista a se ordenarem vectores de "strings" (em vez de vectores de inteiros).
    Possíveis fases: (i) utilização do strcmp, (ii) não utilização do strcmp (implementação de uma função semelhante), (iii) Ordenação através de uma tabela de índices.


  18. Medições...
    Um conjunto de medições é guardado num vector; por exemplo
    [2.1, 1.9, 2.6, 1.8, 1.9, 1.2, 2.0]


    1. Escreva uma função "float media(float v[], int n)" que dá como resultado a média dos n valores do vector v[].


    2. Escreva uma função "float dp(float v[], int n)" que dá como resultado a raíz quadrada de
      ((v[0]-m)^2 + (v[1]-m)^2 +...+ (v[n-1]-m)^2)/(n-1)


    3. Escreva uma função
      "void retira(float v[], int *n)"
      que retira do vector v os valores que se afastam da média (em valor absoluto) mais que
      3*dp(v,n) (ver a alínea anterior).
      Sugestão. Utilizando um vector auxiliar comece por registar os índices dos elementos que devem ser retirados de v[].

      Nota. Pode usar o seguinte programa para testar as funções que escreveu.

      void imprime(float v[], int n){
        int i;
        printf("\n[");
        for(i=0;i<n;i++)
          printf("%4.2f ",v[i]);
        printf("]\n");
      }
      
      ...
      
      main(){
        float v[]={2.1, 1.9, 2.6, 1.8, 1.9, 1.2, 2.0};
        int nv=7;
        imprime(v,nv);
        printf("m=%4.2f, dp=%4.2f\n",media(v,nv),dp(v,nv));
        retira(v,&nv);
        imprime(v,nv);
      }
      


  19. Contando os caracteres... Escreva um programa chamado "conta" que imprime como resultado o número de caracteres do ficheiro "fich" indicado como parâmetro da "shell":
    $ conta fich
    Pode usar uma instrução de impressão do seguinte tipo
    printf("%20s tem %8d caracteres\n",arg[i],nc);

    Modifique o seu programa por forma a funcionar com um número qualquer de ficheiros, escrevendo para cada um o nome e o número de caracteres. Experimente com conta *.


  20.   Dois exercícios de revisão
    1. Trocas...
      Escreva uma função
      void trocapar(int v[],int n)
      que troca cada elemento de índice par do vector v com o elemento seguinte (o último elemento, se tiver índice par não é alterado). Por exemplo, se o vector é:
      v[] = [2,3,4,10,15] deve ficar
      v[] = [3,2,10,4,15].
      Notas. (i) Não deve usar nenhum vector auxiliar.
      (ii) Pode usar o seguinte programa para testar a função trocapar:
      main(){
        int v[]={2,3,4,10,15}, nv=5,i;
        trocapar(v,nv);
        for(i=0;i<nv;i++)
          printf("%3d",v[i]);
      }
      


    2. Sem repetições...
      Escreva uma função
      void unico(char s[])
      que substitui todas a sucessão de ocorrências (consecutivas) do mesmo caracter por esse caracter. Por exemplo, se o "string" é:
      "abbb++bb*****!" deve ficar
      "ab+b*!"
      Notas. (i) Não deve usar nenhum vector auxiliar nem funções de "string" do C (como strlen, etc.). Pode usar o seguinte programa para testar a função unico:
      main(){
       char v[MAX];
       strcpy(v,"as nuvens");
       unico(v);
       printf("<%s>\n",v);
      }
      


  21. De quantas maneiras se pode obter a soma n?
    O inteiro 4 pode ser escrito de 5 formas como soma de inteiros positivos. 1+1+1+1=2+1+1=2+2=3+1=4 O seguinte programa que lê n e imprime todas as formas de escrever n como soma de inteiros positivos.
    #include <stdio.h>
    #define MAX 100
    
    int t[MAX];
    
    void imprime(int m){
      int i;
      for(i=0;i<m;i++)
        printf("%2d",t[i]);
      printf("\n");
    }
    
    /*-- escreve em t[] a partir do indice ti
         a decomposicao nao decrescente de n 
         em inteiros nao  excedendo max.    */
    void somas(int n,int max,int ti){
      int i;
      if(n==0){
        imprime(ti);       /*- Escrever uma soma! */
        return;
      }
      for(i=1;i<=max && i<=n;i++){
        t[ti]=i;           /*- uma parcela...      */
        somas(n-i,i,ti+1); /*- somas do resto...   */
      }
    }
    
    main(){
      int n;
      scanf("%d",&n);
      somas(n,n,0);
    }
    
    Teste o programa e explique o seu funcionamento.


  22. Jogar às cartas...
    1. Um método de gerar uma permutação aleatória dos valores {0,1,...,n} é:
      • Para i=1,2,...,n:
        • Gerar repetidamente um aleatório k entre 1 e n até que k ainda não tenha saído. Imprimir k.
      Em termos de eficiência este método é muito mau. Porquê? Com um dado, gerar uma permutação de {1,2,3,4,5,6}.


    2. Um método melhor é
      • Para i=1,2,...,n faça v[i-1]=i;
      • Para i=0,1,...,n-2
        • Seja r=rand(i,n-1) um aleatório entre i e n-1.
        • Troque v[i] com v[r].
      Implemente uma função
      void baralha(int v[],int n)
      que utilize este método. Pode utilizar a função aleat que está no enunciado dum exercício anterior. Teste a função com o programa principal
      main(){
        int i, n, a[MAX];
        srand(getpid());
        scanf("%d",&n);
        baralha(a,n);
        for(i=0;i<n;i++)
          printf("%3d",a[i]);
        printf("\n");
      }
      


    3. Utilize a função escrita na alínea anterior com vista a "baralhar" um baralho de 52 cartas e imprimir as 13 cartas que saíram a um determinado jogador. Basta para isso, compreender e completar o seguinte programa
      #define MAX 52
      #define MAO 13
      
      main(){
        int i, n, a[MAX];
        char *nome[]={
         "Ap","Rp","Dp","Jp","2p","3p","4p","5p","6p","7p","8p","9p","10p",
         "Ac","Rc","Dc","Jc","2c","3c","4c","5c","6c","7c","8c","9c","10c",
         "Ae","Re","De","Je","2e","3e","4e","5e","6e","7e","8e","9e","10e",
         "Ao","Ro","Do","Jo","2o","3o","4o","5o","6o","7o","8o","9o","10o"};
        srand(getpid());
        baralha(a,MAX);
        for(i=0;i<MAO;i++)
          printf("%5s",???]);
        printf("\n");
      }
      


  23. Permutações
    Escreva um programa que leia n e imprima todas as permutações dos objectos 1, 2,..., n.

    Exemplo:

    ? 3
      1  2  3
      1  3  2
      2  1  3
      2  3  1
      3  2  1
      3  1  2
    

    Sugestão: Um método baseia-se na seguinte observação: suponhamos que para i=1,2,···,n o elemento v[i] é inicializado com i (não estamos a usar v[0]). Colocamos no primeiro elemento do vector sucessivamente 1, 2,..., n e geramos recursivamente todas as permutações possíveis dos elementos seguintes (índices 2 a n ).

       1  2  3     1  3  2
       -           -
    
       2  1  3     2  3  1    (1o elem. trocado com o segundo)
       -           -
    
       3  2  1     3  1  2    (1o elem. trocado com o último )
       -           -
    

    A função

    void perm(int i,int n,int v[])

    tem como objectivo gerar e imprimir todas as permutações dos elementos do vector, supondo-se que os elementos anteriores ao elemento i estão já fixados. Quando acabar por ser chamada com i>n (nas chamadas recursivas o valor de i vai aumentano), o vector contém uma permutação e é impresso.

    Um esquema do respectivo algoritmo pode ser:

    void perm(int i,int n,int v[]){
      Se i>n {escreve o vector; return;}
      para j=i, i+1,...,n:
        troca v[i] <-> v[j]
        //-- E, recursivamente, gera as possiveis 
        //-- permutacoes da parte da frente:
        perm(i+1,n,v);     
        //-- repoe o valor de início
        troca v[i] <-> v[j]
    }
    

    Teste o método indicado para n=2 e para n=3.

    Organização: O seu programa poderá estar organizado em 3 funções:

    #define MAX 100
    
    void escreve(int v[], int n){
      int i;
      for(i=1;i<=n;i++)
        printf("%3d",v[i]);
      printf("\n");
    }
    
    void perm(int i,int n,int v[]){
      ...
    
    main(){
      int i, v[MAX], n;
      scanf("%d",&n);
      for(i=1;i<=n;i++)
        v[i]=i;
      perm(1,n,v);
    }
    


  24. Pequena calculadora
    Implemente uma pequena calculadora capaz de efectuar as 4 operações elementares. Por exemplo, supondo que o programa objecto se chama calc, a execução a partir da "shell" de
    $ calc 12 x 1000
    dá o resultado 12000.

    Ver o exemplo dado nas aulas teóricas relativo à multiplicação de 2 inteiros (na secção parâmetros a partir da "shell".


  25. Máximos
    Um elemento de uma matriz diz-se um máximo local se não for inferior a nenhum dos seus vizinhos. Um elemento que não esteja nos limites da matriz tem 8 vizinhos (e, por exemplo, se for um "canto" tem só 3). Por exemplo, na seguinte matriz
                  0 1 2 3 4
                -------------
              0 | 1 2 3 1 5 | 
              1 | 1 2 8 0 6 | 
              2 | 1 2 2 4 3 | 
              3 | 2 2 4 1 4*| 
              4 | 5 4 8 1 2 |  
    
    temos vários máximos locais; um deles (marcado com *), na linha 3, coluna 4, tem o valor 4.

    Escreva uma função

    int maxr(int lin,int col,int nl, int nc)
    
    que determina se o elemento da linha lin, coluna col da matriz (a matriz é uma variável global) é um máximo local. A matriz tem nl linhas e nc colunas.

    Um programa completo com o objectivo de determinar todos os máximos locais pode então ter a seguinte estrutura:

    int v[][5]={{1,2,3,1,5},
                {1,2,8,0,6},
                {1,2,2,4,3},
                {2,2,4,1,4},
                {5,4,8,1,2}},
      nl=5, nc=5;
    
    
    int maxl(int lin,int col,int nl, int nc){
       ..............
    
    int main(){
      int i,j;
      for(i=0;i<nl;i++)
        for(j=0;j<nc;j++)
          if(maxl(i,j,nl,nc))
            printf("Maximo local de %3d em linha=%3d, col=%3d\n",
                    v[i][j],i,j);
    }
    


  26. Minas
    Com este exercício pretende-se programar parte do conhecido jogo das "minas". Um exemplo de utilização do programa pode ser o seguinte.
    ? 2 2                        (pergunta a linha e a coluna)
    
          0 1 2 3 4 5 6 7 8 9
         --------------------    (indica o número de vizinhos)
      0 |                    |
      1 |                    |
      2 |     4              |
      3 |                    |
      4 |                    |
      5 |                    |
      6 |                    |
      7 |                    |
      8 |                    |
      9 |                    |
         --------------------
    
    ? 7 4
          0 1 2 3 4 5 6 7 8 9    (pergunta a linha e a coluna)
         --------------------
      0 |                    |   (indica o número de vizinhos)
      1 |                    |
      2 |     4              |
      3 |                    |
      4 |                    |
      5 |                    |
      6 |                    |
      7 |         3          |
      8 |                    |
      9 |                    |
         --------------------
    
    ? 1 5                         (pergunta a linha e a coluna)
                                  (Era uma mina, acaba o programa)
    BUUUM!
    
          0 1 2 3 4 5 6 7 8 9
         --------------------
      0 |     *   * *       *|
      1 |     *   * *     *  |
      2 |   *   *   *        |
      3 | *     * * *     * *|
      4 | *   *   * * * * * *|
      5 | * * *              |
      6 |   *   *       * * *|
      7 | *     *       * * *|
      8 |     *     *   *   *|
      9 | * *       * *   * *|
         --------------------
    
    Sugere-se a utilização de 2 variáveis bidimensionais, uma com as minas geradas aleatoriamente e a outra com a situação que é mostrada ao utilizador (com a indicação do número de vizinhos).

    O programa principal pode ter a seguinte estrutura:

    main(){
      char tab[MAX][MAX],    //-- "tabuleiro"
           out[MAX][MAX];    //-- o que mostra
      int nl=10, nc=10,      //-- num de linhas e de colunas
          linha,col,i,j;     //-- escolhidas pelo utilizador
      double prob=0.5;       //-- probabilidade de ser mina
      srand(getpid());
      gera(tab,nl,nc,prob);  //-- Geração aleatória
      espacos(out,nl,nc);    //-- Coloca espaços em out[][]
      do{                    //-- De cada vez:
        mostra(out,nl,nc);   //-- Mostra a situação actual
        scanf("%d %d",&linha,&col); //-- Lê linha e coluna
        if(tab[linha][col]==' ')    //-- Testa se bomba, se não:
          out[linha][col]='0'+vizinhos(linha,col,tab,nl,nc);
      } while(tab[linha][col]==' ');
      printf("BUUUM!\n\n");  //-- Bomba, acabou,
      mostra(tab,nl,nc);     //-- Mostra o tabuleiro
    }
    

    Há pois que implementar as seguintes funções:

    void mostra(char t[][MAX],int nl,int nc):
       mostra a situação ou - no final - o tabuleiro
    
    int random_int(int a, int b): ver um exercício anterior
    void gera(char t[][MAX],int nl,int nc,double prob):
       gera aleatoriamente a posição das minas
    void espacos(char t[][MAX],int nl,int nc):
       preenche uma matriz t[][] de espaços ' '
    
    int vizinhos(int lin,int col,char tab[][MAX],int nl,int nc):
       retorna o número de bombas na vizinhança de tab[lin][col]
    
    -------------------


  27. Minas outra vez
    Com este exercício pretende implementar-se um jogo das minas completo. A principal diferença relativamente ao exercício anterior é a seguinte: sempre que se mostra haver 0 bombas na vizinhança de uma casa, para cada uma das casas dessa vizinhança calcula-se (e mostra-se) o número bombas vizinhas.

    Assim, se as bombas estão nas posições indicadas

           0 1 2 3 4
    ------------------
      0  | 0 X 0 0 0 |
      1  | 0 0 0 0 0 |
      2  | 0 0 0 0 0 |
      3  | 0 X X 0 0 |
      4  | X 0 0 0 0 |
    ------------------
    
    e o utilizador selecciona na primeira jogada a linha 0, coluna 4, deve aparecer:
           0 1 2 3 4
    ------------------
      0  |       : : |
      1  |       : : |
      2  |         : |
      3  |         : |
      4  |         : |
    ------------------
    
    onde o caracter ":" significa 0.

    Poderá utilizar no seu programa a seguinte estruturação.

    //-- numeros maximos de linhas e colunas
    #define NCOLS 30
    #define NLINS 40 
    
    // inteiro aleatório em [a...b]
    int random_int(int a, int b){
      return(a+(rand()%(b-a+1)));
    }
    
    /*-- Gera aleatoriamente em t[][] minas
         com a probabilidade p (inteiro entre 1 e 10,
         correspondendo a probabilidades de 0.1 a 0.9)
         e inicializa d[][]                            --*/
    void gera(int prob,int t[][NCOLS],int d[][NCOLS],int nl,int nc){
    ............
    
    //-- Mostra o tabuleiro ao utilizador
    void mostra(int d[][NCOLS],int nl,int nc){
    ............
    
    //-- Retorna o número de bombas vizinhas de t[i][j]
    int vizinhos(int a,int b,int t[][NCOLS],int nl,int nc){
    ............
     
    /*-- Para cada célula com 0 vizinhos: calcula vizinhos
         (iterativamente)                                 */
    void novos(int t[][NCOLS],int d[][NCOLS],int nl,int nc){
    ............
    
    //-- Perdeu: mostra o tabuleiro (com as bombas)
    void bum(int t[][NCOLS],int d[][NCOLS],int nl,int nc){
    
    /*-- Aceita um inteiro x entre min e max;
         Dá a mensagem mess se for dado um fora dos limites */
    void enter(char *mess,int *x,int min,int max){
    
    -------------------------------------------------------------
    main(){
      int tabu[NLINS][NCOLS],  //-- estado das celulas
          displ[NLINS][NCOLS], //-- quadro mostrado
          nlin,                //-- numero real de linhas
          ncol;                //-- numero real de colunas
    
      int prob,i,j,jogando=1;
      enter("N. de linhas? ",  &nlin,1,NLINS-1);
      enter("N. de colunas? ",&ncol,1,NCOLS-1);
      enter("Probabilidade (0..10, inteiro)? ",&prob,1,9);
      srand(getpid());
      gera(prob,tabu,displ,nlin,ncol);
      while(jogando){
        mostra(displ,nlin,ncol);
        enter("lin= ? ",&i,0,nlin-1);
        enter("col= ? ",&j,0,ncol-1);
        if(tabu[i][j]){
          bum(tabu,displ,nlin,ncol);
          mostra(displ,nlin,ncol);
          jogando=0;
        }
        else
          if(displ[i][j]==NADA){
            displ[i][j]='0'+vizinhos(i,j,tabu,nlin,ncol);
            if(displ[i][j]=='0')
              displ[i][j]=ZERO;
              novos(tabu,displ,nlin,ncol);
          }
      }
    }
    


  28. Explique...
    Siga e explique o funcionamento do programa indicado.
     1| #define MAXF 20
     2| #define MAX  100
      |
     3| main(){
     4|   char *p[MAXF]={"as armas e os baroes",
     5|                  "vamos passear!",
     6|                  "andam 3 nuvens",
     7|                  "lado de cima",
     8|                  ""}, s[MAX];
      |  
     9|   int i,j,c,nf,minc=0;
      |
    10|   nf=0;
    11|   while(p[nf][0]!=0)
    12|     nf++;
    13|   minc=strlen(p[0]);
    14|   for(i=1;i<nf;i++)
    15|     if((c=strlen(p[i]))<minc)
    16|       minc=c;
      |
    17|   for(j=0;j<minc;j++){
    18|     for(i=0;i<nf;i++)
    19|       s[i]=p[i][j];
    20|     s[i]=0;
    21|     printf(" %s\n",s);
    22|   }
    23|  }
    
  29. Jogo dos 30...
    Dois jogadores alternam indicando inteiros entre 1 e 6. Aquele que conseguir completar o total de 30 ganha.

    Exemplo:

       Computador (0) ou humano (1)?  1
       soma = 0              Jogada?  5
       soma = 5     Computador joga   6
       soma = 11             Jogada?  6
       soma = 17    Computador joga   6
       soma = 23             Jogada?  4
       soma = 27    Computador joga   3
       soma = 30
       -- Vitoria do computador!!!
     

    Objectivo: implementar um programa que jogue (bem!) com o utilizador este jogo.

    Sugestão Começar por descobrir uma estratégia vitoriosa (se houver hipótese de ganhar). Implementar essa estratégia quando possível - isto é, quando há hipótese de ganhar - ou seleccionar um inteiro aleatório entre 1 e 6 caso contrário.

    Sugere-se a divisão conveniente do programa em funções que poderão ser, por exemplo (não é obrigatório) - as seguintes

     /*-- retorna um inteiro aleatorio entre a e b (inclusivé)
          int aleat(int a, int b)... ver exercício anterior
    
     /*-- Depois de escrever a mensagem m (Exemplos:
          "Jogada? ", "Computador (0) ou humano (1)? ")
          pede ao utilizador um numero entre a e b, 
          retornando esse número                                 */
          int resposta(char *m,int a,int b)...
    
     /*-- Selecciona uma jogada vitoriosa, se possivel...
          soma: valor actual da soma dos números.                */
          int jogada(int soma)...
    
     //-- main: contém o ciclo principal do jogo
          main()...
     


  30.   Letras frequentes...
    Escreva um programa que leia todos os caracteres (até encontrar EOF) da entrada padrão e que imprima por ordem decrescente as percentagens das ocorrências das letras encontradas; os caracteres que não são letras são ignorados.

    Exemplo

     $ ./a.out < letras.c
    
     f[a] = 11.4%
     f[i] = 11.1%
     f[e] =  9.7%
     f[t] =  9.3%
     f[r] =  9.0%
     f[f] =  8.0%
     f[l] =  7.6%
     f[n] =  6.9%
     ............
     f[b] =  0.0%
     

    Sugere-se o seguinte método para resolver este problema.
    Usar um vector f[] para contar o número de ocorrências de cada letra e um vector let[] com as letras; por exemplo, no início
    f[0]=...=f[25]=0, let[0]='a',...,let[25]='z'

    • Para cada caracter lido c, se for uma letra:
      • Se c for maiúscula converte-se para minúscula
      • Faz-se: f[c-'a']++
    • Ordenam-se por ordem decrescente de frequência os pares
      (f[i],let[i])
    • Escrevem-se esses pares para i=0,...,25 usando um formato apropriado.
     

PC/PI - página reservada - versão 2005.02.08

Sobre a programação, especialmente em linguagem CTopMuitos mais exercícios!Exercícios práticos (muitos...)