solucionador python hangman

Oct 08 2020

Eu escrevi um programa que lê um arquivo csv que contém 100 linhas que se parecem com:

1;S****L;SCHOOL
2;*A*G*A*;HANGMAN

em seguida, tente adivinhar as letras como em um jogo da forca. Meu objetivo é contar todas as letras certas e erradas e, em seguida, somá-las. O código funciona bem, obtenho cerca de 1670 tentativas certas + erradas de adivinhar as letras. Minha abordagem foi criar um dicionário no qual eu armazeno todas as letras do alfabeto e leio todas as palavras do arquivo, em seguida, soma todas as aparições de uma letra e as armazeno no dicionário. Algo como

{
   "A" : 30,
   "B" : 40
}

Em seguida, classifico o dict com base em cada ocorrência de letra e primeiro tento adivinhar a letra com mais aparição.

Minha pergunta. Algo que posso melhorar para conseguir um número menor de tentativas?

import csv

INPUT_FILE = "words.csv"


def oppenFile():        # function to read the file
    with open(INPUT_FILE, "r", encoding="utf-8") as words:
        reader = list(csv.reader(words, delimiter=";"))
        return reader


def letterCount():      # function that count every the letter in the file and return a dict: {A : 2}
    letters = dict.fromkeys("QWERTYUIOPĂÎASDFGHJKLȘȚÂZXCVBNM", 0)
    words = oppenFile()
    for w in range(len(words)):
        for l in list(words[w][2]):
            if l not in list(words[w][1]):
                letters[l] += 1
    return letters


def checkLetters(word, wholeWord, letters):     # function that solve a word return the number of right + wrong attempts
    attempts = 0
    for letter, key in letters.items():
        if letter in wholeWord and letter not in word:
            attempts += 1
            index = [i for i, lit in enumerate(wholeWord) if lit == letter]
            letters[letter] -= len(index)
            for j in range(len(index)):
                word = word[:index[j]] + letter + word[(index[j] + 1):]

        elif '*' not in word:
            break
        else:
            attempts += 1
    return attempts


def hangman():
    words = oppenFile()
    numberOfAttempts = 0
    letters = letterCount()

    for i in range(len(words)):
        letters = dict(sorted(letters.items(), key=lambda x: x[1], reverse=True)) # sort the dict

        numberOfAttempts += checkLetters(words[i][1], words[i][2], letters)

    print(f"{numberOfAttempts} right + wrong attempts")


if __name__ == "__main__":
    hangman()

Respostas

5 hjpotter92 Oct 08 2020 at 04:07

Bem-vindo à revisão do código!

PEP-8

Em python, é comum (e recomendado) seguir o guia de estilo PEP-8 para escrever código limpo, sustentável e consistente.

As funções e variáveis ​​devem ser nomeadas em a lower_snake_case, classes como UpperCamelCasee constantes como UPPER_SNAKE_CASE.

Sugestão de tipo

Com as versões mais recentes do Python, você pode fazer uso da sugestão de tipo para fornecer uma breve visão geral do tipo de variáveis ​​e parâmetros de função.

Contando cartas

Python fornece um recurso embutido collections.Counterpara você usar.

Comentários

Os comentários realmente não ajudam aqui. Além disso, prefira escrever docstring em vez de comentários para funções.

Nomes de variáveis

Você abre um arquivo e nomeia seu ponteiro como words, enquanto a função retorna uma lista de palavras; chamado reader, que por sua vez é armazenado em uma variável chamada words?

Conversões estranhas

Você gera um mapeamento de letras para suas respectivas contagens, como um dicionário (hash-map / table / lookup), então o converte em uma lista de tupla de 2 valores, classifica e converte de volta ao dicionário. Por quê? dicttem \$ O(1) \$ pesquisa e classificação não fazem sentido no seu caso.

Iteração com índice

Você usa a seguinte estrutura de loop:

for i in range(len(words)):

onde, ipor si só, não serve a nenhum propósito. Cada ocorrência de uso de ié da forma words[i]. Você pode apenas iterar sobre os valores da wordsprópria lista:

for word in words: