Lucas Stefano

Jogo da Velha em C

· Lucas Stefano

Eu tinha feito há algum tempo atrás o mesmo jogo em Java, mas não tinha gostado muito do meu código-fonte. Era ineficiente e longo demais. Daí que resolvi refazê-lo, agora em C. Demorei cerca de três horas para terminar.

A inteligência da CPU é bem simples. Ela primeiro testa se existe a possibilidade de ganhar o jogo no ato, e, se houver, ela joga para ganhar. Se não tiver como vencer, ela tenta se defender, testando se existe alguma forma de o jogador ganhar na próxima jogada dele. Se existir, ela se defende.

Pra jogar em uma posição vazia (representada por 0) é só digitar a linha e a coluna, que variam de 1 a 3, separadas por um espaço.

  1/* ***********************************
  2   * Autor: Lucas Stefano 
  3   * Data: 20/12/2023
  4   ***********************************
  5*/
  6 
  7#include <stdio.h>
  8#include <stdlib.h>
  9 
 10#define LINHAS  3
 11#define COLUNAS 3
 12#define CASAS   9
 13 
 14void init_tabuleiro(void);
 15void mostra_tabuleiro(void);
 16void jogada_player(void);
 17void jogada_cpu(void);
 18int update_tabuleiro(int x, int y); // retorna 0 se a operação for bem sucedida
 19int testa_vencedor(void); // 2 - vitória cpu, 1 - vitória player, 0 - nada aconteceu
 20int velha(void); // conta o número de casas vazias no tabuleiro
 21 
 22enum vez { PLAYER, CPU } jogador;
 23 
 24int tabuleiro[LINHAS][COLUNAS];
 25 
 26void main() {
 27    int escolha, status;
 28    jogador = PLAYER; // seta o primeiro jogador para player
 29    init_tabuleiro(); // inicia o tabuleiro com 0s
 30 
 31    while(1) {
 32        if (jogador == PLAYER) {
 33            if (!velha()) break;
 34            mostra_tabuleiro();
 35            jogada_player();
 36            status = testa_vencedor();
 37            if (status) break;
 38        }
 39        if (jogador == CPU) {
 40            if (!velha()) break;
 41            jogada_cpu();
 42            status = testa_vencedor();
 43            if (status) break;
 44        }
 45    }
 46 
 47    mostra_tabuleiro();
 48 
 49    if (status == 1) printf("\nParabéns, você venceu!\n");
 50    else if (status == 2) printf("\nVocê perdeu! :(\n");
 51    else printf("\nDeu velha!\n");
 52 
 53    while(1) {
 54        printf("\nJogar novamente? (1 = sim / 2 = não) : ");
 55        scanf("%d", &escolha);
 56        if (escolha == 1) main();
 57        else if (escolha == 2) exit(0);
 58        else printf("\nEscolha invalida!");
 59    }
 60}
 61 
 62void init_tabuleiro() {
 63    register int i;
 64    int *p;
 65    p = (int *) tabuleiro;
 66 
 67    for (i = 0; i < CASAS; i++ ) *(p+i) = 0;
 68}
 69 
 70int velha() {
 71    register int i;
 72    int *p, zeros = 0;
 73    p = (int *) tabuleiro;
 74 
 75    for (i = 0; i < CASAS; i++ ) if (*(p+i) == 0) zeros++;
 76 
 77    if (!zeros) return 0;
 78    else return 1;
 79}
 80 
 81void mostra_tabuleiro() {
 82    register int i, j;
 83    printf("\n");
 84 
 85    for (i = 0; i < 3; i++) {
 86        for (j = 0; j < 3; j++) {
 87            printf("%d", tabuleiro[i][j]);
 88        }
 89        printf("\n");
 90    }
 91}
 92 
 93int update_tabuleiro(int x, int y) {
 94    if (jogador == PLAYER) {
 95            tabuleiro[x][y] = 1;
 96            jogador = CPU;
 97            return 0;
 98        }
 99    if (jogador == CPU) {
100        if (tabuleiro[x][y] != 0) return 1;
101        else {
102            tabuleiro[x][y] = 2;
103            jogador = PLAYER;
104            return 0;
105        }
106    }
107}
108 
109void jogada_player() {
110    int x, y;
111    printf("\nDigite a linha e a coluna em que deseja jogar: ");
112    scanf("%d %d", &x, &y);
113 
114    x--, y--;
115 
116    if (tabuleiro[x][y] != 0 || x < 0 || x > 2 || y < 0 || y > 2) {
117        printf("\nJogada inválida.\n");
118        jogada_player();
119    }
120    else update_tabuleiro(x, y);
121}
122 
123void jogada_cpu() {
124    register int i, j, x, y;
125    int ad; // ataque e defesa. Quando 'ad' vale 2, a cpu testa a possibilidade de ataque.
126            // se valer 1, ela testa por defesa.
127 
128    // série de testes que verificará se há possibilidade de o jogador ou a CPU vencer
129    // o jogo em alguma linha, alguma coluna ou alguma diagonal.
130 
131    for (ad = 2; ad >= 1; ad--) {
132        for (i = 0; i < 3; i++) { // para todas as linhas e colunas
133            if (tabuleiro[i][1] == ad && tabuleiro[i][2] == ad) 
134                if (!update_tabuleiro(i, 0)) return;
135            if (tabuleiro[i][0] == ad && tabuleiro[i][2] == ad) 
136                if (!update_tabuleiro(i, 1)) return;
137            if (tabuleiro[i][0] == ad && tabuleiro[i][1] == ad) 
138                if (!update_tabuleiro(i, 2)) return;
139            if (tabuleiro[1][i] == ad && tabuleiro[2][i] == ad) 
140                if (!update_tabuleiro(0, i)) return;
141            if (tabuleiro[0][i] == ad && tabuleiro[2][i] == ad) 
142                if (!update_tabuleiro(1, i)) return;
143            if (tabuleiro[0][i] == ad && tabuleiro[1][i] == ad) 
144                if (!update_tabuleiro(2, i)) return;
145        }
146 
147        // para as diagonais
148        if (tabuleiro[0][0] == ad && tabuleiro[2][2] == ad) 
149            if (!update_tabuleiro(1, 1)) return;
150        if (tabuleiro[0][2] == ad && tabuleiro[2][0] == ad) 
151            if (!update_tabuleiro(1, 1)) return;
152        if (tabuleiro[0][2] == ad && tabuleiro[1][1] == ad) 
153            if (!update_tabuleiro(2, 0)) return;
154        if (tabuleiro[2][2] == ad && tabuleiro[1][1] == ad) 
155            if (!update_tabuleiro(0, 0)) return;
156        if (tabuleiro[2][0] == ad && tabuleiro[1][1] == ad) 
157            if (!update_tabuleiro(0, 2)) return;
158        if (tabuleiro[0][0] == ad && tabuleiro[1][1] == ad) 
159            if (!update_tabuleiro(2, 2)) return;
160    }
161 
162    // caso nenhum dos testes acima sejam satisfeitos, a cpu joga aleatoriamente
163 
164    srand(time(NULL));
165 
166    while(1) {
167        x = rand() % 3;
168        y = rand() % 3;
169        if (!update_tabuleiro(x,y)) return;
170    }
171}
172 
173int testa_vencedor() {
174    register int i;
175    int a = (jogador == CPU) ? 1 : 2; // 'a' varia de acordo com quem o chama
176 
177    for (i = 0; i < 3; i++)
178        if (tabuleiro[i][0] == a && tabuleiro[i][1] == a && tabuleiro[i][2] == a) return a;
179    for (i = 0; i < 3; i++)
180        if (tabuleiro[0][i] == a && tabuleiro[1][i] == a && tabuleiro[2][i] == a) return a;
181 
182    if (tabuleiro[2][0] == a && tabuleiro[1][1] == a && tabuleiro[0][2] == a) return a;
183    if (tabuleiro[0][0] == a && tabuleiro[1][1] == a && tabuleiro[2][2] == a) return a;
184 
185    return 0;
186}

#c   #jogo