Created
July 25, 2026 12:30
-
-
Save thelinuxlich/806bdd97a4a4730eccc1a4dafec93403 to your computer and use it in GitHub Desktop.
Jogo da Velha em Python gerado pelo Kimi K3 + oh-my-pi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """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