Advertisement
Luz_Azevedo

2048 completo

Jul 12th, 2019
510
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.66 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4.  
  5. #define TAM 4
  6.  
  7. typedef struct
  8. {
  9.     int linha, coluna;
  10. } Posicao;
  11.  
  12. typedef struct
  13. {
  14.     int mat[TAM][TAM];
  15.     int maiorNum[1];
  16.     int menorNum[1];
  17. } Tabuleiro;
  18.  
  19. typedef struct
  20. {
  21.     char nome[3];
  22.     double tempo;
  23. } Player;
  24.  
  25. void removeEnter(char v[])
  26. {
  27.     int i;
  28.     for(i = 0; v[i] != '\0'; i++)
  29.         if(v[i] == '\n')
  30.         {
  31.             v[i] = '\0';    // substitui o '\n' por '\0'
  32.             break;
  33.         }
  34. }
  35.  
  36. //retorta 1 caso sejam iguais, 0 caso não
  37. int matrizesIguais(int mat1[][TAM], int mat2[][TAM])
  38. {
  39.     int i, j;
  40.     for(i = 0; i < TAM; i++)
  41.         for(j = 0; j < TAM; j++)
  42.             if(mat1[i][j] != mat2[i][j])
  43.                 return 0;
  44.     return 1;
  45. }
  46.  
  47. //retorta 1 caso sejam iguais, 0 caso não
  48. int stringsIguais(char v[], char s[])
  49. {
  50.     int i;
  51.     for(i = 0; v[i] != '\0' && s[i] != '\0'; i++)
  52.         if (v[i] != s[i])
  53.             return 0;
  54.     return 1;
  55. }
  56.  
  57. Tabuleiro atualizaTabuleiro(Tabuleiro tab, char opcao)
  58. {
  59.     int i, j, k;
  60.     switch(opcao)
  61.     {
  62.     case 'w':
  63.     case 'W':
  64.         for(j = 0; j < TAM ; j++)   //lê as colunas da esquerda para a direita
  65.         {
  66.             for(i = 0; i < TAM ; i++) //lê as linhas de cima para baixo
  67.             {
  68.                 if(!tab.mat[i][j])  //caso o elemento seja nulo
  69.                 {
  70.                     for(k = i + 1; k < TAM ; k++) //percorre aquela coluna ate achar um elemento nao-nulo
  71.                         if(tab.mat[k][j])
  72.                         {
  73.                             tab.mat[i][j] = tab.mat[k][j]; //coloca o elemento nao nulo no primeiro elemento nulo daquela coluna
  74.                             tab.mat[k][j] = 0;      //o lugar do elemento nao nulo torna-se nulo
  75.                             break;
  76.                         }
  77.                 }
  78.             }
  79.             for(i = 0; i < TAM - 1; i++) // soma os numeros caso eles sejam iguais
  80.             {
  81.                 if(tab.mat[i + 1][j] == tab.mat[i][j])
  82.                 {
  83.                     tab.mat[i][j] *= 2;
  84.                     for(k = i + 1; k < TAM - 1 && tab.mat[k + 1][j] != 0; k++)
  85.                         tab.mat[k][j] = tab.mat[k + 1][j];
  86.                     tab.mat[k][j] = 0;
  87.                 }
  88.             }
  89.         }
  90.  
  91.         break;
  92.  
  93.     case 'a':
  94.     case 'A':
  95.         for(i = 0; i < TAM ; i++)// lê as linhas de cima para baixo
  96.         {
  97.             for(j = 0; j < TAM ; j++)   //lê as colunas da esquerda para a direita
  98.             {
  99.                 if(!tab.mat[i][j])    //caso o elemento seja nulo
  100.                 {
  101.                     for(k = j + 1; k < TAM ; k++) //percorre aquela linha ate achar um elemento nao-nulo
  102.                         if(tab.mat[i][k])
  103.                         {
  104.                             tab.mat[i][j] = tab.mat[i][k];  //coloca o elemento nao nulo no primeiro elemento nulo daquela linha
  105.                             tab.mat[i][k] = 0;        //o lugar do elemento nao nulo torna-se nulo
  106.                             break;
  107.                         }
  108.                 }
  109.             }
  110.             for(j = 0; j < TAM - 1; j++)
  111.             {
  112.                 if(tab.mat[i][j + 1] == tab.mat[i][j])
  113.                 {
  114.                     tab.mat[i][j] *= 2;
  115.                     for(k = j + 1; k < TAM - 1 && tab.mat[i][k + 1] != 0; k++)
  116.                         tab.mat[i][k] = tab.mat[i][k + 1];
  117.                     tab.mat[i][k] = 0;
  118.                 }
  119.             }
  120.         }
  121.  
  122.         break;
  123.  
  124.     case 's':
  125.     case 'S':
  126.         for(j = 0; j < TAM ; j++)  //lê as colunas da esquerda para a direita
  127.         {
  128.             for(i = TAM - 1; i >= 0 ; i--)  //lê as linhas da baixo para cima
  129.             {
  130.                 if(!tab.mat[i][j])    //caso o elemento seja nulo
  131.                 {
  132.                     for(k = i - 1 ; k >= 0 ; k--) //percorre aquela coluna de baixo para cima ate achar um elemento nao-nulo
  133.                         if(tab.mat[k][j])
  134.                         {
  135.                             tab.mat[i][j] = tab.mat[k][j]; //coloca o elemento nao nulo no ultimo elemento nulo daquela coluna
  136.                             tab.mat[k][j] = 0;        //o lugar do elemento nao nulo torna-se nulo
  137.                             break;
  138.                         }
  139.                 }
  140.             }
  141.             for(i = TAM - 1; i > 0 ; i--)
  142.             {
  143.                 if(tab.mat[i - 1][j] == tab.mat[i][j])
  144.                 {
  145.                     tab.mat[i][j] *= 2;
  146.                     for(k = i - 1; k > 0 && tab.mat[k - 1][j] != 0; k--)
  147.                         tab.mat[k][j] = tab.mat[k - 1][j];
  148.                     tab.mat[k][j] = 0;
  149.                 }
  150.             }
  151.         }
  152.  
  153.         break;
  154.  
  155.     case 'd':
  156.     case 'D':
  157.         for(i = 0; i < TAM ; i++)  // lê as linhas de cima para baixo
  158.         {
  159.             for(j = TAM - 1; j >= 0 ; j--)  //lê as colunas da direita para a esquerda
  160.             {
  161.                 if(!tab.mat[i][j])    //caso o elemento seja nulo
  162.                 {
  163.                     for(k = j - 1; k >= 0; k--) //percorre aquela linha da direita para a esquerda ate achar um elemento nao-nulo
  164.                         if(tab.mat[i][k])
  165.                         {
  166.                             tab.mat[i][j] = tab.mat[i][k]; //coloca o elemento nao nulo no ultimo elemento nulo daquela linha
  167.                             tab.mat[i][k] = 0;        //o lugar do elemento nao nulo torna-se nulo
  168.                             break;
  169.                         }
  170.                 }
  171.             }
  172.             for(j = TAM - 1; j > 0 ; j--)
  173.             {
  174.                 if(tab.mat[i][j - 1] == tab.mat[i][j])
  175.                 {
  176.                     tab.mat[i][j] *= 2;
  177.                     for(k = j - 1; k > 0 && tab.mat[i][k - 1] != 0; k--)
  178.                         tab.mat[i][k] = tab.mat[i][k - 1];
  179.                     tab.mat[i][k] = 0;
  180.                 }
  181.             }
  182.         }
  183.  
  184.         break;
  185.     }
  186.     return tab;
  187. }
  188.  
  189. void imprimeTabuleiro(int mat[][TAM])
  190. {
  191.     printf("\n");
  192.     printf("\t\t16\n");
  193.     printf("\t       ======\n\n");
  194.     int i, j;
  195.     for(i = 0; i < TAM; i++)
  196.     {
  197.         printf("\t ");
  198.         for(j = 0; j < TAM; j++)
  199.             if (mat[i][j] != 0)
  200.             {
  201.                 printf("|%3d ", mat[i][j]);
  202.             }
  203.             else
  204.                 printf("|    ");
  205.         printf("|\n");
  206.     }
  207.     printf("\n\n");
  208.     printf("\t\t^\n");
  209.     printf("\t\tw\n");
  210.     printf("\t    <a     d>\n");
  211.     printf("\t\ts\n");
  212.     printf("\t\tv");
  213. }
  214.  
  215.  
  216. //percorre a matriz até achar o maior e o menor numero dela
  217. Tabuleiro checaMaiorMenor(Tabuleiro tab)
  218. {
  219.     int i, j;
  220.     tab.maiorNum[0] = 0;
  221.     tab.menorNum[0] = 0;
  222.     for(i = 0; i < TAM; i++)
  223.     {
  224.         for(j = 0; j < TAM; j++)
  225.         {
  226.             if (tab.maiorNum[0] < tab.mat[i][j])
  227.                 tab.maiorNum[0] = tab.mat[i][j];
  228.             if (tab.menorNum[0] > tab.mat[i][j])
  229.                 tab.menorNum[0] = tab.mat[i][j];
  230.         }
  231.     }
  232.     return tab;
  233. }
  234.  
  235. int acabouJogo(int mat[][TAM])
  236. {
  237.     int i, j, aux = 1;
  238.     for(i = 0; i < TAM; i++)
  239.         for(j = 0; j < TAM; j++)
  240.         {
  241.             if(mat[i][j] == 16)
  242.                 return 1;
  243.             if(aux == 1)
  244.             {
  245.                 if(mat[i][j] == 0)
  246.                     aux = 0;
  247.                 else if(aux == 1)
  248.                 {
  249.                     if(i - 1 >= 0)
  250.                         if(mat[i - 1][j] == mat[i][j])
  251.                             aux = 0;
  252.                     if(i + 1 < TAM)
  253.                         if(mat[i + 1][j] == mat[i][j])
  254.                             aux = 0;
  255.                     if(j - 1 >= 0)
  256.                         if(mat[i][j - 1] == mat[i][j])
  257.                             aux = 0;
  258.                     if(j + 1 < TAM)
  259.                         if(mat[i][j + 1] == mat[i][j])
  260.                             aux = 0;
  261.                 }
  262.             }
  263.         }
  264.     if(aux)
  265.         return -1;
  266.     return 0;
  267. }
  268.  
  269. Tabuleiro jogo()
  270. {
  271.     Tabuleiro tab, controle, controle1; //variavel do tabuleiro e duas variaveis de controle para comparação
  272.     char direcao; //direção de rotação do tabuleiro escolhida pelo jogador
  273.  
  274.     //variaveis auxiliares
  275.     int novoNum;
  276.     int i, j;
  277.     Posicao posicao;
  278.  
  279.     srand(time(NULL));
  280.  
  281.  
  282.     //preenche o tabuleiro com 0
  283.     for(i = 0; i < TAM; i++)
  284.     {
  285.         for(j = 0; j < TAM; j++)
  286.         {
  287.             tab.mat[i][j] = 0;
  288.         }
  289.     }
  290.     controle = tab;
  291.  
  292.     do
  293.     {
  294.         tab = checaMaiorMenor(tab);
  295.  
  296.         //gera um 2 ou um 4 para colocar no tabuleiro
  297.         novoNum = rand() % 2 + 1;
  298.         novoNum *= 2;
  299.  
  300.         //procura uma posição nula aleatória para armazenar o novo numero gerado
  301.         if (tab.menorNum[0] == 0)
  302.         {
  303.             do
  304.             {
  305.                 posicao.linha = rand() % TAM;
  306.                 posicao.coluna = rand() % TAM;
  307.             }
  308.             while(tab.mat[posicao.linha][posicao.coluna]);
  309.         }
  310.         tab.mat[posicao.linha][posicao.coluna] = novoNum;
  311.  
  312.  
  313.         printf("\n\n");
  314.         system("cls");
  315.         imprimeTabuleiro(tab.mat);
  316.  
  317.         controle = tab;
  318.         do
  319.         {
  320.             scanf("%c%*c", &direcao);
  321.             while(direcao != 'w' && direcao != 'a' && direcao != 's' && direcao != 'd' && direcao != 'W' && direcao != 'A' && direcao != 'S' && direcao != 'D')
  322.             {
  323.                 scanf("%c%*c", &direcao);
  324.             }
  325.             tab = atualizaTabuleiro(tab, direcao);
  326.  
  327.             //rotaciona controle1 para verificar se existe algum movimento possivel
  328.             controle1 = tab;
  329.             controle1 = atualizaTabuleiro(controle1, 'w');
  330.             controle1 = atualizaTabuleiro(controle1, 'a');
  331.             controle1 = atualizaTabuleiro(controle1, 's');
  332.             controle1 = atualizaTabuleiro(controle1, 'd');
  333.  
  334.         }
  335.         //faz tudo isso enquanto há movimentos possíveis e a movimentação não mudar o tabuleiro
  336.         //(ex.: a pessoa aperta w 500x mesmo não existindo mais nenhum movimento apertando a tecla w)
  337.         while(matrizesIguais(tab.mat, controle.mat) && !(matrizesIguais(tab.mat, controle1.mat)));
  338.  
  339.  
  340.         //imprime o novo tabuleiro rotacionado
  341.         system("cls");
  342.         imprimeTabuleiro(tab.mat);
  343.         tab = checaMaiorMenor(tab);
  344.     }
  345.     //verifica se a pessoa terminou o jogo ou se não há mais movimentos possíveis
  346.     while(!acabouJogo(tab.mat));
  347.     system("cls");
  348.     return tab;
  349. }
  350.  
  351.  
  352.  
  353. void salvaRank(Player player[], double tempo_de_cpu)
  354. {
  355.     FILE *ranking;
  356.     int i, j, numJogadores, aux;
  357.  
  358.     for(numJogadores = 0; player[numJogadores].tempo != -1 ; numJogadores++);// conta o numero de nomes que ja foram salvos
  359.  
  360.     //caso o numero de jogadores no rank ja seja maximo e o tempo da pessoa foi maior que o ultimo colocado
  361.     if(numJogadores == 5 && tempo_de_cpu > player[5].tempo)
  362.         return;
  363.  
  364.     //adiciona o player na sua posição no board já ordenado
  365.     aux = 1;
  366.     for(i = 0; i < numJogadores; i++)
  367.     {
  368.         if(tempo_de_cpu < player[i].tempo)
  369.             for(j = numJogadores; j > i; j--)
  370.             {
  371.                 if(j < 5)
  372.                     player[j] = player[j - 1];
  373.  
  374.                 printf("\n\n\tDigite 3 letras: a");
  375.                 fgets(player[i].nome, 4, stdin);
  376.                 removeEnter(player[i].nome);
  377.                 player[i].tempo = tempo_de_cpu;
  378.                 aux = 0;
  379.                 numJogadores++;
  380.                 break;
  381.             }
  382.         if (aux == 0)
  383.             break;
  384.     }
  385.  
  386.     //caso o nome da pessoa não tenha sido adicionado, coloca-o em ultimo
  387.     if(aux)
  388.     {
  389.         printf("\n\n\tDigite 3 letras: b");
  390.         fgets(player[i].nome, 4, stdin);
  391.         removeEnter(player[i].nome);
  392.         player[i].tempo = tempo_de_cpu;
  393.         numJogadores++;
  394.     }
  395.  
  396.     //salva o novo board de ranking no .txt
  397.     ranking = fopen("Ranking.txt", "w");
  398.     if(ranking == NULL)
  399.     {
  400.         system("cls");
  401.         printf("Erro");
  402.         system("pause");
  403.         exit(-1);
  404.     }
  405.  
  406.  
  407.     for(i = 0; i < numJogadores && i < 5; i++)
  408.     {
  409.         fprintf(ranking, "%s\n", player[i].nome);
  410.         fprintf(ranking, "%lf\n", player[i].tempo);
  411.     }
  412. }
  413.  
  414. void imprimeRank(Player player[])
  415. {
  416.     //imprime o ranking atual
  417.     int i;
  418.     system("cls");
  419.     printf("\n\n\t\t  16\n");
  420.     printf("\t         ======\n\n");
  421.     printf("\t      FIM DE JOGO!\n");
  422.     printf("\t     ==============\n\n");
  423.     printf("\n\t\tRANKING:\n");
  424.     printf("\t       ==========\n\n");
  425.     printf("\tLUGAR     NOME      TEMPO\n");
  426.     for(i = 0; i < 5; i++)
  427.     {
  428.         if(player[i].tempo < 0)
  429.             break;
  430.         printf("\t");
  431.         printf("   %d      %-10s   ", i + 1, player[i].nome);
  432.         printf("      %.3lf", player[i].tempo);
  433.         printf("\n");
  434.     }
  435. }
  436.  
  437. void rank(Player player[])
  438. {
  439.     /*
  440.  
  441.     Talvez o outro erro que mencionei esteja aqui, não faço ideia tho, deem uma olhada por essas funções de ranking
  442.     a logica delas é meio estranha, entao se precisarem que eu explique, só me chamar
  443.  
  444.     */
  445.     // abre e coleta os dados no .txt
  446.     int i;
  447.     FILE *ranking;
  448.     ranking = fopen("Ranking.txt", "a");
  449.  
  450.     //preenche o tempo de todos os players com -1 para contagem do numero de players futuramente
  451.     for(i = 0; i < 5 ; i++)
  452.         player[i].tempo = -1;
  453.  
  454.  
  455.     //coloca um EOF no final para comparações futuras
  456.     if(ranking == NULL)
  457.     {
  458.         system("cls");
  459.         printf("Erro");
  460.         system("pause");
  461.         exit(-1);
  462.     }
  463.     fprintf(ranking, "\n%c", EOF);
  464.     fclose(ranking);
  465.  
  466.     ranking = fopen("Ranking.txt", "r");
  467.     if(ranking == NULL)
  468.     {
  469.         system("cls");
  470.         printf("Erro");
  471.         system("pause");
  472.         exit(-1);
  473.     }
  474.  
  475.     for (i = 0; i < 5 && (int)ranking != EOF; i++)
  476.     {
  477.         fgets(player[i].nome, 5, ranking);
  478.         removeEnter(player[i].nome);
  479.         fscanf(ranking, "%lf%*c", &player[i].tempo);
  480.     }
  481.     fclose(ranking);
  482. }
  483.  
  484. void instrucoes()
  485. {
  486.     system("cls");
  487.     printf("\n\n\t\t  16\n");
  488.     printf("\t         ======\n\n");
  489.     printf("\t1: Digite as teclas W, A, S e D para mover a grade\n");
  490.     printf("\t2: Quando voce junta numeros iguais, eles se somam\n");
  491.     printf("\t3: Tente chegar a 2048!\n\n");
  492.     printf("Aperte qualquer tecla para continuar\n");
  493.     scanf("%*c");
  494. }
  495.  
  496. int main(int argc, char** argv)
  497. {
  498.     Tabuleiro tab;
  499.     clock_t inicio, fim;
  500.     double tempo_de_cpu;
  501.     Player player[5];
  502.     char opcao, opcao1;
  503.  
  504.     do
  505.     {
  506.         opcao = 'k';
  507.         do
  508.         {
  509.             system("cls");
  510.             printf("\n\n\t\t  16\n");
  511.             printf("\t         ======\n\n");
  512.             printf("\tJ:JOGAR\n");
  513.             printf("\tI:INSTRUCOES\n");
  514.             printf("\tS:SAIR\n");
  515.             scanf("%c%*c", &opcao);
  516.         }
  517.         while(opcao != 'j' && opcao != 'J' && opcao != 'i' && opcao != 'I' && opcao != 's' && opcao != 'S');
  518.  
  519.         switch(opcao)
  520.         {
  521.         case 'j':
  522.         case 'J':
  523.            
  524.             //conta o tempo de jogo
  525.             inicio = clock();
  526.  
  527.             tab = jogo();
  528.  
  529.             fim  = clock();
  530.             tempo_de_cpu = ((double)(fim - inicio)) / CLOCKS_PER_SEC;
  531.  
  532.  
  533.             //chama as funções de exibição de fim de jogo
  534.             if(tab.maiorNum[0] == 16)
  535.             {
  536.                 rank(player);
  537.                 salvaRank(player, tempo_de_cpu);
  538.                 imprimeRank(player);
  539.             }
  540.             else
  541.             {
  542.                 rank(player);
  543.                 imprimeRank(player);
  544.             }
  545.             break;
  546.  
  547.         case 'i':
  548.         case 'I':
  549.             instrucoes();
  550.             break;
  551.         case 's':
  552.         case 'S':
  553.             break;
  554.         }
  555.         if (opcao == 'j' || opcao == 'J')
  556.         {
  557.             opcao1 = 'k';
  558.             system("cls");
  559.             printf("\n\n\tDIGITE J PARA JOGAR NOVAMENTE\n\tOU QUALQUER OUTRA LETRA PARA SAIR!");
  560.             scanf("%c1%*c", &opcao1);
  561.         }
  562.  
  563.     }
  564.     while(opcao1 == 'j' || opcao1 == 'J' || opcao == 'i' || opcao == 'I');
  565.  
  566.     return 0;
  567. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement