Zanim zaczniesz

Zadania wymagają znajomości podstaw języka JavaScript. Nie martw się, jeżeli go nie znasz! Jest całkiem prosty :-). Używa go obecnie większość stron internetowych - także ta, którą właśnie czytasz. W sekcji 'Materiały do nauki' znajdziesz linki do kilku kursów, które pozwolą Ci zacząć przygodę z programowaniem w JavaScript. Po zarejestrowaniu zarejestrowaniu się uzyskasz dostęp do serwisu do rozwiązywania zadań, a w nim do przykładów przydatnych do rozwiązania poszczególnych zadań.

Zadanie 3. Animacje

 Start: 1 maj 2017
Termin nadsyłania rozwiązań: 1 czerwca 2017

Przypominamy, że dostęp do serwisu do rozwiązywania zadań otrzymasz na maila po rejestracji. Dla osób zarejestrowanych wcześniej: zadanie 3 jest dostępne w tym samym miejscu, co zadanie 2.

Część 1. Animacja 1D (1 wymiar)

Wstęp

Nadszedł czas na kolejną część naszych zadań, w której to części motywem przewodnim będą "ruszające się rzeczy" (lub, mówiąc trochę bardziej skomplikowanym słowami, zasady fizyki). Efekt ruchu osiągniemy w identyczny sposób jak przed prawie dwoma wiekami - wyświetlając szybko po sobie delikatnie zmienione obrazki. Oczywiście w uproszczeniu :-). Na koniec zaimplementujemy grę na dwie (lub więcej) osób. Brzmi interesująco? To zapraszamy!

Opis zadania 

Kod który będzie nas interesował w tym zadaniu znajduje się wyłącznie w pliku kropka.js.

Uruchom zadanie (przycisk run). Na ekranie powinien pojawić się szary kwadrat, a w środku żółta kropka, która coraz szybciej spada w dół, aż w końcu znika.

Dlaczego tak się dzieje? Po prostu z każdym wyświetleniem obrazka zwiększamy prędkość (plik kropka.js, linia 16) i zmieniamy położenie kropki o wartość tej prędkości (kropka.js:17). Czyli między kolejnymi klatkami animacji (używając tego trochę kinematograficznego pojęcia) kropka przebywa coraz dłuższą drogę, co dość naturalnie przypomina działanie siły grawitacji i  spadanie.

Zniknięcie kulki z ekranu trochę nam psuje zabawę - i tutaj pojawia się pole do popisu dla Ciebie: zaimplementuj części funkcji: nastepnePolozenieKropki tak, aby kropka po dotarciu do  dolnej krawędzi płótna odbiła się i wróciła do góry. A później odbiła się jeszcze raz, i jeszcze raz i... no i tak bez końca, tak jak na tym filmiku: 

https://drive.google.com/file/d/0ByBbw5fi2covazZDdURWa2o1aGM/view

Trochę technicznych szczegółów. Szary kwadrat po którym porusza się kulka ma wysokość 400 piksli. Piksel numer 0 znajduje się na samej górze, piksel numer 399 na samym dole. Aby rysunek wyglądał trochę ładniej na początek "spuszczamy" kulkę z piksla numer 20. Chcielibyśmy, aby odbijał się do góry po przekroczeniu 380 piksla.

Jeśli chcesz, odkomentuj linie 18-22 w pliku kropka.js. Tak zmieniony program nie robi tego czego chcemy (kulka nie odbija się, ale wraca na swoje początkowe miejsce po wyjściu za planszę), ale może pomoże Ci on w implementacji.

Ruch piłeczki możesz wstrzymywać i wznawiać klikając szare pole myszką.

Kiedy już uda Ci się zaimplementować odbijanie, możesz (ale nie musisz) poeksperymentować z implementacją bardziej odpowiadającą rzeczywistości: możesz zmienić kod tak, aby kropka odbijała się z każdym odbiciem trochę słabiej (trochę zwalniała), i coraz słabiej, i coraz słabiej i w końcu zatrzymała się. (Tak jak w prawdziwym życiu, gdzie kulka jest spowalniana oporem powietrza). 

Do dzieła!

Część 2. Animacja 2D (2 wymiary)

Wstęp

No dobrze, piłeczka podlegała już działaniu grawitacji - to teraz następny krok. Spróbujemy ją poruszać jeszcze w poziomie. To nic trudnego - po prostu nasza funkcja dostanie informację o obu współrzędnych: x (szerokość) i y (wysokość) - i będzie musiała zwrócić nowe położenie, zależne od prędkości w poziomie (x) i pionie (y). Na jakiej zasadzie ma odbywać się ruch na boki? Bardzo prostej - kulka ma w miarę naturalnie odbijać się od bocznych ścianek pudełka. Tak jak na tym filmiku: 

https://drive.google.com/file/d/0ByBbw5fi2covSjZXSVNBM0YxTW8/view

Opis zadania

Twoim zadaniem jest zaimplementowanie funkcji nastepnePolozenieKropki w pliku kulki.js. Funkcja przyjmuje cztery argumenty współrzedne x, y (szerokość, wysokość) i aktualne prędkości w pionie i poziomie dla pojedynczej piłeczki.

Implementacja funkcji powinna modyfikować te cztery wartości tak, aby po wykonaniu tej funkcji kropka przesunęła się i jeśli trzeba - odbiła od ścianek (jak na filmiku pokazanym wcześniej).

Tym razem użyjemy więcej niż jednej piłeczki (patrz kulki.js, linie 3-16), nie wpłynie to jednak na Twój kod, po prostu kod obliczający następne położenie kulki (funkcja nastepnePolozenieKropki) zostanie wywołany dla kilku kulek (wywołania w pliku index.html, ale możesz je zignorować, nie bedziesz potrzebowała zrozumieć tego pliku).

Tak jak poprzednio, plansza ma wymiary 400 na 400 piksli, ale chcielibyśmy zostawić na każdym boku margines 20 piksli (poruszać się tylko między pikslami 20 a 380, a potem odbijać w drugą stronę).

 

Współrzędną y (wysokość) możesz zmieniać dokładnie tak saom jak w zadaniu 3a. Współrzędną x zmieniaj o prędkość_x, a jeśli dojdziesz do którejś ze ścian zmień prędkość_x na wartość przeciwną (-prędkość_x), tak aby piłka zaczeła poruszać się w drugą stronę.

Do dzieła! 

Część 3. Gra ping-pong

Wstęp

Teraz, kiedy nabraliśmy już sprawności w kontrolowaniu ruchu piłki, zaimplementujemy jedną z najstarszych gier na automaty - Pong - https://pl.wikipedia.org/wiki/Pong. Nie musisz czytać opisu, w skrócie chodzi o zaimplementowanie gry w ping-ponga. Przygotowaliśmy dla Ciebie najprostszą wersję tej gry, podobną do tej http://karpathy.github.io/assets/rl/pong.gif . Twoim zadaniem będzie dodanie rozszerzeń, mamy nadzieję, że na koniec pokażesz nam coś bardziej podobnego do https://media.giphy.com/media/PXqNXjkTmEfRK/giphy.gif ;-).

Zacznij od zagrania!

Najlepiej zacznij od zagrania w grę kilka razy. Uruchom ją przyciskiem run, a potem naciśnij na planszę myszką i wciśnij klawisz r (jak reset). Przysik r zawsze resetuje grę, zarówno myszka jak i spacja wznawiają i pauzują grę.

Lewy prostokąt możesz przesuwać klawiszami a i z, prawy klawiszami k i m. Możesz zagrać w grę z drugą osobą używając tej samej klawiatury! Jeśli jest Was więcej niż dwójka, znajdź w pliku gra.js w funkcji nowaGra zmienną gracze i zobacz, że możecie grać w jeszcze większym gronie! (a kilka linijek dalej możesz też dodać więcej piłek).

To najprostsza wersja gry, którą będziemy teraz wzbogacać o nowe elementy.

Opis techniczny

Aby dodać nowe funkcjonalności do gry, musisz najpierw z grubsza zrozumieć napisany już kod. Skup się na pliku gra.js, w nim znajduje się cała interesująca nas logika. Znajdź w nim funkcję nowaGra. W funkcji tej tworzymy graczy (prostokąty po bokach) i piłeczki. Gracze (tworzeni w funkcji nowyGracz) umieją zaktualizować swoją pozycję na podstawie poprzedniej pozycji i faktu, czy ktoś nacisnął przycisk dół/góra (metoda aktualizujPozycje). Piłeczki odbijają się od góry i dołu planszy, a kiedy dojdą do boku mogą albo odbić się od prostokąta albo wypadają z gry, jeśli prostokąta tam nie ma. Piłeczki także implementują podobną funkcję aktualizujPozycje.

Oprocz wspomnianych już funkcji, w pliku index.html znajduje się kod który w pętli aktualizuje pozycje graczy i piłek oraz śledzi które klawisze zostały naciśnięte. Nie musisz czytać tego pliku w celu dopisania nowych funkcjonalności.

Chcielibyśmy, abyś dodał kilka rozszerzeń. Od zgłoszonego rozwiązania oczekujemy zaimplementowania co najmniej dwóch pierwszych, ale im więcej innych dodasz tym lepiej! Jeśli w międzyczasie będziesz miała/miał jakieś pytania, pytaj koniecznie!

Rozszerzenia których wymagamy

W oryginalnej wersji gry Pong piłka rozpędza się z każdym odbiciem od prostokąta. Sama zdecyduj, jak piłka ma przyspieszać po odbiciu od prostokąta. Zaimplementuj proszę takie rozszerzenie zmieniając metodę aktualizujPozycję dla piłki.

Zaimplementowaliśmy grę tak, że piłka zawsze odbija się od boku pod tym samym kątem, pod którym tam padła, ale tak nie musi być! W szczególności w oryginalnym Pongu piłka po odbiciu od prostokąta poleci: równolegle do sufitu, jeśli udeżymy środkiem prostokąta, w stronę sufitu, jeśli udeżymy górą prostokąta; w stronę podłogi, jeśli udeżymy dołem prostokąta. Rzuć proszę okiem na obrazek https://i1.wp.com/zekechan.net/wp-content/uploads/2015/07/pong-05b.png (opisane również w https://pl.wikipedia.org/wiki/Pong#Rozgrywka w sekcji 'rozgrywka'). Nie musisz zachowywać dokładnych kątów, ale chcielibyśmy abyś zaimplementowała/zaimplementował co najmniej 5 różnych odchyleń, tym większe im dalej od środka piłka uderzyła. Ponownie, musisz zmienić funkcję aktualizujPozycję dla piłki.

Inne rozszerzenia

I to wszystko czego wymagamy! Zachęcamy Cię bardzo do pomyślenia, co sprawiłoby, że gra będzie fajniejsza. Tworzenie gier w dużej mierze na tym polega, trzeba myśleć jakie funkcjonalności sprawią przyjemność i będą wciągające dla użytkowników.

Zaimplementuj któreś ze swoich pomysłów (jak najwięcej)! Docenimy Twoją kreatywność. Kilka pomysłów na rozgrzewkę:

Możesz dodać dodatkowe przeszkody na planszy od których odbijałaby się piłka

Dodaliśmy dla Ciebie funkcję wcisnietoCyfreN, którą możesz chcieć wykorzystać. Funkcja ta wywołuje odpowiedni kod po naciśnięciu klawiszy 0,1,2,..,9. Może np po naciśnięciu 0 lub 9 (tak aby obaj gracze mieli klawisz pod ręką) powinna się tworzyć jedna dodatkowa piłka? A może prostokąt przeciwnika mógłby się wtedy rozszerzać lub zwężać, albo przesuwać trochę w dół/górę? Albo piłka zaczeła by lecieć w górę zamiast w dół (lub odwrotnie). Albo na chwilę przyspieszać lub zwalniać? Wybierz lub wymyśl coś co Tobie pasuje!

Być może po zrestartowaniu gry klawiszem r (funkcja nowaGra) gracze powinni pozostawać na obecnych miejscach, a nie wracać do początkowych? Może licznik wygranych piłek nie powinien się wtedy zerować? Jak uważasz!

W komentarzu koniecznie opisz dokładnie, co niestandardowego robi zaimplementowany przez Ciebie kod!

Powodzenia! Zachęcamy do zadawania pytań.

Zadanie 2. Gry planszowe

Start: 5 luty 2017
Termin nadsyłania rozwiązań: 15 marzec 2017

Przypominamy, że dostęp do serwisu do rozwiązywania zadań otrzymasz na maila po rejestracji. Dla osób zarejestrowanych wcześniej: 5 lutego dostaniecie kolejny mail z instrukcją dostępu do drugiego zadania.

Cześć! W drugim zadaniu implementować będziemy dwie gry: 'memory', znaną także jako 'duo' oraz 'kółko o krzyżyk'. Jeśli nie znasz którejś z nich, opisujemy je poniżej.

Do rozwiązania zadania wystarczy Ci przejrzenie 'Przykładów' do zadań 1. i 2. w systemie do rozwiązywania zadań.

Zanim przystąpisz do rozwiązywania:

Zarejestruj się aby uzyskać dostęp do serwisu pozwalającego na testowanie i przesyłanie rozwiązań.

Gra 1. Memory/Duo

Zadanie 2a. Memory

Cześć! Tym razem Twoim zadaniem będzie zaimplementowanie gry Memory/Duo. Jeśli jej nie znasz. zasady są następujące:
 
Gra polega na odnajdowaniu par takich samych kart. Gracz odsłania 2 karty, jedna po drugiej. Jeśli są to takie same karty, obie pozostają odsłonięte na stałe. Jeśli są różne, pierwsza karta zostaje ponownie zasłonięta. Gra kończy się po odsłonięciu wszystkich par kart.
 
Większość kodu jest już zaimplementowana i gra "prawie działa". Uruchom ją przyciskiem run i poklikaj trochę w karty. Jak widzisz po znalezieniu pary takich samych kart zostają one odsłonięte "na dobre". Po znalezieniu pary na górze zielonego ekranu zobaczysz komunikat "Znalazłaś pasującą parę!".
 
Chcemy, aby zamiast tego komunikat po odsłonięciu ostatniej pary pojawiał się o końcu gry. Aby tak się stało, musimy poprawić (obecnie błędną) implementację funkcji czyWszystkoJuzObrocone w pliku 'LogikaGry.js', linia 112. Kiedy to zrobimy, odpowiedni komunikat zostanie wypisany (patrz plik 'rysowanie.js', linia 85).
 
Jeśli chcesz ułatwić sobię pracę, możesz tymczasowo zakomentować linię 37 w pliku index.html. Dzięki temu karty nie będą się tasować przy nowym rozdaniu. Nie wpłynie to na wykonanie testów automatycznych.
 
Możesz też poeksperymentować z innymi obrazkami - dodawanie obrazków można zmieniać edytując plik index.html, linijki 24-34; funkcja stolik.dodajObrazek rejestruje obrazek na podstawie zewnętrznego adresu.
 
Powodzenia!
 

Zadanie 2b. Memory z trzema kartami 

Rozwiąż najpierw zadanie "2a". To zadanie jest jego kontynuacją.
 
Chcemy teraz utrudnić trochę naszą grę. Zamiast znajdować pary takich samych kart, będziemy znajdować trójki takich samych kart.
 
Gra powinna działać następująco: po kliknięciu w kartę, powinna się ona odsłonić. Po kliknięciu w drugą kartę, powinna się ona również odsłonić. Po kliknięciu w trzecią kartę, jeśli wszystkie trzy karty były takie same, powinny się one odsłonić "na dobre". W przeciwnym wypadku, najstarsza, pierwsza karta zostaje zasłonięta w momencie odsłonięcia karty trzeciej.
 
Naciśnij przycisk run i poklikaj w karty. Jak widzisz, gra działa zupełnie źle. Karty nigdy się nie zasłaniają, gra nie zauważa, że znaleziono trójkę takich samych kart itd.
 
Aby to naprawić, musisz zaimplementować funkcję uzytkownikKliknalNaKarte w pliku LogikaGry.js. Przeczytaj dokładnie implementację tej samej funkcji w zadaniu 2a, W zależności od przypadku, funkcja ma zwracać jeden ze stanów ("nic", "obroc_aktualna_karte" itd.). Gra zacznie zachowywać się tak, jak tego oczekujemy po zaimplementowaniu zwracania odpowiednich stanów.
 
Implementując funkcję uzytkownikKliknalNaKarte musisz zadbać o utrzymywanie odpowiednich wartości w zmiennych zawartoscKart, ostatnia_karta_1, ostatnia_karta_2, znalezioneObrazki. Przeczytaj dokładnie plik LogikaGry.js i komentarze które dla Ciebie tam zostawiliśmy.
 
Jeśli chcesz ułatwić sobie pracę, możesz tymczasowo zakomentować linię 30 w pliku index.html. Dzięki temu karty nie będą się tasować przy nowym rozdaniu. Nie wpłynie to na wykonanie testów automatycznych.
 
Powodzenia!
 

Zadanie 2c. Memory z N kartami  

Rozwiąż najpierw zadania "2a" i "2b". To zadanie jest ich kontynuacją.
 
A teraz utrudnimy naszą grę jeszcze bardziej. W zadaniu 2a. chodziło o znalezienie pary takich samych kart, w 2b. o znalezienie trójki a teraz o znalezienie N takich samych kart, gdzie N jest zdefiniowane w pliku index.html w linii 21. Obecnie N = 4, ale możesz zmienić wartość, jeśli chcesz trochę poeksperymentować.
 
Gra powinna działać następująco: po kliknięciu w kartę powinna się ona odsłonić. Tak samo druga karta, trzecia karta itd., aż przy N-tej odsłoniętej karcie, jeśli wszystkie N kart było takie same, wszystkie powinny odsłonić się "na stałe". W przeciwnym przypadku powinna zasłonić się jedna, najdawniej odsłonięta karta.
 
Tym razem musisz w całości zaimplementować funkcję uzytkownikKliknalNaKarte w pliku LogikaGry.js. W komentarzu jest opisane, jakie wartości powinny być zwracane w każdym przypadku.
 
Zadanie jest podobne do zadania 2b., z jedną duża różnicą. W 2b. indeksy dwóch ostatnio odsłoniętych kart pamiętaliśmy na zmiennych ostatnia_karta_1 i ostatnia_karta_2. Teraz chcemy pamiętać ostatnie N-1 kart i nie możemy ich trzymać każda na osobnej zmiennej.
 
Zamiast tego będziemy używać tablicy ostatnieKarty. Po odsłonięciu nowej karty będziemy ją pamiętać na końcu (pod największym indeksem) w tej tablicy, wołając ostatnieKarty.push(nowy indeks). Po zasłonięciu karty będziemy ją usuwać z początku tablicy (używając ostatnieKarty.shift()).
 
Jeśli chcesz ułatwić sobie pracę, możesz tymczasowo odkomentować linię 31 w pliku index.html. Dzięki temu karty nie będą się tasować przy nowym rozdaniu. Nie wpłynie to na wykonanie testów automatycznych.
 
Powodzenia!
 

Gra 2. Kółko i krzyżyk

Zadanie 2d. Kółko i krzyżyk

Twoim zadaniem jest napisanie gry w kółko i krzyżyk :-). Jeśli nie znasz zasad tej gry znajdziesz je tutaj http://www.math.edu.pl/kolko-krzyzyk 
 
No dobra, duża część gry (taka jak rysowanie planszy, wykrywanie na które pole kliknięto myszką itd.) jest już zaimplementowana, ale nie wszystko. Uruchom grę przyciskiem run. Jak widzisz, można w nią "grać", ale niektóre rzeczy działają źle. Po tym, jak jeden z graczy wygra cały czas można stawiać na planszy kółka i krzyżyki, choć nie powinno się już dać. Inny przykład tego co działa źle: spróbuj postawić kółko na postawionym wcześniej krzyżyku - uda Ci się to, chociaż nie powinno.
 
Gra nie działa do końca dobrze, bo dwie funkcje w pliku LogikaGry.js nie są zaimplementowane. Chodzi o funkcje:
  • wyzerujStanGry - odpowiedzialna za czyszczenie stanu gry, wywoływana w testach automatycznych
  • uzytkownikKliknalPoleNaTablicy która będzie automatycznie wywołana po kliknięciu na narysowaną wcześniej planszę, i która będzie musiała zwrócić wynik określający sytuację na planszy. Jeśli zaimplementujesz tę funkcję tak jak opisaliśmy poniżej, wszystko zacznie działać tak jak powinno 
Funkcja uzytkownikKliknalPoleNaTablicy będzie otrzymywała następujące parametry:
  • wspolrzednaX - indeks klikniętego pola w poziomie, licząc od lewej do prawej, pierwsze pole ma indeks 0, ostatnie 2
  • wspolrzednaY - indeks klikniętego pola w pionie, licząc od góry do dołu, najwyższe pole ma indeks 0, najniższe 2
  • symbolGracza - symbol gracza, który wykonał ruch. Albo znak O, albo X
 
Wynikiem działania funkcji ma być jedna z następującej listy wartości:
  • nic - jeśli kliknięcie nie spowodowało żadnej akcji
  • zaznacz_pole - jeśli po kliknięciu pole powinno być zaznaczone symbolem aktywnego gracza i następne kliknięcie ma być wykonane przez drugiego gracza
  • koniec:wiersz - jeśli pole ma być zaznaczone i spowoduje to koniec gry przez posiadanie wszystkich tych samych znaków w danym wierszu (w którym nastąpiło kliknięcie)

 

  • koniec:kolumna - j.w., tylko te same znaki w klikniętej kolumnie

  • koniec:ukosnik - j.w., tylko te same znaki po przekątnej od górnego lewego boku do dolnego prawego

  • koniec:odwrocony_ukosnik - j.w., tylko przekątna od górnego prawego boku do lewego dolnego

  • remis - jeśli gra zakończyła się remisem
Status gry jest automatycznie wyświetlany nad planszą.
 
Poniżej planszy znajduje się pole przeznaczone dla wyświetlania informacji diagnostycznych - można w ten sposób ułatwić sobie śledzenie tego, co z kodem się dzieje.
 
Do poprawnego działania funkcja będzie musiała przechowywać stan gry - możesz to zrealizować przez zdefiniowanie zmiennych powyżej definicji funkcji i odwoływanie się do takich (globalnych) zmiennych w funkcji.
 

Zadanie 2e. Kółki i Krzyżyk w wersji z wieloma polami

W tym zadaniu czeka Cię coś odrobinę trudniejszego, jako rozgrzewkę upewnij się, że zrobiłaś zadanie 2d: standardową grę w Kółko i Krzyżyk.
 
Zadanie, w porównaniu do poprzedniego, ma możliwość zmiany rozmiaru planszy z 3x3 na NxN. Tym razem wygrywa ten, kto ułoży linię długości N.
 
Dla prawidłowego rozwiązania zadania konieczne jest zaimplementowanie dwóch funkcji umieszczonych w pliku LogikaGry.js:
  • wyzerujStanGry z parametrem pRozmiarTablicy - wywoływanej na początku. Wartość parametru pRozmiarTablicy odpowiada wielkości planszy do gry
  • uzytkownikKliknalPoleNaTablicy - z identycznym zestawem parametrów, jak w zadaniu z planszą 3x3. Rzuć okiem na opis: zadania https://repl.it/teacher/assignments/28713 jeśli chcesz sobie przypomnieć szczegóły. Zestaw zwracanych stałych jest również ten sam:)
 
Dla testów zachowania różnej wielkości planszy możesz sterować drugim parametrem wywołania w linijce 30 pliku index.html, poniżej jest ustawiona na 4
 
var malarzTablicy = new MalarzTablicy(100,4,canvas);
 
Powodzenia!
 

Zadanie 2f. Kółko i Krzyżyk 3D

Na koniec tej porcji zadań ostatnie wyzwanie: oprogramowanie logiki gry w kółko i krzyżyk w wersji trójwymiarowej (3x3x3)!
 
 

 
 
Dla ułatwienia obsługi klikania po planszy została ona "spłaszczona" - każda "ścianka" kostki widziana z przodu jest przedstawiona jako osobna plansza.
 
 
Do rozwiązania zadania wystarczy zaimplementować w pliku LogikaGry.js funkcje:
 
wyzerujStanGry - nie przyjmuje żadnych parametrów, rozmiar kostki jest stały - a jej zadaniem, jak poprzednio, jest przygotowanie struktur danych do nowej try.
 
uzytkownikKliknalPoleNaTablicy - obsługującej logikę gry. Przyjmuje ona następujące parametry:
  • x - indeks pola w linii poziomej, od 0 (lewa strona) do 2 (prawa strona)
  • y - indeks pola w linii pionowej, od 0 (góra) do 2 (dół)
  • z - indeks pola w osi, od 0 (najbardziej z tyłu) do 2 (najbardziej z przodu)
  • symbolGracza - jak poprzednio, albo X, albo O
 
Wierzchołki sześcianu mają następujące współrzędne wg tej konwencji:
  • H - x:0, y:0, z:0
  • E - x:0, y:0, z:2
  • A - x:0, y:2, z:2
  • D - x:0, y:2, z:0
  • C - x:2, y:2, z:0
  • B - x:2, y:2, z:2
  • F - x:2, y:0, z:2
  • G - x:2, y:0, z:0
 
Dozwolone są następujące wyniki zwracane z tej funkcji:
  • "nic" - jeśli kliknięcie nie spowodowało żadnej akcji
  • "zaznacz_pole" - jeśli kliknięcie tylko zaznaczyło pole
  • "remis" - jeśli gra skończyła się remisem
  • "koniec:wiersz" - jeśli wygrał gracz, który umieścił swoje symbole w tym samym wierszu (ta sama wartość współrzędnej x)
 

 
  • "koniec:kolumna" - jeśli wygrał gracz, który umieścił swoje symbole w tej samej kolumnie (ta sama wartość współrzędnej y)
 

 
  • "koniec:os" - jeśli wygrał gracz, który umieścił swoje symbole w tej samej osi (ta sama wartość współrzędnej z)
 

 
  • "koniec:skos:hc" - jeśli wygrał gracz, który umieścił swoje symbole w tej samej linii po skosie w polach o tej samej wartości współrzędnej Z - czyli w płaszczyźnie HCBE
 

 
  • "koniec:skos:ha" - jeśli wygrał gracz, który umieścił swoje symbole w tej samej linii po skosie w polach o tej samej wartości współrzędnej X - czyli w płaszczyźnie HABG
 

 
  • "koniec:skos:hf" - jeśli wygrał gracz, który umieścił swoje symbole w tej samej linii po skosie w polach o tej samej wartości współrzędnej Y - czyli w płaszczyźnie HFBD
 

 
  • "koniec:skos:gd" - jeśli wygrał gracz, który umieścił swoje symbole w tej samej linii po skosie w polach o tej samej wartości współrzędnej Z - czyli w płaszczyźnie GDAF
 

 
  • "koniec:skos:gb" - jeśli wygrał gracz, który umieścił swoje symbole w tej samej linii po skosie w polach o tej samej wartości współrzędnej X - czyli w płaszczyźnie GHAB
 

 
  • "koniec:skos:fh" - jeśli wygrał gracz, który umieścił swoje symbole w tej samej linii po skosie w polach o tej samej wartości współrzędnej Y - czyli w płaszczyźnie FHDB
 

 
  • "koniec:przekatna:bh" - jeśli wygrał gracz, który umieścił swoje symbole na odcinku BH
 

 
  • "koniec:przekatna:ag" - jeśli wygrał gracz, który umieścił swoje symbole na odcinku AG
 

 
  • "koniec:przekatna:df" - jeśli wygrał gracz, który umieścił swoje symbole na odcinku DF
 

 
  • "koniec:przekatna:ce" - jeśli wygrał gracz, który umieścił swoje symbole na odcinku CE
 
 

 
Powodzenia!

 

Zadanie 1. ASCII art czyli rysowanie znakami

Start: 24 grudnia 2016
Termin nadsyłania rozwiązań: 31 stycznia 2017

Cześć!

Oto pierwsze zadanie, które pomoże Ci w nauce programowania.

Zanim przystąpisz do rozwiązywania:

Zarejestruj się aby uzyskać dostęp do serwisu pozwalającego na testowanie i przesyłanie rozwiązań.

ASCII art - wprowadzenie

Komputery (oraz smartfony, tablety i inne urządzenia, których używacie na co dzień) umieją współcześnie na swoich ekranach pokazać dosłownie cokolwiek. :) Ale nie zawsze tak było…

Pierwsze komputery osobiste wyświetlały dane na tzw. konsoli (zwanej też terminalem lub wierszem poleceń). Wyglądała ona tak:

Mogła wyświetlać tekst, innymi słowy – znaki z klawiatury, i nic więcej.

Ale ponieważ programiści to wesołe i kreatywne istoty, zaczęli ozdabiać sobie życie nawet w tak ograniczonym środowisku. :)

Na przykład, żeby oddzielić od siebie pewne informacje, można dodać linię pomiędzy paragrafami. A linia na terminalu to nic innego jak po prostu ciąg myślników („-”), na przykład:

Wybierz imię bohatera:
----------------------
1) Ola
2) Ala
3) Kasia
 

A kiedy umiemy już narysować linie, możemy też stworzyć np. strzałkę: 

Wybierz imię bohatera:
----------------------
1) Ola
2) Ala
3) Kasia <--- podpowiem, że to najczęściej wybierana opcja


Ale przecież znakami i literami można narysować znacznie więcej niż tylko linie i strzałki.

Można tworzyć z nich duże napisy:

Motywy świąteczne:

Czy choćby jednorożce. :)

Nasze pierwsze zadanie będzie polegało właśnie na tym – na rysowaniu różnych, prostych i trochę bardziej skomplikowanych, rysunków z wykorzystaniem liter i znaków.

Dla ciekawskich:

Czy wiecie, że komputery nie zawsze miały ekran i klawiatury?! Pierwsze komputery „porozumiewały się” z człowiekiem w znacznie bardziej mozolny sposób.  Na przykład za pomocą kart perforowanych:

Taką kartę (a raczej wielki stos takich kart) wsadzało się do komputera i na ich podstawie przeprowadzał on obliczenia. Dziurki w karcie przekazywały komputerowi informacje o operacjach, które ma wykonać, i o danych, na których ma je wykonać. Karty perforowane były formą kodowania informacji, tak aby komputer mógł ją zrozumieć.

ASCII to skrót od American Standard Code for Information Interchange, czyli Amerykańskiego Standardu Kodowania Informacji. Komputery głęboko w środku potrafią zrozumieć tylko liczby (a właściwie, tak naprawdę, wszystko gdzieś na końcu dla komputera staje się zerem albo jedynką). Kody ASCII zostały wprowadzone po to, aby móc reprezentować znaki za pomocą liczb. Np. 97 reprezentuje „a”, a 35 to „#”.

Twoje zadanie 

Uwaga: Treść poniższych zadań (z dodatkowymi przykładami) dostępna jest również w systemie do testowania i zgłaszania rozwiązań, dostępnym po rejestracji. Jeśli chcesz wziąć udział w naszej akcji, rozwiązuj zadania właśnie tam!

Twoim celem będzie narysowanie na konsoli kilku prostych obrazków. Podzieliliśmy to zadanie na kilka podzadań, aby ułatwić Ci rozwiązywanie ich krok po kroku.

Krok 1: Linia prosta

function linia(n) {
    return "Powinnam zwrócić linię o długości " + n;
}
console.log(linia(5));
 

U góry widzisz prosty program, który przy pomocy funkcji console.log() wypisuje na ekranie tekst zwrócony z funkcji linia(). W tym momencie zwraca ona tekst „Powinnam zwrócić linię o długości 5” i taki też tekst ukaże się na ekranie, kiedy klikniesz przycisk run (w systemie do testowania dostępnym po rejestracji!).

Jak widzisz, do funkcji linia() przekazywana jest pojedyncza liczba n. Twoim zadaniem jest zmiana tej funkcji tak, aby zwrócony przez nią tekst wyglądał jak pozioma linia. Parametr n będzie określał jej długość. A więc na przykład dla n równego 5, funkcja linia() powinna zwrócić tekst „-----”.

Przygotowaliśmy specjalny zestaw testów, który sprawdza, czy zadanie zostało wykonane poprawnie. Aby je wykonać, kliknij strzałkę w dół obok przycisku run, a następnie run tests. Jeśli zadanie zostanie poprawnie rozwiązane, powinnaś przy każdym wykonanym teście zobaczyć taką ikonę:

Pamiętaj, że wywołanie funkcji console.log(), znajdujące się pod spodem, jest tylko po to, by ułatwić Ci zadanie; przekazuje ono na konsolę wynik działania funkcji, a więc wypisuje pod spodem to, co zwróciła funkcja linia(). Możesz zmieniać ten wiersz programu tak, aby na bieżąco sprawdzać, czy Twoja funkcja działa prawidłowo, np. jeśli zmienisz ją na console.log(3), a następnie klikniesz przycisk run(), na ekranie powinien się pojawić napis „---”. Natomiast nasz automat sprawdzający będzie zwracał uwagę jedynie na to, co zwróci funkcja linia().

Powodzenia!

Krok 2: Prostokąt 

function prostokat(szer, wys) {
  return "Powinnam zwrócić\nprostokąt o wymiarach\n" + szer + "x" + wys;
}
console.log(prostokat(14, 5));
 

Skoro potrafisz już utworzyć linię, czas „narysować” prostokąt. 

Tym razem u góry widzisz funkcję prostokat(), która przyjmuje dwa parametry: szer i wys, oznaczające odpowiednio szerokość i wysokość prostokąta. Będziemy go tworzyć z gwiazdek („*”, Shift+8 na większości klawiatur). Na przykład prostokąt o szerokości 3 kolumn i wysokości 4 rzędów wygląda tak:

****
****
****
 

Podobnie jak poprzednio, funkcja powinna zwrócić napis, który — przekazany do funkcji console.log() — spowoduje wyświetlenie na ekranie prostokąta o odpowiednich wymiarach. Problemem, na który się natkniesz, będzie na pewno stworzenie napisu, który będzie miał tyle rzędów, ile trzeba. W edytorze tekstu nacisnęlibyśmy po prostu klawisz Enter, a kursor przeszedłby do następnej linii. W języku JavaScript używamy do tego celu specjalnej sekwencji znaków \n. W miejscu, w którym pojawi się ten symbol, komputer umieści w tekście specjalny symbol, który powoduje przejście do następnej linii. 

Spróbuj wykonać przykładowy program, aby zobaczyć, jak działa symbol końca linii. Potem zmień funkcję prostokat() tak, aby zwracała co trzeba. Podobnie jak poprzednio, przygotowaliśmy zestaw testów, który sprawdzi, czy poprawnie rozwiązałaś zadanie.

Powodzenia!

Krok 3: Pusty prostokąt 

function pustyProstokąt(szer, wys) {
  return "Bardzo pusty prostokąt";
}
console.log(pustyProstokąt(7, 5));
 

Narysowanie wypełnionego prostokąta to wcale nie koniec: teraz twoim zadaniem będzie zrobienie pustego prostokąta, czyli na przykład czegoś takiego:

*******
*     *
*     *
*     *
*******
 

To jest pusty prostokąt o wymiarach 7 kolumn na 5 rzędów. Aby uzyskać taki efekt, jego wnętrze musi być wypełnione spacjami, a nie gwiazdkami.

Do dzieła!

Krok 4: Trójkąt

function trojkąt(n) {
  return "        Kiedyś\n    będę potrafiła\nrysować piękne trójkąty";
}
console.log(trojkąt(4));
 
        Kiedyś
    będę potrafiła
rysować piękne trójkąty
 

Wspaniale, potrafisz już rysować proste kształty! A jak moglibyśmy narysować trójkąt? Najlepiej od razu taki ładny, równoramienny:

  *
 ***
*****
 

Tym razem musimy nie tylko narysować określoną ilość linii, ale zadbać o to, aby w każdym rzędzie była odpowiednia ilość gwiazdek, poprzedzona odpowiednią ilość spacji.

Krok 5: Choinka

Czas na ostateczne wyzwanie! Uzbrojona w umiejętność składania prostych rysunków ze znaków na ekranie, jesteś teraz gotowa, by puścić wodze wyobraźni i narysować jak najładniejszą choinkę. 

Tu już nie będzie automatycznych testów, bo i też nie ma jedynego właściwego rozwiązania; liczy się Twoja inwencja. Możesz wykorzystać napisane wcześniej funkcje, możesz też napisać wszystko od nowa. Poeksperymentuj z różnymi znakami. Spróbuj udekorować swoją choinkę losowo rozmieszczonymi ozdobami. Jedynym wymaganiem jest dodanie parametru umożliwiającego zmianę wyglądu rysowanej choinki. Może to być wysokość, liczba/rodzaj ozdób, liczba narysowanych choinek, prezentów pod choinką itp. Puść wodze wyobraźni :).

Dobrej zabawy!

Jeżeli będziesz miała pytania lub wątpliwości, zajrzyj na nasze forum, na którym chętnie odpowiemy na wszystkie Twoje pytania. W razie problemów z użyciem forum napisz do nas na adres dresscode-pl@google.com.