Skip to content

Instantly share code, notes, and snippets.

@thelinuxlich
Created July 25, 2026 12:30
Show Gist options
  • Select an option

  • Save thelinuxlich/806bdd97a4a4730eccc1a4dafec93403 to your computer and use it in GitHub Desktop.

Select an option

Save thelinuxlich/806bdd97a4a4730eccc1a4dafec93403 to your computer and use it in GitHub Desktop.
Jogo da Velha em Python gerado pelo Kimi K3 + oh-my-pi
"""Jogo da Velha (tic-tac-toe) para terminal.
Modos: Jogador vs Jogador e Jogador vs Computador.
IA: fácil (aleatória) e difícil (minimax — nunca perde).
Somente biblioteca padrão. Execute com: python3 jogo_da_velha.py
"""
import random
from functools import cache
VAZIO = " "
LINHAS_VITORIA = (
(0, 1, 2), (3, 4, 5), (6, 7, 8), # horizontais
(0, 3, 6), (1, 4, 7), (2, 5, 8), # verticais
(0, 4, 8), (2, 4, 6), # diagonais
)
# ---------------------------------------------------------------- tabuleiro
def vencedor(tab):
"""Retorna 'X' ou 'O' se alguém venceu, senão None."""
for a, b, c in LINHAS_VITORIA:
if tab[a] != VAZIO and tab[a] == tab[b] == tab[c]:
return tab[a]
return None
def casas_livres(tab):
"""Índices (0-8) das casas ainda vazias."""
return [i for i, casa in enumerate(tab) if casa == VAZIO]
def mostrar(tab):
"""Desenha o tabuleiro; casas vazias mostram o número da posição."""
def marca(i):
return tab[i] if tab[i] != VAZIO else str(i + 1)
linhas = [f" {marca(a)} | {marca(b)} | {marca(c)} " for a, b, c in ((0, 1, 2), (3, 4, 5), (6, 7, 8))]
print(("\n---+---+---\n").join(linhas))
print()
def limpar_tela():
print("\033[2J\033[H", end="")
# ---------------------------------------------------------------------- IA
@cache
def _minimax(tab, vez, eu):
"""Melhor (pontuação, jogada) para o jogador `eu` a partir de `tab`.
Pontuação: positiva = vitória de `eu` (maior se mais rápida),
negativa = derrota (menor se mais rápida), 0 = empate.
"""
ganhador = vencedor(tab)
livres = casas_livres(tab)
if ganhador or not livres:
profundidade = 9 - len(livres)
if ganhador == eu:
return 10 - profundidade, None
if ganhador is not None:
return profundidade - 10, None
return 0, None
adversario = "O" if vez == "X" else "X"
melhor_jogada, melhor_pontos = None, float("-inf") if vez == eu else float("inf")
for casa in livres:
pontos, _ = _minimax(tab[:casa] + (vez,) + tab[casa + 1:], adversario, eu)
if vez == eu and pontos > melhor_pontos:
melhor_jogada, melhor_pontos = casa, pontos
elif vez != eu and pontos < melhor_pontos:
melhor_jogada, melhor_pontos = casa, pontos
return melhor_pontos, melhor_jogada
def jogada_computador(tab, dificuldade):
"""Fácil: casa aleatória. Difícil: minimax (o computador é sempre 'O')."""
if dificuldade == "facil":
return random.choice(casas_livres(tab))
return _minimax(tuple(tab), "O", "O")[1]
# -------------------------------------------------------------------- input
def ler_opcao(prompt, validas):
"""Lê uma opção entre `validas`; repete até receber entrada válida."""
while True:
try:
entrada = input(prompt).strip().lower()
except (EOFError, KeyboardInterrupt):
print("\nAté a próxima!")
raise SystemExit(0)
if entrada in validas:
return entrada
print(f"Opção inválida. Escolha entre: {', '.join(validas)}.")
def ler_jogada(tab, jogador):
"""Lê uma jogada (1-9) válida e em casa livre."""
while True:
try:
entrada = input(f"Jogador {jogador}, escolha uma casa (1-9): ").strip()
except (EOFError, KeyboardInterrupt):
print("\nAté a próxima!")
raise SystemExit(0)
if not entrada.isdigit() or not 1 <= int(entrada) <= 9:
print("Digite um número inteiro de 1 a 9.")
continue
casa = int(entrada) - 1
if tab[casa] != VAZIO:
print("Essa casa já está ocupada. Tente outra.")
continue
return casa
# -------------------------------------------------------------------- jogo
def jogar_partida(modo, dificuldade=None):
"""Roda uma partida. modo: 'pvp' ou 'pvc'. No 'pvc', humano é 'X' e começa."""
tab = [VAZIO] * 9
vez = "X"
while True:
limpar_tela()
print("=== Jogo da Velha ===\n")
mostrar(tab)
if modo == "pvc" and vez == "O":
casa = jogada_computador(tab, dificuldade)
print(f"Computador jogou na casa {casa + 1}.")
input("Pressione Enter para continuar...")
else:
casa = ler_jogada(tab, vez)
tab[casa] = vez
if vencedor(tab) or not casas_livres(tab):
break
vez = "O" if vez == "X" else "X"
limpar_tela()
print("=== Jogo da Velha ===\n")
mostrar(tab)
ganhador = vencedor(tab)
if ganhador is None:
print("Empate! Deu velha.")
elif modo == "pvc":
print("Você venceu! Parabéns!" if ganhador == "X" else "O computador venceu!")
else:
print(f"Jogador {ganhador} venceu! Parabéns!")
def menu_principal():
"""Loop principal: escolhe modo, joga e permite repetir sem reiniciar."""
while True:
limpar_tela()
print("=== Jogo da Velha ===\n")
print("1 - Jogador vs Jogador")
print("2 - Jogador vs Computador")
print("3 - Sair\n")
opcao = ler_opcao("Escolha uma opção (1-3): ", ("1", "2", "3"))
if opcao == "3":
print("Até a próxima!")
return
if opcao == "1":
modo, dificuldade = "pvp", None
else:
modo = "pvc"
print("\nDificuldade:")
print("1 - Fácil (jogadas aleatórias)")
print("2 - Difícil (imbatível)\n")
dificuldade = "facil" if ler_opcao("Escolha (1-2): ", ("1", "2")) == "1" else "dificil"
while True:
jogar_partida(modo, dificuldade)
if ler_opcao("\nJogar novamente? (s/n): ", ("s", "n")) == "n":
break
if __name__ == "__main__":
menu_principal()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment