Na potrzeby tego ćwiczenia stworzysz aplikację na rolkę kostką do gry w Androida. Gdy użytkownik rzuci kostką, zostanie wygenerowany losowy wynik. Wynik uwzględnia liczbę boków kości. Na przykład kości 6-stronne można rzucać tylko na wartości z zakresu 1–6.
Tak będzie wyglądać ostateczna wersja aplikacji.
Aby pomóc Ci skoncentrować się na nowych pojęciach związanych z programowaniem tej aplikacji, utworzysz w przeglądarce Kotlin dostępne w przeglądarce podstawowe funkcje aplikacji. Wyniki wyświetlą się w konsoli. Później zaimplementujesz interfejs w Android Studio.
W ramach pierwszego ćwiczenia z programowania stworzymy program Kotlin, który symuluje rzut kostką i wyświetla losową liczbę tak samo jak kości.
Wymagania wstępne
- Otwieranie, edytowanie i uruchamianie kodu na stronie https://try.kotlinlang.org/
- Utwórz i uruchom program Kotlin, który korzysta ze zmiennych i funkcji, a następnie drukuje wynik w konsoli.
- Sformatuj liczby w tekście za pomocą szablonu ciągu znaków z notacją
${variable}
.
Czego się nauczysz
- Jak automatycznie generować losowe liczby, by symulować rzut kostką.
- Jak utworzyć kod, tworząc klasę
Dice
ze zmienną i metodą. - Jak utworzyć instancję obiektu klasy, zmodyfikować zmienne i wywołać jego metody.
Co stworzysz
- Program Kotlin w oprogramowaniu opartym na przeglądarce narzędzie Kotlin, które może wykonywać losowe kostki.
Wymagania
- komputera z dostępem do internetu,
Gry często zawierają elementy losowe. Możesz zdobyć losową nagrodę lub przejść przez losową liczbę kroków na planszy. W codziennym życiu możesz korzystać z losowych cyfr i liter, aby generować bezpieczniejsze hasła.
Zamiast rzucać kostką, możesz napisać program, który symuluje rzut kostką. Za każdym razem, gdy rzucisz kostką, możesz podać dowolną wartość z zakresu możliwych wartości. Na szczęście nie musisz tworzyć własnego generatora liczb losowych na potrzeby tego programu. Większość języków programowania, w tym Kotlin, ma wbudowany sposób generowania losowych liczb. W tym zadaniu użyjesz kodu Kotlin, by wygenerować liczbę losową.
Skonfiguruj kod startowy
- W przeglądarce otwórz stronę https://try.kotlinlang.org/.
- Usuń cały istniejący kod w edytorze kodu i zastąp go poniższym kodem. To funkcja z
main()
używana przez Ciebie podczas wcześniejszych ćwiczeń z programowania (zobacz artykuł Tworzenie pierwszego programu Kotlin).
fun main() {
}
Używanie funkcji losowej
Aby rzucić kostką, należy podać sposób reprezentowania wszystkich prawidłowych. W przypadku zwykłej kości 6-stronnej dozwolone są rzuty kostką: 1, 2, 3, 4, 5 i 6.
Wcześniej dowiedzieliśmy się, że dostępne są takie typy danych jak Int
(liczba całkowita) oraz String
(tekst). IntRange
to inny typ danych, który reprezentuje zakres liczb całkowitych od punktu początkowego do punktu końcowego. IntRange
to odpowiedni typ danych, który reprezentuje możliwe wartości rzutu kostką.
- W ramach funkcji
main()
zdefiniuj zmienną jakoval
o nazwiediceRange
. Przypisz ją doIntRange
z zakresu od 1 do 6. Podaje zakres liczb całkowitych, które może rzucić kostką.
val diceRange = 1..6
Możesz rozpoznać, że zakres 1..6
to kotlin, ponieważ zawiera on numer początkowy, dwie kropki, a następnie numer końcowy (bez spacji między słowami). Inne przykłady zakresów liczb całkowitych to 2..5
dla liczb od 2 do 5 oraz 100..200
dla liczb od 100 do 200.
Podobnie jak wywołanie println()
informuje system, że ma wydrukować konkretny tekst, możesz użyć funkcji o nazwie random()
, która wygeneruje i zwróci liczbę losową dla wybranego zakresu. Tak jak wcześniej, możesz zapisać wynik w zmiennej.
- W zasadzie
main()
zdefiniuj zmienną jakoval
o nazwierandomNumber
. - Ustaw wartość
randomNumber
jako wartość wywołaniarandom()
w zakresiediceRange
, jak pokazano poniżej.
val randomNumber = diceRange.random()
Zwróć uwagę, że w wywołaniu funkcji random()
diceRange
występuje kropka (kropka) między zmienną a wywołaniem funkcji. Możesz to odczytać jako &generujące liczby losowe z operatora diceRange
" wynik jest przechowywany w zmiennej randomNumber
.
- Aby zobaczyć wygenerowany losowo numer, użyj formatu formatowania ciągu (nazywanego też „szablonem ciągu”)
${randomNumber}
, by go wydrukować, jak widać poniżej.
println("Random number: ${randomNumber}")
Gotowy kod powinien wyglądać następująco.
fun main() {
val diceRange = 1..6
val randomNumber = diceRange.random()
println("Random number: ${randomNumber}")
}
- Uruchom kod kilka razy. Za każdym razem wyniki powinny być widoczne poniżej, ale z różnymi losowymi liczbami.
Random number: 4
Rzut kostką to prawdziwy przedmiot w Twoich rękach. Wpisany właśnie kod świetnie działa, ale trudno sobie wyobrazić, że chodzi o kostkę. Organizowanie programu w taki sposób, aby przypominał to, co przedstawia, ułatwia zrozumienie jego treści. Fajnie jest też mieć rzut kolekcjonerski.
Wszystkie kości działają tak samo. Mają te same właściwości (np. boki) i działają tak samo jak wcześniej. W Kotlin możesz utworzyć zautomatyzowany plan kości kości, który informuje, że kostki mają boki i mogą losować liczbę. Ten plan nazywa się klasą.
Na podstawie tych zajęć możesz tworzyć obiekty zwane kościami, czyli wystąpienia obiektów. Możesz na przykład utworzyć kostkę dwunastokątną lub czworokątną.
Definiowanie klasy kości
W kolejnych krokach zdefiniujesz nową klasę o nazwie Dice
, która reprezentuje kości do zwijania.
- Aby zacząć od nowa, wyczyść kod w funkcji
main()
, tak by wyglądał tak, jak na ilustracji poniżej.
fun main() {
}
- Poniżej tej funkcji
main()
dodaj pusty wiersz, a następnie dodaj kod, aby utworzyć klasęDice
. Jak pokazano poniżej, zacznij od słowa kluczowegoclass
, a następnie nazwy klasy, po której następuje otwierający i zamykający nawias klamrowy. Rozdziel je nawiasami klamrowymi.
class Dice {
}
W definicji klasy możesz określić co najmniej jedną właściwość klasy, używając zmiennych. Kostki mogą mieć kilka boków, koloru lub wagi. W tym zadaniu skupisz się na liczbie boków kości.
- W ramach klasy
Dice
dodajvar
o nazwiesides
, określającej liczbę stron kości do gry. Ustaw:sides
na 6.
class Dice {
var sides = 6
}
To wszystko. Masz teraz bardzo prostą klasę, która reprezentuje kości.
Tworzenie instancji klasy kości
Ta klasa Dice
zawiera plan działania kostki. Aby wstawić kości do swojego programu, musisz utworzyć instancję obiektu Dice
. Jeśli musisz mieć 3 kostki, musisz utworzyć 3 instancje obiektu.
- Aby utworzyć instancję obiektu typu
Dice
, w funkcjimain()
utwórzval
o nazwiemyFirstDice
i zainicjuj go jako instancję klasyDice
. Zwróć uwagę na nawiasy po nazwie klasy, które wskazują, że tworzysz nową instancję obiektu z klasy.
fun main() {
val myFirstDice = Dice()
}
Teraz gdy masz obiekt myFirstDice
, obiekt utworzony na podstawie planu, możesz uzyskać dostęp do jego właściwości. Jedyną właściwością elementu Dice
jest sides
. Aby uzyskać dostęp do usługi, użyj ¬acji; Aby uzyskać dostęp do właściwości sides
elementu myFirstDice
, wywołujesz funkcję myFirstDice.sides
, której wymowa "myFirstDice
; kropka sides
".
- Pod deklaracją
myFirstDice
dodaj instrukcjęprintln()
, by wyświetlać liczbęsides
zmyFirstDice.
println(myFirstDice.sides)
Twój kod powinien wyglądać tak.
fun main() {
val myFirstDice = Dice()
println(myFirstDice.sides)
}
class Dice {
var sides = 6
}
- Uruchom program, a jego wartość powinna odpowiadać liczbie
sides
określonej w klasieDice
.
6
Masz teraz klasę Dice
i rzeczywistą kostkę myFirstDice
z 6 sides
.
Rzuć kostką!
Rzuć kostką
Wcześniej do wykonywania czynności drukowanych warstw ciasta była funkcja. Rzut kostką to czynność, którą można zaimplementować jako funkcję. Ponieważ można rzucić kostką, można dodać dla niej funkcję w klasie Dice
. Funkcja zdefiniowana w klasie jest również nazywana metodą.
- W klasie
Dice
pod zmiennąsides
wstaw pusty wiersz i utwórz nową funkcję rzucania kostką. Zacznij od słowa kluczowegofun
Kotlin, po którym następuje nazwa metody, po których następuje nawiasy()
, a następnie nawiasy klamrowe otwierające i zamykające{}
. Między nawiasami klamrowymi możesz pozostawić pusty wiersz, aby zrobić więcej miejsca, jak widać poniżej. Klasa powinna wyglądać następująco.
class Dice {
var sides = 6
fun roll() {
}
}
Rzut kostką ma losową liczbę od 1 do 6.
- W metodzie
roll()
utwórzval randomNumber
. Przypisz losową liczbę w zakresie1..6
. Aby zapisaćrandom()
w zakresie, użyj kropki.
val randomNumber = (1..6).random()
- Po wygenerowaniu liczby losowej wydrukuj ją w konsoli. Ukończona metoda
roll()
powinna wyglądać tak jak poniżej.
fun roll() {
val randomNumber = (1..6).random()
println(randomNumber)
}
- Aby rozpocząć,
myFirstDice
wywołaj metodęmain()
dlaroll()
metodęmyFirstDice
. Wywołujesz metodę za pomocą ¬acji; Aby wywołać metodęroll()
myFirstDice
, wpiszmyFirstDice.roll()
, jak wymówić:myFirstDice
, kropkaroll()
".
myFirstDice.roll()
Ukończony kod powinien wyglądać tak.
fun main() {
val myFirstDice = Dice()
println(myFirstDice.sides)
myFirstDice.roll()
}
class Dice {
var sides = 6
fun roll() {
val randomNumber = (1..6).random()
println(randomNumber)
}
}
- Uruchom kod. Wynik liczby rzutów kostką powinien być widoczny poniżej liczby boków. Uruchamiaj swój kod kilka razy i zauważ, że liczba boków jest taka sama, a końcowa rzut kostką się zmienia.
6 4
Gratulacje! Klasa Dice
została zdefiniowana przez zmienną sides
i funkcję roll()
. W funkcji main()
utworzono nową instancję obiektu Dice
, a następnie wywołałeś dla niej metodę roll()
, by wygenerować liczbę losową.
Obecnie drukujesz wartość randomNumber
w funkcji roll()
i działa to doskonale. Czasami jednak lepiej jest wrócić do wyniku dowolnej funkcji nazywanej funkcją. Możesz na przykład przypisać wynik metody roll()
do zmiennej i przenieść odtwarzacz o taką samą kwotę. Zobaczmy, jak to się robi.
- W
main()
zmień wiersz o nazwiemyFirstDice.roll()
. Utwórzval
o nazwiediceRoll
. Ustaw jego wartość, która jest zwracana przez metodęroll()
.
val diceRoll = myFirstDice.roll()
Na razie to nic nie dzieje się, bo roll()
nie zwraca jeszcze żadnych wyników. Aby kod działał poprawnie, roll()
musi zwrócić jakiś element.
Z wcześniejszych ćwiczeń z programowania dowiesz się, że musisz określić typ danych dla argumentów wejściowych dla funkcji. W ten sam sposób musisz określić typ danych, które zwraca funkcja.
- Zmień funkcję
roll()
, by określić, jakie typy danych będą zwracane. W tym przypadku losowa liczba toInt
, więc typ zwrotu toInt
. Składnia określająca typ zwracania: po nazwie funkcji po nawiasie dodaj dwukropek, spację, a następnie słowo kluczoweInt
dla typu zwracanego działania. Definicja funkcji powinna wyglądać jak w poniższym kodzie.
fun roll(): Int {
- Uruchom ten kod. W widoku problemów pojawi się błąd. Wiadomość brzmi:
A ‘return' expression is required in a function with a block body.
Zmiana definicji funkcji powoduje zwrócenie Int
, ale system zgłasza,
nie zwraca Int
. "Zablokuj treść" lub "body body" dotyczy kodu między nawiasami klamrowymi funkcji. Możesz naprawić ten błąd, zwracając wartość z funkcji przy użyciu instrukcji return
na końcu treści.
- W sekcji
roll()
usuń instrukcjęprintln()
i zastąp ją instrukcjąreturn
dla atrybuturandomNumber
. Twoja funkcjaroll()
powinna przypominać poniższy kod.
fun roll(): Int {
val randomNumber = (1..6).random()
return randomNumber
}
- W
main()
musisz usunąć informacje o drukowanych krawędziach kości. - Dodaj oświadczenie, aby wydrukować wartości
sides
idiceRoll
w zrozumiałym zdaniu. Twoja gotowa funkcjamain()
powinna wyglądać podobnie do tego.
fun main() {
val myFirstDice = Dice()
val diceRoll = myFirstDice.roll()
println("Your ${myFirstDice.sides} sided dice rolled ${diceRoll}!")
}
- Uruchom kod, a wynik powinien wyglądać tak.
Your 6 sided dice rolled 4!
Oto Twój cały kod.
fun main() {
val myFirstDice = Dice()
val diceRoll = myFirstDice.roll()
println("Your ${myFirstDice.sides} sided dice rolled ${diceRoll}!")
}
class Dice {
var sides = 6
fun roll(): Int {
val randomNumber = (1..6).random()
return randomNumber
}
}
Nie wszystkie kostki mają 6 boków. Kostki mogą mieć różne kształty i rozmiary: 4 strony, 8 boków, do 120 boków!
- W metodzie
roll()
w metodzieroll()
zmień zakodowany na stałe1..6
nasides
, tak by zakres, a tym samym liczba losowa, była zawsze odpowiednia dla liczby boków.
val randomNumber = (1..sides).random()
- W funkcji
main()
poniżej i po wydrukowaniu rzutu kostką zmieńsides
mojejFirstDice
na 20.
myFirstDice.sides = 20
- Skopiuj i wklej istniejącą deklarację drukowania po zmianie liczby boków.
- Zastąp drukowanie
diceRoll
wynikiem drukowania metodyroll()
z metodąmyFirstDice
.
println("Your ${myFirstDice.sides} sided dice has rolled a ${myFirstDice.roll()}!")
Twój program powinien wyglądać tak.
fun main() {
val myFirstDice = Dice()
val diceRoll = myFirstDice.roll()
println("Your ${myFirstDice.sides} sided dice rolled ${diceRoll}!")
myFirstDice.sides = 20
println("Your ${myFirstDice.sides} sided dice rolled ${myFirstDice.roll()}!")
}
class Dice {
var sides = 6
fun roll(): Int {
val randomNumber = (1..sides).random()
return randomNumber
}
}
- Uruchom program, powinien pojawić się komunikat dla kości 6-stronnych i drugi dla 20.
Your 6 sided dice rolled 3! Your 20 sided dice rolled 15!
Zajęcia pozwalają reprezentować rzeczy, często w świecie rzeczywistym, W tym przypadku klasa Dice
reprezentuje kostki fizyczne. W świecie rzeczywistym kostki nie mogą zmienić liczby boków. Jeśli chcesz mieć różne boki, musisz zdobyć inną kostkę. Oznacza to, że zamiast zmieniać właściwość boków istniejącego wystąpienia obiektu Dice
, musisz utworzyć nową instancję kości do gry z potrzebną liczbą boków.
W tym zadaniu będziesz modyfikować klasę Dice
, aby określić liczbę stron podczas tworzenia nowej instancji. Zmień definicję klasy Dice
, aby zaakceptować argument dla liczby boków. Przypomina to sposób, w jaki funkcja może przyjmować argumenty wejściowe.
- Edytuj definicję klasy
Dice
, aby zaakceptować argument liczby całkowitej o nazwienumSides
. Kod zajęć nie zmieni się.
class Dice(val numSides: Int) {
// Code inside does not change.
}
- Usuń klasę
sides
z klasyDice
, ponieważ teraz możesz używać właściwościnumSides
. - Popraw zakres, aby
numSides
.
Klasa Dice
powinna wyglądać następująco.
class Dice (val numSides: Int) {
fun roll(): Int {
val randomNumber = (1..numSides).random()
return randomNumber
}
}
Jeśli uruchomisz ten kod, wyświetli się wiele błędów, bo musisz zaktualizować main()
, by dostosować się do zmian w klasie Dice
.
- W funkcji
main()
, aby utworzyćmyFirstDice
z 6 bokami, musisz teraz podać liczbę boków w postaci argumentu klasyDice
, jak pokazano poniżej.
val myFirstDice = Dice(6)
- W zestawieniu operacji zmień
sides
nanumSides
. - Poniżej usuń kod, który zmienia
sides
na 20, bo ta zmienna już nie istnieje. - Możesz też usunąć instrukcje
println
pod spodem.
Twoja funkcja main()
powinna wyglądać tak jak poniżej, a jeśli ją uruchomisz, nie powinno być żadnych błędów.
fun main() {
val myFirstDice = Dice(6)
val diceRoll = myFirstDice.roll()
println("Your ${myFirstDice.numSides} sided dice rolled ${diceRoll}!")
}
- Po wydrukowaniu pierwszej kostki dodaj kod, aby utworzyć i wydrukować drugi obiekt
Dice
o nazwiemySecondDice
z 20 bokami.
val mySecondDice = Dice(20)
- Dodaj oświadczenie drukowane, które zwraca i wyświetla zwróconą wartość.
println("Your ${mySecondDice.numSides} sided dice rolled ${mySecondDice.roll()}!")
- Twoja gotowa funkcja
main()
powinna wyglądać tak.
fun main() {
val myFirstDice = Dice(6)
val diceRoll = myFirstDice.roll()
println("Your ${myFirstDice.numSides} sided dice rolled ${diceRoll}!")
val mySecondDice = Dice(20)
println("Your ${mySecondDice.numSides} sided dice rolled ${mySecondDice.roll()}!")
}
class Dice (val numSides: Int) {
fun roll(): Int {
val randomNumber = (1..numSides).random()
return randomNumber
}
}
- Uruchom gotowy program, a wynik powinien wyglądać tak.
Your 6 sided dice rolled 5! Your 20 sided dice rolled 7!
W kodowaniu zwięzłym tekst jest lepszy. Możesz się pozbyć zmiennej randomNumber
i zwrócić liczbę losową.
- Zmień instrukcję
return
, by zwracała liczbę losową bezpośrednio.
fun roll(): Int {
return (1..numSides).random()
}
W 2 informacji drukujesz wywołanie, by uzyskać losowy numer do szablonu ciągu znaków. Aby pozbyć się zmiennej diceRoll
, możesz zrobić to samo w pierwszej instrukcji drukowania.
- Wywołaj
myFirstDice.roll()
w szablonie ciągu znaków i usuń zmiennądiceRoll
. Pierwsze 2 wiersze kodu main() wyglądają teraz tak.
val myFirstDice = Dice(6)
println("Your ${myFirstDice.numSides} sided dice rolled ${myFirstDice.roll()}!")
- Uruchom kod. Dane wyjściowe powinny się nie różnić.
Jest to ostateczny kod po refaktoryzacji go .
fun main() {
val myFirstDice = Dice(6)
println("Your ${myFirstDice.numSides} sided dice rolled ${myFirstDice.roll()}!")
val mySecondDice = Dice(20)
println("Your ${mySecondDice.numSides} sided dice rolled ${mySecondDice.roll()}!")
}
class Dice (val numSides: Int) {
fun roll(): Int {
return (1..numSides).random()
}
}
fun main() {
val myFirstDice = Dice(6)
val diceRoll = myFirstDice.roll()
println("Your ${myFirstDice.numSides} sided dice rolled ${diceRoll}!")
val mySecondDice = Dice(20)
println("Your ${mySecondDice.numSides} sided dice rolled ${mySecondDice.roll()}!")
}
class Dice (val numSides: Int) {
fun roll(): Int {
return (1..numSides).random()
}
}
- Wywołaj funkcję
random()
wIntRange
, aby wygenerować liczbę losową:(1..6).random()
- Klasy są planem obiektu. Mogą mieć właściwości i zachowania zaimplementowane jako zmienne i funkcje.
- Wystąpienie klasy reprezentuje obiekt, często obiekt fizyczny, taki jak kości. Możesz wywołać działania na obiekcie i zmienić jego atrybuty.
- Podczas tworzenia instancji możesz przekazać dane wejściowe do klasy, określając argument definicji klasy. Przykład:
class Dice(val numSides: Int)
, a następnie utwórz instancjęDice(6)
. - Funkcje mogą zwracać wyniki. Określ typ danych, który zostanie zwrócony w definicji funkcji, i użyj instrukcji
return
w treści funkcji, aby coś zwrócić. Na przykład:fun example(): Int { return 5 }
.
Wykonaj te czynności:
- Nadaj swojej klasie
Dice
inny atrybut koloru i utwórz kilka wystąpień kości kości, które będą miały różne boki i kolory. - Utwórz klasę
Coin
, nadaj jej funkcję odwracania, utwórz instancję klasy i rzuć kilka monet. W jaki sposób użyjesz funkcji losowej z zakresem do uzyskania rzutu monetą?