I feel like I got a little sloppy with these challenges. Any alternative suggestions are welcome.
Bronze Challenge:
I modeled my code based on the principle that Zombies (or any monsters, for that matter) could potentially get stronger–for example, after it is instantiated somewhere else in the code and it’s power is directly manipulated (if we choose to keep that public), we would still be able to reduce the population of the current town to 0 if the population threshold is exceeded and not go into negative numbers.
super.terrorizeTown()
only needs to be called if there is a population left after the Zombie is done terrorizing, so I included that in only the default
case in the switch
statement.
And lastly, I changed my new zombieTerrorPower
and population
to be a UInt
, because it made more sense to me that the power of a monster would be a positive number, not a negative number (same with the population). Plus, it allows me some compile-time safety so that I know what I’m getting (no negative numbers!). This means a bit of refactoring, adding a check to see if a monster is attacking, but worth the effort.
/// Town.swift
struct Town {
var population: UInt = 5422
var numberOfStoplights = 4
var isMonsterAttacking = false
func printDescription() {
print("Population: \(population), number of stoplights: \(numberOfStoplights)")
}
mutating func changePopulation(by amount: UInt) {
if isMonsterAttacking {
population -= amount
} else {
population += amount
}
}
}
/// Zombie.swift
class Zombie: Monster {
var walksWithLimp = true
var zombieTerrorPower: UInt = 10
final override func terrorizeTown() {
town?.isMonsterAttacking = true
if let currentPop = town?.population {
switch currentPop {
case 0: // no population--do nothing.
print("\(self.name) tried terrorizing but everyone's dead...nobody left to terrorize.")
case 1 ... zombieTerrorPower: // scales with zombie power
town?.population = 0
print("\(self.name) terrorized the town, and now everyone is dead.")
default: // fallback
super.terrorizeTown()
town?.changePopulation(by: zombieTerrorPower)
}
}
town?.isMonsterAttacking = false
}
}
Silver Challenge:
Similar in structure to the Zombie, but less cases (more work to do in each case though):
/// Vampire.swift
class Vampire: Monster {
var convertedVamps = [Vampire]()
var vampireTerrorPower: UInt = 1
final override func terrorizeTown() {
town?.isMonsterAttacking = true
if let currentPop = town?.population {
switch currentPop {
case 0: // no population--do nothing.
print("\(self.name) tried terrorizing but everyone's either dead or a vampire...nobody left to terrorize.")
printVampireCount()
default: // fallback
super.terrorizeTown()
town?.changePopulation(by: vampireTerrorPower)
convertedVamps.append(Vampire())
printVampireCount()
}
}
town?.isMonsterAttacking = false
}
func printVampireCount() {
print("There are \(convertedVamps.count) vampires in this town.")
}
}
/// main.swift (testing the code)
var myTown = Town()
myTown.printDescription()
let dracula = Vampire()
dracula.name = "Dracula"
dracula.town = myTown
dracula.terrorizeTown()
dracula.terrorizeTown()
dracula.terrorizeTown()
dracula.town?.printDescription()
let fredTheZombie = Zombie()
fredTheZombie.town = myTown
fredTheZombie.name = "Zombie"
fredTheZombie.zombieTerrorPower = 10000
fredTheZombie.terrorizeTown()
fredTheZombie.town?.printDescription()
Console Output:
Population: 5422, number of stoplights: 4
Dracula is terrorizing a town!
There are 1 vampires in this town.
Dracula is terrorizing a town!
There are 2 vampires in this town.
Dracula is terrorizing a town!
There are 3 vampires in this town.
Population: 5419, number of stoplights: 4
Zombie terrorized the town, and now everyone is dead.
Population: 0, number of stoplights: 4