Készítsen Python szorzótábla alkalmazást az OOP segítségével

Ebben a cikkben egy szorzótábla alkalmazást fog készíteni a Python objektumorientált programozásának (OOP) erejének felhasználásával.

Gyakorolni fogod az OOP főbb fogalmait, és azt, hogyan használd őket egy teljesen működőképes alkalmazásban.

A Python egy többparadigmás programozási nyelv, ami azt jelenti, hogy mi fejlesztőként minden helyzetre és problémára kiválaszthatjuk a legjobb megoldást. Amikor objektum-orientált programozásról beszélünk, az elmúlt évtizedek egyik leggyakrabban használt paradigmájára utalunk a méretezhető alkalmazások létrehozására.

Az OOP alapjai

Gyorsan áttekintjük a Python OOP legfontosabb fogalmát, az osztályokat.

Az osztály egy sablon, amelyben meghatározzuk az objektumok szerkezetét és viselkedését. Ez a sablon lehetővé teszi, hogy példányokat hozzunk létre, amelyek nem más, mint az osztály összetételét követő egyedi objektumok.

Egy egyszerű könyvosztály a cím és a szín attribútumaival a következőképpen határozható meg.

class Book:
    def __init__(self, title, color):
        self.title = title
        self.color = color

Ha példányokat akarunk létrehozni az osztálykönyvből, meg kell hívnunk az osztályt, és argumentumokat kell átadnunk neki.

# Instance objects of Book class
blue_book = Book("The blue kid", "Blue")
green_book = Book("The frog story", "Green")

Jelenlegi programunkat jól reprezentálná:

A félelmetes dolog az, hogy amikor ellenőrizzük a blue_book és a green_book példányok típusát, a „Könyv” szöveget kapjuk.

# Printing the type of the books

print(type(blue_book))
# <class '__main__.Book'>
print(type(green_book))
# <class '__main__.Book'>

Miután ezek a koncepciók kristálytiszták, elkezdhetjük építeni a projektet 😃.

Projekt nyilatkozat

Fejlesztői/programozói munka közben az idő nagy részét nem kódírással tölti az újságverem csak az időnk egyharmadát töltjük kódírással vagy újrafeldolgozással.

A másik kétharmadot azzal töltöttük, hogy elolvassuk mások kódját, és elemezzük a problémát, amelyen dolgozunk.

Tehát ehhez a projekthez generálok egy problémanyilatkozatot, és elemezzük, hogyan hozhatjuk létre az alkalmazásunkat. Ennek eredményeként a teljes folyamatot elkészítjük, a megoldás gondolkodásától a kóddal történő alkalmazásig.

Egy általános iskolai tanár szeretne egy játékot, amellyel tesztelheti a 8 és 10 év közötti diákok szorzási készségeit.

A játéknak élet- és pontrendszerrel kell rendelkeznie, ahol a tanuló 3 élettel kezd, és el kell érnie egy bizonyos mennyiségű pontot, hogy nyerjen. A programnak „vesztés” üzenetet kell mutatnia, ha a tanuló egész életét kimeríti.

A játéknak két móddal kell rendelkeznie: véletlenszerű szorzás és asztali szorzás.

Az elsőnek 1-től 10-ig véletlenszerű szorzást kell adnia a tanulónak, és helyesen kell válaszolnia, hogy pontot nyerjen. Ha ez nem történik meg, a diák elveszít egy élőt, és a játék folytatódik. A tanuló csak akkor nyer, ha eléri az 5 pontot.

A második módban egy 1-től 10-ig terjedő szorzótáblát kell megjeleníteni, ahol a tanulónak be kell írnia a megfelelő szorzás eredményét. Ha a tanuló 3-szor bukik, veszít, de ha két asztalt teljesít, akkor a játék véget ér.

Tudom, hogy a követelmények talán kicsit nagyobbak, de ígérem, hogy ebben a cikkben megoldjuk őket 😁.

Oszd meg és uralkodj

A programozás legfontosabb készsége a problémamegoldás. Ennek az az oka, hogy tervet kell készítenie, mielőtt elkezdi feltörni a kódot.

Mindig azt javaslom, hogy vegyük a nagyobb problémát, és osszuk fel kisebbekre, amelyek mindketten könnyen és hatékonyan megoldhatók.

  A Chrome összes inaktív lapján lejátszott hang automatikus némítása

Tehát ha játékot kell létrehoznia, kezdje azzal, hogy fel kell bontania a legfontosabb részeire. Ezeket a részproblémákat sokkal könnyebb lesz megoldani.

Ekkor világossá válik, hogyan kell végrehajtani és integrálni mindent kóddal.

Tehát készítsünk egy grafikont arról, hogyan nézne ki a játék.

Ez a grafika létrehozza az alkalmazásunk objektumai közötti kapcsolatokat. Mint látható, a két fő objektum a véletlenszerű szorzás és a táblázat szorzása. És az egyetlen dolog, amit megosztanak, az a Pontok és Életek tulajdonságai.

Mindezeket az információkat szem előtt tartva, menjünk bele a kódba.

A Szülőjáték osztály létrehozása

Amikor objektum-orientált programozással dolgozunk, a kódismétlődés elkerülésének legtisztább módját keressük. Ezt nevezik SZÁRAZ (ne ismételd magad).

Megjegyzés: Ez a cél nem a kevesebb kódsor írására vonatkozik (a kód minőségét nem szabad ezzel a szemponttal mérni), hanem a leggyakrabban használt logika elvonatkoztatására.

Az előző elképzelés szerint alkalmazásunk szülőosztályának kell kialakítania a másik két osztály szerkezetét és kívánt viselkedését.

Lássuk, hogyan készülne.

class BaseGame:

    # Lenght which the message is centered
    message_lenght = 60
    
    description = ""    
        
    def __init__(self, points_to_win, n_lives=3):
        """Base game class

        Args:
            points_to_win (int): the points the game will need to be finished 
            n_lives (int): The number of lives the student have. Defaults to 3.
        """
        self.points_to_win = points_to_win

        self.points = 0
        
        self.lives = n_lives

    def get_numeric_input(self, message=""):

        while True:
            # Get the user input
            user_input = input(message) 
            
            # If the input is numeric, return it
            # If it isn't, print a message and repeat
            if user_input.isnumeric():
                return int(user_input)
            else:
                print("The input must be a number")
                continue     
             
    def print_welcome_message(self):
        print("PYTHON MULTIPLICATION GAME".center(self.message_lenght))

    def print_lose_message(self):
        print("SORRY YOU LOST ALL OF YOUR LIVES".center(self.message_lenght))

    def print_win_message(self):
        print(f"CONGRATULATION YOU REACHED {self.points}".center(self.message_lenght))
        
    def print_current_lives(self):
        print(f"Currently you have {self.lives} livesn")

    def print_current_score(self):
        print(f"nYour score is {self.points}")

    def print_description(self):
        print("nn" + self.description.center(self.message_lenght) + "n")

    # Basic run method
    def run(self):
        self.print_welcome_message()
        
        self.print_description()

Hú, ez elég nagy osztálynak tűnik. Hadd magyarázzam el mélyen.

Először is ismerjük meg az osztályattribútumokat és a konstruktort.

Az osztályattribútumok alapvetően az osztályon belül, de a konstruktoron vagy bármely metóduson kívül létrehozott változók.

Míg a példányattribútumok csak a konstruktoron belül létrehozott változók.

A fő különbség a kettő között a hatókör. azaz az osztályattribútumok elérhetők egy példány objektumból és az osztályból is. Másrészt a példányattribútumok csak egy példányobjektumból érhetők el.

game = BaseGame(5)

# Accessing game message lenght class attr from class
print(game.message_lenght) # 60

# Accessing the message_lenght class attr from class
print(BaseGame.message_lenght)  # 60

# Accessing the points instance attr from instance
print(game.points) # 0

# Accesing the points instance attribute from class
print(BaseGame.points) # Attribute error

Egy másik cikk mélyebbre merülhet ebben a témában. Maradjon kapcsolatban, hogy elolvashassa.

A get_numeric_input függvény arra szolgál, hogy megakadályozza, hogy a felhasználó olyan bemenetet adjon meg, amely nem numerikus. Amint azt észreveheti, ez a módszer arra szolgál, hogy megkérdezze a felhasználót, amíg nem kap numerikus bevitelt. Később a gyerek óráin használjuk.

A nyomtatási módszerek lehetővé teszik, hogy elmentsük azt az ismétlődést, hogy ugyanazt a nyomtatást minden alkalommal, amikor egy esemény történik a játékban.

  6 Online közjegyzői szoftver jogi dokumentumok létrehozásához és szerkesztéséhez

Végül, de nem utolsósorban, a futtatási metódus csak egy burkoló, amelyet a Véletlenszerű szorzás és a Táblázat szorzás osztályok használnak a felhasználóval való interakcióhoz, és mindent működőképessé tesznek.

A gyermek osztályok létrehozása

Miután létrehoztuk azt a szülőosztályt, amely meghatározza az alkalmazásunk szerkezetét és néhány funkcióját, itt az ideje a tényleges játékmód osztályok létrehozásának az öröklődés erejével.

Véletlenszerű szorzási osztály

Ez az osztály fogja futtatni játékunk „első módját”. Természetesen a random modult fogja használni, ami lehetővé teszi számunkra, hogy 1-től 10-ig véletlenszerű műveleteket kérjünk a felhasználótól. Itt egy remek cikk a véletlenszerű modulokról (és más fontos modulokról) 😉.

import random # Module for random operations
class RandomMultiplication(BaseGame):

    description = "In this game you must answer the random multiplication correctlynYou win if you reach 5 points, or lose if you lose all your lives"

    def __init__(self):
        # The numbers of points needed to win are 5
        # Pass 5 "points_to_win" argument
        super().__init__(5)

    def get_random_numbers(self):

        first_number = random.randint(1, 10)
        second_number = random.randint(1, 10)

        return first_number, second_number
        
    def run(self):
        
        # Call the upper class to print the welcome messages
        super().run()
        

        while self.lives > 0 and self.points_to_win > self.points:
            # Gets two random numbers
            number1, number2 = self.get_random_numbers()

            operation = f"{number1} x {number2}: "

            # Asks the user to answer that operation 
            # Prevent value errors
            user_answer = self.get_numeric_input(message=operation)

            if user_answer == number1 * number2:
                print("nYour answer is correctn")
                
                # Adds a point
                self.points += 1
            else:
                print("nSorry, your answer is incorrectn")

                # Substracts a live
                self.lives -= 1
            
            self.print_current_score()
            self.print_current_lives()
            
        # Only get executed when the game is finished
        # And none of the conditions are true
        else:
            # Prints the final message
            
            if self.points >= self.points_to_win:
                self.print_win_message()
            else:
                self.print_lose_message()

Íme egy újabb hatalmas óra 😅. De ahogy korábban is mondtam, nem a sorok számától függ, hanem az, hogy mennyire olvasható és hatékony. A Pythonban pedig az a legjobb, hogy lehetővé teszi a fejlesztők számára, hogy tiszta és olvasható kódot készítsenek, mintha normál angolul beszélnének.

Ezen az órán van egy dolog, ami megzavarhatja, de a lehető legegyszerűbben elmagyarázom.

    # Parent class
    def __init__(self, points_to_win, n_lives=3):
        "...
    # Child class
    def __init__(self):
        # The numbers of points needed to win are 5
        # Pass 5 "points_to_win" argument
        super().__init__(5)

A gyerekosztály konstruktora meghívja a szuper függvényt, amely egyben a szülő (BaseGame) osztályra is utal. Alapvetően ezt mondja a Pythonnak:

Töltsd ki a szülőosztály „nyertes_pontok” attribútuma 5-tel!

Nem szükséges self-et tenni a super().__init__() részbe csak azért, mert a konstruktor belsejében super-t hívunk, és az redundáns lesz.

A futási metódusban a szuper függvényt is használjuk, és látni fogjuk, mi történik abban a kódrészletben.

    # Basic run method
    # Parent method
    def run(self):
        self.print_welcome_message()
        
        self.print_description()
    def run(self):
        
        # Call the upper class to print the welcome messages
        super().run()
        
        .....

Ahogy észreveheti a futtatási metódust a szülőosztályban, nyomtassa ki az üdvözlő és leíró üzenetet. De jó ötlet megtartani ezt a funkciót, és továbbiakat is hozzáadni a gyermekosztályokhoz. Ennek megfelelően a super-t használjuk a szülő metódus összes kódjának futtatására a következő darab futtatása előtt.

  Portré mód elérése nem támogatott iPhone-on

A futtatási funkció másik része meglehetősen egyszerű. Számot kér a felhasználótól a művelet üzenetével, amelyre válaszolnia kell. Ezután az eredményt összehasonlítjuk a valós szorzással, és ha egyenlők, akkor hozzáad egy pontot, ha nem vesz fel 1 életet.

Érdemes elmondani, hogy while-else ciklusokat használunk. Ez meghaladja a cikk kereteit, de néhány napon belül közzéteszek egyet róla.

Végül a get_random_numbers a random.randint függvényt használja, amely egy véletlenszerű egész számot ad vissza a megadott tartományon belül. Ezután két véletlenszerű egész szám sorát adja vissza.

Véletlenszerű szorzási osztály

A „második mód”-nak szorzótábla formátumban kell megjelenítenie a játékot, és meg kell győződnie arról, hogy a felhasználó legalább 2 táblázatra helyesen válaszol.

Ebből a célból ismét felhasználjuk a super képességét, és a szülőosztály point_to_win attribútuma 2-re módosítja.

class TableMultiplication(BaseGame):

    description = "In this game you must resolve the complete multiplication table correctlynYou win if you solve 2 tables"
    
    def __init__(self):
        # Needs to complete 2 tables to win
        super().__init__(2)

    def run(self):

        # Print welcome messages
        super().run()

        while self.lives > 0 and self.points_to_win > self.points:
            # Gets two random numbers
            number = random.randint(1, 10)            

            for i in range(1, 11):
                
                if self.lives <= 0:
                    # Ensure that the game can't continue 
                    # if the user depletes the lives

                    self.points = 0
                    break 
                
                operation = f"{number} x {i}: "

                user_answer = self.get_numeric_input(message=operation)

                if user_answer == number * i:
                    print("Great! Your answer is correct")
                else:
                    print("Sorry your answer isn't correct") 

                    self.lives -= 1

            self.points += 1
            
        # Only get executed when the game is finished
        # And none of the conditions are true
        else:
            # Prints the final message
            
            if self.points >= self.points_to_win:
                self.print_win_message()
            else:
                self.print_lose_message()

Mint látható, csak ennek az osztálynak a futtatási metódusát módosítjuk. Ez az öröklődés varázsa, egyszer leírjuk azt a logikát, amit több helyen is használunk, és elfelejtjük 😅.

A futtatási metódusban egy for ciklust használunk, hogy megkapjuk a számokat 1-től 10-ig, és felépítettük a műveletet, amely megjelenik a felhasználó számára.

Ha az életek kimerülnek, vagy elérik a nyeréshez szükséges pontokat, a while hurok ismét megszakad, és megjelenik a nyer vagy veszít üzenet.

IGEN, létrehoztuk a játék két módját, de eddig semmi sem fog történni, ha futtatjuk a programot.

Tehát véglegesítsük a programot úgy, hogy végrehajtjuk a módválasztást, és a választástól függően példányosítjuk az osztályokat.

Választás megvalósítása

A felhasználó kiválaszthatja, hogy melyik módban szeretne játszani. Lássuk tehát, hogyan kell megvalósítani.

if __name__ == "__main__":

    print("Select Game mode")

    choice = input("[1],[2]: ")

    if choice == "1":
        game = RandomMultiplication()
    elif choice == "2":
        game = TableMultiplication()
    else:
        print("Please, select a valid game mode")
        exit()

    game.run()

Először is megkérjük a felhasználót, hogy válasszon az 1 vagy a 2 mód közül. Ha a bemenet nem érvényes, a szkript leáll. Ha a felhasználó az első módot választja, a program a Véletlenszerű szorzás játékmódot, ha pedig a másodikat választja, a Táblázat szorzás módot futtatja.

Íme, hogyan nézne ki.

Következtetés

Gratulálok, te csak Python alkalmazás létrehozása objektum-orientált programozással.

Az összes kód elérhető a Github adattár.

Ebben a cikkben megtanulta:

  • Használjon Python osztályú konstruktorokat
  • Hozzon létre egy funkcionális alkalmazást az OOP segítségével
  • Használja a szuper függvényt a Python osztályokban
  • Alkalmazza az öröklődés alapfogalmait
  • Osztály- és példányattribútumok megvalósítása

Boldog kódolást 👨‍💻

Ezután fedezze fel a legjobb Python IDE-t a jobb termelékenység érdekében.