Swift #5: Bajka o smoku, czyli co można zrobić ze strukturami (część 2)

Nauka programownia

Opublikowany: Oct 23, 2018

W poprzedniej części przygotowaliśmy strukturę Smok, Owca i mieszkaniec. Zostało nam uzupełnienie Struktury Smok i spięcie wszystkich elementów programu razem.

ILE SMOK MOŻE ZJEŚĆ?

Za każdym razem, gdy smok będzie zjadał owcę, musi zapamiętać ile zjadł siarki. Jest to jego wewnętrzny stan, więc zmienna przechowująca tą wartość musi być polem struktury Smoka [1].

Dodamy więc do klasy Smok pole zjedzonaSiarka, typu Int

var zjedzonaSiarka = 0

Za każdym razem, gdy smok zje jakąś owcę, będziemy zwiększać wartość tego pola

zjedzonaSiarka += owca.siarka

STAN SMOKA

Po drugie musimy wiedzieć, jaki smok ma stan. Pole przechowujące aktualny stan zadeklarowaliśmy już w poprzedniej części, przypisując mu wartość stanu początkowego Zly:

var stan = Stan.Zly

Jego stan może się zmienić wtedy, gdy osiągnie pewien próg wytrzymałości. A więć Lakomy będzie, gdy zjedzonaSiarka przekroczy 10 (kilogramów), Zmeczony, gdy przekroczy 30 (kilogramów). W stanie Wykonczony pozostanie niezależnie od ilości zjedzonej siarki.

let progi:[Stan:Int] = [Stan.Zly : 10,Stan.Lakomy : 20,Stan.Zmeczony : 30,Stan.Wykonczony : Int.max]

Potrzebujemy więc stałej progi, która zdefiniuje nam progi zjedzonej siarki skutkujące zmianą stanu smoka.

ZJEDZMY COŚ WRESZCIE

Po trzecie musimy zaimplementować funkcję, która pozwoli smokowi najeść się. Niech to będzie funkcja zjedz. Funkcje reprezentują zwykle pewnne czynności, które wykonują obiekty struktur[2]. Dlatego dobrą praktyką będzie nazywanie ich czasownikami [3].

mutating func zjedz(owca:Owca){
        if stan == .Wykonczony {
          print("S: Jestem \(stan)")
          return
        }
        print("S: Mniam")
        zjedzonaSiarka += owca.siarka
        if(zjedzonaSiarka >= progi[stan]!){
            stan.next()
            print("S: Jestem \(stan)")
        }
}

Definicja funkcji składa się z nagłówka

mutating func zjedz(owca:Owca)

zawierającego słowo kluczowe

mutating func zjedz(owca:Owca)

nazwę

mutating func zjedz(owca:Owca)

Listy parametrów

mutating func zjedz(owca:Owca)

oraz zawartego między nawiasami {} kodu funkcji. Mutating oznacza, że funkcja będzie mogła zmieniać wartości w strukturze, w której jest zdefiniowana. Inaczej nie dałoby się przypisać do pola zjedzonaSiarka nowej wartości.

Parametrem funkcji jest obiekt struktury Owca. Nie ilość siarki czy ilosć owiec[4]

Powyższy kod sprawdza, jaki jest stan Smoka. Jeśli wykończony, to już nie je. Jeśli smok jest wykończony, wypisuje tylko swój stan i kończy jedzenie. Jeśli jednak nie, to zjada owcę. Jednocześnie dodaje do swojej właściwości (zjedzonaSiarka) ilość siarki, która była w zjedzonej owcy. Jeśli zjedzona siarka przekroczy próg określony w tablicy progi, stan smoka zmienia się na następny.

Pełna wersja struktury Smok wygląda więc tak:

struct Smok{
    var zjedzonaSiarka = 0
    let progi:[Stan:Int] = [Stan.Zly : 10,Stan.Zmeczony : 30,Stan.Lakomy : 20,Stan.Wykonczony : 40]
    var stan = Stan.Zly

    mutating func zjedz(owca:Owca){
        if stan == .Wykonczony {return}
        print("S: Mniam")
        zjedzonaSiarka += owca.siarka
        if(zjedzonaSiarka >= progi[stan]!){
            stan.next()
            print("S: Jestem \(stan). Zjadłem \(zjedzonaSiarka)")
        }
    }
    func powitaj(m: Mieszkaniec){
        if (stan != .Wykonczony){
         print("S: Arrrrr ")
         m.przypal()
        }
    }
}

Pozostaje zatem napisać program, w którym mieszkaniec nakarmi smoka owcami. Potrzebujemy stada owiec, które będziemy przechowywać w tablicy stado

var smok = Smok()
var mieszkaniec = Mieszkaniec()
mieszkaniec.powitaj(smoka: smok)

var stado = [Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:3),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:3),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:2)]

for owca in stado{
    smok.zjedz(owca: owca)
}
mieszkaniec.powitaj(smoka: smok)

Jaki będzie wynik działania tego programu? Bajka o smoku jak się patrzy! W dodatku w formie scenariusza ?

M: Witaj smoku 
S: Arrrrr 
M: Auuuu 
S: Mniam
S: Mniam
S: Mniam
S: Mniam
S: Mniam
S: Mniam
S: Jestem Lakomy. Zjadłem 11
S: Mniam
S: Mniam
S: Mniam
S: Mniam
S: Mniam
S: Mniam
S: Jestem Zmeczony. Zjadłem 20
S: Mniam
S: Mniam
S: Mniam
S: Mniam
S: Mniam
S: Mniam
S: Jestem Wykonczony. Zjadłem 31
M: Witaj smoku

PONIŻEJ PEŁEN KOD ROZWIĄZANIA

import Cocoa

var str = "Hello, playground"

enum Stan{
    case Zly, Lakomy, Zmeczony, Wykonczony
    mutating func next(){
        switch self{
        case .Zly: self = .Lakomy
        case .Lakomy: self = .Zmeczony
        case .Zmeczony: self = .Wykonczony
        case .Wykonczony: self = .Wykonczony
        }
    }
}

struct Owca{
    var siarka:Int
}

struct Smok{
    var zjedzonaSiarka = 0
    let progi:[Stan:Int] = [Stan.Zly : 10,Stan.Zmeczony : 30,Stan.Lakomy : 20,Stan.Wykonczony : 40]
    var stan = Stan.Zly

    mutating func zjedz(owca:Owca){
        if stan == .Wykonczony {return}
        print("S: Mniam")
        zjedzonaSiarka += owca.siarka
        if(zjedzonaSiarka >= progi[stan]!){
            stan.next()
            print("S: Jestem \(stan). Zjadłem \(zjedzonaSiarka)")
        }
    }

    func powitaj(mieszkanca m: Mieszkaniec){
        print("S: Arrrrr ")
        m.przypal()
    }
}

struct Mieszkaniec{
    func powitaj(smoka s: Smok){
        print("M: Witaj smoku ")
        s.powitaj(mieszkanca: self)
    }
    func przypal(){
        print("M: Auuuu ")
    }
}

var smok = Smok()
var mieszkaniec = Mieszkaniec()
mieszkaniec.powitaj(smoka: smok)

var stado = [Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:3),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:3),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:2),
             Owca(siarka:1),
             Owca(siarka:2)]

for owca in stado{
    smok.zjedz(owca: owca)
}


dr Błażej Zyglarski

Autoryzowany Trener Apple (Swift), praktyk z wieloletnim doświadczeniem

Od lat pasjonat technologii mobilnych. Autor dziesiątek aplikacji dla systemów iOS, tvOS i watchOS. Wykładowca na Wydziale Matematyki i Informatyki Uniwersytetu Mikołaja Kopernika w Toruniu. Praktykujący deweloper iOS. Współzałożyciel Asuri Solutions.



  1. Tak jak w prawdziwym świecie, ilości zjedzonej siarki byłby świadom żołądek Smoka lub klas
  2. Na razie po polsku, ale w prawdziwych programach będziemy używać języka angielskiego, jako standardu
  3. Jak w prawdziwym świecie o ilości siarki Smok dowie się dopiero jak zje owcę.

Image
Programowanie Swift
Swift on Windows
Sep 23, 2020
Image
Felieton
Zarabianie Schrodingera
Sep 03, 2019
Image
Felieton
Rozliczanie aplikacji sprzedanych w AppStore
Jun 10, 2019
Image
Felieton
Cały internet na płycie CD
Apr 01, 2019
Image
Nauka programownia
Swift: O co chodzi z tymi kolejkami?
Feb 17, 2019

Nasze szkolenia