Levels in the game of old

Asked

Viewed 1,214 times

0

I am working on an old game in Python, and I have 3-level codes (easy, medium and hard) distinct, as it could implement an initial "menu" where the user could choose one of the levels and be immediately directed to the same. And at the end of the game he could choose the level again.

import random

#-------------------------------------------------------------------------------
# Funções utilizadas pelo programa 
#-------------------------------------------------------------------------------

# função que atualiza a estrutura de dados que representa as filas de fechamento
#-------------------------------------------------------------------------------
def atualizaFilas():
    global lins, cols, dgns

    lins = [linha for linha in tabuleiro]

    cols = [
            [tabuleiro[linha][0] for linha in range(3)], \
            [tabuleiro[linha][1] for linha in range(3)], \
            [tabuleiro[linha][2] for linha in range(3)]  \
           ]

    dgns = [
            [tabuleiro[linha][linha]  for linha in range(3)],
            [tabuleiro[linha][coluna] for linha in range(3)
                                          for coluna in range(3)
                                              if (linha+coluna) == 2]
           ]

    return(lins + cols + dgns)

# função que apresenta jogo ao usuário
#-------------------------------------------------------------------------------
def apresentaJogo():
    print(2*'\n')
    print('Nesta implementação do Jogo da Velha, as casas do tabuleiro são numeradas da seguinte forma: \n\n' \
          ' 11 | 12 | 13 \n' \
          '----+----+----\n' \
          ' 21 | 22 | 23 \n' \
          '----+----+----\n' \
          ' 31 | 32 | 33 \n')
    print('Ao fazer seu lance, indique em qual dessas casas você quer jogar.')

# função que exibe o tabuleiro
#-------------------------------------------------------------------------------
def exibeTabuleiro():
    print()
    print(' ' + tabuleiro[0][0] + ' |' + ' ' + tabuleiro[0][1] + ' |' + ' ' + tabuleiro[0][2] + ' \n' \
          '---+---+---\n' \
          ' ' + tabuleiro[1][0] + ' |' + ' ' + tabuleiro[1][1] + ' |' + ' ' + tabuleiro[1][2] + ' \n' \
          '---+---+---\n' \
          ' ' + tabuleiro[2][0] + ' |' + ' ' + tabuleiro[2][1] + ' |' + ' ' + tabuleiro[2][2] + ' \n' )

# função que verifica o fechamento do jogo
#-------------------------------------------------------------------------------
def verificaFechamento():

    # seta indicador de fechamento
    for fila in filas:
        if fila in fechamentos:
            status = True
            break
    else:
        status = False

    return status

# função que obtém e processa lance do jogador
#-------------------------------------------------------------------------------
def processaLanceJogador():
    global filas, jogada, tabuleiro

    # contabiliza jogada do jogador
    jogada += 1

    # exibe lista de casas disponíveis
    print('\nNo momento, o tabuleiro está com as seguintes casas disponíveis:\n', \
          casasDisponíveis, '\n')

    # obtém lance do jogador
    while True:
        try:
            casa = int(input('Em qual delas você quer jogar? '))
            if casa not in casasDisponíveis:
                raise ValueError
            else:
                # elimina casa escolhida da relação das casas disponíveis
                casasDisponíveis.remove(casa)
                break
        except ValueError:
            print('Você digitou um valor inválido ou uma casa já ocupada. Tente novamente.\n')

    # atualiza tabuleiro
    tabuleiro[casa//10-1][casa%10-1] = 'X'

    # atualiza a estrutura de dados que representa as filas de fechamento
    filas = atualizaFilas()

# função que obtém lance do computador
#-------------------------------------------------------------------------------
def processaLanceComputador():
    global jogada, filas

    # contabiliza jogada do computador
    jogada += 1
    # gera lance do computador
    casa = random.choice(casasDisponíveis)
    # elimina casa escolhida da relação das casas disponíveis
    casasDisponíveis.remove(casa)
    # atualiza tabuleiro
    tabuleiro[casa//10-1][casa%10-1] = 'O'
    # atualiza a estrutura de dados que representa as filas de fechamento
    filas = atualizaFilas()

# inicializa a estrutura de dados que representa o tabuleiro
tabuleiro = [[' ']*3, [' ']*3, [' ']*3]

# define e inicializa a estrutura de dados que representa os padrões de fechamento
fechamentos = [3*['X'], 3*['O']]

# cria lista de casas disponíveis para lance
casasDisponíveis = [i*10+j for i in range(1,4) \
                               for j in range(1,4) \
                                   if tabuleiro[i-1][j-1] == ' ']

# inicializa a estrutura de dados que representa as filas de fechamento
filas = atualizaFilas()

# seta a condição de encerramento do jogo
jogada, fechou = 0, False
terminar = (jogada == 9) or (fechou == True)

#-------------------------------------------------------------------------------
# Corpo do programa
#-------------------------------------------------------------------------------

# apresenta jogo ao jogador
apresentaJogo()

# enquanto não terminar
while (not terminar):
    # processa jogada do jogador
    processaLanceJogador()
    # verifica Fechamento
    fechou = verificaFechamento()
    # atualiza sinalizador de encerramento do jogo
    terminar = (jogada == 9) or fechou == True
    # se for para terminar:
    if terminar:
        # exibe tabuleiro
        exibeTabuleiro()
        # termina o jogo
        break
    # processa jogada do computador
    processaLanceComputador()
    # verifica Fechamento
    fechou = verificaFechamento()
    # atualiza sinalizador de encerramento do jogo
    terminar = (jogada == 9) or fechou == True
    # exibe tabuleiro
    exibeTabuleiro()

# em caso de fechamento, verifica vencedor e emite mensagem correspondente:
if fechou:
   # se o vencedor for o jogador:
    if jogada in [1, 3, 5, 7, 9]:
       # emite mensagem de congratulação:
        print('Parabéns, você venceu!')
   # se o vencedor for o computador:
    else:
       # emite mensagem de zoação:
        print('Você é um pato!')
# se a partida não fechou, emite mensagem de empate
else:
    print('Deu velha !')
  • If your question is just implementing a menu, I suggest using some GUI like Pyqt, Kivy, Tkinter, etc.

  • But I do not want a graphical interface, I just wanted that when opening the program the user could choose the level and be directed to the same. The ideal would be for the user to type "easy" and be directed to this level. I don’t know if this would be possible with Tkinter

  • This code I posted is the easy level, there are 2 more, "join" the three and apply this initial menu

  • 1

    If you don’t want a graphical interface, then use input. Ex: https://www.python-course.eu/input.php

  • 1

    I wonder how it would work level in the game of old. Technically it is not a game, because two people who know how to play will draw eternally. Only if the algorithm draws first will it lose or not, in different percentages.

  • @Bacco, I created some time ago an old game in Java, where the player plays against the computer. From there you can define the levels of "cleverness" of the computer...

  • @Rogériodec, thank you very much, but as I do to interconnect the 3 levels in the same code?

  • You can do what you want by using "smart agents". Don’t worry, it’s AI but it’s nothing out of the world. It is only a modeling, which in case is suitable for your case. One of the agents may be the player, and the other agent the machine that will challenge the player.

Show 3 more comments

2 answers

1

To repeat several times and choose the difficulty:

jogando = True
while jogando:
    #Você pode criar uma função que dê print o menu e retorne a dificuldade ou sair
    print("Dificuldades:")
    print("1 - Fácil")
    print("2 - Médio")
    print("3 - Difícil")
    print("\n4 - Sair")
    dificuldade = input("Digite a dificuldade desejada ou saia(Ex.: 1 OU `facil`): ")
    while dificuldade != '1' and dificuldade != '2' and dificuldade != '3' and dificuldade.lower() != 'facil' and dificuldade.lower() != 'medio' and dificuldade.lower() != 'dificil' and dificuldade != '4' and dificuldade.lower() != 'sair':
        dificuldade = input("\nEscolha Inválida!\nDigite a dificuldade desejada (Ex.: 1 OU `facil`): ")
    if dificuldade == '4' or dificuldade.lower() == 'sair':
        terminar = True
        jogando = False
    else:
        apresentaJogo()
    # enquanto não terminar
    while (not terminar):
       # processa jogada do jogador
       processaLanceJogador()
       # verifica Fechamento
       fechou = verificaFechamento()
       # atualiza sinalizador de encerramento do jogo
       terminar = (jogada == 9) or fechou == True
       # se for para terminar:
       if terminar:
          # exibe tabuleiro
          exibeTabuleiro()
          # termina o jogo
          break
      # processa jogada do computador
      if dificuldade == '1' or dificuldade.lower() == 'facil':
          processaLanceComputador(1) #OU processaLanceFacilComputador()
      elif dificuldade == '2' or dificuldade.lower() == 'medio':
          processaLanceComputador(2) #OU processaLanceMedioComputador()
      elif dificuldade == '3' or dificuldade.lower() == 'dificil':
          processaLanceComputador(3) #OU processaLanceDificilComputador()
      # verifica Fechamento
      fechou = verificaFechamento()
      # atualiza sinalizador de encerramento do jogo
      terminar = (jogada == 9) or fechou == True
      # exibe tabuleiro
      exibeTabuleiro()

      # em caso de fechamento, verifica vencedor e emite mensagem correspondente:
      if fechou:
      # se o vencedor for o jogador:
         if jogada in [1, 3, 5, 7, 9]:
             # emite mensagem de congratulação:
             print('Parabéns, você venceu!')
         # se o vencedor for o computador:
         else:
             # emite mensagem de zoação:
             print('Você é um pato!')
             # se a partida não fechou, emite mensagem de empate
      else:
         print('Deu velha !')

0

Here’s the code I made (player against computer). It is not AI, but the computer can play at the "beginner" (for children) and "expert" level (where it does not fail). Then I did it to learn Java, then is in this language, but is easily adaptable to Python.

The code below is just the Java kernel (does not include the graphical interface), but it has all the logic for you to convert to Python or any other language:

import java.util.Arrays;
import java.util.Random;
//import org.apache.commons.lang3.ArrayUtils;

/**
 * Created by Rogério Dec (http://rogeriodec.com.br - [email protected]) on 20/01/2017.
 */
public class Velha {
    public static int i, ContMatriz, jogada, jogadaX, numjogada = 0;
    public static char[] MatrizJogo = new char[10];
    public static int[][] JogadasPossiveis = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {1, 4, 7}, {2, 5, 8}, {3, 6, 9}, {1, 5, 9}, {3, 5, 7}};
    public static int[][] Log = new int[2][10];
    static Random rnd = new Random();

    public static String Velha(int botao) {
        if (JogoDaVelha.Iniciante.isSelected()) { // modo iniciante
            if (botao == 0) // computador começa
                PreencheVazio('O');
            else {
                MatrizJogo[botao] = 'X'; // armazena jogada humana na matriz, posição escolhida
                ContMatriz++;
                if (FazVelha('X') == 3)  // Jogador X fez 3 casas (velha)?
                    return "X"; // humano ganhou
                PreencheVazio('O');
                if (FazVelha('O') == 3) 
                    return "O"; // máquina ganhou
                if (ContMatriz > 8) // não achou jogada possível, preenche qualquer um ...
                    return "E"; // empate
            }
        }
        else { // modo experto
            if (botao == 0) // computador começa
                ataca();
            else {
                MatrizJogo[botao] = 'X'; // armazena jogada humana na matriz, posição escolhida
                ContMatriz++; // incrementa contador da matrizes já utilizadas
                // fechou velha?
                if (FazVelha('X') == 3)  // Jogador X fez 3 casas (velha)?
                    return "X"; // humano ganhou
                jogadaX = jogada; // guarda para comparar jogadaX
                if (FazVelha('O') == 2) {
                    jogadaX = jogada; // guarda para comparar jogadaX
                    defende();
                    return "O";
                }
                // humano consegue velha?
                if (FazVelha('X') == 2)  // Jogador X fez 2 casas, então pode fazer velha
                    defende();
                else 
                    ataca();
                if (ContMatriz >= 8) // não achou jogada possível, preenche qualquer um ...
                    return "E"; // empate
                // máquina consegue velha?
            }
        }

//        ********** começa computador, modo experto, x = 3, 4, O = 5, 1 e ai faz 8 e 9 de uma vez
        return null;
    }

     public static void desenha(){
        if (MatrizJogo[1] != '\0') JogoDaVelha.b1.setText((Character.toString(MatrizJogo[1])));
        if (MatrizJogo[2] != '\0') JogoDaVelha.b2.setText((Character.toString(MatrizJogo[2])));
        if (MatrizJogo[3] != '\0') JogoDaVelha.b3.setText((Character.toString(MatrizJogo[3])));
        if (MatrizJogo[4] != '\0') JogoDaVelha.b4.setText((Character.toString(MatrizJogo[4])));
        if (MatrizJogo[5] != '\0') JogoDaVelha.b5.setText((Character.toString(MatrizJogo[5])));
        if (MatrizJogo[6] != '\0') JogoDaVelha.b6.setText((Character.toString(MatrizJogo[6])));
        if (MatrizJogo[7] != '\0') JogoDaVelha.b7.setText((Character.toString(MatrizJogo[7])));
        if (MatrizJogo[8] != '\0') JogoDaVelha.b8.setText((Character.toString(MatrizJogo[8])));
        if (MatrizJogo[9] != '\0') JogoDaVelha.b9.setText((Character.toString(MatrizJogo[9])));
        numjogada++;
        int jogador = 0;
        for (int casa = 1; casa < 10; casa++) {
acha:       {
                if (MatrizJogo[casa] == '\0')
                    continue;
                if (MatrizJogo[casa] == 'X')
                    jogador = 0;
                if (MatrizJogo[casa] == 'O')
                    jogador = 1;
                for (i = 1; i<10; i++) { // ve se a casa já havia sido registrada em aguma jogada
                    if (Log[jogador][i] == casa)
                        break acha; // se já havia sido registrada, vai para proxima casa
            }
            Log[jogador][numjogada] = casa;
            }
        }
    }

    private static int FazVelha (char jogador) {
        int ContVelha, ContVelhaAnt = 0, jogadaAnt = 0;
        for (jogada=0; jogada<8; jogada++) { // Rastreia Jogadas Possíveis, uma por uma para ver qual tem mais combinações
            ContVelha = 0;
            for (int casa = 0; casa < 3; casa++) { // compara
                int CasaPossivel = JogadasPossiveis[jogada][casa];
                if (MatrizJogo[CasaPossivel] == jogador)
                    ContVelha++;
                else if (MatrizJogo[CasaPossivel] != '\0'){ // se casa estiver preenchida com do OUTRO jogador, anula esta jogada possível
                    ContVelha = 0;
                    break;
                }
            }
//            if (ContVelha >= 3)
            if (ContVelha >= (JogoDaVelha.Iniciante.isSelected() ? 3 : 2)) {
                if (ContVelhaAnt < ContVelha) {
                    ContVelhaAnt = ContVelha;
                    jogadaAnt = jogada;
                }
            }
        }
        jogada = jogadaAnt;
        return ContVelhaAnt;
    }

    private static void defende() {
        int ContVazias = 0, casa, ContImpares = 0;
        for (casa = 0; casa < 3; casa++) {
            if (MatrizJogo[JogadasPossiveis[jogadaX][casa]] == '\0') // encontrou casa vazia
                ContVazias++;
        }
        if (ContVazias == 0) {
            PreencheVazio('O');
            return;
        }
        if (ContVazias == 3) { // se as 3 casas da jogada escolhida estiverem vazias, joga numa que não seja par
            int [] CasasImpares = new int [3];
            for (casa = 0; casa < 3; casa++) { // conta quantas casas da jogada são impares
                if (JogadasPossiveis[jogadaX][casa] % 2 != 0) 
                    CasasImpares[ContImpares++] = JogadasPossiveis[jogadaX][casa];
            }
            if (ContImpares == 1) // se encontrou apenas 1 casa impar na jogada escolhida
                casa = CasasImpares[0]; // pega a 1a casa impar encontrada
            else 
                casa = CasasImpares[rnd.nextInt(ContImpares)]; // sorteia entre a 1a e a 2a casa impar encontrada
            MatrizJogo[casa] = 'O';
        }
        else {
            int CasaEscolhida = rnd.nextInt(ContVazias);
            i = 0;
            for (casa = 0; casa < 3; casa++) {
                if (MatrizJogo[JogadasPossiveis[jogadaX][casa]] == '\0') {
                    if (i == CasaEscolhida) {
                        MatrizJogo[JogadasPossiveis[jogadaX][casa]] = 'O'; // preenche com O
                        break;
                    }
                    i++;
                }
            }
        }
        ContMatriz++;
    }

    private static void ataca() {
        if (ContMatriz == 0) { // primeira jogada, computador começando
            int [] primeiraJogada = {1,3,5,7,9};
            i = rnd.nextInt(5); 
            MatrizJogo[primeiraJogada[i]] = 'O';
            ContMatriz++;
            return;
        }

        i=0;
        int [] JogadasPossiveisO = new int [8];
        int [] ProbabilidadeJogada = new int [8];
        int ContProb=0; // contador de probabilides encontradas

        // Rastreia Jogadas Possíveis para O (máquina)
        for (jogada = 0; jogada < 8; jogada++) {
            proxJogada: {
                for (int casa = 0; casa < 3; casa++) { // compara
                    int CasaPossivel = JogadasPossiveis[jogada][casa];
                    if (MatrizJogo[CasaPossivel] == 'X') { // se encontrou algum X, a jogada não é possível, tenta outra jogada possível
                        if (ProbabilidadeJogada[i] > 0) {
                            ProbabilidadeJogada[i] = 0; // zera contador de probabilidade desta jogada
                            ContProb--; // volta no contador de probabilidades
                        }
                        break proxJogada;
                    }
                    if (MatrizJogo[CasaPossivel] == 'O') { // se encontrou algum O, aumenta a probabilidade da jogada se escolhida
                        ProbabilidadeJogada[i]++; // aumenta contador de probabilidade desta jogada
                        ContProb++; // mais uma probabilidade encontrada
                    }
                }
                JogadasPossiveisO[i++] = jogada;
            }
        } // aqui já tem todas as jogadas possívels para O suas probabilidades
        if (i == 0) { // se não encontrou nenhuma jogada possível, preenche qualquer espaço vazio para acabar o jogo
            PreencheVazio('O');
            return;
        }
        int MelhorJogada = 0;
        int JogadaEscolhida = 0;
        int x = 0;
        if (ContProb == 0) 
            MelhorJogada = rnd.nextInt(i); 
        else {
            JogadaEscolhida = rnd.nextInt(ContProb); // define aleatoriamente qual das melhores jogadas encontradas será usada
            for (i = 0; i < 8; i++) { // localiza a jogada de maior probabilidade
                if (ProbabilidadeJogada[i] > 0) {
                    if (x == JogadaEscolhida) {
                        MelhorJogada = i; // define qual a melhor jogada
                        break;
                    }
                    x++;
                }
            }
        }
        jogadaX = JogadasPossiveisO[MelhorJogada]; // define a melhor jogada dentro da maior probabilidade. Se nenhuma probabilidade foi encontrada, pega a 1a jogada possível.
        defende(); // preenche a jogada
    }
    private static void PreencheVazio(char jogador) {
        int [] vazios = new int[10];
        int ContVazios = 0;
        for (i = 1; i <= 9; i++) { // procura primeiro espaço vazio
            if (MatrizJogo[i] == '\0') 
                vazios[++ContVazios] = i;
        }
        if (ContVazios != 0) {
            i = rnd.nextInt(ContVazios) + 1; 
            MatrizJogo[vazios[i]] = jogador;
        }
        ContMatriz++;
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.