Das verschlossene Labor 1: Räume und Befehle
Kurz gesagt: Ein Text-Fluchtspiel: Räume und Gegenstände sind Objekte, die Ausgänge stehen in einem Dictionary, das Inventar in einer Liste, jeder Befehl ist eine Klasse und ein unbekannter Befehl ist eine Exception.
Problem
Im Labor eingesperrt
Du bist abends lange im Labor geblieben. Das Sicherheitssystem hat die Türen automatisch verriegelt. Du musst raus, bevor morgens der Wachdienst kommt. Es gibt keine Kämpfe, nur Räume, Gegenstände und Rätsel.
Das Spiel läuft als Text. Der Spieler tippt Befehle, und das Spiel antwortet:
> geh norden[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westen> nimm schlüsselHier gibt es keinen Gegenstand „schlüssel“.Die erste Idee ist ein großes if: Wenn der Befehl „geh“ ist, tu dies, wenn er „nimm“ ist, tu das. Es wächst mit jedem neuen Befehl, und ein Fehler in einem Zweig bringt die anderen kaputt. In dieser Lektion werden die Befehle zu eigenen Klassen, und die Räume und Gegenstände werden zu Objekten in Collections.
Die Idee
Räume und Gegenstände
Ein Gegenstand hat einen Namen und eine Beschreibung:
class Item { private String name; private String description;
public Item(String name, String description) { this.name = name; this.description = description; }
public String getName() { return name; }
public String getDescription() { return description; }}class Item{ public string Name { get; } public string Description { get; }
public Item(string name, string description) { Name = name; Description = description; }}class Item: def __init__(self, name, description): self._name = name self._description = description
@property def name(self): return self._name
@property def description(self): return self._descriptionclass Item { #name; #description;
constructor(name, description) { this.#name = name; this.#description = description; }
get name() { return this.#name; }
get description() { return this.#description; }}Ein Raum hat einen Namen, eine Beschreibung, Ausgänge und Gegenstände. Die Ausgänge stehen in einem Dictionary: Die Richtung ist der Schlüssel, der Nachbarraum ist der Wert. Die Gegenstände stehen in einer Liste, weil ihre Anzahl sich ändert:
private static final String[] DIRECTIONS = { "norden", "süden", "osten", "westen" };
private String name;private String description;private Map<String, Room> exits = new HashMap<>();private List<Item> items = new ArrayList<>();private static readonly string[] Directions = { "norden", "süden", "osten", "westen" };
public string Name { get; }public string Description { get; }private Dictionary<string, Room> exits = new Dictionary<string, Room>();private List<Item> items = new List<Item>();DIRECTIONS = ("norden", "süden", "osten", "westen")
def __init__(self, name, description): self._name = name self._description = description self._exits = {} self._items = []static DIRECTIONS = ["norden", "süden", "osten", "westen"];
#name;#description;#exits = new Map();#items = [];public void addExit(String direction, Room room) { exits.put(direction, room);}
public Room getExit(String direction) { return exits.get(direction);}public void AddExit(string direction, Room room){ exits[direction] = room;}
public Room GetExit(string direction){ if (exits.ContainsKey(direction)) { return exits[direction]; } return null;}def add_exit(self, direction, room): self._exits[direction] = room
def get_exit(self, direction): return self._exits.get(direction)addExit(direction, room) { this.#exits.set(direction, room);}
getExit(direction) { return this.#exits.get(direction);}Der Indexer exits[direction] wirft KeyNotFoundException, wenn der Schlüssel fehlt. Darum fragt GetExit zuerst ContainsKey und gibt null zurück, wenn es keinen Ausgang gibt.
Sieh es dir an
Was im Raum ist
Beim Nehmen verschwindet der Gegenstand aus dem Raum und wird zurückgegeben. Ist er nicht da, kommt null zurück:
public void addItem(Item item) { items.add(item);}
public Item takeItem(String name) { for (int i = 0; i < items.size(); i++) { if (items.get(i).getName().equals(name)) { return items.remove(i); } } return null;}public void AddItem(Item item){ items.Add(item);}
public Item TakeItem(string name){ for (int i = 0; i < items.Count; i++) { if (items[i].Name == name) { Item item = items[i]; items.RemoveAt(i); return item; } } return null;}def add_item(self, item): self._items.append(item)
def take_item(self, name): for item in self._items: if item.name == name: self._items.remove(item) return item return NoneaddItem(item) { this.#items.push(item);}
takeItem(name) { for (let i = 0; i < this.#items.length; i++) { if (this.#items[i].name === name) { return this.#items.splice(i, 1)[0]; } } return null;}Die Beschreibung sammelt die Namen der Gegenstände und die Ausgänge. Die Richtungen stehen in fester Reihenfolge (norden, süden, osten, westen), damit der Text nicht von der Reihenfolge im Dictionary abhängt:
public String describe() { String text = "[" + name + "] " + description; if (!items.isEmpty()) { List<String> names = new ArrayList<>(); for (Item item : items) { names.add(item.getName()); } text += "\nHier siehst du: " + String.join(", ", names); } List<String> ways = new ArrayList<>(); for (String direction : DIRECTIONS) { if (exits.containsKey(direction)) { ways.add(direction); } } return text + "\nAusgänge: " + String.join(", ", ways);}public string Describe(){ string text = "[" + Name + "] " + Description; if (items.Count > 0) { List<string> names = new List<string>(); foreach (Item item in items) { names.Add(item.Name); } text += "\nHier siehst du: " + string.Join(", ", names); } List<string> ways = new List<string>(); foreach (string direction in Directions) { if (exits.ContainsKey(direction)) { ways.Add(direction); } } return text + "\nAusgänge: " + string.Join(", ", ways);}def describe(self): text = f"[{self._name}] {self._description}" if self._items: names = [] for item in self._items: names.append(item.name) text += "\nHier siehst du: " + ", ".join(names) ways = [] for direction in Room.DIRECTIONS: if direction in self._exits: ways.append(direction) return text + "\nAusgänge: " + ", ".join(ways)describe() { let text = `[${this.#name}] ${this.#description}`; if (this.#items.length > 0) { const names = []; for (const item of this.#items) { names.push(item.name); } text += `\nHier siehst du: ${names.join(", ")}`; } const ways = []; for (const direction of Room.DIRECTIONS) { if (this.#exits.has(direction)) { ways.push(direction); } } return `${text}\nAusgänge: ${ways.join(", ")}`;}Probier es aus
Ausgang oder null?
Was gibt das Programm aus?
Room hall = new Room("flur", "Ein langer Flur.");Room store = new Room("lager", "Regale mit Kartons.");hall.AddExit("osten", store);store.AddExit("westen", hall);store.AddItem(new Item("schlüssel", "Ein Messingschlüssel."));Console.WriteLine(hall.GetExit("osten").Name);Console.WriteLine(hall.GetExit("westen") == null);Console.WriteLine(store.TakeItem("schlüssel") != null);Console.WriteLine(store.TakeItem("schlüssel") != null);Im Osten des Flurs liegt das Lager. Im Westen des Flurs gibt es keinen Ausgang, also ist das Ergebnis null. Beim ersten Nehmen des Schlüssels findet das Programm den Gegenstand und entfernt ihn aus der Liste. Beim zweiten Mal findet es nichts und gibt null zurück.
Die Idee
Jeder Befehl ist eine Klasse
Alle Befehle folgen einem Vertrag: Sie bekommen das Spiel und das Wort nach dem Befehl und geben den Text zurück, den der Spieler sieht:
interface Command { String execute(Game game, String argument);}interface ICommand{ string Execute(Game game, string argument);}class Command(ABC): @abstractmethod def execute(self, game, argument): pass// JavaScript hat kein interface. Der „Befehl“-Vertrag ist eine Absprache:// Jeder Befehl ist eine Klasse mit einer Methode execute(game, argument),// die den Text zurückgibt, den der Spieler sieht.Nehmen und Gehen sind zwei kleine Klassen. Jede kennt nur ihre eigene Aufgabe:
class TakeCommand implements Command { @Override public String execute(Game game, String argument) { if (argument.isEmpty()) { return "Was möchtest du nehmen?"; } Item item = game.getCurrent().takeItem(argument); if (item == null) { return "Hier gibt es keinen Gegenstand „" + argument + "“."; } game.getInventory().add(item); return "Du nimmst: " + item.getName() + ". " + item.getDescription(); }}class TakeCommand : ICommand{ public string Execute(Game game, string argument) { if (argument == "") { return "Was möchtest du nehmen?"; } Item item = game.Current.TakeItem(argument); if (item == null) { return "Hier gibt es keinen Gegenstand „" + argument + "“."; } game.Inventory.Add(item); return "Du nimmst: " + item.Name + ". " + item.Description; }}class TakeCommand(Command): def execute(self, game, argument): if argument == "": return "Was möchtest du nehmen?" item = game.current.take_item(argument) if item is None: return f"Hier gibt es keinen Gegenstand „{argument}“." game.inventory.append(item) return f"Du nimmst: {item.name}. {item.description}"class TakeCommand { execute(game, argument) { if (argument === "") { return "Was möchtest du nehmen?"; } const item = game.current.takeItem(argument); if (item === null) { return `Hier gibt es keinen Gegenstand „${argument}“.`; } game.inventory.push(item); return `Du nimmst: ${item.name}. ${item.description}`; }}class GoCommand implements Command { @Override public String execute(Game game, String argument) { Room next = game.getCurrent().getExit(argument); if (next == null) { return "In diese Richtung gibt es keinen Ausgang."; } game.setCurrent(next); return next.describe(); }}class GoCommand : ICommand{ public string Execute(Game game, string argument) { Room next = game.Current.GetExit(argument); if (next == null) { return "In diese Richtung gibt es keinen Ausgang."; } game.Current = next; return next.Describe(); }}class GoCommand(Command): def execute(self, game, argument): next_room = game.current.get_exit(argument) if next_room is None: return "In diese Richtung gibt es keinen Ausgang." game.current = next_room return next_room.describe()class GoCommand { execute(game, argument) { const next = game.current.getExit(argument); if (next === undefined) { return "In diese Richtung gibt es keinen Ausgang."; } game.current = next; return next.describe(); }}Die Befehle geben nichts aus. Sie geben Text zurück. So entscheidet das Spiel, wo es ihn zeigt, und du kannst einen Befehl testen, ohne auf den Bildschirm zu schauen.
Die Idee
Ein Dictionary für die Befehle
Das Spiel hält die Befehle in einem Dictionary: Das Wort ist der Schlüssel, das Befehlsobjekt ist der Wert. Einen Befehl hinzuzufügen ist eine Zeile:
private Map<String, Room> rooms;private Map<String, Command> commands = new HashMap<>();private List<Item> inventory = new ArrayList<>();private Room current;
public Game() { rooms = buildWorld(); current = rooms.get("labor"); commands.put("schau", new LookCommand()); commands.put("nimm", new TakeCommand()); commands.put("geh", new GoCommand());}private Dictionary<string, Room> rooms;private Dictionary<string, ICommand> commands = new Dictionary<string, ICommand>();
public Room Current { get; set; }public List<Item> Inventory { get; } = new List<Item>();
public Game(){ rooms = BuildWorld(); Current = rooms["labor"]; commands["schau"] = new LookCommand(); commands["nimm"] = new TakeCommand(); commands["geh"] = new GoCommand();}def __init__(self): self._rooms = self._build_world() self._current = self._rooms["labor"] self._inventory = [] self._commands = { "schau": LookCommand(), "nimm": TakeCommand(), "geh": GoCommand(), }#rooms;#commands = new Map();#inventory = [];#current;
constructor() { this.#rooms = this.#buildWorld(); this.#current = this.#rooms.get("labor"); this.#commands.set("schau", new LookCommand()); this.#commands.set("nimm", new TakeCommand()); this.#commands.set("geh", new GoCommand());}Handle entfernt die Leerzeichen an den Enden, macht die Zeile klein und zerlegt sie in Wörter. Das erste Wort ist der Befehl, das zweite das Argument. Steht das Wort nicht im Dictionary, wirft Find eine eigene Exception, und Handle fängt sie und sagt „Das verstehe ich nicht“:
public String handle(String line) { String[] words = line.trim().toLowerCase().split(" "); String argument = words.length > 1 ? words[1] : ""; try { Command command = find(words[0]); return command.execute(this, argument); } catch (UnknownCommandException e) { return "Ich verstehe „" + e.getVerb() + "“ nicht."; }}
private Command find(String verb) throws UnknownCommandException { Command command = commands.get(verb); if (command == null) { throw new UnknownCommandException(verb); } return command;}public string Handle(string line){ string[] words = line.Trim().ToLower().Split(' '); string argument = words.Length > 1 ? words[1] : ""; try { ICommand command = Find(words[0]); return command.Execute(this, argument); } catch (UnknownCommandException e) { return "Ich verstehe „" + e.Verb + "“ nicht."; }}
private ICommand Find(string verb){ if (!commands.ContainsKey(verb)) { throw new UnknownCommandException(verb); } return commands[verb];}def handle(self, line): words = line.strip().lower().split(" ") argument = words[1] if len(words) > 1 else "" try: command = self._find(words[0]) return command.execute(self, argument) except UnknownCommandError as e: return f"Ich verstehe „{e.verb}“ nicht."
def _find(self, verb): command = self._commands.get(verb) if command is None: raise UnknownCommandError(verb) return commandhandle(line) { const words = line.trim().toLowerCase().split(" "); const argument = words.length > 1 ? words[1] : ""; try { const command = this.#find(words[0]); return command.execute(this, argument); } catch (e) { if (!(e instanceof UnknownCommandError)) { throw e; } return `Ich verstehe „${e.verb}“ nicht.`; }}
#find(verb) { const command = this.#commands.get(verb); if (command === undefined) { throw new UnknownCommandError(verb); } return command;}class UnknownCommandException extends Exception { private String verb;
public UnknownCommandException(String verb) { super("unbekannter Befehl: " + verb); this.verb = verb; }
public String getVerb() { return verb; }}class UnknownCommandException : Exception{ public string Verb { get; }
public UnknownCommandException(string verb) : base("unbekannter Befehl: " + verb) { Verb = verb; }}class UnknownCommandError(Exception): def __init__(self, verb): super().__init__(f"unbekannter Befehl: {verb}") self.verb = verbclass UnknownCommandError extends Error { constructor(verb) { super(`unbekannter Befehl: ${verb}`); this.name = "UnknownCommandError"; this.verb = verb; }}Genauer, für Neugierige
- Das Spiel kennt nur
ICommand. WelchesExecuteläuft, entscheidet das Objekt im Dictionary. Das ist der Polymorphismus aus dem Modul über Vererbung, nur dass die Objekte in einem Dictionary liegen und nicht in einem Array. - Eine andere Möglichkeit ist ein
switchauf das Wort. Für vier Befehle ist das in Ordnung. Bei zwanzig Befehlen mit jeweils eigenen Regeln sind eigene Klassen leichter zu lesen und zu ändern. Split(' ', StringSplitOptions.RemoveEmptyEntries)überspringt die leeren Wörter, wenn mehrere Leerzeichen hintereinander stehen. Hier genügt ein Leerzeichen.
Probier es aus
Finde den Fehler
Der Spieler tippt „Schau“ mit großem Anfangsbuchstaben, und das Spiel antwortet Ich verstehe „Schau“ nicht. In welcher Zeile steckt der Fehler?
Wähle die Zeile mit dem Fehler.
Die Schlüssel im Dictionary sind klein geschrieben, und „Schau“ ist nicht „schau“. Die Zeile muss line.Trim().ToLower().Split(' ') lauten. Dann wird jeder Befehl verstanden, egal wie der Spieler ihn schreibt.
Sieh es dir an
Ein erster Rundgang
Main zeigt den ersten Raum und liest dann Befehl für Befehl, bis die Eingabe zu Ende ist. Vor jedem Befehl gibt es > aus, damit du siehst, was der Spieler getippt hat:
Game game = new Game();System.out.println(game.getCurrent().describe());Scanner in = new Scanner(System.in);while (in.hasNextLine()) { String line = in.nextLine(); System.out.println("> " + line); System.out.println(game.handle(line));}[labor] Die Tische sind voller Kolben. Die Tür hinter dir hat sich von selbst verriegelt.Hier siehst du: taschenlampeAusgänge: norden> Nimm taschenlampeDu nimmst: taschenlampe. Sie funktioniert, und der Akku ist fast voll.> schau[labor] Die Tische sind voller Kolben. Die Tür hinter dir hat sich von selbst verriegelt.Ausgänge: norden> nimm taschenlampeHier gibt es keinen Gegenstand „taschenlampe“.> tanzeIch verstehe „tanze“ nicht.> geh norden[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westen> geh osten[lager] Regale mit Kartons bis zur Decke. An der Wand hängt ein Kalender: „Inventur am 19. Oktober“.Hier siehst du: schlüsselAusgänge: westen> nimm schlüsselDu nimmst: schlüssel. Ein kleiner Messingschlüssel. Auf dem Anhänger steht „Büro“.> geh westen[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westen> geh obenIn diese Richtung gibt es keinen Ausgang.> geh westen[büro] Ein Schreibtisch, ein Stuhl und ein Schrank voller Ordner.Hier siehst du: zettelAusgänge: osten> nimm zettelDu nimmst: zettel. „Foyer-Code: 47 und der Tag der Inventur.“Game game = new Game();Console.WriteLine(game.Current.Describe());string line = Console.ReadLine();while (line != null){ Console.WriteLine("> " + line); Console.WriteLine(game.Handle(line)); line = Console.ReadLine();}[labor] Die Tische sind voller Kolben. Die Tür hinter dir hat sich von selbst verriegelt.Hier siehst du: taschenlampeAusgänge: norden> Nimm taschenlampeDu nimmst: taschenlampe. Sie funktioniert, und der Akku ist fast voll.> schau[labor] Die Tische sind voller Kolben. Die Tür hinter dir hat sich von selbst verriegelt.Ausgänge: norden> nimm taschenlampeHier gibt es keinen Gegenstand „taschenlampe“.> tanzeIch verstehe „tanze“ nicht.> geh norden[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westen> geh osten[lager] Regale mit Kartons bis zur Decke. An der Wand hängt ein Kalender: „Inventur am 19. Oktober“.Hier siehst du: schlüsselAusgänge: westen> nimm schlüsselDu nimmst: schlüssel. Ein kleiner Messingschlüssel. Auf dem Anhänger steht „Büro“.> geh westen[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westen> geh obenIn diese Richtung gibt es keinen Ausgang.> geh westen[büro] Ein Schreibtisch, ein Stuhl und ein Schrank voller Ordner.Hier siehst du: zettelAusgänge: osten> nimm zettelDu nimmst: zettel. „Foyer-Code: 47 und der Tag der Inventur.“game = Game()print(game.current.describe())for line in sys.stdin: line = line.rstrip("\n") print(f"> {line}") print(game.handle(line))[labor] Die Tische sind voller Kolben. Die Tür hinter dir hat sich von selbst verriegelt.Hier siehst du: taschenlampeAusgänge: norden> Nimm taschenlampeDu nimmst: taschenlampe. Sie funktioniert, und der Akku ist fast voll.> schau[labor] Die Tische sind voller Kolben. Die Tür hinter dir hat sich von selbst verriegelt.Ausgänge: norden> nimm taschenlampeHier gibt es keinen Gegenstand „taschenlampe“.> tanzeIch verstehe „tanze“ nicht.> geh norden[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westen> geh osten[lager] Regale mit Kartons bis zur Decke. An der Wand hängt ein Kalender: „Inventur am 19. Oktober“.Hier siehst du: schlüsselAusgänge: westen> nimm schlüsselDu nimmst: schlüssel. Ein kleiner Messingschlüssel. Auf dem Anhänger steht „Büro“.> geh westen[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westen> geh obenIn diese Richtung gibt es keinen Ausgang.> geh westen[büro] Ein Schreibtisch, ein Stuhl und ein Schrank voller Ordner.Hier siehst du: zettelAusgänge: osten> nimm zettelDu nimmst: zettel. „Foyer-Code: 47 und der Tag der Inventur.“const game = new Game();console.log(game.current.describe());let line = await ask("");while (line !== undefined) { console.log(`> ${line}`); console.log(game.handle(line)); line = await ask("");}rl.close();[labor] Die Tische sind voller Kolben. Die Tür hinter dir hat sich von selbst verriegelt.Hier siehst du: taschenlampeAusgänge: norden> Nimm taschenlampeDu nimmst: taschenlampe. Sie funktioniert, und der Akku ist fast voll.> schau[labor] Die Tische sind voller Kolben. Die Tür hinter dir hat sich von selbst verriegelt.Ausgänge: norden> nimm taschenlampeHier gibt es keinen Gegenstand „taschenlampe“.> tanzeIch verstehe „tanze“ nicht.> geh norden[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westen> geh osten[lager] Regale mit Kartons bis zur Decke. An der Wand hängt ein Kalender: „Inventur am 19. Oktober“.Hier siehst du: schlüsselAusgänge: westen> nimm schlüsselDu nimmst: schlüssel. Ein kleiner Messingschlüssel. Auf dem Anhänger steht „Büro“.> geh westen[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westen> geh obenIn diese Richtung gibt es keinen Ausgang.> geh westen[büro] Ein Schreibtisch, ein Stuhl und ein Schrank voller Ordner.Hier siehst du: zettelAusgänge: osten> nimm zettelDu nimmst: zettel. „Foyer-Code: 47 und der Tag der Inventur.“Mit dieser Eingabe:
Nimm taschenlampeschaunimm taschenlampetanzegeh nordengeh ostennimm schlüsselgeh westengeh obengeh westennimm zettelDer Zettel sagt, der Foyer-Code ist 47 und der Tag der Inventur. Der Kalender im Lager sagt 19. Aber ein Foyer gibt es noch nicht, und das Büro ist auch nicht verschlossen. Die Rätsel kommen in der nächsten Lektion.
Game game = new Game();Console.WriteLine(game.Current.Describe());string line = Console.ReadLine();while (line != null){ Console.WriteLine("> " + line); Console.WriteLine(game.Handle(line)); line = Console.ReadLine();}Schritt für Schritt, in Worten
- Das Spiel beginnt im Raum „labor“. Die Befehle stehen in einem Dictionary: Das Wort ist der Schlüssel, das Befehlsobjekt ist der Wert.
- Du tippst „Nimm taschenlampe“. Die Zeile wird zu Kleinbuchstaben. „nimm“ ist ein Schlüssel im Dictionary, und der Befehl ist TakeCommand. Der Gegenstand „taschenlampe“ wandert aus dem Raum in den Rucksack.
- Du tippst „schau“. „schau“ ist ein Schlüssel im Dictionary, und der Befehl ist LookCommand. Er beschreibt den Raum noch einmal, jetzt ohne den Gegenstand, den du genommen hast.
- Du tippst „nimm taschenlampe“. „nimm“ ist ein Schlüssel im Dictionary, und der Befehl ist TakeCommand. Im Raum ist „taschenlampe“ nicht mehr, also lautet die Antwort „Hier gibt es keinen Gegenstand“.
- Du tippst „tanze“. „tanze“ steht nicht im Dictionary: Find wirft UnknownCommandException, und Handle sagt „Das verstehe ich nicht“.
- Du tippst „geh norden“. „geh“ ist ein Schlüssel im Dictionary, und der Befehl ist GoCommand. GetExit("norden") im Raum „labor“ ergibt „flur“.
- Du tippst „geh osten“. „geh“ ist ein Schlüssel im Dictionary, und der Befehl ist GoCommand. GetExit("osten") im Raum „flur“ ergibt „lager“.
- Du tippst „nimm schlüssel“. „nimm“ ist ein Schlüssel im Dictionary, und der Befehl ist TakeCommand. Der Gegenstand „schlüssel“ wandert aus dem Raum in den Rucksack.
- Du tippst „geh westen“. „geh“ ist ein Schlüssel im Dictionary, und der Befehl ist GoCommand. GetExit("westen") im Raum „lager“ ergibt „flur“.
- Du tippst „geh oben“. „geh“ ist ein Schlüssel im Dictionary, und der Befehl ist GoCommand. Die Ausgänge von „flur“ haben keinen Schlüssel „oben“: In diese Richtung gibt es keinen Ausgang.
- Du tippst „geh westen“. „geh“ ist ein Schlüssel im Dictionary, und der Befehl ist GoCommand. GetExit("westen") im Raum „flur“ ergibt „büro“.
- Du tippst „nimm zettel“. „nimm“ ist ein Schlüssel im Dictionary, und der Befehl ist TakeCommand. Der Gegenstand „zettel“ wandert aus dem Raum in den Rucksack.
- Die Eingabe ist zu Ende, und die Schleife hört auf. Der Rucksack: taschenlampe, schlüssel, zettel.
Übung
Mehr Befehle und Räume
Löse die Aufgaben in deinem Editor, mit den Klassen aus der Lektion. Füge das Neue von außen hinzu, mit game.AddCommand und game.GetRoom, ohne Game anzufassen.
1. Inventar. Ein Befehl „inventar“ sagt, was im Rucksack ist oder dass er leer ist.
inventarnimm taschenlampegeh nordengeh ostennimm schlüsselinventar[labor] Die Tische sind voller Kolben. Die Tür hinter dir hat sich von selbst verriegelt.Hier siehst du: taschenlampeAusgänge: norden> inventarDein Rucksack ist leer.> nimm taschenlampeDu nimmst: taschenlampe. Sie funktioniert, und der Akku ist fast voll.> geh norden[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westen> geh osten[lager] Regale mit Kartons bis zur Decke. An der Wand hängt ein Kalender: „Inventur am 19. Oktober“.Hier siehst du: schlüsselAusgänge: westen> nimm schlüsselDu nimmst: schlüssel. Ein kleiner Messingschlüssel. Auf dem Anhänger steht „Büro“.> inventarIn deinem Rucksack: taschenlampe, schlüssel2. Ein neuer Raum. Ein Serverraum nördlich des Lagers, mit einem Netzwerkkabel darin. Seine Beschreibung lautet „Racks mit blinkenden Lichtern. Die Lüfter summen.“
geh nordengeh ostengeh nordennimm kabelgeh süden[labor] Die Tische sind voller Kolben. Die Tür hinter dir hat sich von selbst verriegelt.Hier siehst du: taschenlampeAusgänge: norden> geh norden[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westen> geh osten[lager] Regale mit Kartons bis zur Decke. An der Wand hängt ein Kalender: „Inventur am 19. Oktober“.Hier siehst du: schlüsselAusgänge: norden, westen> geh norden[serverraum] Racks mit blinkenden Lichtern. Die Lüfter summen.Hier siehst du: kabelAusgänge: süden> nimm kabelDu nimmst: kabel. Ein langes Netzwerkkabel.> geh süden[lager] Regale mit Kartons bis zur Decke. An der Wand hängt ein Kalender: „Inventur am 19. Oktober“.Hier siehst du: schlüsselAusgänge: norden, westen3. Synonyme. „schnapp“ soll „nimm“ bedeuten, „lauf“ soll „geh“ bedeuten und „guck“ soll „schau“ bedeuten. Tipp: Derselbe Befehl kann der Wert mehrerer Schlüssel sein.
schnapp taschenlampelauf nordenguck[labor] Die Tische sind voller Kolben. Die Tür hinter dir hat sich von selbst verriegelt.Hier siehst du: taschenlampeAusgänge: norden> schnapp taschenlampeDu nimmst: taschenlampe. Sie funktioniert, und der Akku ist fast voll.> lauf norden[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westen> guck[flur] Ein langer Flur. Die Deckenlampe flackert.Ausgänge: süden, osten, westenWeitere Aufgaben
- Ablegen. Ein Befehl „leg schlüssel“ legt den Gegenstand aus dem Rucksack zurück in den Raum.
- Hilfe. Ein Befehl „hilfe“ listet alle Wörter aus dem Dictionary der Befehle auf.
- Kurze Richtungen. „n“, „s“, „o“, „w“ sollen norden, süden, osten, westen bedeuten.
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Exceptions · Werfen und eigene Exceptions · Listen · Dictionary und HashSet
- Aufgaben zum Thema: Wir bauen ein Spiel