Pac Man

Pacman

 20160408164533!Pacmanfigura

Fazer modificações para funcionar multi-plataformas.

Todos nos lembramos do Pac-Man, com certeza fez parte da nossa infância. Para os que não o conhece, o jogo tem uma criatura parecida com uma bolinha amarela com uma boca chamada de Pacman. O jogador controla o Pacman e precisa comer o máximo de bolinhas amarelas no mapa e algumas frutas para acumular pontos. Deve-se tomar cuidado pois no jogo não e só sair controlando o Pac-Man e comendo as coisas que aparecem pela frente. O Pacman tem que tomar cuidado com os 4 fantasmas, que estão ali para te levar dessa para outra rsrs. Exatamente isso, estão lá para te dar um GAME OVER. Então vamos aprender a construir esse game épico.

Curiosidades sobre o jogo : Nomes dos fantasmas, comportamentos, personalidades, etc.

PacMan 35 anos de vida 35 curiosidades

Primeira Versão: PacMan e O Fantasma Blinky – TextoGrafico

Nesta primeira versão vamos focar em construir o funcionamento do jogo, usando um estilo de gráfico simples em texto apenas para verificação de funcionamento. Nas próximas versões focaremos em trabalhar com o gráfico mais amigável.

Passo 1: Construindo Mapa

Nesse passo iremos construir nossa função Constroe_Mapa com o objetivo de alocar o espaço da nossa matriz e colocar as paredes Graficamente. O Mapa padrão constitui em uma matriz 20×20. Como nosso mapa será uma Martiz de char, então usaremos M para nomeá-la. O valor dim, será passado na main como 20.

   char** Constroe_Mapa(int dim)
   {
       int i, j;
       char **M;
       M = (char**) malloc(dim *sizeof(char*));        /*Alocação de uma dimensão da sala*/
       for(i = 0; i < dim; i++)
       {
           M[i] = (char*) malloc(dim *sizeof(char));  /*Alocação da segunda dimensão da sala*/
           for(j = 0; j < dim; j++)
           {
               /*CONTRUÇÃO DO MAPA*/
               if(i == 0 || i == (dim-1) || j == 0 || j == (dim-1) )
                   M[i][j] = 'H';
               else
               {
                   M[i][j] = '.';
               }
            }
       }
       return M;
   }

Dessa forma, printrando a matriz M, vamos ter isso:

Constroe_mapa

Passo 2: Construindo Obstáculos

Nesse passo iremos construir obstáculos no interior do mapa. Os obstáculos ou paredes serão representados pela letra “H”. Devemos lembrar que no jogo clássico existe uma área onde os fantasmas nascem, esse espaço sera representado pelo espaço livre ” “. Essa área esta representada pela cor verde claro no esquema mais a baixo Para realizar nosso objetivo nesse Passo 2, iremos construir uma função chamada Constroe_Obstaculo, responsável por construir as paredes no interior do mapa e o ninho dos fantasmas. O restante dos espaços devem permanecer com as moedas (pontos finais “.”) no restante do mapa.

Nessa imagem esta representada como os obstáculos devem ficar ao final do Passo2. O esquema esta representado com cores melhor representação.(Cores representativas)

PacManEX

Passando como parâmetro para função uma matriz M**, iremos dar as posições X e Y desta matriz onde devem ser construída as paredes No código abaixo esta comentado qual bloco esta sendo construído em relação ao esquema representado em cores acima.

void Constroe_Obstaculos(char **M)
{
   /*LUGARES DOS FANTASMAS */
   M[10][9] = ' ';
   M[10][10] = ' ';
   M[11][9] = ' ';
   M[11][10] = ' ';
   //    
   //
   /* CONTRUINDO OBSTACULOS*/
   /*BLOCO VERMELHO SUPERIOR ESQUERDO*/
   M[2][2] = 'H';
   M[2][3] = 'H';
   M[2][4] = 'H';
   M[3][2] = 'H';
   M[3][3] = ' ';
   M[3][4] = 'H';
   M[4][2] = 'H';
   M[4][3] = ' ';
   M[4][4] = 'H';
   M[5][2] = 'H';
   M[5][3] = 'H';
   M[5][4] = 'H';
   //
   /*BLOCO AZUL SUPERIOR ESQUERDO*/
   M[2][6] = 'H';
   M[3][6] = 'H';
   M[4][6] = 'H';
   M[5][6] = 'H';
   M[2][7] = 'H';
   M[3][7] = 'H';
   M[4][7] = 'H';
   M[5][7] = 'H';
   //    
   /*BLOCO AZUL SUPERIOR DIREITO*/
   M[2][12] = 'H';
   M[3][12] = 'H';
   M[4][12] = 'H';
   M[5][12] = 'H';
   M[2][13] = 'H';
   M[3][13] = 'H';
   M[4][13] = 'H';
   M[5][13] = 'H';
   //
   /*BLOCO VERMELHO SUPERIOR DIREITO*/
   M[2][15] = 'H';
   M[2][16] = 'H';
   M[2][17] = 'H';
   M[3][15] = 'H';
   M[3][16] = ' ';
   M[3][17] = 'H';
   M[4][15] = 'H';
   M[4][16] = ' ';
   M[4][17] = 'H';
   M[5][15] = 'H';
   M[5][16] = 'H';
   M[5][17] = 'H';
   //
   /*BLOCO VERDE SUPERIOR*/
   M[1][9] = 'H';
   M[2][9] = 'H';
   M[3][9] = 'H';
   M[4][9] = 'H';
   M[5][9] = 'H';
   M[1][10] = 'H';
   M[2][10] = 'H';
   M[3][10] = 'H';
   M[4][10] = 'H';
   M[5][10] = 'H';
   //
   /*BLOCO DIREITO AMARELHO*/
   M[7][1] = 'H';
   M[7][2] = 'H';
   M[7][3] = 'H';
   M[8][1] = 'H';
   M[9][3] = 'H';
   M[10][2] = 'H';
   M[10][3] = 'H';
   M[11][3] = 'H';
   M[12][1] = 'H';
   M[13][1] = 'H';
   M[13][2] = 'H';
   M[13][3] = 'H';
   //
   /*BLOCOS MARRONS*/
   M[12][7] = 'H';
   M[12][12] = 'H';
   //
   /*BLOCO ESQUERDO AMARELHO*/
   M[7][16] = 'H';
   M[7][17] = 'H';
   M[7][18] = 'H';
   M[8][18] = 'H';
   M[9][16] = 'H';
   M[10][16] = 'H';
   M[10][17] = 'H';
   M[11][16] = 'H';
   M[12][18] = 'H';
   M[13][18] = 'H';
   M[13][17] = 'H';
   M[13][16] = 'H';
   //
   /*BLOCO ROXO ESQUERO*/
   M[7][5] = 'H';
   M[8][5] = 'H';
   M[9][5] = 'H';
   M[10][5] = 'H';
   M[11][5] = 'H';
   M[12][5] = 'H';
   M[9][6] = 'H';
   M[9][7] = 'H';
   M[10][6] = 'H';
   M[10][7] = 'H';
   //
   /*BLOCO ROXO DIREITO*/
   M[7][14] = 'H';
   M[8][14] = 'H';
   M[9][14] = 'H';
   M[10][14] = 'H';
   M[11][14] = 'H';
   M[12][14] = 'H';
   M[9][13] = 'H';
   M[9][12] = 'H';
   M[10][13] = 'H';
   M[10][12] = 'H';
   //
   /*BLOCO LARANJA SUPERIOR*/
   M[7][7] = 'H';
   M[7][8] = 'H';
   M[7][9] = 'H';
   M[7][10] = 'H';
   M[7][11] = 'H';
   M[7][12] = 'H';
   M[8][9] = 'H';
   M[8][10] = 'H';
   M[9][9] = 'H';
   M[9][10] = 'H';
   //
   /*BLOCO LARANJA INFERIOR*/
   M[14][7] = 'H';
   M[14][8] = 'H';
   M[14][9] = 'H';
   M[14][10] = 'H';
   M[14][11] = 'H';
   M[14][12] = 'H';
   M[13][9] = 'H';
   M[13][10] = 'H';
   M[12][9] = 'H';
   M[12][10] = 'H';
   //
   /*BLOCO VERMELHO INFERIOR ESQUERDO*/
   M[15][2] = 'H';
   M[15][3] = 'H';
   M[15][4] = 'H';
   M[16][2] = 'H';
   M[16][3] = ' ';
   M[16][4] = ' ';
   M[17][2] = 'H';
   M[17][3] = 'H';
   M[17][4] = 'H';
   M[14][5] = 'H';
   M[15][5] = 'H';
   M[16][5] = 'H';
   M[17][5] = 'H';
   //
   /*BLOCO VERMELHO INFERIOR DIREITO*/
   M[15][15] = 'H';
   M[15][16] = 'H';
   M[15][17] = 'H';
   M[16][15] = ' ';
   M[16][16] = ' ';
   M[16][17] = 'H';
   M[17][15] = 'H';
   M[17][16] = 'H';
   M[17][17] = 'H';
   M[14][14] = 'H';
   M[15][14] = 'H';
   M[16][14] = 'H';
   M[17][14] = 'H';
   //
   /*BLOCO AZUL SUPERIOR ESQUERDO*/
   M[16][7] = 'H';
   M[17][7] = 'H';
   //
   /*BLOCO AZUL SUPERIOR DIREITO*/
   M[16][12] = 'H';
   M[17][12] = 'H';
   //
   /*BLOCO VERDE SUPERIOR*/
   M[16][9] = 'H';
   M[17][9] = 'H';
   M[18][9] = 'H';
   M[16][10] = 'H';
   M[17][10] = 'H';
   M[18][10] = 'H';
}

Resultado final ficara assim:

ConstroeObstaculo

Passo 3: Dando vida ao Personagem PacMan

Chegamos no passo onde faremos nosso amiguinho comilão seguir nossos comandos. Aqui nesse passo daremos vida ao personagem Pac-Man colocando ele em nosso mapa e construindo seus controles de movimento. Iremos criar uma função void chamada Controle_PacMan, a qual tem como parâmetros de entrada os seguintes itens:

*A matriz M que representa o mapa;
*A posição X atual do Pac-man;
*A posição Y atual do Pac-man;
*O botão apertado;
*A quantidade de pontos.

O protótipo da nossa função ficara assim:

   void Controle_PacMan(char **M, int *PMposX, int *PMposY, char controle, int *Pontos)

Como podemos observar os parâmetros de posições do nosso Pac-Man e de pontos estão sendo passados por referencia, pelo fato dos originais serem alterados dentro da própria função.

Dento da função temos que fazer com que apertado tal tecla o nosso Pac-man ande para tal direção. Usaremos o padrão WASD, W(Cima),S(Baixo),A(Esquerda),D(Direita).

Na nossa matriz as grandezas escalares estão distribuídas de tal forma:

EixoXeY

Dessa maneira, se quisermos mexer nosso personagem para a direita, por exemplo, Temos que apenas decrementar -1 no eixo x. Devemos tomar atenção para o fato do eixo Y ser invertido, sabendo que o ponto de origem(0,0) ser no canto superior esquerdo da matriz. Sabendo dessa particularidade do eixo Y, se quisermos por exemplo mexer para cima, precisamos decrementar -1 no eixo y. Caso o objetivo seja mexer para baixo incrementamos 1 no eixo Y.

Botão A

Um char esta sendo passado como parâmetro em nossa função, assim basta verificarmos se este char é o caracter ‘a’. O botão A, responsavel por mexer nosso personagem para a esquerda, mudara no eixo X do personagem decrementando -1 no PMposX. Uma outra coisa que devemos dar atenção, e no fato da nova direção que mandamos o Pac-man ir ser diferente de uma parede, assim dando efeito de colisão, pois caso seja uma parede o mesmo não deve executar nenhuma função, ou seja, continuar como no mesmo movimento passado. Devemos tambem colocar um controle de pontuação, de forma que quando o nosso personagem Pac-Man passe por uma posição que tenha uma moeda ou ‘.’ o mesmo ganha um ponto. Como nosso Pac-Man come o que tiver pela frente, o ponto comido não estará mais ali.

  if(controle == 'a' )                     //Verificamos se é o caracter 'a'
   {
      if(M[(*PMposY)][(*PMposX)-1] == 'H')     //Verificando se a posição a esquerda do Pac-Man é uma parede
      {
          /*Nao altera mapa*/                      //Caso seja, não Efetue nenhuma ação
      }
      else                                     //Caso a posição a esquerda do Pac-Man não seja uma parede
      {
          if(M[(*PMposY)][(*PMposX)-1] == '.')     //Verificando se a posição a esquerda do Pac_Man é tem um ponto
              (*Pontos)++;                             //Caso tenha incremente 1 nos pontos
          M[(*PMposY)][(*PMposX)] = ' ';           //Deixando vazio por onde Pac_man passar
          (*PMposX) = (*PMposX) - 1;               //Atribuindo a nova posição à nosso personagem
          M[(*PMposY)][(*PMposX)] = 'C';           //Colocando o nosso Personagem na posição nova dado a ele
      }
   }

Botão D

Um char esta sendo passado como parâmetro em nossa função, assim basta verificarmos se este char é o caracter ‘d’. O botão D, responsavel por mexer nosso personagem para a direita, mudara no eixo X do personagem incrementando 1 no PMposX. Deve ser dado os mesmas verificações de colisão e pontuação dadas aos botões anteriores.

   if(controle == 'd' )
   {
      if(M[(*PMposY)][(*PMposX)+1] == 'H')
      {
          /*Nao altera mapa*/
      }
      else
      {
          if(M[(*PMposY)][(*PMposX)+1] == '.')
              (*Pontos)++;
          M[(*PMposY)][(*PMposX)] = ' ';
          (*PMposX) = (*PMposX) + 1;
          M[(*PMposY)][(*PMposX)] = 'C';
      }
   }

Botão W

Um char esta sendo passado como parâmetro em nossa função, assim basta verificarmos se este char é o caracter ‘w’. O botão W, responsável por mexer nosso personagem para cima, mudara no eixo Y do personagem (Lembrando que o Eixo Y é invertido) decrementando -1 no PMposY. Deve ser dado os mesmas verificações de colisão e pontuação dadas aos botões anteriores.

   if(controle == 'w' )
   {
      if(M[(*PMposY)-1][(*PMposX)] == 'H')
      {
          /*Nao altera mapa*/
      }
      else
      {
          if(M[(*PMposY)-1][(*PMposX)] == '.')
              (*Pontos)++;
          M[(*PMposY)][(*PMposX)] = ' ';
          (*PMposY) = (*PMposY) - 1;
          M[(*PMposY)][(*PMposX)] = 'C';
      }
   }

Botão S

Um char esta sendo passado como parâmetro em nossa função, assim basta verificarmos se este char é o caracter ‘s’. O botão S, responsável por mexer nosso personagem para baixo, mudara no eixo Y do personagem (Lembrando que o Eixo Y é invertido) incrementando 1 no PMposY. Deve ser dado os mesmas verificações de colisão e pontuação dadas aos botões anteriores.

   if(controle == 's' )
   {
      if(M[(*PMposY)+1][(*PMposX)] == 'H')
      {
          /*Nao altera mapa*/
      }
      else
      {
          if(M[(*PMposY)+1][(*PMposX)] == '.')
              (*Pontos)++;
          M[(*PMposY)][(*PMposX)] = ' ';
          (*PMposY) = (*PMposY) + 1;
          M[(*PMposY)][(*PMposX)] = 'C';
      }
   }

Passo 4: Trazendo dos Mortos os Fantasmas Inteligentes

Nesse Passo vamos dar vida aos sem vida (piada sem graça rsrs), continuando, nesse passo iremos construir os nosso fantasmas. Iremos fazer a função Controle_Ghost a qual tem a função de controlar nosso fatasmas, escolhendo qual posição deve ir para pegar o Pac-Man.

Nessa função vamos passar como parâmetros:

*A matriz M que representa o mapa;
*O char que esta da posição anterior a do fantasma;
*A posição X do Pac-man;
*A posição Y do Pac-man;
*A posição X atual do Fantasma;
*A posição Y atual do Fantasma;
*O numero de vidas do Pac-Man

A função sera void, nao retornando nada assim alterando os valores do fantasma.

   void Controle_Ghost(char **M, char *antGhost, int *PMposX, int *PMposY, int *GHTposX, int *GHTposY, int *life_Pacman)

A ideia da engenharia da nossa função sera decidir qual posição escolher dentre as posições ao lado dele, de forma que a posição escolhida deve ser a mais próxima do Pac-Man.

Calculando Distancia entre dois Pontos

Para Calcular essa distancia usaremos o calculo de distancia entre dois pontos.

   sqrt(pow(x2-x1,2) + pow(y2-y1,2))

Como sera muito utilizado esse calculo, deixaremos especificado em uma função para facilitar a chamada de tal calculo.

Retornando o valor inteiro absoluto da distancia entre os pontos.

   int Calcula_dist(int X, int Y, int x, int y)
   {
      return sqrt(pow(X-x,2) + pow(Y-y,2));
   }

Verificando Qual posição Escolher

Para melhor controle de qual posição sera menor criaremos algumas variáveis.

  int dist_menor;
  int GHTposX_menor;
  int GHTposY_menor;

Para a distancia menor não receber algum valor aleatorio de memoria, devemos atribuir como menor distancia, a atual do Fantasma em relação ao Pac-Man.

  dist_menor = Calcula_dist((*GHTposX),(*GHTposY),(*PMposX),(*PMposY));
  GHTposX_menor = (*GHTposX) ;
  GHTposY_menor = (*GHTposY);

Nesse momento vamos verificar as quatro posições (cima, baixo, esquerda, direita) sera menor e assim escolhida.Nesse momento de verificação de qual posição escolher, e usado um Algoritmo conhecido na area de IA chamado A*(A-estrela) com distancia de Manhattan. Devemos lembrar que antes de verificar se esta posição e menor, devemos também verificar se esta posição e uma posição valida, ou seja, esta posição não seja uma parede.

  if((M[(*GHTposY)][(*GHTposX) - 1] != 'H') && (Calcula_dist(((*GHTposX)-1),(*GHTposY),(*PMposX),(*PMposY)) < dist_menor))
  {
      GHTposX_menor = ((*GHTposX) - 1) ;
      GHTposY_menor = (*GHTposY);
  
  if((M[(*GHTposY)][(*GHTposX) + 1] != 'H') && (Calcula_dist(((*GHTposX)+1),(*GHTposY),(*PMposX),(*PMposY)) < dist_menor))
  {
      GHTposX_menor = ((*GHTposX) + 1) ;
      GHTposY_menor = (*GHTposY);
  }
  if((M[((*GHTposY) - 1)][(*GHTposX)] != 'H') && (Calcula_dist((*GHTposX),((*GHTposY)-1),(*PMposX),(*PMposY)) < dist_menor))
  {
      GHTposX_menor = (*GHTposX);
      GHTposY_menor = ((*GHTposY) - 1);
  }
  if((M[((*GHTposY) + 1)][(*GHTposX)] != 'H') && (Calcula_dist((*GHTposX),((*GHTposY)+1),(*PMposX),(*PMposY)) < dist_menor))
  {
      GHTposX_menor = (*GHTposX);
      GHTposY_menor = ((*GHTposY) + 1);
  }

Existe a possibilidade de a posição menor, e as vezes a unica dependendo das paredes em volta do fantasma, ser uma posição invalida por esta ser uma parede. Precisamos entao fazer uma segunda verificação, caso o fantasma nao tenha escolhido uma posição forçaremos ele a escolher com outro critério, antes escolhendo por menor posição, agora escolhendo por coluna ou linha mais próxima.

  if((*GHTposX) == GHTposX_menor && ((*GHTposY) == GHTposY_menor))
  {
      if( pow( ((*GHTposX)-1) - (*PMposX) ,2) < pow( ((*GHTposX) - (*PMposX)) ,2)  && M[(*GHTposY)][(*GHTposX)-1] != 'H' )
          GHTposX_menor = (*GHTposX)-1;
      else if( pow( ((*GHTposX)+1) - (*PMposX), 2) < pow( ((*GHTposX) - (*PMposX)), 2) && M[(*GHTposY)][(*GHTposX)+1]!= 'H' )
          GHTposX_menor = (*GHTposX)+1;
      if( pow( ((*GHTposY)-1) - (*PMposY) ,2) < pow( ((*GHTposY) - (*PMposY)) ,2) && M[(*GHTposY)-1][(*GHTposX)]!= 'H' )
          GHTposY_menor = (*GHTposY)-1;
      else if( pow( ((*GHTposY)+1) - (*PMposY), 2) < pow( ((*GHTposY) - (*PMposY)), 2) && M[(*GHTposY)+1][(*GHTposX)]!= 'H' )
          GHTposY_menor = (*GHTposY)+1;
  }

Apos nosso fantasma inteligente ter tomado sua decisão, iremos então mover os personagens no mapa. Aqui precisamos de uma atenção especial para um detalhe, o fantasma não come os pontos, ou seja, se ele passar por um ‘.’ no mapa, este não deve sumir como e feito com o Pac-Man. Por tal motivo, é guardado o char da posição que ele esta sobreposto, dessa maneira caso seja um ponto, quando ele for para outra posição o ponto ainda estará la. A variável para guar esse char sera chamada antGhost, assim que o fantasma for mudar a posição, o char guardado em antGhost, volta para a posição de antes(ou seja a que o fantasma esta) e depois o fantasma anda.

  /*APOS ENCONTRAR MELHOR POSIÇÃO PARA IR ATRAS DE PAC MAN*/
  if((*antGhost) == ' ')
      M[(*GHTposY)][(*GHTposX)] = ' ';
  if((*antGhost) == '.')
      M[(*GHTposY)][(*GHTposX)] = '.';
  if((*antGhost) == 'H')
      M[(*GHTposY)][(*GHTposX)] = 'H';

Apos ter sido verificado se o fantasma estava sobreposto a um ponto, iremos mudar a posição do fantasma para a posição de distancia menor escolhida anteriormente.

  (*GHTposX) = GHTposX_menor;
  (*GHTposY) = GHTposY_menor;

Guardamos então o char da nova posição decidida pelo fantasma em antGhost, recebendo da matriz qual char esta la.

  (*antGhost) = M[(*GHTposY)][(*GHTposX)];

E o ponto mais esperado dos vilões, esse momento verificamos se o fantasma encostou (mesma posição X,Y do Pac-Man) e assim matou nosso Herói Comilão.

  if((*GHTposY) == (*PMposY) && (*GHTposX)== (*PMposX))
      (*life_Pacman) = 0;

Código do Fantasma Estruturado:

 int Calcula_dist(int X, int Y, int x, int y)
 {
    return sqrt(pow(X-x,2) + pow(Y-y,2));
 }
 void Controle_Ghost1(char **M, char *antGhost, int *PMposX, int *PMposY, int *GHTposX, int *GHTposY, int *life_Pacman)
 {
   int i;
   int j;
   int dist_menor;
   int GHTposX_menor;
   int GHTposY_menor;
   dist_menor = Calcula_dist((*GHTposX),(*GHTposY),(*PMposX),(*PMposY));
   GHTposX_menor = (*GHTposX) ;
   GHTposY_menor = (*GHTposY);
   if((M[(*GHTposY)][(*GHTposX) - 1] != 'H') && (Calcula_dist(((*GHTposX)-1),(*GHTposY),(*PMposX),(*PMposY)) < dist_menor))
   {
      GHTposX_menor = ((*GHTposX) - 1) ;
      GHTposY_menor = (*GHTposY);
   }
   if((M[(*GHTposY)][(*GHTposX) + 1] != 'H') && (Calcula_dist(((*GHTposX)+1),(*GHTposY),(*PMposX),(*PMposY)) < dist_menor))
   {
      GHTposX_menor = ((*GHTposX) + 1) ;
      GHTposY_menor = (*GHTposY);
   }
   if((M[((*GHTposY) - 1)][(*GHTposX)] != 'H') && (Calcula_dist((*GHTposX),((*GHTposY)-1),(*PMposX),(*PMposY)) < dist_menor))
   {
      GHTposX_menor = (*GHTposX);
      GHTposY_menor = ((*GHTposY) - 1);
   }
   if((M[((*GHTposY) + 1)][(*GHTposX)] != 'H') && (Calcula_dist((*GHTposX),((*GHTposY)+1),(*PMposX),(*PMposY)) < dist_menor))
   {
      GHTposX_menor = (*GHTposX);
      GHTposY_menor = ((*GHTposY) + 1);
   }
   if((*GHTposX) == GHTposX_menor && ((*GHTposY) == GHTposY_menor))
   {
      if( pow( ((*GHTposX)-1) - (*PMposX) ,2) < pow( ((*GHTposX) - (*PMposX)) ,2)  && M[(*GHTposY)][(*GHTposX)-1] != 'H' )
          GHTposX_menor = (*GHTposX)-1;
      else if( pow( ((*GHTposX)+1) - (*PMposX), 2) < pow( ((*GHTposX) - (*PMposX)), 2) && M[(*GHTposY)][(*GHTposX)+1]!= 'H' )
          GHTposX_menor = (*GHTposX)+1;
      if( pow( ((*GHTposY)-1) - (*PMposY) ,2) < pow( ((*GHTposY) - (*PMposY)) ,2) && M[(*GHTposY)-1][(*GHTposX)]!= 'H' )
          GHTposY_menor = (*GHTposY)-1;
      else if( pow( ((*GHTposY)+1) - (*PMposY), 2) < pow( ((*GHTposY) - (*PMposY)), 2) && M[(*GHTposY)+1][(*GHTposX)]!= 'H' )
          GHTposY_menor = (*GHTposY)+1;
   }
   /*APOS ENCONTRAR MELHOR POSIÇÃO PARA IR ATRAS DE PAC MAN*/
   if((*antGhost) == ' ')
      M[(*GHTposY)][(*GHTposX)] = ' ';
   if((*antGhost) == '.')
      M[(*GHTposY)][(*GHTposX)] = '.';
   if((*antGhost) == 'H')
      M[(*GHTposY)][(*GHTposX)] = 'H';
   (*GHTposX) = GHTposX_menor;
   (*GHTposY) = GHTposY_menor;
   (*antGhost) = M[(*GHTposY)][(*GHTposX)];
   if((*GHTposY) == (*PMposY) && (*GHTposX)== (*PMposX))
      (*life_Pacman) = 0;
 }

Passo 5: Construindo nossa arma Caça-Fantasmas

Passo 6: Construindo nossa Função Main

Aqui iremos contruir a função responsável por rodar todo o jogo, dando sentido e ordem para as funções(engrenagens) construídas anteriormente.

int main()
{
  int i, j;
  char **M;
  int dim = 20;               //Dimensão do mapa
  int Pontos_Maximos = 167;   //Numero de pontos total, Caso Pontos == Pontos_Máximos  ,então WIN!!
  int life = 1;               //Numero de Vidas do Pac-Man
  int Pontos = 0;             //Pontos adquiridor pelo Pac-man
  int PMposX = 1;             //Posição x inicial do Pac-Man
  int PMposY = 18;            //Posição y inicial do Pac-Man
  int Ghost1posX = 9 ;        //Posição x inicial do Fantasma1
  int Ghost1posY = 11 ;       //Posição y inicial do Fantasma1
  char ant_Ghost1 = ' ';      //Controle inicial de caracter o qual Fantasma1 esta sobreposto.
  char controle;
  M = Constroe_Mapa(dim);
  Constroe_Obstaculos(M);
  Imprime_Mapa(dim,&Pontos,PMposX,PMposY,Ghost1posX,Ghost1posY,M);
  while(life == 1 && Pontos != Pontos_Maximos)       //Jogo roda enquanto Pac-Man tiver vida e Nao tiver comido todos os pontos
  {
      controle = getch();
      if(controle == 'a' || controle == 'd' || controle == 's' || controle == 'w')
      {
          Controle_PacMan(M,&PMposX,&PMposY,controle,&Pontos);
          Controle_Ghost1(M,&ant_Ghost1,&PMposX,&PMposY, &Ghost1posX, &Ghost1posY, &life);
          Imprime_Mapa(dim,&Pontos,PMposX,PMposY,Ghost1posX,Ghost1posY,M);
      }
  }
  return 0;
}

Segunda Versão: PacMan e a Turma Completa de Fantasmas – TextoGrafico

Codigo Windons

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
void Imprime_Mapa(int dim, int *Pontos, int PacMan_pos_x, int PacMan_pos_y, int Ghost_posX, int Ghost_posY, char **M)
{
   int i, j;
   /*Recebe posição do Pac Man */
   M[PacMan_pos_y][PacMan_pos_x] = 'C';
   M[Ghost_posY][Ghost_posX] = 'A';
   system("cls");
   printf("\n               PAC MAN \n");
   for(i = 0; i< dim; i++)
   {
       printf("\n");
       for(j = 0 ; j<dim; j++)
           printf(" %c",M[i][j]);
   }
   printf("\nPONTOS: %d",(*Pontos));
   printf("\nMovimento: ");
} 
void Constroe_Obstaculos(char **M)
{
   /*LUGARES DOS FANTASMAS */
   M[10][9] = ' ';
   M[10][10] = ' ';
   M[11][9] = ' ';
   M[11][10] = ' ';
   /* CONTRUINDO OBSTACULOS*/
   /*BLOCO VERMELHO SUPERIOR ESQUERDO*/
   M[2][2] = 'H';
   M[2][3] = 'H';
   M[2][4] = 'H';
   M[3][2] = 'H';
   M[3][3] = ' ';
   M[3][4] = 'H';
   M[4][2] = 'H';
   M[4][3] = ' ';
   M[4][4] = 'H';
   M[5][2] = 'H';
   M[5][3] = 'H';
   M[5][4] = 'H';
   /*BLOCO AZUL SUPERIOR ESQUERDO*/
   M[2][6] = 'H';
   M[3][6] = 'H';
   M[4][6] = 'H';
   M[5][6] = 'H';
   M[2][7] = 'H';
   M[3][7] = 'H';
   M[4][7] = 'H';
   M[5][7] = 'H';
   /*BLOCO AZUL SUPERIOR DIREITO*/
   M[2][12] = 'H';
   M[3][12] = 'H';
   M[4][12] = 'H';
   M[5][12] = 'H';
   M[2][13] = 'H';
   M[3][13] = 'H';
   M[4][13] = 'H';
   M[5][13] = 'H';
   /*BLOCO VERMELHO SUPERIOR DIREITO*/
   M[2][15] = 'H';
   M[2][16] = 'H';
   M[2][17] = 'H';
   M[3][15] = 'H';
   M[3][16] = ' ';
   M[3][17] = 'H';
   M[4][15] = 'H';
   M[4][16] = ' ';
   M[4][17] = 'H';
   M[5][15] = 'H';
   M[5][16] = 'H';
   M[5][17] = 'H';
   /*BLOCO VERDE SUPERIOR*/
   M[1][9] = 'H';
   M[2][9] = 'H';
   M[3][9] = 'H';
   M[4][9] = 'H';
   M[5][9] = 'H';
   M[1][10] = 'H';
   M[2][10] = 'H';
   M[3][10] = 'H';
   M[4][10] = 'H';
   M[5][10] = 'H';
   /*BLOCO DIREITO AMARELHO*/
   M[7][1] = 'H';
   M[7][2] = 'H';
   M[7][3] = 'H';
   M[8][1] = 'H';
   M[9][3] = 'H';
   M[10][2] = 'H';
   M[10][3] = 'H';
   M[11][3] = 'H';
   M[12][1] = 'H';
   M[13][1] = 'H';
   M[13][2] = 'H';
   M[13][3] = 'H';
   /*BLOCOS MARRONS*/
    M[12][7] = 'H';
    M[12][12] = 'H';
   /*BLOCO ESQUERDO AMARELHO*/
   M[7][16] = 'H';
   M[7][17] = 'H';
   M[7][18] = 'H';
   M[8][18] = 'H';
   M[9][16] = 'H';
   M[10][16] = 'H';
   M[10][17] = 'H';
   M[11][16] = 'H';
   M[12][18] = 'H';
   M[13][18] = 'H';
   M[13][17] = 'H';
   M[13][16] = 'H';
   /*BLOCO ROXO ESQUERO*/
   M[7][5] = 'H';
   M[8][5] = 'H';
   M[9][5] = 'H';
   M[10][5] = 'H';
   M[11][5] = 'H';
   M[12][5] = 'H';
   M[9][6] = 'H';
   M[9][7] = 'H';
   M[10][6] = 'H';
   M[10][7] = 'H';
   /*BLOCO ROXO DIREITO*/
   M[7][14] = 'H';
   M[8][14] = 'H';
   M[9][14] = 'H';
   M[10][14] = 'H';
   M[11][14] = 'H';
   M[12][14] = 'H';
   M[9][13] = 'H';
   M[9][12] = 'H';
   M[10][13] = 'H';
   M[10][12] = 'H';
   /*BLOCO LARANJA SUPERIOR*/
   M[7][7] = 'H';
   M[7][8] = 'H';
   M[7][9] = 'H';
   M[7][10] = 'H';
   M[7][11] = 'H';
   M[7][12] = 'H';
   M[8][9] = 'H';
   M[8][10] = 'H';
   M[9][9] = 'H';
   M[9][10] = 'H';
   /*BLOCO LARANJA INFERIOR*/
   M[14][7] = 'H';
   M[14][8] = 'H';
   M[14][9] = 'H';
   M[14][10] = 'H';
   M[14][11] = 'H';
   M[14][12] = 'H';
   M[13][9] = 'H';
   M[13][10] = 'H';
   M[12][9] = 'H';
   M[12][10] = 'H';
   /*BLOCO VERMELHO INFERIOR ESQUERDO*/
   M[15][2] = 'H';
   M[15][3] = 'H';
   M[15][4] = 'H';
   M[16][2] = 'H';
   M[16][3] = ' ';
   M[16][4] = ' ';
   M[17][2] = 'H';
   M[17][3] = 'H';
   M[17][4] = 'H';
   M[14][5] = 'H';
   M[15][5] = 'H';
   M[16][5] = 'H';
   M[17][5] = 'H';
   /*BLOCO VERMELHO INFERIOR DIREITO*/
   M[15][15] = 'H';
   M[15][16] = 'H';
   M[15][17] = 'H';
   M[16][15] = ' ';
   M[16][16] = ' ';
   M[16][17] = 'H';
   M[17][15] = 'H';
   M[17][16] = 'H';
   M[17][17] = 'H';
   M[14][14] = 'H';
   M[15][14] = 'H';
   M[16][14] = 'H';
   M[17][14] = 'H';
   /*BLOCO AZUL SUPERIOR ESQUERDO*/
   M[16][7] = 'H';
   M[17][7] = 'H';
   /*BLOCO AZUL SUPERIOR DIREITO*/
   M[16][12] = 'H';
   M[17][12] = 'H';
   /*BLOCO VERDE SUPERIOR*/
   M[16][9] = 'H';
   M[17][9] = 'H';
   M[18][9] = 'H';
   M[16][10] = 'H';
   M[17][10] = 'H';
   M[18][10] = 'H';
}
void Controle_PacMan(char **M, int *PMposX, int *PMposY, char controle, int *Pontos)
{
   if(controle == 'a' )
   {
       if(M[(*PMposY)][(*PMposX)-1] == 'H')
       {
           /*Nao altera mapa*/
       }
       else
       {
           if(M[(*PMposY)][(*PMposX)-1] == '.')
               (*Pontos)++;
           M[(*PMposY)][(*PMposX)] = ' ';
           (*PMposX) = (*PMposX) - 1;
           M[(*PMposY)][(*PMposX)] = 'C';
       }
   }
   if(controle == 'd' )
   {
       if(M[(*PMposY)][(*PMposX)+1] == 'H')
       {
           /*Nao altera mapa*/
       }
       else
       {
           if(M[(*PMposY)][(*PMposX)+1] == '.')
               (*Pontos)++;
           M[(*PMposY)][(*PMposX)] = ' ';
           (*PMposX) = (*PMposX) + 1;
           M[(*PMposY)][(*PMposX)] = 'C';
       }
   }
   if(controle == 'w' )
   {
       if(M[(*PMposY)-1][(*PMposX)] == 'H')
       {
           /*Nao altera mapa*/
       }
       else
       {
           if(M[(*PMposY)-1][(*PMposX)] == '.')
               (*Pontos)++;
           M[(*PMposY)][(*PMposX)] = ' ';
           (*PMposY) = (*PMposY) - 1;
           M[(*PMposY)][(*PMposX)] = 'C';
       }
   }
   if(controle == 's' )
   {
       if(M[(*PMposY)+1][(*PMposX)] == 'H')
       {
           /*Nao altera mapa*/
       }
       else
       {
           if(M[(*PMposY)+1][(*PMposX)] == '.')
               (*Pontos)++;
           M[(*PMposY)][(*PMposX)] = ' ';
           (*PMposY) = (*PMposY) + 1;
           M[(*PMposY)][(*PMposX)] = 'C';
       }
   }
}
char** Constroe_Mapa(int dim)
{
   int i, j;
   char **M;
   M = (char**) malloc(dim *sizeof(char*));        /*Alocação de uma dimensão da sala*/
   for(i = 0; i < dim; i++)
   {
       M[i] = (char*) malloc(dim *sizeof(char));  /*Alocação da segunda dimensão da sala*/
       for(j = 0; j < dim; j++)
       {
           /*CONTRUÇÃO DO MAPA*/
           if(i == 0 || i == (dim-1) || j == 0 || j == (dim-1) )
               M[i][j] = 'H';
           else
           {
               M[i][j] = '.';
           }
       }
   }
   return M;
}
int Calcula_dist(int X, int Y, int x, int y)
{
   return sqrt(pow(X-x,2) + pow(Y-y,2));
}
void Controle_Ghost1(char **M, char *antGhost, int *PMposX, int *PMposY, int *GHTposX, int *GHTposY, int *life_Pacman)
{
   int i;
   int j;
   int dist_menor;
   int GHTposX_menor;
   int GHTposY_menor;
   dist_menor = Calcula_dist((*GHTposX),(*GHTposY),(*PMposX),(*PMposY));
   GHTposX_menor = (*GHTposX) ;
   GHTposY_menor = (*GHTposY);
   if((M[(*GHTposY)][(*GHTposX) - 1] != 'H') && (Calcula_dist(((*GHTposX)-1),(*GHTposY),(*PMposX),(*PMposY)) < dist_menor))
   {
       GHTposX_menor = ((*GHTposX) - 1) ;
       GHTposY_menor = (*GHTposY);
   }
   if((M[(*GHTposY)][(*GHTposX) + 1] != 'H') && (Calcula_dist(((*GHTposX)+1),(*GHTposY),(*PMposX),(*PMposY)) < dist_menor))
   {
       GHTposX_menor = ((*GHTposX) + 1) ;
       GHTposY_menor = (*GHTposY);
   }
   if((M[((*GHTposY) - 1)][(*GHTposX)] != 'H') && (Calcula_dist((*GHTposX),((*GHTposY)-1),(*PMposX),(*PMposY)) < dist_menor))
   {
       GHTposX_menor = (*GHTposX);
       GHTposY_menor = ((*GHTposY) - 1);
   }
   if((M[((*GHTposY) + 1)][(*GHTposX)] != 'H') && (Calcula_dist((*GHTposX),((*GHTposY)+1),(*PMposX),(*PMposY)) < dist_menor))
   {
       GHTposX_menor = (*GHTposX);
       GHTposY_menor = ((*GHTposY) + 1);
   }
   if((*GHTposX) == GHTposX_menor && ((*GHTposY) == GHTposY_menor))
   {
       if( pow( ((*GHTposX)-1) - (*PMposX) ,2) < pow( ((*GHTposX) - (*PMposX)) ,2)  && M[(*GHTposY)][(*GHTposX)-1] != 'H' )
           GHTposX_menor = (*GHTposX)-1;
       else if( pow( ((*GHTposX)+1) - (*PMposX), 2) < pow( ((*GHTposX) - (*PMposX)), 2) && M[(*GHTposY)][(*GHTposX)+1]!= 'H' )
           GHTposX_menor = (*GHTposX)+1;
       if( pow( ((*GHTposY)-1) - (*PMposY) ,2) < pow( ((*GHTposY) - (*PMposY)) ,2) && M[(*GHTposY)-1][(*GHTposX)]!= 'H' )
           GHTposY_menor = (*GHTposY)-1;
       else if( pow( ((*GHTposY)+1) - (*PMposY), 2) < pow( ((*GHTposY) - (*PMposY)), 2) && M[(*GHTposY)+1][(*GHTposX)]!= 'H' )
           GHTposY_menor = (*GHTposY)+1;
   }
   /*APOS ENCONTRAR MELHOR POSIÇÃO PARA IR ATRAS DE PAC MAN*/
   if((*antGhost) == ' ')
       M[(*GHTposY)][(*GHTposX)] = ' ';
   if((*antGhost) == '.')
       M[(*GHTposY)][(*GHTposX)] = '.';
   if((*antGhost) == 'H')
       M[(*GHTposY)][(*GHTposX)] = 'H';
   (*GHTposX) = GHTposX_menor;
   (*GHTposY) = GHTposY_menor;
   (*antGhost) = M[(*GHTposY)][(*GHTposX)];
   if((*GHTposY) == (*PMposY) && (*GHTposX)== (*PMposX))
       (*life_Pacman) = 0;
}
int main()
{
   int i, j;
   char **M;
   int dim = 20;
   int Pontos_Maximos = 0;
   int life = 1;
   int Pontos = 0;
   int PMposX = 1;
   int PMposY = 18;
   int Ghost1posX = 9 ;
   int Ghost1posY = 11 ;
   char ant_Ghost1 = ' ';
   /*
       int Ghost2posX = ;
       int Ghost2posY = ;
       int Ghost3posX = ;
       int Ghost3posY = ;
       int Ghost4posX = ;
       int Ghost4posY = ;
   */
   char controle;
   M = Constroe_Mapa(dim);
   Constroe_Obstaculos(M);
   Imprime_Mapa(dim,&Pontos,PMposX,PMposY,Ghost1posX,Ghost1posY,M);
   while(life == 1)
   {
       controle = getch();
       if(controle == 'a' || controle == 'd' || controle == 's' || controle == 'w')
       {
           Controle_PacMan(M,&PMposX,&PMposY,controle,&Pontos);
           Controle_Ghost1(M,&ant_Ghost1,&PMposX,&PMposY, &Ghost1posX, &Ghost1posY, &life);
           Imprime_Mapa(dim,&Pontos,PMposX,PMposY,Ghost1posX,Ghost1posY,M);
       }
   }
   return 0;
}

Codigo Linux

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <ncurses.h>
#define  TICKRATE 1000
void Imprime_Mapa(int dim, int *Pontos, int PacMan_pos_x, int PacMan_pos_y, int Ghost_posX, int Ghost_posY, char **M)
{
  int i, j;
  /*Recebe posição do Pac Man */
  M[PacMan_pos_y][PacMan_pos_x] = 'C';
  M[Ghost_posY][Ghost_posX] = 'A';
  clear();
  refresh();
  printw("\n               PAC MAN \n");
  for(i = 0; i< dim; i++)
  {
      printw("\n");
      for(j = 0 ; j<dim; j++)
          printw(" %c",M[i][j]);
  }
  refresh();
  printw("\nPONTOS: %d",(*Pontos));
  printw("\nMovimento: ");
  //clear();
  refresh();
}
void Constroe_Obstaculos(char **M)
{
  /*LUGARES DOS FANTASMAS */
  M[10][9] = ' ';
  M[10][10] = ' ';
  M[11][9] = ' ';
  M[11][10] = ' ';
  /* CONTRUINDO OBSTACULOS*/
  /*BLOCO VERMELHO SUPERIOR ESQUERDO*/
  M[2][2] = 'H';
  M[2][3] = 'H';
  M[2][4] = 'H';
  M[3][2] = 'H';
  M[3][3] = ' ';
  M[3][4] = 'H';
  M[4][2] = 'H';
  M[4][3] = ' ';
  M[4][4] = 'H';
  M[5][2] = 'H';
  M[5][3] = 'H';
  M[5][4] = 'H';
  /*BLOCO AZUL SUPERIOR ESQUERDO*/
  M[2][6] = 'H';
  M[3][6] = 'H';
  M[4][6] = 'H';
  M[5][6] = 'H';
  M[2][7] = 'H';
  M[3][7] = 'H';
  M[4][7] = 'H';
  M[5][7] = 'H';
  /*BLOCO AZUL SUPERIOR DIREITO*/
  M[2][12] = 'H';
  M[3][12] = 'H';
  M[4][12] = 'H';
  M[5][12] = 'H';
  M[2][13] = 'H';
  M[3][13] = 'H';
  M[4][13] = 'H';
  M[5][13] = 'H';
  /*BLOCO VERMELHO SUPERIOR DIREITO*/
  M[2][15] = 'H';
  M[2][16] = 'H';
  M[2][17] = 'H';
  M[3][15] = 'H';
  M[3][16] = ' ';
  M[3][17] = 'H';
  M[4][15] = 'H';
  M[4][16] = ' ';
  M[4][17] = 'H';
  M[5][15] = 'H';
  M[5][16] = 'H';
  M[5][17] = 'H';
  /*BLOCO VERDE SUPERIOR*/
  M[1][9] = 'H';
  M[2][9] = 'H';
  M[3][9] = 'H';
  M[4][9] = 'H';
  M[5][9] = 'H';
  M[1][10] = 'H';
  M[2][10] = 'H';
  M[3][10] = 'H';
  M[4][10] = 'H';
  M[5][10] = 'H';
  /*BLOCO DIREITO AMARELHO*/
  M[7][1] = 'H';
  M[7][2] = 'H';
  M[7][3] = 'H';
  M[8][1] = 'H';
  M[9][3] = 'H';
  M[10][2] = 'H';
  M[10][3] = 'H';
  M[11][3] = 'H';
  M[12][1] = 'H';
  M[13][1] = 'H';
  M[13][2] = 'H';
  M[13][3] = 'H';
  /*BLOCOS MARRONS*/
  M[12][7] = 'H';
  M[12][12] = 'H';
  /*BLOCO ESQUERDO AMARELHO*/
  M[7][16] = 'H';
  M[7][17] = 'H';
  M[7][18] = 'H';
  M[8][18] = 'H';
  M[9][16] = 'H';
  M[10][16] = 'H';
  M[10][17] = 'H';
  M[11][16] = 'H';
  M[12][18] = 'H';
  M[13][18] = 'H';
  M[13][17] = 'H';
  M[13][16] = 'H';
  /*BLOCO ROXO ESQUERO*/
  M[7][5] = 'H';
  M[8][5] = 'H';
  M[9][5] = 'H';
  M[10][5] = 'H';
  M[11][5] = 'H';
  M[12][5] = 'H';
  M[9][6] = 'H';
  M[9][7] = 'H';
  M[10][6] = 'H';
  M[10][7] = 'H';
  /*BLOCO ROXO DIREITO*/
  M[7][14] = 'H';
  M[8][14] = 'H';
  M[9][14] = 'H';
  M[10][14] = 'H';
  M[11][14] = 'H';
  M[12][14] = 'H';
  M[9][13] = 'H';
  M[9][12] = 'H';
  M[10][13] = 'H';
  M[10][12] = 'H';
  /*BLOCO LARANJA SUPERIOR*/
  M[7][7] = 'H';
  M[7][8] = 'H';
  M[7][9] = 'H';
  M[7][10] = 'H';
  M[7][11] = 'H';
  M[7][12] = 'H';
  M[8][9] = 'H';
  M[8][10] = 'H';
  M[9][9] = 'H';
  M[9][10] = 'H';
  /*BLOCO LARANJA INFERIOR*/
  M[14][7] = 'H';
  M[14][8] = 'H';
  M[14][9] = 'H';
  M[14][10] = 'H';
  M[14][11] = 'H';
  M[14][12] = 'H';
  M[13][9] = 'H';
  M[13][10] = 'H';
  M[12][9] = 'H';
  M[12][10] = 'H';
  /*BLOCO VERMELHO INFERIOR ESQUERDO*/
  M[15][2] = 'H';
  M[15][3] = 'H';
  M[15][4] = 'H';
  M[16][2] = 'H';
  M[16][3] = ' ';
  M[16][4] = ' ';
  M[17][2] = 'H';
  M[17][3] = 'H';
  M[17][4] = 'H';
  M[14][5] = 'H';
  M[15][5] = 'H';
  M[16][5] = 'H';
  M[17][5] = 'H';
  /*BLOCO VERMELHO INFERIOR DIREITO*/
  M[15][15] = 'H';
  M[15][16] = 'H';
  M[15][17] = 'H';
  M[16][15] = ' ';
  M[16][16] = ' ';
  M[16][17] = 'H';
  M[17][15] = 'H';
  M[17][16] = 'H';
  M[17][17] = 'H';
  M[14][14] = 'H';
  M[15][14] = 'H';
  M[16][14] = 'H';
  M[17][14] = 'H';
  /*BLOCO AZUL SUPERIOR ESQUERDO*/
  M[16][7] = 'H';
  M[17][7] = 'H';
  /*BLOCO AZUL SUPERIOR DIREITO*/
  M[16][12] = 'H';
  M[17][12] = 'H';
  /*BLOCO VERDE SUPERIOR*/
  M[16][9] = 'H';
  M[17][9] = 'H';
  M[18][9] = 'H';
  M[16][10] = 'H';
  M[17][10] = 'H';
  M[18][10] = 'H';
}
void Controle_PacMan(char **M, int *PMposX, int *PMposY, char controle, int *Pontos)
{
  if(controle == 'a' )
  {
      if(M[(*PMposY)][(*PMposX)-1] == 'H')
      {
          /*Nao altera mapa*/
      }
      else
      {
          if(M[(*PMposY)][(*PMposX)-1] == '.')
              (*Pontos)++;
          M[(*PMposY)][(*PMposX)] = ' ';
          (*PMposX) = (*PMposX) - 1;
          M[(*PMposY)][(*PMposX)] = 'C';
      }
  }
  if(controle == 'd' )
  {
      if(M[(*PMposY)][(*PMposX)+1] == 'H')
      {
          /*Nao altera mapa*/
      }
      else
      {
          if(M[(*PMposY)][(*PMposX)+1] == '.')
              (*Pontos)++;
          M[(*PMposY)][(*PMposX)] = ' ';
          (*PMposX) = (*PMposX) + 1;
          M[(*PMposY)][(*PMposX)] = 'C';
      }
  }
  if(controle == 'w' )
  {
      if(M[(*PMposY)-1][(*PMposX)] == 'H')
      {
          /*Nao altera mapa*/
      }
      else
      {
          if(M[(*PMposY)-1][(*PMposX)] == '.')
              (*Pontos)++;
          M[(*PMposY)][(*PMposX)] = ' ';
          (*PMposY) = (*PMposY) - 1;
          M[(*PMposY)][(*PMposX)] = 'C';
      }
  }
  if(controle == 's' )
  {
      if(M[(*PMposY)+1][(*PMposX)] == 'H')
      {
          /*Nao altera mapa*/
      }
      else
      {
          if(M[(*PMposY)+1][(*PMposX)] == '.')
              (*Pontos)++;
          M[(*PMposY)][(*PMposX)] = ' ';
          (*PMposY) = (*PMposY) + 1;
          M[(*PMposY)][(*PMposX)] = 'C';
      }
  }
}
char** Constroe_Mapa(int dim)
{
  int i, j;
  char **M;
  M = (char**) malloc(dim *sizeof(char*));        /*Alocação de uma dimensão da sala*/
  for(i = 0; i < dim; i++)
  {
      M[i] = (char*) malloc(dim *sizeof(char));  /*Alocação da segunda dimensão da sala*/
      for(j = 0; j < dim; j++)
      {
          /*CONTRUÇÃO DO MAPA*/
          if(i == 0 || i == (dim-1) || j == 0 || j == (dim-1) )
              M[i][j] = 'H';
          else
          {
              M[i][j] = '.';
          }
      }
  }
  return M;
}
int Calcula_dist(int X, int Y, int x, int y)
{
  return sqrt(pow(X-x,2) + pow(Y-y,2));
}
void Controle_Ghost1(char **M, char *antGhost, int *PMposX, int *PMposY, int *GHTposX, int *GHTposY, int *life_Pacman)
{
  int i;
  int j;
  int dist_menor;
  int GHTposX_menor;
  int GHTposY_menor;
  dist_menor = Calcula_dist((*GHTposX),(*GHTposY),(*PMposX),(*PMposY));
  GHTposX_menor = (*GHTposX) ;
  GHTposY_menor = (*GHTposY);
  if((M[(*GHTposY)][(*GHTposX) - 1] != 'H') && (Calcula_dist(((*GHTposX)-1),(*GHTposY),(*PMposX),(*PMposY)) < dist_menor))
  {
      GHTposX_menor = ((*GHTposX) - 1) ;
      GHTposY_menor = (*GHTposY);
  }
  if((M[(*GHTposY)][(*GHTposX) + 1] != 'H') && (Calcula_dist(((*GHTposX)+1),(*GHTposY),(*PMposX),(*PMposY)) < dist_menor))
  {
      GHTposX_menor = ((*GHTposX) + 1) ;
      GHTposY_menor = (*GHTposY);
  }
  if((M[((*GHTposY) - 1)][(*GHTposX)] != 'H') && (Calcula_dist((*GHTposX),((*GHTposY)-1),(*PMposX),(*PMposY)) < dist_menor))
  {
      GHTposX_menor = (*GHTposX);
      GHTposY_menor = ((*GHTposY) - 1);
  }
  if((M[((*GHTposY) + 1)][(*GHTposX)] != 'H') && (Calcula_dist((*GHTposX),((*GHTposY)+1),(*PMposX),(*PMposY)) < dist_menor))
  {
      GHTposX_menor = (*GHTposX);
      GHTposY_menor = ((*GHTposY) + 1);
  }
  if((*GHTposX) == GHTposX_menor && ((*GHTposY) == GHTposY_menor))
  {
      if( pow( ((*GHTposX)-1) - (*PMposX) ,2) < pow( ((*GHTposX) - (*PMposX)) ,2)  && M[(*GHTposY)][(*GHTposX)-1] != 'H' )
          GHTposX_menor = (*GHTposX)-1;
      else if( pow( ((*GHTposX)+1) - (*PMposX), 2) < pow( ((*GHTposX) - (*PMposX)), 2) && M[(*GHTposY)][(*GHTposX)+1]!= 'H' )
          GHTposX_menor = (*GHTposX)+1;
      if( pow( ((*GHTposY)-1) - (*PMposY) ,2) < pow( ((*GHTposY) - (*PMposY)) ,2) && M[(*GHTposY)-1][(*GHTposX)]!= 'H' )
          GHTposY_menor = (*GHTposY)-1;
      else if( pow( ((*GHTposY)+1) - (*PMposY), 2) < pow( ((*GHTposY) - (*PMposY)), 2) && M[(*GHTposY)+1][(*GHTposX)]!= 'H' )
          GHTposY_menor = (*GHTposY)+1;
  }
  /*APOS ENCONTRAR MELHOR POSIÇÃO PARA IR ATRAS DE PAC MAN*/
  if((*antGhost) == ' ')
      M[(*GHTposY)][(*GHTposX)] = ' ';
  if((*antGhost) == '.')
      M[(*GHTposY)][(*GHTposX)] = '.';
  if((*antGhost) == 'H')
      M[(*GHTposY)][(*GHTposX)] = 'H';
  (*GHTposX) = GHTposX_menor;
  (*GHTposY) = GHTposY_menor;
  (*antGhost) = M[(*GHTposY)][(*GHTposX)];
  if((*GHTposY) == (*PMposY) && (*GHTposX)== (*PMposX))
      (*life_Pacman) = 0;
}
int main()
{
  WINDOW *teste;
  int ch;
  initscr();
  noecho();
  cbreak();
  timeout(TICKRATE);
  keypad(stdscr, TRUE);
  int i, j;
  char **M;
  int dim = 20;
  int Pontos_Maximos = 0;
  int life = 1;
  int Pontos = 0;
  int PMposX = 1;
  int PMposY = 18;
  int Ghost1posX = 9 ;
  int Ghost1posY = 11 ;
  char ant_Ghost1 = ' ';
  /*
      int Ghost2posX = ;
      int Ghost2posY = ;
      int Ghost3posX = ;
      int Ghost3posY = ;
      int Ghost4posX = ;
      int Ghost4posY = ;
  */
  char controle;
  M = Constroe_Mapa(dim);
  Constroe_Obstaculos(M);
  Imprime_Mapa(dim,&Pontos,PMposX,PMposY,Ghost1posX,Ghost1posY,M);
  while(controle != 'x')
  {
      controle = getch();
      if(controle == 'a' || controle == 'd' || controle == 's' || controle == 'w')
      {
          Controle_PacMan(M,&PMposX,&PMposY,controle,&Pontos);
          Controle_Ghost1(M,&ant_Ghost1,&PMposX,&PMposY, &Ghost1posX, &Ghost1posY, &life);
          Imprime_Mapa(dim,&Pontos,PMposX,PMposY,Ghost1posX,Ghost1posY,M);
      }
  }
  endwin();
  return 0;
}

Versão 1: Simples, sem fantasma, sem gráfico, sem nada Código de exemplo funcional

Para todas as versões abaixo: tutorial do 0 sobre Allegro

Versão2 : Implementando gráficos sem animação, game ainda sem IA. parte de um pacman – Tem parte de um game pronto, utiliza a biblioteca graphics… a ideia é usar esse como exemplo e implementar com a Allegro

mais informações sobre Allegro

versão3: Adição de animação ao game. video-aulas tudo sobre sprites/animation com Allegro

versão4: Adicionar IA aos fantasmas. Artigo Intel explicando um pouco sobre IA

mais explicação sobre IA dos fantasmas Não há códigos prontos para essa parte…
Esboço