QuizMe: Różnice pomiędzy wersjami

Z Wiki Mistrzowie Kodowania
Skocz do: nawigacji, wyszukiwania
(Wyświetl pierwsze pytanie)
(Zeskanuj próbną aplikację do telefonu)
 
(Nie pokazano 26 pośrednich wersji utworzonych przez tego samego użytkownika)
Linia 2: Linia 2:
  
 
==Co tworzysz?==
 
==Co tworzysz?==
QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.
+
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.
 
   
 
   
 
W  grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.
 
W  grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.
Linia 90: Linia 90:
 
|}
 
|}
 
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).
 
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).
 +
[[Plik:t6-2.png]]
  
 
==Programowanie aplikacji==
 
==Programowanie aplikacji==
Linia 127: Linia 128:
  
 
Bloki powinny wyglądać następująco:
 
Bloki powinny wyglądać następująco:
 +
 +
[[Plik:t6-3.png]]
 
===Zdefiniuj ukrytą zmienną Index===
 
===Zdefiniuj ukrytą zmienną Index===
 
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.
 
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.
Linia 144: Linia 147:
 
|}
 
|}
 
Bloki powinny wyglądać następująco:
 
Bloki powinny wyglądać następująco:
 +
 +
[[Plik:t6-4.png]]
  
 
===Wyświetl pierwsze pytanie===
 
===Wyświetl pierwsze pytanie===
Linia 178: Linia 183:
 
|}
 
|}
 
Bloki powinny wyglądać następująco:
 
Bloki powinny wyglądać następująco:
 +
 +
[[Plik:t6-5.png]]
  
 
===Jak działają bloki?===
 
===Jak działają bloki?===
Linia 186: Linia 193:
 
==Iteracja pytań==
 
==Iteracja pytań==
 
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:
 
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:
Typ bloku Kategoria Działanie
+
{| class="wikitable"
when NextButton.Click NextButton Uruchamia obsługę zdarzeń po kliknięciu przycisku
+
!Typ bloku
set currentQuestionIndex to Zmienne Decyduje o ustawieniu indeksu wybranej listy
+
!Kategoria
+ Math Służy do zwiększania wartości zmiennej currentQuestionIndex
+
!Działanie
get global currentQuestionIndex Zmienne Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1
+
|-
0 (1) Math Dla + 1
+
|when NextButton.Click
set QuestionLabel.Text to QuestionLabel Wyświetla kolejne pytanie
+
|NextButton
select list item Listy Ustawia element listy jako wartość QuestionLabel
+
|Uruchamia obsługę zdarzeń po kliknięciu przycisku
get global QuestionList Zmienne Wskazuje, która lista będzie wybrana
+
|-
get global currentQuestionIndex Zmienne Wskazuje, który element wybranej listy będzie wybrany  
+
|set currentQuestionIndex to
 +
|Zmienne
 +
|Decyduje o ustawieniu indeksu wybranej listy
 +
|-
 +
|+  
 +
|Math
 +
|Służy do zwiększania wartości zmiennej currentQuestionIndex
 +
|-
 +
|get global currentQuestionIndex
 +
|Zmienne
 +
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1
 +
|-
 +
|0 (1)
 +
|Math
 +
|Dla + 1
 +
|-
 +
|set QuestionLabel.Text to
 +
|QuestionLabel
 +
|Wyświetla kolejne pytanie
 +
|-
 +
|select list item
 +
|Listy
 +
|Ustawia element listy jako wartość QuestionLabel
 +
|-
 +
|get global QuestionList
 +
|Zmienne
 +
|Wskazuje, która lista będzie wybrana
 +
|-
 +
|get global currentQuestionIndex
 +
|Zmienne
 +
|Wskazuje, który element wybranej listy będzie wybrany
 +
|}
 
Bloki powinny wyglądać następująco:
 
Bloki powinny wyglądać następująco:
 +
 +
[[Plik:t6-6.png]]
  
 
===Jak działają bloki?===
 
===Jak działają bloki?===
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie
+
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.
 +
 
 
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:
 
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:
 +
 +
[[Plik:t6-7.png]]
 
   
 
   
 
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.
 
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.
 +
 +
[[Plik:t6-8.png]]
 
   
 
   
 
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.
 
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.
Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).
+
 
 +
[[Plik:info.png|left]]''Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).''
 +
 
 +
 
 
===Przetestuj to zachowanie===
 
===Przetestuj to zachowanie===
 
Przetestuj zachowanie przycisku NextButton,  aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?
 
Przetestuj zachowanie przycisku NextButton,  aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?
 +
 
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.
 
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.
 +
 
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.
 
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.
 +
 
Będziesz potrzebował następujących bloków:
 
Będziesz potrzebował następujących bloków:
Typ bloku Kategoria Działanie
+
{| class="wikitable"
if then Control sprawdzenie, czy użytkownik jest na etapie ostatniego pytania
+
!Typ bloku
= Math sprawdzenie, czy currentQuestionIndex ma wartość 3
+
!Kategoria
get global currentQuestionIndex Variables
+
!Działanie
0 (3) Math 3 to numer na liście
+
|-
set currentQuestionIndex to Variables ustawienie na 0, aby wrócić do pierwszego pytania
+
|if then
0 Math ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1
+
|Control
 +
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania
 +
|-
 +
|=  
 +
|Math
 +
|sprawdzenie, czy currentQuestionIndex ma wartość 3
 +
|-
 +
|get global currentQuestionIndex
 +
|Variables
 +
|
 +
|-
 +
|0 (3)
 +
|Math
 +
|3 to numer na liście
 +
|-
 +
|set currentQuestionIndex to
 +
|Variables
 +
|ustawienie na 0, aby wrócić do pierwszego pytania
 +
|-
 +
|0
 +
|Math
 +
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1
 +
|}
 
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:
 
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:
 +
 +
[[Plik:t6-9.png]]
 
   
 
   
 
===Jak działają bloki===
 
===Jak działają bloki===
 
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.
 
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.
 +
 
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==
 
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==
 
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami.  
 
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami.  
 
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:
 
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:
 +
 +
[[Plik:t6-10.png]]
 
   
 
   
Przetestuj zmodyfikowaną aplikację. Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.
+
===Przetestuj zmodyfikowaną aplikację.===
 +
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.
 +
 
 
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:
 
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:
 +
 +
[[Plik:t6-11.png]]
 +
 +
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.
 
   
 
   
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.
 
 
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:
 
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:
Typ bloku Szuflada Działanie
+
{| class="wikitable"
length of list Lists Pyta, ile elementów jest w zmiennej QuestionList
+
!Typ bloku
get global QuestionList Variables Określa, o którą listę chodzi
+
!Szuflada
 +
!Działanie
 +
|-
 +
|length of list
 +
|Lists
 +
|Pyta, ile elementów jest w zmiennej QuestionList
 +
|-
 +
|get global QuestionList
 +
|Variables
 +
|Określa, o którą listę chodzi
 +
|}
 
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:
 
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:
 +
 +
[[Plik:t6-12.png]]
 
   
 
   
 
 
 +
 
===Jak działają bloki?===
 
===Jak działają bloki?===
 
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.
 
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.
 +
 
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?
 
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?
 +
 
==Przełączanie zdjęcia dla każdego pytania==
 
==Przełączanie zdjęcia dla każdego pytania==
 
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.
 
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.
 
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:
 
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:
 +
 +
[[Plik:t6-13.png]]
 
   
 
   
 
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:
 
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:
Typ bloku Kategoria Działanie
+
{| class="wikitable"
set Image1.Picture to Image1 ustaw, aby zmieniać zdjęcie
+
!Typ bloku
select list item Lists należy wybrać zdjęcie odpowiadające na aktualne pytanie
+
!Kategoria
get global PictureList Variables wybierz nazwę pliku z tej listy
+
!Działanie
get global currentQuestionIndex Variables wybierz element o n-tym indeksie currentQuestionIndex
+
|-
 +
|set Image1.Picture to
 +
|Image1
 +
|ustaw, aby zmieniać zdjęcie
 +
|-
 +
|select list item
 +
|Lists
 +
|należy wybrać zdjęcie odpowiadające na aktualne pytanie
 +
|-
 +
|get global PictureList
 +
|Variables
 +
|wybierz nazwę pliku z tej listy
 +
|-
 +
|get global currentQuestionIndex
 +
|Variables
 +
|wybierz element o n-tym indeksie currentQuestionIndex
 +
|}
 
Oto jak powinny wyglądać bloki:
 
Oto jak powinny wyglądać bloki:
+
 
 +
[[Plik:t6-14.png]]
 +
 
 
===Jak działają bloki?===
 
===Jak działają bloki?===
 
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?).  
 
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?).  
 
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?
 
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?
 +
 
==Ocena udzielanych odpowiedzi==
 
==Ocena udzielanych odpowiedzi==
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie. Do tego zachowania będą potrzebne następujące bloki:
+
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.
Typ bloku Kategoria Działanie
+
 
when AnswerButton.Click AnswerButton zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton
+
Do tego zachowania będą potrzebne następujące bloki:
if... then... Control Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego
+
{| class="wikitable"
= Math sprawdzenie, czy odpowiedź jest prawidłowa
+
!Typ bloku
AnswerText.Text AnswerText Odpowiedź użytkownika pojawia się w tym polu tekstowym
+
!Kategoria
select list item Lists wybrać bieżącą odpowiedź z listy AnswerList
+
!Działanie
get global AnswerList Variables lista, z której jest wybierany element
+
|-
get global currentQuestionIndex Variables numer pytania (i numer odpowiedzi), przy którym jest użytkownik
+
|when AnswerButton.Click
set RightWrongLabel.Text to RightWrongLabel tutaj podaj odpowiedź
+
|AnswerButton
Dobrze! Text jeżeli odpowiedź jest prawidłowa
+
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton
set RightWrongLabel.Text to RightWrongLabel tutaj podaj odpowiedź
+
|-
, Źle Text jeżeli odpowiedź jest nieprawidłowa
+
|if... then...
 +
|Control
 +
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego
 +
|-
 +
|=  
 +
|Math
 +
|sprawdzenie, czy odpowiedź jest prawidłowa
 +
|-
 +
|AnswerText.Text
 +
|AnswerText
 +
|Odpowiedź użytkownika pojawia się w tym polu tekstowym
 +
|-
 +
|select list item
 +
|Lists
 +
|wybrać bieżącą odpowiedź z listy AnswerList
 +
|-
 +
|get global AnswerList
 +
|Variables
 +
|lista, z której jest wybierany element
 +
|-
 +
|get global currentQuestionIndex
 +
|Variables
 +
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik
 +
|-
 +
|set RightWrongLabel.Text to
 +
|RightWrongLabel
 +
|tutaj podaj odpowiedź
 +
|-
 +
|Dobrze!
 +
|Text
 +
|jeżeli odpowiedź jest prawidłowa
 +
|-
 +
|set RightWrongLabel.Text to
 +
|RightWrongLabel
 +
|tutaj podaj odpowiedź
 +
|-
 +
|Źle
 +
|Text
 +
|jeżeli odpowiedź jest nieprawidłowa
 +
|}
 
Bloki powinny wyglądać następująco:
 
Bloki powinny wyglądać następująco:
+
 
 +
[[Plik:t6-15.png]]
 +
 
 
===Jak działają bloki?===
 
===Jak działają bloki?===
 
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.
 
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.
 +
 
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.
 
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.
 +
 
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:
 
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:
+
{| class="wikitable"
Typ bloku Kategoria Działanie
+
!Typ bloku
set RightWrongLabel.Text to RightWrongLabel Ustawia wartość etykiety na…
+
!Kategoria
„ „ Text …pusty tekst
+
!Działanie
set AnswerText.Text to AnswerText Ustawia wartość etykiety na…
+
|-
„ „ Text …pusty tekst
+
|set RightWrongLabel.Text to
 +
|RightWrongLabel
 +
|Ustawia wartość etykiety na…
 +
|-
 +
|„ „
 +
|Text
 +
|pusty tekst
 +
|-
 +
|set AnswerText.Text to
 +
|AnswerText
 +
|Ustawia wartość etykiety na…
 +
|-
 +
|„ „
 +
|Text
 +
|pusty tekst
 +
|}
 
Bloki powinny wyglądać następująco:
 
Bloki powinny wyglądać następująco:
+
 
 +
[[Plik:t6-16.png]]
 +
 
 
===Jak działają bloki?===
 
===Jak działają bloki?===
 
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.
 
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.
 
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?
 
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?
 +
 
==Ostateczna postać programu==
 
==Ostateczna postać programu==
 
Oto gotowa aplikacja QuizMe:
 
Oto gotowa aplikacja QuizMe:
 +
 +
[[Plik:t6-17.png]]
 
   
 
   
 
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.
 
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.
Modyfikacje
+
 
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?  
+
===Modyfikacje===
 +
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?
 +
 
 
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.
 
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.
 +
 
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.
 
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.
 +
 
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.
 
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.
 
 
 +
 
==Podsumowanie==
 
==Podsumowanie==
 
Oto niektóre koncepcje omówione w tym przewodniku:
 
Oto niektóre koncepcje omówione w tym przewodniku:
Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.
+
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li>
Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.
+
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul>
 +
 
 
==Zeskanuj próbną aplikację do telefonu==
 
==Zeskanuj próbną aplikację do telefonu==
 
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:
 
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:
+
 
 +
[[Plik:t6-18.png]]
 +
 
 
==Pobierz kod źródłowy==
 
==Pobierz kod źródłowy==
 
Jeżeli chcesz pracować z tą próbką w programie App Inventor:
 
Jeżeli chcesz pracować z tą próbką w programie App Inventor:
pobierz na komputer kod źródłowy: (http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia
+
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li>
otwórz program App Inventor,  
+
<li>otwórz program App Inventor,</li>
kliknij opcję  My Projects,  
+
<li>kliknij opcję  My Projects,</li>
wybierz Import project (.aia) from my computer...
+
<li>wybierz Import project (.aia) from my computer...</li>
znajdź i zatwierdź pobrany kod źródłowy.
+
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul>

Aktualna wersja na dzień 19:42, 15 mar 2015

Aplikacja QuizMe dla App Inventor 2

Co tworzysz?

T6-1.png
QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.

W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.

Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.

Zaczynamy!

Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.

Wstęp

Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.

W tym przewodniku omówimy:

  • definiowanie i wyświetlanie listy informacji;
  • przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;
  • zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;
  • Zmianę zdjęcia w zależności od sytuacji.

Projektowanie aplikacji

Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami. Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:

Typ komponentu Kategoria Jaką nadać jej nazwę Działanie Działanie komponentu
Image User interface Image1 Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie. Obrazkowa część pytania
Label User interface QuestionLabel Zmień właściwość tekstu (Text) na Pytanie: Wyświetla bieżące pytanie
HorizontalArrangement Layout HorizontalArrangement1 Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)
Label User interface AnswerPromptLabel Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1. Wyświetla tekst prośby o odpowiedź.
TextBox User interface AnswerText Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1. Tutaj użytkownik podaje odpowiedź.
Label User interface RightWrongLabel Zmień właściwość tekstu (Text) na Dobrze/Źle. Tutaj wyświetlana jest ocena Dobrze/Źle.
HorizontalArrangement Layout HorizontalArrangement2 Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).
Przycisk User interface AnswerButton Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2. Użytkownik klika, aby przesłać odpowiedź.
Przycisk User interface NextButton Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2. Użytkownik klika, aby przejść do następnego pytania.

Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje). T6-2.png

Programowanie aplikacji

Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.

Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:

Typ bloku Kategoria Działanie
initialize global name to Variables Definiuje zmienną QuestionList (zmień jej nazwę)
initialize global name to Variables Definiuje zmienną AnswerList (zmień jej nazwę)
make a list Lists Służy do dodawania elementów do zmiennej QuestionList
„ „ (trzykrotnie) Lists Służy do wpisania pytań
make a list Lists Służy do dodawania elementów do zmiennej AnswerList
„ „ (trzykrotnie) Text Służy do wpisania odpowiedzi

Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.

Bloki powinny wyglądać następująco:

T6-3.png

Zdefiniuj ukrytą zmienną Index

Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList. Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:

Typ bloku Kategoria Działanie
initialize global name to Variables Definiuje zmienną currentQuestionIndex (zmień nazwę)
0 (1) Math Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)

Bloki powinny wyglądać następująco:

T6-4.png

Wyświetl pierwsze pytanie

Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.

W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.

Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:

Typ bloku Kategoria Działanie
when Screen1.Initialize Screen1 Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia
set QuestionLabel.Text to QuestionLabel Umieszcza pierwsze pytanie w etykiecie QuestionLabel
select list item Lists Wybiera pierwsze pytanie z etykiety QuestionLabel
get Variables Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList
0 (1) Math Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.

Bloki powinny wyglądać następująco:

T6-5.png

Jak działają bloki?

Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.

Przetestuj to zachowanie

Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).

Iteracja pytań

Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:

Typ bloku Kategoria Działanie
when NextButton.Click NextButton Uruchamia obsługę zdarzeń po kliknięciu przycisku
set currentQuestionIndex to Zmienne Decyduje o ustawieniu indeksu wybranej listy
Math Służy do zwiększania wartości zmiennej currentQuestionIndex
get global currentQuestionIndex Zmienne Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1
0 (1) Math Dla + 1
set QuestionLabel.Text to QuestionLabel Wyświetla kolejne pytanie
select list item Listy Ustawia element listy jako wartość QuestionLabel
get global QuestionList Zmienne Wskazuje, która lista będzie wybrana
get global currentQuestionIndex Zmienne Wskazuje, który element wybranej listy będzie wybrany

Bloki powinny wyglądać następująco:

T6-6.png

Jak działają bloki?

Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.

Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:

T6-7.png

Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.

T6-8.png

Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.

Info.png
Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).


Przetestuj to zachowanie

Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?

Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.

Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.

Będziesz potrzebował następujących bloków:

Typ bloku Kategoria Działanie
if then Control sprawdzenie, czy użytkownik jest na etapie ostatniego pytania
= Math sprawdzenie, czy currentQuestionIndex ma wartość 3
get global currentQuestionIndex Variables
0 (3) Math 3 to numer na liście
set currentQuestionIndex to Variables ustawienie na 0, aby wrócić do pierwszego pytania
0 Math ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1

Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:

T6-9.png

Jak działają bloki

Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.

Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań

Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:

T6-10.png

Przetestuj zmodyfikowaną aplikację.

Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.

Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:

T6-11.png

Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.

Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:

Typ bloku Szuflada Działanie
length of list Lists Pyta, ile elementów jest w zmiennej QuestionList
get global QuestionList Variables Określa, o którą listę chodzi

Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:

T6-12.png

Jak działają bloki?

Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.

Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?

Przełączanie zdjęcia dla każdego pytania

Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie. Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:

T6-13.png

Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:

Typ bloku Kategoria Działanie
set Image1.Picture to Image1 ustaw, aby zmieniać zdjęcie
select list item Lists należy wybrać zdjęcie odpowiadające na aktualne pytanie
get global PictureList Variables wybierz nazwę pliku z tej listy
get global currentQuestionIndex Variables wybierz element o n-tym indeksie currentQuestionIndex

Oto jak powinny wyglądać bloki:

T6-14.png

Jak działają bloki?

Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?

Ocena udzielanych odpowiedzi

Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.

Do tego zachowania będą potrzebne następujące bloki:

Typ bloku Kategoria Działanie
when AnswerButton.Click AnswerButton zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton
if... then... Control Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego
= Math sprawdzenie, czy odpowiedź jest prawidłowa
AnswerText.Text AnswerText Odpowiedź użytkownika pojawia się w tym polu tekstowym
select list item Lists wybrać bieżącą odpowiedź z listy AnswerList
get global AnswerList Variables lista, z której jest wybierany element
get global currentQuestionIndex Variables numer pytania (i numer odpowiedzi), przy którym jest użytkownik
set RightWrongLabel.Text to RightWrongLabel tutaj podaj odpowiedź
Dobrze! Text jeżeli odpowiedź jest prawidłowa
set RightWrongLabel.Text to RightWrongLabel tutaj podaj odpowiedź
Źle Text jeżeli odpowiedź jest nieprawidłowa

Bloki powinny wyglądać następująco:

T6-15.png

Jak działają bloki?

Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.

Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.

Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:

Typ bloku Kategoria Działanie
set RightWrongLabel.Text to RightWrongLabel Ustawia wartość etykiety na…
„ „ Text pusty tekst
set AnswerText.Text to AnswerText Ustawia wartość etykiety na…
„ „ Text pusty tekst

Bloki powinny wyglądać następująco:

T6-16.png

Jak działają bloki?

Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText. Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?

Ostateczna postać programu

Oto gotowa aplikacja QuizMe:

T6-17.png

Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.

Modyfikacje

Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?

Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.

Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.

Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.  

Podsumowanie

Oto niektóre koncepcje omówione w tym przewodniku:

  • Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.
  • Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.

Zeskanuj próbną aplikację do telefonu

Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:

T6-18.png

Pobierz kod źródłowy

Jeżeli chcesz pracować z tą próbką w programie App Inventor: