W1911 Finite State Machine

From Coder Merlin

Prerequisites[edit]

Research[edit]

Examples[edit]

RPG[edit]

enum State {
    case inTheCourtyard
    case inTheCastle
    case inTheDungeon
    case death
}

// Prompt the user for an entry
// Continue to prompt until a valid entry is returned
// We ignore any invalid or superfluous input
// The selected character is returned
func getKeyboardInput(prompt:String, allowedCharacters:Set<Character>) -> Character {
    var key : Character = "\u{0000}"
    repeat {
        print("\(prompt) ->", terminator:"")
        if let line = readLine() {
           key = line.first ?? key
        }

        if !allowedCharacters.contains(key) {
            print("Invalid entry.  Press one of \(allowedCharacters) followed by <ENTER>.")
        }
    } while !allowedCharacters.contains(key)
    return key
}

func handleCourtyardInteraction() -> State {
    print("You find yourself in a wide courtyard.")
    var key : Character
    repeat {
        key = getKeyboardInput(prompt:"Would you like to go to the C)astle or wait for the D)ragon?", allowedCharacters:["C", "D"])
        switch key {
        case "C":
            print("Let's head to the castle!")
        case "D":
            print("You look above and see no dragon yet.")
        default:
            fatalError("Unexpected key \(key).")
        }
    } while key != "C";
    return .inTheCastle
}

func handleCastleInteraction() -> State {
    print("You find yourself in a dark, dank castle.")

    var key : Character
    repeat {
        key = getKeyboardInput(prompt:"Would you like to light a C)andle or look for the L)ight switch?", allowedCharacters:["C", "L"])
        switch key {
        case "C":
            print("You (very surprisingly) find a box of matches in your armor's front pocket.  You successfully light the candle.")
            print("You see a long, winding stairway immediately in front of you, and realize that had you taken another step in ")
            print("the dark, it would have been your last.")
            print("You descend carefully down the stairs to find yourself...")
        case "L":
            print("You slowly turn to your right, feeling in front of you for a light switch.")
            print("You touch only air.")
        default:
            fatalError("Unexpected key \(key).")
        }
    } while key != "C"
    return .inTheDungeon
}

func handleDungeonInteraction() -> State {
    print("You find yourself in a dungeon.")

    var key : Character
    repeat {
        key = getKeyboardInput(prompt:"Would you like to turn R)ight, L)eft, or move F)orwards?", allowedCharacters:["R", "L", "F"])
        switch key {
        case "R":
            print("You move cautiously to your right.  You see a flickering, momentary shadow.")
        case "L":
            print("You dart anxiously to your left.  You hear a deep, growl and sense a whiff of dragon's breath... but then it's gone.")
        case "F":
            print("You, quite briefly, see teeth.  Oh sh... is your final thought.")
        default:
            fatalError("Unexpected key \(key).")
        }
    } while key != "F"
    return .death
}

func main() {
    var state = State.inTheCourtyard
    repeat {
        switch state {
        case .inTheCourtyard:
            state = handleCourtyardInteraction()
        case .inTheCastle:
            state = handleCastleInteraction()
        case .inTheDungeon:
            state = handleDungeonInteraction()
        case .death:
            do {}
        }
    } while state != .death
    print("It's over.  Goodbye.")
}

main()

Exercises[edit]

  1. Using Draw IO construct a Finite State Machine Diagram accurately and comprehensively describing:
    • an automatic-flush toilet
    • a traffic light

Key Concepts[edit]

  • A finite state diagram describes a system of
    • finite states (there are limited, though potentially large, number of states)
    • transitions which are triggered under specific conditions and move the machine from one state to another
  • The diagram uses:
    • Boxes to represent states
    • Unidirectional arrows to represent transitions
    • A unidirectional arrow with a dot on the opposing side to represent the initial state
  • Finite state machines diagrams are not flow charts