import random alfabeto = "abcdefghi" nome_um = "\N{WHITE CIRCLE}" nome_dois = "\N{BLACK CIRCLE}" exemplo = { "tamanho": 4, "jogadas": ["1ab", "23a", "12a", "12c", "1bc", "12b", "2ab","2bc"], nome_um: ["1b"], nome_dois: ["1c"], } def cria_jogo(tamanho): pass def jogadas_válidas(jogo): pass def arestas_do_quadrado(quadrado): pass def jogo_acabou(jogo): pass def jogador_humano(jogo, vez): pass def jogador_aleatório(jogo, vez): pass # você pode mudar o nome da próxima função se quiser def jogador_guloso(jogo, vez): pass # você pode mudar o nome da próxima função se quiser def jogador_que_você_criou(jogo, vez): pass ############################################# ####### Funções prontas (não editar): ####### ############################################# def mostra(jogo): """ Imprime na tela uma representação gráfica da situação atual do jogo de Dots and Boxes """ p = "\N{MIDDLE DOT}" h = "\N{HORIZONTAL BAR}" * 3 v = "\N{VERTICAL LINE}" s = "\n" tamanho = jogo["tamanho"] for i in range(tamanho): # imprimir arestas horizontais na linha de rótulo tamanho-i s += f"{tamanho - i:<{1 + len(str(tamanho))}}" s += p for j in range(tamanho - 1): letra_atual = alfabeto[j] próxima_letra = alfabeto[j + 1] if f"{tamanho - i}{letra_atual}{próxima_letra}" in jogo["jogadas"]: s += h else: s += " " * len(h) s += p s += "\n" # imprimir arestas verticais entre linhas tamanho-i e tamanho-i-1 s += " " * (1 + len(str(tamanho))) if i < tamanho - 1: for j, letra in enumerate(alfabeto[:tamanho]): if j > 0: if f"{tamanho - i - 1}{letra}" in jogo[nome_um]: s += f" {nome_um} " elif f"{tamanho - i - 1}{letra}" in jogo[nome_dois]: s += f" {nome_dois} " else: s += " " * len(h) if f"{tamanho - i - 1}{tamanho - i}{letra}" in jogo["jogadas"]: s += v else: s += " " s += "\n" else: for letra in alfabeto[: tamanho - 1]: s += letra s += " " * len(h) s += alfabeto[tamanho - 1] print(s) def quadrados_contendo(aresta, tamanho): quadrados = [] if aresta[1].isdigit(): # jogada vertical linha_baixo = int(aresta[0]) linha_cima = int(aresta[1]) coluna = aresta[2] indice_coluna = alfabeto.find(coluna) if indice_coluna > 0: # tem quadrado à esquerda quadrados.append(f'{linha_baixo}{coluna}') if indice_coluna < tamanho-1: # tem quadrado à direita prox_coluna = alfabeto[indice_coluna +1] quadrados.append(f'{linha_baixo}{prox_coluna}') else: linha = int(aresta[0]) coluna_direita = aresta[2] if linha > 1: # tem quadrado abaixo quadrados.append(f'{linha-1}{coluna_direita}') if linha < tamanho: # tem quadrado acima quadrados.append(f'{linha}{coluna_direita}') return quadrados def quadrados_capturados(jogada, jogo): candidatos = quadrados_contendo(jogada, jogo['tamanho']) return [quadrado for quadrado in candidatos if all(aresta in jogo['jogadas'] for aresta in arestas_do_quadrado(quadrado))] def outro(vez): "Retorna o nome do _outro_ jogador" if vez == nome_um: return nome_dois return nome_um def jogar(primeiro, segundo, tamanho=4, interativo=True): """ Roda um jogo de Dots and Boxes entre os jogadores primeiro e segundo , em uma malha de lado tamanho. Se interativo for True, o estado do jogo é exibido a cada rodada, e o resultado é impresso na tela (sem retorno). Se interativo for False, nada é exibido na tela, e o resultado do jogo é retornado pela função (o vencedor, caso haja, ou a string 'empate') """ J = cria_jogo(tamanho) vez = nome_um # Loop principal do jogo: mostra o jogo na tela e pede a próxima jogada do jogador da vez. while True: if interativo: mostra(J) capturou = False while True: # Recebe a jogada do jogador da vez em loop até que seja uma jogada válida if vez == nome_um: jogada = primeiro(J, vez) else: jogada = segundo(J, vez) if jogada in jogadas_válidas(J): # jogada aceita, podemos sair do loop! break # Registra a jogada J["jogadas"].append(jogada) # Verificamos se a jogada capturou quadrados, e em caso positivo, registramos esse fato: capturados = quadrados_capturados(jogada, J) if len(capturados) > 0: for quadrado in capturados: J[vez].append(quadrado) # Verificamos se o jogo acabou de ser vencido resultado = jogo_acabou(J) if resultado in {nome_um, nome_dois}: if interativo: mostra(J) print(f"!!! {resultado} venceu !!!") return else: return resultado elif resultado == "empate": # Verificamos se o jogo acabou em empate if interativo: mostra(J) print("Empate...") return else: return "empate" # Vejamos se a vez troca para a próxima rodada if len(capturados) == 0: vez = outro(vez) def torneio(jogador_um, jogador_dois, número_partidas=10**2, tamanho=None): """ Roda um 'torneio' de 2*número_partidas jogos entre os jogadores passados como argumento (metade como cada um sendo o primeiro a jogar). Se for passado o argumento tamanho , todos os jogos são jogados na malha com o tamanho especificado; senão, as partidas são jogadas em malhas de tamanho aleatório de 3 a 9. O valor retornado é um dicionário com as porcentagens de vezes em que cada resultado foi obtido nos jogos. """ s = "" if jogador_um == jogador_dois: # Vamos usar asteriscos para diferencias as duas "cópias" do mesmo jogador s = "*" um = f"{jogador_um.__name__}{s}" dois = f"{jogador_dois.__name__}{s * 2}" resultados = {um: 0, dois: 0, "empate": 0} for _ in range(número_partidas): if tamanho is None: tamanho = random.randint(3, 9) res = jogar(jogador_um, jogador_dois, tamanho, interativo=False) if res == nome_um: resultados[um] += 1 elif res == nome_dois: resultados[dois] += 1 else: resultados["empate"] += 1 res = jogar(jogador_dois, jogador_um, tamanho, interativo=False) if res == nome_um: resultados[dois] += 1 elif res == nome_dois: resultados[um] += 1 else: resultados["empate"] += 1 for c in resultados: resultados[c] = f"{100 * resultados[c] / (2 * número_partidas):.2f}%" return resultados