Jogo da velha em Python
Aprenda a criar um jogo da velha simples em Python. Aplique conceitos do Python estruturando e construindo a lógica do jogo.
Construiremos um jogo da velha para dois jogadores, que será jogado pela linha de comando.
Inicialmente, construiremos um tabuleiro vazio e depois receberemos e interpretaremos informações das entradas dos jogadores.
Após isso verificaremos se a entrada é possível e não fere as regras do jogo, como marcar um local já preenchido, por exemplo.
Dado a entrada válida, verificaremos a condição de vitória e declararemos o jogador vencedor, ou se todo o tabuleiro for preenchido e ninguém ganhar, declararemos o resultado como “Empate”, ou como chamamos na minha região: “Velha”.
Conhecendo o jogo da velha
O jogo da velha é uma “brincadeira” milenar, também conhecido por jogo do galo ou tic-tac-toe.
Alguns historiadores de jogos(sim, isso existe) dizem que existem registros de tabuleiros 3 × 3 do jogo esculpidos em pedra ainda no Antigo Egito.
A versão mais aceita é que o jogo adquiriu esse nome quando era jogado por senhoras idosas nas cortes europeias que já não tinham a visão tão boa para bordar, porém, isto não é confirmado.
Para mais detalhes e mais versões do jogo veja este artigo.
Regras
- O jogo da velha é jogado em um tabuleiro 3 × 3 por dois jogadores, que alternadamente colocam as marcas X e 0 em um dos nove espaços da grade. No exemplo a seguir, o primeiro jogador (X) ganha o jogo em sete etapas:
-
Não existe uma regra universalmente aceita sobre quem joga primeiro, mas neste artigo a convenção de que X joga primeiro é utilizada.
-
Os jogadores se revezam colocando suas marcas em quadrados vazios.
-
O jogador que conseguir colocar três de suas marcas em uma linha horizontal, vertical ou diagonal é o vencedor.
-
Quando todos os 9 quadrados estiverem marcados, o jogo termina. Se nenhum jogador tiver 3 marcas consecutivas, o jogo termina empatado.
Construindo o jogo
Construiremos o jogo utilizando Python
, portanto é necessário instala-lo na sua máquina.
Este é um projeto simples, porém você necessita conhecer alguns conceitos básicos da linguagem:
- Conhecimento básico de
Python
- Conhecer e saber utilizar dicionários em Python.
-
- Conhecer e saber utilizar listas e tuplas em Python.
- Conhecer estruturas de repetição(for e while) em Python.
- Condicionais, classes e funções em
Python
.
Inicialmente criaremos uma classe chamada “JogoDaVelha”, inicialmente vazia.
class JogoDaVela:
def _init__():
...
Tabuleiro
Para representar o tabuleiro utilizaremos um dicionário.
Primeiro, veremos como utilizaremos um dicionário para criar nosso tabuleiro de jogo.
Um dicionário é um tipo de dado primitivo em Python
que armazena dados no formato “chave: valor”.
Para representar o tabuleiro criaremos um dicionário com 9 chaves, e cada chave representará um bloco no tabuleiro e seu valor correspondente representará a jogada feita por um jogador.
O tabuleiro é numerado como o teclado numérico do teclado.
Criaremos um método para exibir o tabuleiro.
class JogoDaVela:
tabuleiro = {'7': ' ' , '8': ' ' , '9': ' ',
'4': ' ' , '5': ' ' , '6': ' ',
'1': ' ' , '2': ' ' , '3': ' '}
def _init__():
...
def exibirTabuleiro(self):
print("┌───┬───┬───┐")
print(f"│ {self.tabuleiro['7']} │ {self.tabuleiro['8']} │ {self.tabuleiro['9']} │")
print("├───┼───┼───┤")
print(f"│ {self.tabuleiro['4']} │ {self.tabuleiro['5']} │ {self.tabuleiro['6']} │")
print("├───┼───┼───┤")
print(f"│ {self.tabuleiro['1']} │ {self.tabuleiro['2']} │ {self.tabuleiro['3']} │")
print("└───┴───┴───┘")
Instanciaremos a classe JogoDaVela
na variável jogo
, depois exibiremos o tabuleiro apenas para verificar se tudo
está como desejado.
jogo = JogoDaVela()
jogo.exibirTabuleiro()
A saída será como isto:
┌───┬───┬───┐
│ │ │ │
├───┼───┼───┤
│ │ │ │
├───┼───┼───┤
│ │ │ │
└───┴───┴───┘
Verificando se a jogada é válida
Definiremos uma variável para o jogador responsável pelo próximo turno.
Também adicionaremos um parâmetro na função __init__
para definir o jogador inicial, que por padrão será o X
.
class JogoDaVela:
...
turno = None
def __init__(self, jogador_inicial="X"):
self.turno = jogador_inicial
...
Criaremos um método para verificar se a jogada é válida.
class JogoDaVela:
...
def verificarJogada(self, jogada):
if jogada in self.tabuleiro.keys():
if self.tabuleiro[jogada] == " ":
return True
return False
...
Na primeira condicional é verificado se a jogada é uma das nove posições possíveis no tabuleiro e na segunda verifica se a posição ainda está vazia.
Você pode estar se perguntando: por que utilizar duas condicionais e não apenas uma com o operador and
como no exemplo
abaixo?
class JogoDaVela:
...
def verificarJogada(self, jogada):
if jogada in self.tabuleiro.keys() and self.tabuleiro[jogada] == " ":
return True
return False
...
A resposta é simples, se fizer dessa maneira, caso a chave jogada
não esteja no dicionário tabuleiro
um erro
ocorrerá.
Verificando o resultado do jogo
Agora criaremos um método que irá verificar o estado do tabuleiro, se já temos um vencedor ou se podemos declarar um empate.
Para isto, basta verificar se algum jogador preencheu 3 casas consecutivas.
class JogoDaVela:
...
def verificarTabuleiro(self):
# Verificações das 3 verticais
if self.tabuleiro['7'] == self.tabuleiro['4'] == self.tabuleiro['1'] != ' ':
return self.tabuleiro['7']
elif self.tabuleiro['8'] == self.tabuleiro['5'] == self.tabuleiro['2'] != ' ':
return self.tabuleiro['8']
elif self.tabuleiro['9'] == self.tabuleiro['6'] == self.tabuleiro['3'] != ' ':
return self.tabuleiro['9']
# Verificações das 3 horizontais
elif self.tabuleiro['7'] == self.tabuleiro['8'] == self.tabuleiro['9'] != ' ':
return self.tabuleiro['7']
elif self.tabuleiro['4'] == self.tabuleiro['5'] == self.tabuleiro['6'] != ' ':
return self.tabuleiro['8']
elif self.tabuleiro['1'] == self.tabuleiro['2'] == self.tabuleiro['3'] != ' ':
return self.tabuleiro['1']
# Verificações das 2 diagonais
elif self.tabuleiro['7'] == self.tabuleiro['5'] == self.tabuleiro['3'] != ' ':
return self.tabuleiro['7']
elif self.tabuleiro['1'] == self.tabuleiro['5'] == self.tabuleiro['9'] != ' ':
return self.tabuleiro['1']
# Verificando empate
if [*self.tabuleiro.values()].count(' ') == 0:
return "empate"
else:
return [*self.tabuleiro.values()].count(' ')
...
Caso algum jogador tenha preenchido 3 casas consecutivas é retornado o vencedor.
Caso a condição acima não ocorra, e caso todas as casas já estejam ocupadas(a quantidade de casas vazias seja igual a
zero), é retornado empate
.
Se nem uma das duas condições forem verdadeiras, é retornado a quantidade de casas que ainda faltam serem preenchidas.
Montando o jogo
Agora com os métodos essenciais já definidos, criaremos o método jogar
que será responsável pela comunicação com os
jogadores, lendo as jogadas e fazendo as chamadas para os métodos já definidos.
class JogoDaVela:
...
def jogar(self):
while True:
self.exibirTabuleiro()
print(f"Turno do {self.turno}, qual sua jogada?")
# Enquanto o jogador não fizer uma jogada válida
while True:
jogada = input("Jogada: ")
if self.verificarJogada(jogada): # Se a jogada for válida...
break # Encerra o loop
else:
print(f"jogado do {self.turno} inválida, jogue novamente.")
self.tabuleiro[jogada] = self.turno
estado = self.verificarTabuleiro()
if estado == "X":
print("X é o vencedor!!!")
break
elif estado == "O":
print("O é o vencedor!!!")
break
if estado == "empate":
print("EMPATE!!!")
break
# Troca o jogador do próximo turno
self.turno = "X" if self.turno == "O" else "O"
...
Em cada iteração é exibido o tabuleiro, após isso ocorre a leitura da jogada, temos a então a verificação do estado do tabuleiro, caso o jogo ainda não esteja finalizado é iniciado um novo turno alternando o jogador responsável pela jogada.
Conclusão
Para construir esse jogo é necessário apenas um conhecimento básico de Python
.
Caso tenha dificuldade em entender o tabuleiro
recomendo esse artigo sobre dicionários.
Caso tenha dificuldade em entender o loop
de execução do jogo, recomendo
esse artigo sobre iteração(for e while).
Caso queira ver outras formas de exibir informações com o usuário, recomendo esse artigo sobre a função print.
Abaixo temos o código completo caso não tenha conseguido acompanhar todas as etapas durante o artigo.
class JogoDaVela:
tabuleiro = {'7': ' ', '8': ' ', '9': ' ', '4': ' ', '5': ' ', '6': ' ', '1': ' ', '2': ' ', '3': ' '}
turno = None
def __init__(self, jogador_inicial="X"):
self.turno = jogador_inicial
def exibir_tabuleiro(self):
print("┌───┬───┬───┐")
print(f"│ {self.tabuleiro['7']} │ {self.tabuleiro['8']} │ {self.tabuleiro['9']} │")
print("├───┼───┼───┤")
print(f"│ {self.tabuleiro['4']} │ {self.tabuleiro['5']} │ {self.tabuleiro['6']} │")
print("├───┼───┼───┤")
print(f"│ {self.tabuleiro['1']} │ {self.tabuleiro['2']} │ {self.tabuleiro['3']} │")
print("└───┴───┴───┘")
def verificar_jogada(self, jogada):
if jogada in self.tabuleiro.keys():
if self.tabuleiro[jogada] == " ":
return True
return False
def verificar_tabuleiro(self):
# Verificações das 3 verticais
if self.tabuleiro['7'] == self.tabuleiro['4'] == self.tabuleiro['1'] != ' ':
return self.tabuleiro['7']
elif self.tabuleiro['8'] == self.tabuleiro['5'] == self.tabuleiro['2'] != ' ':
return self.tabuleiro['8']
elif self.tabuleiro['9'] == self.tabuleiro['6'] == self.tabuleiro['3'] != ' ':
return self.tabuleiro['9']
# Verificações das 3 horizontais
elif self.tabuleiro['7'] == self.tabuleiro['8'] == self.tabuleiro['9'] != ' ':
return self.tabuleiro['7']
elif self.tabuleiro['4'] == self.tabuleiro['5'] == self.tabuleiro['6'] != ' ':
return self.tabuleiro['8']
elif self.tabuleiro['1'] == self.tabuleiro['2'] == self.tabuleiro['3'] != ' ':
return self.tabuleiro['1']
# Verificações das 2 diagonais
elif self.tabuleiro['7'] == self.tabuleiro['5'] == self.tabuleiro['3'] != ' ':
return self.tabuleiro['7']
elif self.tabuleiro['1'] == self.tabuleiro['5'] == self.tabuleiro['9'] != ' ':
return self.tabuleiro['1']
# Verificando empate
if [*self.tabuleiro.values()].count(' ') == 0:
return "empate"
else:
return [*self.tabuleiro.values()].count(' ')
def jogar(self):
while True:
self.exibir_tabuleiro()
print(f"Turno do {self.turno}, qual sua jogada?")
# Enquanto o jogador não fizer uma jogada válida
while True:
jogada = input("Jogada: ")
if self.verificar_jogada(jogada): # Se a jogada for válida...
break # Encerra o loop
else:
print(f"jogado do {self.turno} inválida, jogue novamente.")
self.tabuleiro[jogada] = self.turno
estado = self.verificar_tabuleiro()
if estado == "X":
print("X é o vencedor!!!")
break
elif estado == "O":
print("O é o vencedor!!!")
break
if estado == "empate":
print("EMPATE!!!")
break
# Troca o jogador do próximo turno
self.turno = "X" if self.turno == "O" else "O"
self.exibir_tabuleiro()
jogo = JogoDaVela()
jogo.jogar()