Pong 3D - ciąg dalszy zabawy...



Pozwoliłem sobie nagrać piłkę odbijającą się w sześcianie - tak w ramach pochwalenia się. Poniżej - kod przykładu.

Pong3D - cz. 1

Razem z Pawłem zabraliśmy się za robienie Ponga3D w trybie multiplayer przez sieć. Moją rolą, jest napisanie serwera, a Pawła - klienta. Ja piszę w Pythonie, a Paweł w C++.

Jakie są ogólne założenia?

  1. Piłka porusza się wewnątrz sześcianu 201x201x201 punktów.
  2. Piłka jest traktowana jakby miała punkt na punkt.
  3. Środkiem układu współrzędnych (punktem (0, 0, 0)) jest środek sześcianu.
  4. Paletki są na przeciwległych ścianach. Tylko ściany z paletkami nie odbijają piłki.
  5. Gra kończy się wraz z nie odbiciem paletki przez któregoś gracza (oba klienty się wyłączają).
  6. Klient i serwer komunikują się wysyłając do siebie liczby całkowite oddzielone znakami nowej linii.

Jak ma wyglądać klient?
Mniej więcej tak.

Jak wygląda na razie kod serwera?


Jak wygląda na razie kod klienta?
Jak złapię Pawła, to go chłopak pokaże. :)

C++ - przykład operacji na plikach

Na fakultecie w poprzedni piątek mieliśmy zadanie - napisać program który wczyta znaki z jednego pliku i zapisze je w odwrotnej kolejności przy okazji zamieniając duże litery na małe (i na odwrót).





PS. Jak widać testuję nowy sposób osadzania kodu na blogu. Bonus - wersja w Pythonie.

Python #3 - sekwencje, pętla for

Otwórzcie IDLE.

Inne języki posiadają konstrukt językowy znany jako tablice - ciągi elementów do których można się odwoływać przy użyciu numeru. Python (o czym wspomniałem już w lekcji #1)  posiada wbudowane dwa podobne typy - listy i tuple (krotki) zwane razem sekwencjami.

W Pythonie (tak jak w C++, C, Javie, C#, JavaScriptcie i każdym języku poza Pascalem) numery ich elementów są liczone od zera. Elementy sekwencji w Pythonie nie muszą być wszystkie tego samego typu.


Krotki mają to do siebie, że raz utworzone, nie mogą się zmieniać. Można do zmiennej przypisać nową krotkę, ale nie można zmienić zawartości starej. Ma to swoje wady i zalety - w momencie, gdy sekwencja ma być na stałe zapisana w kodzie programu, lepiej zastosować krotkę (tym bardziej, że jest nieco szybsza od listy).



Z kolei listy mogą się zmieniać (mówimy o nich, że są mutowalne) - można zmieniać ich elementy. Dużo lepiej nadają się do sytuacji, gdy sekwencja zostaje wygenerowana przez program, albo zmienia się w czasie jego działania.



Zarówno listy jak i krotki obsługują też inne sztuczki (listy mają ich więcej, ale o nich kiedy indziej), w tym:

  • ujemne indeksy
  • sprawdzanie długości
  • wycinanie fragmentów



Poza pętlą while, którą już widzieliśmy, w Pythonie istnieje także pętla for - wykonuje ona zawarty w niej kod przypisując po kolei elementy podanej sekwencji do jednej zmiennej.



Zadanie 0
Napiszcie program który wypisze tekst piosenki 99 Bottles of Beer.
Zadanie 1
Napiszcie program FizzBuzz (program ma wypisywać liczby od 1 do 100, podzielne przez 3 zastępować słowem "Fizz", podzielne przez 5 słowem "Buzz", a podzielne przez obie słowem "FizzBuzz".

Python #2 - wyrażenia logiczne, instrukcja if, pętla while

Otwórzcie IDLE.


Typ logiczny w Pythonie nazywa się bool, a jego wartości to True i False. Wartości tego typu mają m. in. wyrażenia oparte na operatorach porównania.



Ponadto, wyrażenia można łączyć odpowiednikami kwantyfikatorów znanych z logiki - operatory logiczne (and, or i not) budując z nich wyrażenia bardziej skomplikowane.



Aby w zależności od jakiegoś warunku wykonać (lub nie) fragment kodu należy zastosować instrukcję warunkową if.

Jeśli wybór jest bardziej skomplikowany możemy się posiłkować konstrukcją if, else lub if, elif, else.




Czasem pojawia się potrzeba wykonywania kilku czynności wiele razy, dopóki pewien warunek jest prawdziwy. Wtedy stosujemy instrukcję pętli while. Działa ona w ten sposób, że podany warunek sprawdzany jest przed wykonaniem kodu znajdującego się wewnątrz pętli, a kod ten wykonuje się tylko jeśli warunek jest prawdziwy. Po wykonaniu kodu warunek sprawdzany jest ponownie i tak w kółko, aż do momentu gdy warunek okaże się fałszywy i program przejdzie dalej.



Na koniec parę zadań do poćwiczenia:


Zadanie 0

Napisz program sprawdzający czy liczba jest pierwsza (25 % 6 - reszta z dzielenia całkowitego 25 przez 6).
Zadanie 1
Napisz program wypisujący kilka pierwszych liczb Fibbonaciego.

Python #1 - zmienne, typy danych, wyrażenia i instrukcje

Uruchomcie shella w IDLE. Przykłady wykonujcie w shellu i obserwujcie wyniki.


Podstawowym pojęciem w programowaniu jest zmienna - czyli miejsce w którym komputer zapamiętuje jakąś wartość. W niektórych językach zmienną trzeba zawczasu utworzyć, aby potem można było jej użyć. Python nie jest jednym z nich - w języku spod znaku węża zmienna powstaje w momencie gdy pierwszy raz przypisze się do niej wartość.



Języki takie jak C++, C, Pascal, C# czy Java są typowane statycznie. Co to znaczy? Że zmienna ma na stałe przypisany typ - jeśli miała przechowywać liczby całkowite, to będzie przechowywać tylko liczby całkowite, a nie np. znaki, napisy lub liczby zmiennoprzecinkowe.


Po raz kolejny Python się wyłamuje - tutaj typowanie jest dynamiczne. Znaczy to, że zmienna nie ma na stałe przypisanego typu. Zmienna ma wartość i jest takiego typu jak jej aktualna wartość. Co więcej, wartość nie przypisana do zmiennej też ma typ.



Python posiada dość typowy zestaw tzw. typów wbudowanych - czyli standardowo dostępnych w każdym programie. Są to:

  • int - liczba całkowita
  • float - liczba zmiennoprzecinkowa
  • bool - wartość logiczna (prawda lub fałsz)
  • str - napis (w Pythonie nie ma osobnego typu znakowego - znak to jednoelementowy napis)
  • list - lista elementów dowolnego typu, przypomina tablice z innych języków, ale ma większe możliwości
  • tuple - w polskiej nomenklaturze: tupla, krotka; przypomina listę, z tym, że nie można zmienić jej poszczególnych elementów - można najwyżej stworzyć nową tuplę w miejsce starej
  • dict - słownik, w innych językach zwany też hashem lub mapą, podobnie jak w listach i tuplach, zawiera wiele elementów dowolnych typów, z których każdy ma przypisany klucz, klucze także mogą być różnych typów, ale nie mogą się powtarzać
Typy wbudowane różnią się od niestandardowych (o których dowiecie się później) m. in. tym, że posiadają literały. Literał to specjalny sposób zapisania wartości danego typu będący częścią składni języka.



Ponad to, w programie znajdziemy nie tylko proste wartości wyrażone jako literały - napotkamy także wyrażenia. Wyrażenia składają się ze zmiennych, literałów i innych wyrażeń. Interpreter Pythona oblicza wartości napotkanych w programie wyrażeń. Wyrażenia mogą być operacjami matematycznymi, logicznymi lub innymi.



Trzeba pamiętać, że wyrażenie jest zastępowane przez swoją wartość w danym momencie. Dlatego jeśli pod zmienną y przypiszemy 5, a pod zmienną z wartość zmiennej y dodać 1, to zmiana wartości zmiennej y nie wpłynie na wartość zmiennej z. Nazywamy to wartościowaniem zachłannym i jest to zachowanie typowe dla większości języków programowania, choć Python umożliwia także zastosowanie podejścia odwrotnego (zwanego leniwym), o czym dowiecie się później.



Jednak z samych literałów, zmiennych i wyrażeń nie zbuduje się sensownego programu - do tego konieczne są jeszcze instrukcje. Instrukcje nie mają wartości. Instrukcje mówią komputerowi co ma zrobić. Widzieliście już jedną instrukcję - instrukcję przypisania, która nadaje zmiennej wartość (to ta ze znakiem =). Inną instrukcją jest print, która służy do wypisywania wartości na ekran (podobnie jak write i writeln z Pascala). Jeśli chcemy w jednej linii umieścić więcej niż jedną wartość - oddzielamy je przecinkami. Python sam wstawi między nie odstępy.



Nie zawsze coś można zaliczyć tylko do instrukcji, albo tylko do wyrażeń. W wielu przypadkach problem taki występuje przy funkcjach. Widzieliście już składnię funkcji w działaniu - najpierw podaje się nazwę funkcji, a następnie w nawiasach jej argumenty (dane niezbędne do jej działania). Tak wygląda m. in. sprawdzanie typów przy użyciu type.


Niestety type nie jest dobrym przykładem bycia jednocześnie instrukcją i wyrażeniem. Dlaczego? Bo type działa jak typowe wyrażenie, nie robi nic poza tym, że zwraca pewną wartość. Lepszym przykładem jest raw_input - funkcja ta jako jedyny argument pobiera napis, wypisuje go, a następnie jako swoją wartość zwraca to co w reakcji na zaczepkę napisze użytkownik.



Na koniec wspomnę jeszcze o konwersji typów, czyli zamianie wartości z jednych na drugich. Czasami może się zdarzyć, że wartość jednego typu (np. int) będziemy musieli zamienić na inną (np. float) - jest to akurat dość częsty przypadek, bo przy dzieleniu przez siebie intów "gubią się" części ułamkowe (którego problemu nie mają floaty). Konwersje między typami najczęściej jak wywołania funkcji (którymi rzeczywiści są) nazywających się tak samo jak typy.



Zadanie 0
Napisz program który bezczelnie poleca tego bloga każdemu kto go uruchomi.
Zadanie 1
Napisz program który pyta użytkownika o imię i grzecznie się z nim wita.
Zadanie 2
Napisz program który liczy średnią z dwóch podanych przez użytkowika liczb.

Python #0 - przygotowanie środowiska pracy

Pod Linuksem i w Mac OS Xie od 10.5 wzwyż Python zazwyczaj już jest. Czasem (np. w Ubuntu) może brakować IDLE. Kto używa wie jak doinstalować.


Pod Windowsem Pythona trzeba doinstalować - od razu dostajemy interpreter, IDLE i parę innych narzędzi. W tym celu udajemy się na stronę http://python.org/ i z menu po lewej wybieramy Quick Links (2.6.4) >> Windows Installer i zapisujemy na dysku. Instalator jest w formacie MSI (przyzwyczajonych do instalatorów w EXE uspokajam - to format od Microsoftu).


W tym momencie w odpowiednim menu środowiska graficznego naszego OSa powinien znajdować się Python w wersji 2.6 razem z IDLE. Odpalamy to drugie maleństwo.


IDLE na starcie wyświetla pojedyńcze okno - tzw. interaktywny interpreter. Można w nim wpisywać kod, który od razu się wykonuje (bardzo przydatna rzecz, np. kiedy zapomnimy jak coś działa i chcemy to szybko sprawdzić).


W menu File > New Window mamy możliwość otwarcia nowego okna edycji pliku. Kiedy już w takim oknie jesteśmy możemy otwierać i zapisywać pliki. Standard. Ciekawsza jest opcja w menu Run > Run Module. Odpala ona program w oknie interpretera (zwanego też shellem). To samo uzyskamy naciskając na klawiaturze F5. Jeśli próbujemy wykonać niezapisany plik, IDLE poprosi o zapisanie go.


Tyle o obsłudze, ważna jest jednak konfiguracja. Otwieramy ją w menu Options > Configure IDLE. Pojawi się okienko z kilkoma zakładkami.


Pierwsza pozwala ustawić czcionkę (najlepsza będzie taka o stałej szerokości np. Courier New), jej rozmiar i szerokość wcięcia (domyśle ustawienie to 4 spacje i jest to standard którego praktycznie wszyscy się trzymają - oznacza to, że naciśnięcie klawisza Tab na początku linii wstawi 4 spacje, które usuwane będą pojedyńczym naciśnięciem klawisza Backspace).


Druga zakładka pozwala na manipulowanie kolorami którymi IDLE podświetla składnię, a trzecia - wybrać lub zmodyfikować ustawienia skrótów klawiaturowych.

Czwarta zakładka zawiera różne inne ustawienia. Możemy np. wybrać czy IDLE ma przy starcie uruchamiać edytor czy shella, czy ma się upewniać przed zapisaniem pliku po naciśnięciu F5 itp. Najważniejsze jest jednak ustawienie domyślnego kodowania znaków na UTF-8.



Po dokonaniu zmian w konfiguracji naciskamy przycisk [Apply] na dole okna, aby wprowadzić zmiany i zamykamy okno.