Como programar o Jogo da Velha em C

Jogo da Velha em CAgora que já ensinamos os conceitos básicos da linguagem C, os testes condicionais e loopings, Funções e Vetores (matrizes), vamos colocar em prática nossos conhecimentos para criar algo interessante:
O Famoso Jogo da Velha

Nesse tutorial vamos ensinar as regras como se jogar em nosso aplicativo, bem como a lógica do jogo.
É importante você tentar fazer o seu, pois só assim você irá aprender.

Não tenha medo, a primeira vez que tentamos, o código fica gigantesco e confuso.
Mas o começo é assim mesmo.

No próximo artigo, vamos comentar cada parte do código aqui mostrado, ensinando passo-a-passo como se cria o jogo.

Cliqui aqui se quiser ver o código e lógica comentada do Jogo da Velha em C.

Como jogar o Jogo da Velha

O jogo da velha é um jogo para duas pessoas.
A estrutura do jogo é apenas um tabuleiro 3x3 posições, onde os jogadores marcam ou 'X' ou 'O' em cada campo do tabuleiro.

Para vencer o jogo, um dos jogadores deve preencher uma linha, uma coluna ou uma diagonal inteira com 'X' ou 'O'. O primeiro que fizer isso vence, e o jogo termina.
Caso o tabuleiro fique totalmente preenchido e ninguém ganhar, teremos um empate.

Nessa versão de nosso jogo, o primeiro jogador será representado pelo 'X' e o segundo pelo 'O'.

Como nosso aplicativo roda na tela de comandos (DOS ou Terminal), a cada jogada precisamos fornecer dois números que representam a posição do tabuleiro em que queremos jogar: a linha e a coluna, nessa ordem.
As linhas, bem como as colunas, variam de 1 até 3 e somente os locais vazios podem ser escolhidos como jogada.

Lembrando que a linha é horizontal e coluna é vertical.

Recomendações

Com base nas regras acima, tente criar seu próprio jogo da velha.
Essa tentativa provavelmente vai ser frustrada. Não deixe se abater se não souber nem por onde começar.

Como recomendamos várias vezes ao longo do curso, faça por partes.
Tente exibir na tela o tabuleiro, atrás de uma matriz 3x3.
Peça ao usuário o número da linha e da coluna.
Lembre-se: a cada jogada, é um dos dois jogadores que irá jogar, sempre alternando.
Faça com que o primeiro marque um 'X' na tela e o segundo um 'O'.

Evite usar números mágicos, use #define DIM.
Deixe sua função main() a mais enxuta e limpa possível.
Divida ao máximo seu programa em funções, onde cada função deve fazer uma tarefa de cada vez.

Evite usar fflush() ou system().
Para evitar fflush(), você pode usar as funções getchar() ou trabalhar com números.
Em vez de usar system("cls") caso use Windows, ou system("clear") caso use Linux, simplesmente imprima na tela vários caracteres de newline.
Pois, como já havíamos dito, essas funções são lentas e há problemas de segurança ao usar elas.

Embora nosso curso seja focado nos iniciantes, é importante você adquirir esses hábitos desde o início, para eliminar os vícios.

Uma outra maneira de você treinar, é vendo o tutorial comentado do código do Jogo da Velha em C, sem olhar pro código, e tentar criar a partir do que você entendeu da lógica do programa.

Código completo do Jogo da Velha em C


#include <stdio.h>
#define DIM 3
int vez;
 
int menu(void);
void clear(void);
void zeraTabuleiro(int tabuleiro[][DIM]);
void exibeTabuleiro(int tabuleiro[][DIM]);
void jogar(int tabuleiro[][DIM]);
int checaLocal(int tabuleiro[][DIM], int linha, int coluna);
int checaLinha(int tabuleiro[][DIM]);
int checaColuna(int tabuleiro[][DIM]);
int checaDiagonal(int tabuleiro[][DIM]);
int checaEmpate(int tabuleiro[][DIM]);
int checaTermino(int tabuleiro[][DIM], int vez);
void jogada(int tabuleiro[][DIM]);
 
int main(void)
{
    int tabuleiro[DIM][DIM],
        continuar;
 
    do
    {
        vez=1;
        continuar = menu();
        if(continuar == 1)
            jogar(tabuleiro);
 
    }while(continuar);
 
    return 0;
}
 
int menu(void)
{
    int opcao;
 
        printf("\t\tJogo da Velha 1.0 - Site C Progressivo\n");
        printf("\n1.Jogar\n");
        printf("0.Sair\n");
        printf("\nOpcao: ");
 
        scanf("%d", &opcao);
 
        switch(opcao)
        {
           case 1:
           case 0:
                break;
           default:
                clear();
                printf("Opcao invalida. Tente de novo!\n");
        }
 
    return opcao;
}
 
void clear(void)
{
    int count=0;
 
    while(count != 100)
    {
        putchar('\n');
        count++;
    }
}
 
void zeraTabuleiro(int tabuleiro[][DIM])
{
    int linha, coluna;
    for(linha = 0 ; linha < DIM ; linha++)
        for(coluna = 0 ; coluna < DIM ; coluna++)
            tabuleiro[linha][coluna] = 0;
}
 
void exibeTabuleiro(int tabuleiro[][DIM])
{
    int linha, coluna;
    putchar('\n');
 
    for(linha = 0 ; linha < DIM ; linha++)
    {
        for(coluna = 0 ; coluna < DIM ; coluna++)
        {
            if(tabuleiro[linha][coluna] == 0)
                printf("    ");
            else
                if(tabuleiro[linha][coluna] == 1)
                    printf("  X ");
                else
                    printf("  O ");
 
            if(coluna != (DIM-1))
                printf("|");
        }
        putchar('\n');
    }
    putchar('\n');
}
 
void jogar(int tabuleiro[][DIM])
{
    int continua;
    zeraTabuleiro(tabuleiro);
 
    do
    {
        clear();
        exibeTabuleiro(tabuleiro);
        jogada(tabuleiro);
 
    }while(checaTermino(tabuleiro, vez) != 1);
}
 
 
int checaLocal(int tabuleiro[][DIM], int linha, int coluna)
{
    if(linha < 0 || linha > (DIM-1) || coluna < 0 || coluna > (DIM-1) || tabuleiro[linha][coluna] != 0)
        return 0;
    else
        return 1;
}
 
int checaLinha(int tabuleiro[][DIM])
{
    int linha, coluna,
        soma;
 
    for(linha = 0 ; linha < DIM ; linha++)
    {
        soma=0;
 
        for(coluna = 0 ; coluna < DIM ; coluna++)
            soma += tabuleiro[linha][coluna];
 
        if(soma==DIM || soma == (-1)*DIM)
            return 1;
    }
 
    return 0;
}
 
int checaColuna(int tabuleiro[][DIM])
{
    int linha, coluna,
        soma;
 
 
    for(coluna = 0 ; coluna < DIM ; coluna++)
    {
        soma=0;
 
        for(linha = 0 ; linha < DIM ; linha++)
            soma += tabuleiro[linha][coluna];
 
        if(soma==DIM || soma == (-1)*DIM)
            return 1;
    }
 
    return 0;
}
 
int checaDiagonal(int tabuleiro[][DIM])
{
    int linha,
        diagonal_principal=0,
        diagonal_secundaria=0;
 
    for(linha = 0 ; linha < DIM ; linha++)
    {
        diagonal_principal += tabuleiro[linha][linha];
        diagonal_secundaria += tabuleiro[linha][DIM-linha-1];
    }
 
    if(diagonal_principal==DIM || diagonal_principal==(-1)*DIM ||
       diagonal_secundaria==DIM || diagonal_secundaria==(-1)*DIM)
       return 1;
 
    return 0;
}
 
int checaEmpate(int tabuleiro[][DIM])
{
    int linha, coluna;
 
    for(linha = 0 ; linha < DIM ; linha++)
        for(coluna = 0 ; coluna < DIM ; coluna++)
            if(tabuleiro[linha][coluna] == 0)
                return 0;
 
    return 1;
}
 
int checaTermino(int tabuleiro[][DIM], int vez)
{
    if(checaLinha(tabuleiro))
    {
        printf("Jogo encerrado. Jogador %d venceu !\n\n", (vez%2)+1);
        exibeTabuleiro(tabuleiro);
        return 1;
    }
 
    if(checaColuna(tabuleiro))
    {
        printf("Jogo encerrado. Jogador %d venceu !\n\n", (vez%2)+1);
        exibeTabuleiro(tabuleiro);
        return 1;
    }
 
    if(checaDiagonal(tabuleiro))
    {
        printf("Jogo encerrado. Jogador %d venceu !\n\n", (vez%2)+1);
        exibeTabuleiro(tabuleiro);
        return 1;
    }
 
    if(checaEmpate(tabuleiro))
    {
        printf("Jogo encerrado. Ocorreu um empate! !\n\n");
        exibeTabuleiro(tabuleiro);
        return 1;
    }
 
    return 0;
}
 
void jogada(int tabuleiro[][DIM])
{
    int linha, coluna;
    vez++;
    printf("\n--> Jogador %d \n", (vez % 2) + 1);
 
    do
    {
        printf("Linha: ");
        scanf("%d", &linha);
        linha--;
 
        printf("Coluna: ");
        scanf("%d", &coluna);
        coluna--;
 
        if(checaLocal(tabuleiro, linha, coluna) == 0)
            printf("Posicao ocupada ou inexistente, escolha outra.\n");
 
    } while(checaLocal(tabuleiro, linha, coluna) == 0);
 
    if(vez%2)
        tabuleiro[linha][coluna] = -1;
    else
        tabuleiro[linha][coluna] = 1;
}
 

9 comentários:

fmarkes disse...

nao obtive sucesso na execução, verifiquei duas vezes o codigo e nao tive erros de compilacao mas a execução abriu a tela de informação

"it seems that this file has not been built yet.
do you want to build it now?"

se dou sim nada acontece se dou nao acontece isso

Process returned 1979577481 <0x75FDF489> execution time : 0.001 s
Press any key to continue.

Alex disse...

Eu fiz o Meu!!!!
E ficou bem + legal q o d v6 hehehe...
Pena q por ser muito Grande ñ pude Postar aki :(
OBRIGADO C Progressivo!!!!!
Esta me Ajudando MUITO MUITO MUITO!!!
Ate o prossimo exercicio ;)

Antonio Souza disse...

Fmarkes eu fis assim no Linux.
gcc jogodavelha.c -o jogodavelha
./jogodavelha

E rodou direitinho.

Vinícius Miani disse...

Opa, muito legal o site.
Só não entendi uma parte
int tabuleiro[][DIM])

Quando você chama a função tem que passar os argumentos, pq o primeiro você não passou. O que isso significa?

Obrigado.

Apostila de C disse...

Olá Vinícius,

Para passar um vetor para uma função, você pode passar somente como: vetor[]

Não precisa passar o número de elementos, pois na verdade está passando um endereço (do primeiro elemento).

No cato de uma vetor multidimensional (Matriz), você pode passar como: matriz[][Dimensao]

Leia mais em:
http://www.cprogressivo.net/2013/03/Como-passar-vetores-arrays-e-Matrizes-vetores-multidimensionais-para-funcoes-emC.html

Qualquer dúvida, é só perguntar.

Farofa disse...

olá, c progressivo! Obrigado pelo incrivel curso! Tem me ajudado demais. Eu consegui fazer o jogo ao meu jeito mas não sei se está de uma maneira digamos "dentro das boas práticas". Porque funciono,mas tem uns códigos estranhos. Gostaria de mandar meu código para correção,voces fariam isso?
eu colei o meu código no site pastebin, o link :


http://pastebin.com/bMuKRvwX


Obrigado pela atenção

Raphael Mouta disse...

Gosto muito dos materiais deste site!

Eu fiz a minha versão do jogo da velha... E com todo o respeito, ficou bem melhor! Mas posso dizer que o resultado que obtive foi por merecimento da equipe que desenvolveu este curso, pois tudo que fiz foi com grande ajuda do que aprendi aqui! Vlw galera do C Progressivo, vcs são fera d+! Abração!

John Rambo disse...

Oi gente.
Tenho muitas dúvidas em C, com por exemplo manipulaçao de arquivos, processamento de texto e manipulaçao de pixels, afinal, se der e me ajudarem, faço um
#include curso_de_c_extremo
entrem em contato:
qwqwqw3013@yahoo.com.br

Manuel Curral disse...

Olá , funcionou direitinho e o programa esta bem simples!

Tenho só uma dúvida no código que é: "continuar" o que é e para que serve não encontrei a declaração dela (sei que existe "continua" e ela esta declarada como variável).
Conheço a palavra reservada "continue" que avança para a próxima iteração dentro de um ciclo.

Gostou desse tutorial de C?
Sabia que o acervo do portal C Progressivo é o mesmo, ou maior que, de um livro ou curso presencial?
E o melhor: totalmente gratuito.

Mas para nosso projeto se manter é preciso divulgação.
Para isso, basta curtir nossa página no Facebook e/ou clicar no botão +1 do Google.
Contamos e precisamos de seu apoio.