Strona główna » programowanie

Tag: programowanie

Bartosz Gala autor bloga devhobby.eu – pragnę powitać w serwisie programowanie z kotem na kolanach. Zapraszam do przeczytania moich artykułów o C++ na blogu.

std::default_random_engine – opis podstawowy

Do tej pory w wielu publikacjach spotykamy się z opisem generatora liczb pseudolosowych w wersji dla języka C, czyli korzystamy z generatora „ziarna” srand (),a następnie generatora  rand(). Natomiast od wersji C++11 powinno się korzystać z dobrodziejstwa biblioteki random. W tym artykule opiszę mechanizm:

std::default_random_engine 

Samo korzystanie z nowej metody generowania liczb losowych w pierwszym momencie może wydawać się mało zrozumiałe, jednak postaram się w prostych słowach wyjaśnić same podstawy, niezbędne, aby można w pełni zamienić stary kod nowym. 

Komenda default_random_engine w przeciwieństwie do srand() nie jest generatorem ziarna – czyli prościej nie jest mechanizmem, który zapobiega otrzymywaniu identycznych ciągów liczb pseudolosowych, tylko jest inicjatorem generatora, i wskazuje jaki algorytm generowania liczb będziemy używać. Oczywiście możemy skorzystać z innych algorytmów, a nawet (jeśli posiadamy) ze sprzętowego generatora liczb losowych (wszystko opisane pod tym adresem).  tak więc komenda std::default_random_engine generator oznacza, że od teraz generator jest naszą liczbą losową a dokładniej całym ciągiem liczb, zmieniających się przy każdym wykorzystaniu i na razie zupełnie dla nas nieprzydatnych. Poniżej krótki program, który pozwoli to w pełni zrozumieć:

Kolejną komendą, jaka jest potrzebna to: 

std::uniform_int_distribution

Dzięki tej komendzie zamienimy ciąg liczb losowych na liczby z zadanego nam przedziału. Komendy używamy w następujący sposób:  std::uniform_int_distribution<int> distribution(a, b) gdzie: <int> określa typ zmiennej, jaki będzie zwracać generator, distribution to nazwa dla naszego generatora, natomiast (a,b) to zakres liczb, jaki będzie zwracany (na przykład od 0 do 20).

Teraz możemy już korzystać z komendy distribution(generator) aby wygenerować liczbę pseudolosową z zadanego zakresu. Poniżej krótki programik, który pokazuje cały mechanizm w działaniu. Oczywiście zamiast "generator" i "distribution" możemy skorzystać z dowolnych innych określeń (niebędących już istniejącymi komendami języka lub nazwami zmiennych) co pozwoli na płynne stosowanie wielu zakresów liczb losowych oraz kilku algorytmów generowania tych liczb (jeśli byłoby to potrzebne).

Mam nadzieję, że ten kawałek kodu wyjaśnia wszelkie wątpliwości, jeśli jakieś się pojawiły, i od teraz podstawowe mechanizmy związane z biblioteką random stały się proste i oczywiste.

*W artykule używam zamiennie nazw liczba losowa i pseudo losowa – w większości przypadków chodzi mi o liczby pseudo losowe, poza wzmianką o sprzętowym generatorze liczb losowych.

** Tak stworzone liczby pseudo losowe będą identyczne za każdym razem (taka sama sekwencja). W następnym artykule napiszę jak to zmienić, oraz opiszę prawidłowo wykonywany pomiar czasu w C++11.

Devhobby.eu na Devstyle.pl

Programowanie – pasja utracona.

Eh, te blogi… Ukazał się mały felietonik mojego autorstwa na serwisie Macieja Aniserowicza.

Nie wspominałbym o tym, gdyby nie to, że właśnie dostałem maila od kogoś, kto ma bardzo podobne doświadczenia w życiu i także zderzał się z pytaniem: czy mając 30 lat i więcej jest sens zabierać się za programowanie? Osobiście uważam, że jeśli tylko tego chcesz, to nie ma na co czekać, tylko działać 🙂 Nie ma się co obawiać, przejmować, szczególnie że zauważyłem bardzo przyjazne podejście programistów do tych, którzy uczą się programować nie dla kasy, ale dla radości i hobby.

Pewne kwestie poruszone w tym felietonie można znaleźć na tym blogu. Parę słów o tym napisałem we wstępie do artykułu o wiedzy w internecie, ale na Devstyle opisałem całą, historię programowania, które przestało być fajne i nie tylko.

Felieton znajdziecie na tej stronie portalu devstyle.pl – zapraszam do przeczytania.

Tak przy okazji słówko prywatne: Macieju, dziękuje za kawał dobrej motywacji do wystartowania z blogiem i całej reszty. Nie wiem, czy zmienisz profesjonalny świat IT, ale ten hobbystyczny na pewno już zmieniasz na lepsze. 

Projekt: Tworzymy własną grę – Po konsultacji :)

Pierwsza część projektu             Poprzednia część projektu      

Dzisiaj tylko krótka informacja techniczna: Kod projektu został rzucony na pastwę zawodowców, co oczywiście obnażyło jego słabe strony.

Po konsultacji

z rewelacyjną ekipą Cpp Polska kod gry jest w trakcie zamieszczania często dość istotnych zmian. Z jednej strony jest co poprawiać, ale to także świetny kawałek nauki. Poniżej umieszczam listę zaleconych poprawek, nad którymi pracuje, natomiast mam nadzieję, do tygodnia pojawi się pierwsza część Projekt: Tworzymy własną grę – refactoring/poprawki. Natomiast krótka przerwa jest potrzebna, na to, żebym mógł zapoznać się z kilkoma kwestiami zawartymi w uwagach do kodu i je ciut przećwiczyć. 

Uwagi do kodu: 

1. Za dużo komentarzy. Poleciłbym Ci lepsze nazewnictwo kosztem mniejszej ilości komentarzy.
2. Mam wrazenie, ze sporo ifow moglbys zamienic na switche.
W logikę nie chcę się wtrącać, bo nie znam modelu projektu.

Main.cpp
9 – w nowym c++ powinno używać się std::random_device do generowania ziarna. Tutaj więcej szczegółów: http://en.cppreference.com/w/cpp/numeric/random
17 – musisz popracować nad nazewnictwem, w linii 35 masz „endGame = startGame” ….
27 – nie potrzebujesz dwuwymiarowej dynamicznej tablicy. Znasz rozmiar w czasie kompilacji, możesz użyć std::array
32 – memory leak. Nie usuwasz pamięci po stworzeniu obiektu. Nie potrzebujesz dynamicznej alokacji, możesz stworzyć Player na stosie.
Da się uniknąć wszystkich new/delete w tym pliku

Player.h
dużo magicznych wartości, możesz zrobić klasy wyliczeniowe „enum class”

Player.cpp
9 – domyślny konstruktor tylko po to, żeby wypisać błąd. Nie potrzebujesz domyślnego konstruktora
16 – membery class możesz zainicjalizować w pliku .hpp
58 – gameOver?:)
63 – aż się prosi o switch/case i enum class

ScoreBoard.h
8 – możesz użyć std::array

ScoreBoard.cpp
25 – używaj algorytmów z std::algorithm, w szczególności std::sort (który również działa na tablicach)
52 – uchwyt do pliku jest automatycznie zamykany w destruktorze. I robisz close() nawet jak się nie uda otworzyć pliku
57 – użytkownika chyba nie interesuje czy plik istniał czy nie, jak jest pierwszy na pewno będzie o tym wiedział
60 – Nie potrzebujesz takich sprytnych algorytmów. Potrzebujesz użyć dobrej struktury danych. Użyj std::set, który jest posortowany (std::map jak będziesz chciał dodać nazwy), będziesz mógł łatwo wstawiać elementy
Może warto dodać do klasy nazwę użytkownika, nie tylko najlepszy wynik?

Ogólnie
Sformatuj kod clang-formatem, bardzo ciężko się czyta.
Nie masz żadnych testów, a to bardzo niedobrze 🙂

Tak więc czekają mnie dwie linie artykułów: będą to 2-3 artykuły związane z poprawkami do kodu oraz zupełnie osobna cześć bloga, czyli testy jednostkowe. Tak więc zaraz po majowym długim weekendzie będzie się sporo działo.

Na zakończenie wpisu, chcę bardzo podziękować ekipie z CPP Polska, a szczególnie osobą, które poświęciły bezinteresownie swój czas na code review – Jesteście wielcy!!! 🙂 

 

Programowanie – co to jest, i czy mogę się nauczyć?

Witaj!

Jeśli czytasz ten artykuł, to zapewne o programowaniu wiesz tylko tyle, że istnieje. W tym artykule chcę, w jak najbardziej przystępny sposób opisać co to jest, jak się to robi oraz, czy można się tego ot tak nauczyć?

Co to jest programowanie?

Program to nic innego jak przepis, który krok po kroku mówi komputerowi, co ma zrobić. Wyobraźmy sobie, że komputer to nasz nowy pomocnik kuchenny, który co prawda wie, jak działa mniej więcej sprzęt kuchenny, ale nic więcej. I wtedy wkraczamy my – i tworzymy program gotowania, wydając pomocnikowi komendy… Weź tuzin jaj, rozdziel żółtka od białek, zmiksuj białka mikserem na pianę, uprzednio dodając szczyptę soli…. Moment – co to jest tuzin? Jakie mieszadełka do miksera? Jak rozbijać te jajka? Czy już piana dobra?…  Niestety, nasz pomocnik okazał się ciężkim przypadkiem… tak ciężkim, jak komputer.

Niestety komputer nie myśli (podobnie jak nasz pomocnik) i trzeba mu bardzo dokładnie wszystko wytłumaczyć, każdy najmniejszy krok musimy zawrzeć w programie. To wydaje się dość uciążliwe, jednak dość szybko może przerodzić się w niezłą zabawę, wystarczy, że opanujemy podstawy i zaczniemy rozmawiać z komputerem w jego języku, a jest tych języków wiele, prawie jak u ludzi i jest w czym wybierać. Jak taka „rozmowa” wyglądałaby po polsku? Mniej więcej tak:

Teraz zacznij robić to co ci mówię
Wyświetl na ekranie tekst "witaj! jak masz na imię"
czekaj na odpowiedź użytkownika, a gdy ją uzyskasz: zapamiętaj ją
sprawdź jaka jest ostatnia litera imienia
jeśli imię kończy się na "a" napisz "O, fajna z ciebie dziewucha"
jeśli imię nie kończy się na "a" napisz "O Fajny chłopak jesteś"....
 

I tak dalej, kroczek po kroczku prowadzimy komputer, aby wykonywał dokładnie to, co od niego chcemy. Oczywiście posługujemy się nie polskimi zdaniami, tylko komendami języka oprogramowania, tutaj bardzo przyda się znajomość Angielskiego, gdyż większość komend jest niczym innym, jak słowami z tego języka. Do tego troszeczkę „Gramatyki” a w zasadzie składni, bo komputer jest niezwykle czuły na to, jak do niego mówimy, liczy się każdy nawias, każda kropka czy kolejność zapisu, ale przy „zdaniach” które na początku nie przekraczają 4-6 „słów” to naprawdę nie jest trudne. Gwarantuje, że nawet łatwiejsze niż użeranie się w rodzimym języku z naszym pomocnikiem kuchennym.

Czy mogę się tego nauczyć?

Ok, zaraz zrobimy test! Skoro już wiesz co to jest programowanie, to jeśli potrafisz powiedzieć, co zrobi pseudo program zapisany poniżej, to znaczy, że jesteś w stanie rozpocząć naukę programowania, i na pewno coś osiągniesz – jak dużo, to już zależy od czasu i samo zaparcia w nauce. Tak więc nasz program (nie jest on w żadnym języku programowania, ale to na prawdę nic nie zmienia)

rozpocznij program
Wypisz „Ile masz lat”
wczytaj wiek
jeśli wiek < 18 wypisz „jesteś niepełnoletni”
jeśli wiek = 18 wypisz „Oh! Jesteś w najfajniejszym wieku w życiu!”
jeśli wiek >18 wypisz „Witam, jesteś poważną, pełnoletnią osobą”
wypisz „koniec programu, do widzenia następnym razem”
zakończ program

 

I jak? Wiesz, co zrobi ten program? Świetnie, a teraz po prostu podstawiając pod polskie słowa odpowiednie komendy i czasem dodając tu i ówdzie jakiś nawias czy średnik możesz kazać wykonać dokładnie te zadania swojemu komputerowi. 

Oczywiście, wraz z nauką pojawiają się coraz trudniejsze zagadnienia, całość się komplikuje, ale powoli zdobywając wiedzę, uczymy się tego jak robienia na drutach: najpierw łańcuszek, potem gładki kawałek szalika, potem wzorek, kolorowe włóczki… krok po kroku można opanować powoli nawet najtrudniejsze techniki i rozwiązać pozornie niemożliwe do rozwiązania problemy. 

Czy programowanie jest dla mnie?

Na to pytanie nie ma odpowiedzi wprost. Jeśli poczujesz, że to lubisz, że jest to coś fajnego to tak, jest to dla ciebie, ale jeśli ktoś nie lubi programować, zabrał się za to tylko bo wszędzie mówią, że to wspaniała kasa, doskonała robota to odradzam iść w tym kierunku, bo programowanie na siłę nie dość, że będzie diabelnie ciężkie do nauczenia, to potem stanie się pracą – koszmarem, codzienną walką o przetrwanie i „byle do końca”.  Pamiętaj też, że do nauki programowania potrzebna jest konsekwencja i czas. Dla hobbysty wystarczy siąść sobie raz na dzień/dwa przez godzinkę czy dwie i powolutku się rozwijać, dla kogoś, kto ma ambicję pracować w zawodzie poświęcenie mniej niż 4-5 godzin dziennie przez 5 dni w tygodniu rozciągnie czas nauki do wymaganego poziomu z miesięcy na lata. Jak ktoś mnie pyta, czy to dla niego zwykle radzę: dojdź do poziomu, gdy samodzielnie napiszesz pierwszy program, który będzie działał i miał praktyczne zastosowanie (to zajmuje kilka – kilkanaście godzin nauki, więc nie dużo) i wtedy będziesz wiedzieć, czy sprawiło to radość, czy było tylko mozolnym i męczącym zmaganiem z kodem.

 

Na zakończenie

Teraz już wiesz, co to jest programowanie, jak sprawdzić, czy się do tego nadajesz i czy to lubisz. Od tego momentu tylko od ciebie zależy czy twoje zainteresowania poszybują w tym kierunku. I nigdy nie daj sobie wmówić, że posiadanie humanistycznego umysłu, bycie kobietą, dojrzały wiek czy cokolwiek innego jest jakąkolwiek przeszkodą w programowaniu – bo to kłamstwo, i jedynie sami możemy dać sobie odpowiedź na to, czy nam to leży, czy się podoba, czy jest to hobby a może nawet praca dla nas. 

 

Merlin duma nad grzybemA oto nasz pomocnik, podczas próby przygotowania grzyba do suszenia – programowanie na prawdę jest prostsze 😉 

Projekt: tworzymy własną grę (7): Koniec gry i tablica wyników

Pierwsza część projektu             Poprzednia część projektu      

W tym odcinku kończy się przygoda z główną częścią gry, do której będziemy w następnych odcinkach dopisywać nowe funkcjonalności. Dodam dzisiaj jedną metodę do klasy Player oraz stworze osobną klasę obsługującą tylko i wyłącznie obsługę wyników gry w tym tabelę wyników i zapisywanie/odczyt wyników do pliku.

Tablica wyników

Najpierw nowa klasa, która obsłuży tablicę wyników. Zdecydowałem się umieścić ją osobno, bo to bardzo uniwersalny kawałek kodu, który może się przydać w innych projektach. Poniżej link do kodu, który zaraz będę omawiać: 

ScoreBoard.h + ScoreBoard.cpp

W tej klasie bardzo dużo pracy wykonuje konstruktor i destruktor. To w konstruktorze dochodzi do odczytu danych z pliku do tablicy wyników lub stworzenia pustej tablicy oraz następuje sortowanie wyników od najmniejszego, do największego. Zdecydowałem się na sortowanie „bąbelkowe” – jest to najprostsze i najszybsze w zapisie sortowanie, a w wypadku tylko 10 pozycji nie ustępuje szybkością innym, bardziej zaawansowanym algorytmom. Zastosowałem tu też najwygodniejszy i zarazem najbezpieczniejszy zapis kodu służący do odczytu/zapisu całej tablicy: for(auto& i: tab) i = 0– wypełnianie po kolei wszystkich komórek tablicy tab liczbą zero. Polecam zapamiętać ten zapis, bywa bardzo przydatny. Tablica wyników tworzona jest tylko dla wysokiej trudności gry, oczywiście można to zmienić albo na tej samej tablicy, albo tworząc dodatkowy plik wyników, lub zapisując dwie tablice wyników w jednym pliku, co możliwe, że w dalszej części tworzenia projektu zostanie wprowadzone.

Metoda showScoreBoard odpowiada za wyświetlanie wyników na ekranie oraz jeśli wynik gracza mieści się w pierwszej dziesiątce zapisuje ten wynik na ostatnim miejscu tablicy (czyli nadpisuje wynik, który opuszcza tabelę). 

W destruktorze dochodzi do zapisu tablicy wyników do pliku, a jeśli nie ma takiego pliku jest on tworzony i zapisywany. Zastosowana jest najprostsza forma zapisu pliku, bardzo użyteczna w przypadku małych ilości danych.

Koniec gry

Pora uzupełnić grę o zakończenie. Do klasy Player dodaje metodę o wdzięcznej nazwie gameOver i używam jej jako wyjście z funkcji startGame (plik game.cpp linia 40)  return p_player->gameOver(); zamykając w ten sposób główną pętlę gry. Jeszcze kilka drobnych poprawek, które z łatwością można znaleźć przy pomocy GitHuba i gra w wersji beta już gotowa (dla niektórych firm to już wersja Release, a cała reszta to DLC 😉 )

Link do aktualnej wersji gry na GitHub.

W następnej części zatrzymam się jeszcze nad kodem i postaram się go w miarę własnej wiedzy „udoskonalić”, szczególnie że w międzyczasie pisania sam nauczyłem się kilku nowych rzeczy, które warto by zastosować, oraz usłyszałem kilka uwag do kodu, które wypada wziąć pod uwagę. Tak więc, zamiast pisać DLC biorę się za Patch 0.2 🙂 

 

Inne:

W kodzie czasem w komentarzach używam na początku określenia TODO: – to bardzo wygodna opcja, dla osób korzystających z reShapera, taki komentarz podświetla się na niebiesko, oraz zaznacza na pasku bocznym reShapera, co bardzo pomaga odnaleźć takie miejsce.

Przyznam się do grzechu… uparłem się, zrobić interfejs graficzny gry przy pomocy biblioteki windows.h tak jak „Microsoft to wymyślił”. Wiem, że są łatwiejsze i bardziej eleganckie metody i że ten sposób to pisanie w C, a nie C++, ale niestety, założyłem się, że dam radę, więc nie mam wyjścia. Jak skończę, to opiszę moją walkę w osobnym artykule.

 

Następna część projektu

 

Projekt: tworzymy własną grę w (6)-2: Spacerem po grze

Pierwsza część projektu      Poprzednia część projektu

Dokończenie pierwszej części artykułu. Dzisiaj opiszę wreszcie obiecywany ruch gracza, oraz gra uzyska status alfa1, co znaczy, że będzie grywalna z wykorzystaniem podstawowych funkcji. Dzisiejszym zadaniem jest:

Poruszanie w grze.

W tym odcinku zostanie dodany ruch postaci pomiędzy obszarami wraz z pełną informacją opisową dla gracza. Na sam początek gra informuje gracza o tym, gdzie może iść, przy okazji przypominając zasady sterowania. Sprawdzone zostanie to, które drzwi są otwarte, więc można z nich skorzystać.

Następnie zostanie z klawiatury odczytana decyzja gracza i przekazana do metody klasy Player. Można to zrobić na dwa, w gruncie rzeczy identyczne sposoby: Klasycznie wykorzystując komendy if – else if:

lub wykorzystując operator ?:

Oba te sposoby są poprawne i działają identycznie. Dobrze jest znać oba te sposoby zapisu. Na tym etapie sprawdzane jest jaki klawisz został wciśnięty, analizowane są zarówno duże, jak i małe litery, oraz wykluczana jest możliwość przejścia przez drzwi zamknięte.

Na zakończenie należy dodać funkcjonalność, która wykorzysta tę informację do przemieszczenia gracza, dopisując odpowiednią metodę do klasy Player:

Oczywiście trzeba wpisać jeszcze wywołanie do funkcji i metody w główną pętlę gry. Po wykonaniu ruchu wszystko zaczyna się od nowa… albo kończy. Jeszcze brakuje właściwego zakończenia gry, ale ten moduł zostanie dopisany w następnej części. Można już poruszać się po obszarze gry, sprawdzić, czy opisy pomieszczeń, zamykanie drzwi i inne elementy działają. W następnej części: wynik gry oraz zapis i odczyt pliku. Dzięki temu uzyskamy w pełni grywalną grę, do której będzie można już tylko dodawać kolejne funkcjonalności. 

Link do projektu na GitHub (W kodzie „wykomentowane” są części kodu, które będą dołączone i omówione w następnej części).

Następna część projektu.