Dziś zaczynamy nową serię postów pod tytułem Czas Pythona. Będzie to seria gdzie będziemy realizować konkretne projekty w Pythonie, by trochę potrenować w praktyce. W tej serii trochę się rozpiszę, bo i projekty podzielę na kilka artykułów, byś miał czas poszukać czegoś czasem na własną rękę. Zaczynamy od gry Bajgle w Pythonie. Jest to gra, w której na podstawie podpowiedzi, musimy odgadnąć liczbę jaką wylosował komputer.
Komputer losuje swój typ, a my zgadujemy, po czym dostajemy podpowiedź czy jakaś cyfra z kombinacji, którą podaliśmy pasuje, czy nie. Jako gracz możemy otrzymać trzy rodzaje wskazówek. Jest to Piko, Femi i Bajgle. Przy czym pierwsze słowo oznacza, że jakaś cyfra, podana przez nas znajduje się na którejś z pozycji. Natomiast cyfra ta jest przez nas podana na złej pozycji. Drugie ze słówek to poprawna cyfra jak i pozycja. Ostatnie - Bajgle oznacza, że nic się nie zgadza.
Planowanie na bieżąco
W tym kodzie będziemy sobie planować na bieżąco, po prostu zaczniemy kodować z mniej więcej jakąś wizją, a w miarę postępów będziemy uszczegóławiać nasz obraz. Na pewno wykorzystamy podział na funkcje (jeśli jeszcze ich nie znacz to zapraszam tutaj) - na pewno będziemy potrzebować funkcji głównej, main i losującej. Pewnie przyda się też funkcja do zwracania podpowiedzi. Zacznijmy zatem.
Podstawowe funkcje i instrukcje gry bajgle w Pytonie
Najpierw oczywiście będziemy potrzebowali funkcji main. Czyli tej funkcji głównej, która będzie wszystkim zarządzała i uruchamiała inne funkcje w razie potrzeby. Będzie też potrzebny komunikat początkowo, żeby "użyszkodnik" wiedział w ogóle, co uruchomił. Zacznijmy więc od prostego kodu

Jak można zauważyć przy konstruowaniu komunikatu w funkcji main(), użyłem metody format. Jest to metoda klasy str, która wstawia wartości w kolejności w placeholdery w stringu. Innymi słowy w powyższym łańcuchu znaków użyłem nawiasów { }. Dałem tym znać "tu coś będzie, ale powiem co dopiero metodą format". I taka metoda format sobie odszukuje każde z takich miejsc. Następnie wstawia tam swoje argumenty, w kolejności w jakiej je podano.
Na początku programu ustaliłem NUM_DIGITS, a po sposobie zapisu dużymi literami, stwierdzamy, że będzie to uznawane za stałą (umownie). Dlaczego tak? Ponieważ będę pewnie używał tej wartości w kilku miejscach, więc w ten sposób będę musiał zmienić ją tylko tutaj. Ułatwia to zmianę konfiguracji gry. Tak samo zrobię z liczbą prób - pewnie będę sprawdzał je w pętli.
Generowanie liczby
W tej grze, mamy zgadywać liczbę. Zatem potrzebujemy by komputer ją nam wygenerował. Trochę o tym wspominałem w jednym z moich filmów. Krótko mówiąc użyjemy sobie modułu random umożliwiającego losowanie. Do tworzenia takiej liczby będzie osobna funkcja w myśl zasady single responsibility. Napiszmy to zatem.

Na początku definiujemy nową funkcję, którą tutaj nazwałem getSecretNum(). Zaraz potem utworzyłem zmienną numbers i za pomocą list dałem jej do przechowywania listę cyfr od 0 do 9. Z takiego ciągu funkcja list zrobi list, a linia random.shuffle pomiesza nam te cyfry. Efekt możemy zobaczyć poniżej dzięki funkcją print. Oczywiście po wywołaniu funkcji w main.

Widzimy listę, a następnie tą samą listą, ale w innej kolejności. Polecam poczytać sobie o supermocach jakieg daje nam moduł random. Który oczywiście musimy zaimportować by to wszystko działało.
No i super, mamy swoją listę z cyframi, ale potrzebujemy z niej zrobić sekretną liczbę. Do tego, chcemy by można było robić liczbę długości takiej jak zdefiniujemy w stałej NUM_DIGITS, czego więc potrzebujemy użyć? Masz rację, potrzebujemy pętli! Mamy dokładnie określone ile powtórzeń będzie mieć taka pętla, zatem naturalny wybór to for.

Tutaj uzupełniłem funckję getSecetNum o deklarację zmiennej secretNum do przechowywania naszej liczby. Na razie mamy tam pusty ciąg znaków. Jednak w pętli for, która powtarza tyle razy jak duża liczba jest w NUM_DIGITS, doklejamy (dokonkatenowujemy? ) kolejne liczby. W praktyce pętla for powtarza się trzy razy, i za każdym razem zwraca kolejną cyfrę z listy numbers. Funkcja str zamienia zaś zwróconą wartość na string, daletego możliwe jest doklejenie jej do reszty łańcucha.
Zwracanie wartości secretNum
Na koniec zwracamy zmienną secretNum za pomocą słowa return. Co jednocześnie kończy działanie funkcji i przekazuje sterowanie razem ze zwracanymi danymi do miejsca wywołania. Tutaj miejscem wywołania jest główna funkcja - main. Dla uwidocznienia wyświetlam wylosowaną liczbę.

Jak widzimy uzyskujemy losową wartość, która przy każdym uruchomieniu będzie oczywiście inna. Uruchom program kilka razy i zobacz jak się ta wartość zmienia.
Wracamy do main
Skoro już zwracamy wartość wylosowaną do miejsca wywołania, to wypada wrócić trochę i zająć się funkcją main. W głównej funkcji zapiszemy sobie wylosowaną liczbę w zmiennej, a następnie wyświetlimy ilo prób ma aktualnie gracz. Będziemy oczywiście zmniejszać tą liczbę prób, zatem potrzebujemy też ją gdzieś przetrzymywać. Użyjmy do tego stałej, by można było rekonfigurować także liczbę prób.

I proszę, mamy w naszej grze dwie stałe NUM_DIGITS i MAX_GUESSES. Pozwala nam to na łatwą zmianę liczby prób czy długości losowanej liczby tylko w jednym miejscu w kodzie. Piękne, prawda?
Komunikat o próbach
Teraz powinniśmy wyświetlać komunikat o tych próbach. Tutaj, by być konsekwentnym, także wykorzystam metodę format.

I proszę. Oto nasza pętla while, ale uwaga, jest nieskończona. Znaczy to, że nigdy się nie kończy, ponieważ True będzie zawsze True, a pętla powtarza się dopóki warunek jest prawdziwy. Zatem jeśli ją uruchomisz, to wiec, że będziesz musiał wymusić zatrzymanie skryptu w IDE lub poprzez ctrl + c w terminalu. Tutaj nie będzie to przeszkadzać, w odpowiednim momencie użyjemy instrukcji brake by wyjść z pętli przerywając jej działanie.
Teraz utworzymy sobie jeszcze jedną pętlę, która będzie się wykonywać dopóki gracz nie osiągnie maksymalnej liczby prób. Oczywiście do tego będzie potrzebna zmienna przechowująca numer aktualnej próby.

Od razu też rezerwujemy miejsce na input użytkownika w postaci zmiennej guess. Będziemy tu przyjmować kolejne strzały gracza, dopóki nie oziągniemy maksymalnej ilości prób. Oczywiście potrzebujemy też zabezpieczyć się na wypadek błędnych danych i to zrobimy... kolejną pętlą while, powtarzającą się dopóki prawdą jest, że gracz podał coś innego niż liczbę lub długość podanego str nie zgadza się z długością tego wylosowanego.
Co dalej? Teraz jak mamy już odpowiedź gracza w zmiennej guess i wylosowaną liczbę w zmiennej secretNum wypadałoby je porównać, zostaje jeszcze zwiększanie i sprawdzanie ilości prób, bo na razie nic z tym nie robimy. Pobaw się z tym i zobacz czy jesteś w stanie to zrealizować samemu. W razie czego za tydzień będziemy kontynuować grę Bajgle w Pythonie!

[…] Dokładniej będziemy dalej pisać skrypt ją realizujący, jeśli jeszcze nie czytałeś, to zapraszam do poprzedniego odcinka. Zatem dziś kontynuujemy Bajgle, czyli grę polegającą na dedukcji liczby. W ostatnim artykule […]