• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

python, optymalizacja i nauka

VPS Starter Arubacloud
+1 głos
579 wizyt
pytanie zadane 24 września 2019 w Python przez ninjaa Nowicjusz (240 p.)

Witam, napisałem swoją pierwszą grę - Wisielec. Jak go można poprawić lub zoptymalizować?

Czy takie proste gry lepiej pisać w klasach czy w funkcjach też jest OK?

Poniżej wklejam kod gry.

####wisielec
import random
import os


#dopisac sprawdzenie pliku
def losuj_wyraz():
    plik = open("wyrazy.txt", "r")
    lista = plik.readlines()

    wyrazy = []
    for i in lista:
        wyraz = i.strip()
        wyrazy.append(wyraz)

    liczba = random.randint(0, 9)

    return wyrazy[liczba]

def odwroc_wyraz(wyraz):
    odwrocony = ""
    for i in range(len(wyraz)):
        odwrocony += "-"

    return odwrocony

def start(szanse):
    os.system('cls')

    print("""
 __        ___     _      _           
 \ \      / (_)___(_) ___| | ___  ___ 
  \ \ /\ / /| / __| |/ _ \ |/ _ \/ __|
   \ V  V / | \__ \ |  __/ |  __/ (__ 
    \_/\_/  |_|___/_|\___|_|\___|\___|
    """)
    print("Witaj w grze Wisielec! Masz {} prob by zgadnac wyraz. \nPowodzenia!\n".format(szanse))

    input("Nacisnij dowolny przycisk aby zaczac gre...")

#dopisac sprawdzenie czy to litera
def wyswietl_i_wczytaj(wyraz, wpisane, proby):
    os.system('cls')
    obrazy_ascii(proby)
    print("\nTwoj wyraz: {}".format(wyraz))
    print("Poprzednie litery: {}".format(wpisane))
    print("Pozostalo prob: {}\n".format(proby))
    litera = input("Wpisz litere:")
    return litera

def sprawdz_litere(wyraz, litera):

    lista = list(wyraz)
    zwroc = []

    for i, letter in enumerate(lista):
        if letter == litera:
            zwroc.append(i)

    return zwroc

def odkryj_litere(lista, litera, odwrocony):

    odwrocona_lista = list(odwrocony)

    for i in lista:
        odwrocona_lista[i] = litera

    odwrocony_wyraz = "".join(odwrocona_lista)

    return odwrocony_wyraz

def przegrales(wyraz, szanse):
    os.system('cls')
    obrazy_ascii(szanse)
    print("Niestety, przegrales.\n Poprawny wyraz: {}".format(wyraz.upper()))
    input("\nNacisnij dowolny klawisz aby wyjsc z gry...")
    exit()

def wygrales(wyraz):

    odwrocony = list(wyraz)

    for i in odwrocony:
        if i == "-":
            return False

    return True

def obrazy_ascii(szanse):
    HANGMANPICS = ['''
      +---+
          |
          |
          |
          |
          |
    =========''', '''
      +---+
      |   |
          |
          |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
          |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
      |   |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
     /|   |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
     /|\  |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
     /|\  |
     /    |
          |
    =========''', '''
      +---+
      |   |
      O   |
     /|\  |
     / \  |
          |
    =========''']

    obraz = -(szanse+1)
    print(HANGMANPICS[obraz])

def main():
    wyraz = losuj_wyraz()
    odwrocony = odwroc_wyraz(wyraz)
    szanse = 7
    wpisane = []



    start(szanse)

    while szanse:
        litera = wyswietl_i_wczytaj(odwrocony, wpisane, szanse)
        sprawdz = sprawdz_litere(wyraz, litera)
        if sprawdz:
            print("Trafiles! Oby tak dalej!")
            wpisane.append(litera)
            odwrocony = odkryj_litere(sprawdz, litera, odwrocony)
            if wygrales(odwrocony):
                print("\nBRAWO!! WYGRALES!!!\n Odgadniety wyraz: {}\n".format(odwrocony.upper()))
                input("\nNacisnij dowolny klawisz aby wyjsc z gry...")
                exit()
        else:
            print("Niestety, nie trafiles. Sproboj jeszcze raz.\n")
            wpisane.append(litera)
            szanse -= 1

    przegrales(wyraz, szanse)

if __name__ == "__main__":
    main()

 

3 odpowiedzi

+1 głos
odpowiedź 24 września 2019 przez RafalS VIP (122,820 p.)
wybrane 25 września 2019 przez ninjaa
 
Najlepsza

Tragedii nie ma ale jest sporo niezręczności i niejasnego kodu.

Np funkcja

def sprawdz_litere(wyraz, litera):

Zwraca listę indeksów zawierających dana literkę. Nigdy przenigdy bym tego nie wywnioskował po nazwie.

def odkryj_litere(lista, litera, odwrocony):

czym jest lista? Nie jestem w stanie domyslić się ani po nazwie a po ciele funkcji też ciężko. Dopiero analiza przebiegu całego kodu pozwala to zrozumieć. To dosyć poważny błąd.

 A tak bym zrefactorował niektóre funkcje:

def odwroc_wyraz(wyraz):
    odwrocony = ""
    for i in range(len(wyraz)):
        odwrocony += "-"

    return odwrocony


def reverse_string(str_: str):
    return str_[::-1]

 

def losuj_wyraz():
    plik = open("wyrazy.txt", "r")
    lista = plik.readlines()

    wyrazy = []
    for i in lista:
        wyraz = i.strip()
        wyrazy.append(wyraz)

    liczba = random.randint(0, 9)

    return wyrazy[liczba]


def get_random_word():
    with open("wyrazy.txt") as words_file:
        words = [line.strip() for line in words_file]
    return random.choice(words)
def wygrales(wyraz):
    odwrocony = list(wyraz)

    for i in odwrocony:
        if i == "-":
            return False

    return True


def is_win(phrase: str):
    return "-" in phrase
def sprawdz_litere(wyraz, litera):
    lista = list(wyraz)
    zwroc = []

    for i, letter in enumerate(lista):
        if letter == litera:
            zwroc.append(i)

    return zwroc


def check_letter(current_phrase: str, whole_phrase: str, letter: str) -> bool:
    return letter in whole_phrase and letter not in current_phrase


def odkryj_litere(lista, litera, odwrocony):
    odwrocona_lista = list(odwrocony)

    for i in lista:
        odwrocona_lista[i] = litera

    odwrocony_wyraz = "".join(odwrocona_lista)

    return odwrocony_wyraz


def reveal_letter(current_phrase: str, whole_phrase: str, letter_to_reveal: str) -> str:
    current_phrase_list = list(current_phrase)
    for idx, letter in enumerate(whole_phrase):
        if letter == letter_to_reveal:
            current_phrase_list[idx] = letter
    return "".join(current_phrase_list)

obrazy_ascii jak sama nazwa wskazuje nie powinny byc funkcja tylko listą stringów.

 

komentarz 25 września 2019 przez ninjaa Nowicjusz (240 p.)

Są jakieś książki, gdzie opisane są zasady umieszczania poszczególnych elementów kodu programu i nazywania ich w taki sposób by inni nie musieli analizować całego kodu by wiedzieć jak działa i co robi?

Tego bym się chciał najbardziej nauczyć bo tego nie ogarniam - co sam zauważyłeś :D

Chciałem by to działało a teraz chcę to ulepszać.

 

def reverse_string(str_: str):
    return str_[::-1]

Do tego poziomu jeszcze nie doszedłem :D

Nie wiedziałem też, że pętle "for" można zapisać w jednej linii.

Jeszcze dużo nauki przede mną.

 

Dzięki za analizę, mam teraz nad czym myśleć :D

Pozdro.

 

komentarz 26 września 2019 przez RafalS VIP (122,820 p.)
Poszukaj hasła czysty kod (clean code). Jest o tym temacie jedna książka o właśnie tej nazwie i masa materiałów, aczkolwiek generalnie na tym etapie polecam raczej przeczytać jakiś krótki artykuł i pisać kod a książkę zostawić na później, bo tym więcej z niech wyniesiesz im więcej problemów zrozumiesz :P
+2 głosów
odpowiedź 24 września 2019 przez reaktywny Nałogowiec (40,650 p.)
Nie jest źle, tu OOP to byłby przerost formy nad treścią.

Jedyne co się rzuca w oczy - polskie nazwy zmiennych, funkcji powinno się zmienić na angielskie.

Poprawiłbym drobne rzeczy jak zapis:

obraz = -(szanse+1)

Funkcję randint zamieniłbym na random.choice - ale to już szczegół.

HANGMANPICS  wyciągnąłbym z funkcji na początek programu.

Można zmienić dużo drobnych rzeczy - ale z czasem będziesz wiedział sam w czym rzecz.
komentarz 25 września 2019 przez ninjaa Nowicjusz (240 p.)
obraz = -(szanse+1)

Jak to poprawić?

Angielskiego dopiero zaczynam się uczyć, więc na razie używam polskiego.

O funkcji "random.choice" pierwsze słyszę - poczytam, dzięki.

HANGMANPICS dałem do funkcji bo według mnie łatwiej tego użyć.

Są jakieś książki, gdzie opisane są zasady umieszczania poszczególnych elementów kodu programu i nazywania ich w taki sposób by inni nie musieli analizować całego kodu by wiedzieć jak działa i co robi? Jeśli tak, proszę o tytuły.

 

Dzięki za komentarz.

Pozdro :)

komentarz 25 września 2019 przez reaktywny Nałogowiec (40,650 p.)
edycja 25 września 2019 przez reaktywny
obraz = -1 - szanse

( chodzi o czytelność ).

 

Co do książek - wszystko co ma w nazwie "clean code" albo "pythonic way".

Do tego zasady PEP8 oraz książka Fluent Python.

 

Clean Code in Python. Ebook. Mariano Anaya. Księgarnia informatyczna Helion.pl

https://helion.pl/ksiazki/clean-code-in-python-mariano-anaya,e_157a.htm#format/e

Python Clean Coding | Udemy
https://www.udemy.com/course/python-clean-coding/
+1 głos
odpowiedź 24 września 2019 przez Maciej Złotorowicz Gaduła (4,230 p.)
edycja 24 września 2019 przez Maciej Złotorowicz

W pythonie wygląda to tak że z każdym kolejnym skryptem dowiadujesz się o istnieniu nowej funkcji czy sztuczki  i po prostu googlując problemy i szukając w dokumentacji będziesz się dowiadywał jak kod optymalizować czy jak go "upiększyć"  
 

obraz = -(szanse+1)

Tu się coś dziwnego stało

 

def odwroc_wyraz(wyraz):
    odwrocony = ""
    for i in range(len(wyraz)):
        odwrocony += "-"
 
    return odwrocony

Tu przekombinowałeś 
można np ładnie tak:

def odwroc(wyraz):
	return "-"*len(wyraz)

 

wgl to niżej ktoś wspomniał że po angielsku powinno się pisać i ma racje


w for możesz iterować po stringach co wygląda lepiej niż zamiana stringa na liste a potem po niej iteracja

def wygrales(wyraz):
 
    odwrocony = list(wyraz) #Ta zamiana na liste o której mowiełem po co?
"""
for i in wyraz:
    ...
"""
  
    for i in odwrocony:
        if i == "-":
            return False
 
    return True

Użyj find in



W sumie to można by tak gadać cały dzień i analizować każdą linijkę i czy nie dało by się tego ładniej zrobić. Tylko to nie ma sensu. Dużą częścią zabawy tym językiem jest właśnie odkrywanie takich niuansów. 

komentarz 24 września 2019 przez RafalS VIP (122,820 p.)

Użyj find 

Nigdy w życiu. Użyj in :P

komentarz 24 września 2019 przez Maciej Złotorowicz Gaduła (4,230 p.)
A no in xD
Zapomniałem że to istnieje
To poprawie
komentarz 25 września 2019 przez ninjaa Nowicjusz (240 p.)
obraz = -(szanse+1)

Nie mam na to innego pomysłu, serio.

def odwroc(wyraz):
    return "-"*len(wyraz)

Na to nie wpadłem. Dużo ładniej i prościej.

Zapomniałem ze po stringu można iterować :D

Podobne pytania

0 głosów
1 odpowiedź 180 wizyt
+1 głos
3 odpowiedzi 275 wizyt
pytanie zadane 29 września 2021 w Python przez Gowi Użytkownik (820 p.)
0 głosów
0 odpowiedzi 113 wizyt

92,453 zapytań

141,262 odpowiedzi

319,088 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...