Musterlösung zu Aufgabe 8 -- laby.m2


MODULE laby;

FROM Arguments IMPORT GetArg, Usage, InitArgs, AllArgs;
FROM InOut IMPORT Write, WriteCard, WriteString, WriteLn;
FROM StdIO IMPORT FILE, MODE, Fopen, Fclose, Fgetc, stdin, stdout, stderr;
FROM FtdIO IMPORT FwriteString, FwriteLn, FwriteChar;
FROM ASCII IMPORT nl;
FROM SysExit IMPORT Exit;

FROM Labyrinth IMPORT Labyrinth, Lines, Columns, ShowLab, ErrMesg, ReadKey;


VAR char : CHAR;

CONST	Wand = '#';
	Leer = ' ';
	Weg = 'X';
	Mark = '0';

(* ------------------------------------------------------------ *)
(* Labyrinth einlesen und pruefen *)

PROCEDURE ReadLaby(infile : ARRAY OF CHAR; VAR eing : CARDINAL; VAR lab : Labyrinth) : BOOLEAN;
VAR fp : FILE;
    zeile, spalte : CARDINAL;
    ch	: CHAR;
    ausgang : BOOLEAN;
BEGIN
    zeile := 0; spalte := 0; eing := 0;
    ausgang := FALSE;

    IF NOT Fopen(fp, infile, read, TRUE) THEN
	ErrMesg("Kann Datei nicht oeffnen");
    END;

    WHILE Fgetc(ch, fp) DO
	IF zeile > Lines-1 THEN
	    ErrMesg("Labyrinth ist zu hoch");
	ELSIF spalte > Columns THEN
	    ErrMesg("Zeile zu lang");
	END;
	CASE ch OF 
	| nl : 
	    IF spalte = Columns THEN
		lab[zeile, spalte] := 0C;
		spalte := 0; INC(zeile);
	    ELSIF spalte < Columns THEN 
		ErrMesg("Zeile zu kurz");
	    END;
	| Leer :
	    IF ( zeile = 0) OR (zeile = Lines-1) THEN
		ErrMesg("Labyrinth hat oben oder unten einen Eingang !");
	    ELSIF spalte = Columns-1 THEN
		IF ausgang THEN
		    ErrMesg("Labyrinth hat mehr als einen Ausgang");
		END;
		ausgang := TRUE;
	    ELSIF (spalte = 0) THEN
		IF eing <> 0 THEN
		    ErrMesg("Labyrinth hat mehr als einen Eingang");
		END;
		eing := zeile;
	    END;
	    lab[zeile, spalte] := Leer;
	    INC(spalte);
	ELSE
	    lab[zeile, spalte] := Wand;
	    INC(spalte);
	END;
    END;

    IF zeile < Lines THEN
	ErrMesg("Labyrinth hat zu wenig Zeilen");
    END;

    IF NOT ausgang THEN
	ErrMesg("Labyrinth hat keinen Ausgang");
    END;

    IF eing = 0 THEN
	ErrMesg("Labyrinth hat keinen Eingang");
    END;

    IF NOT Fclose(fp) THEN
	ErrMesg("Kann Datei nicht schliessen");
    END;

    RETURN TRUE;
END ReadLaby;

(* ------------------------------------------------------------ *)

PROCEDURE SucheAusgang(zeile, spalte : CARDINAL; VAR lab : Labyrinth) : BOOLEAN;
VAR gefunden : BOOLEAN;
    i : CARDINAL;
    ch : CHAR;
BEGIN
    IF spalte = Columns-1 THEN    	(* Ausgang gefunden *)
	lab[zeile, spalte] := Weg;
	RETURN TRUE;
    END;

    lab[zeile, spalte] := Mark;	    (* Stelle markieren - hier war ich schon *)
    gefunden := FALSE;

    ShowLab(lab);
    ch := ReadKey();

    (* nach Osten *)
    IF  lab[zeile, spalte+1] = Leer THEN
	gefunden := SucheAusgang(zeile, spalte+1, lab);
    END;

    (* nach Norden *)
    IF (NOT gefunden) AND (zeile > 0) AND (lab[zeile-1, spalte] = Leer) THEN
	gefunden := SucheAusgang(zeile-1, spalte, lab);
    END;

    (* nach Sueden *)
    IF (NOT gefunden) AND (lab[zeile+1, spalte] = Leer) THEN
	gefunden := SucheAusgang(zeile+1, spalte, lab);
    END;

    (* nach Westen *)
    IF (NOT gefunden) AND (spalte > 0) AND (lab[zeile, spalte-1] = Leer) THEN
	gefunden := SucheAusgang(zeile, spalte-1, lab);
    END;
    
    IF gefunden THEN
	lab[zeile, spalte] := Weg;	(* Weg markieren *)
	ShowLab(lab);
	ch := ReadKey();
	RETURN TRUE;
    ELSE
	RETURN FALSE;
    END;

END SucheAusgang;

(* ------------------------------------------------------------ *)
(* Labyrinth ausgegen *)

PROCEDURE PrintLaby(fp : FILE; lab : Labyrinth);
VAR zeile, spalte : CARDINAL;
BEGIN
    FOR zeile := 0 TO Lines-1 DO
	FwriteString(fp, lab[zeile]); FwriteLn(fp);
    END;
END PrintLaby;

(* ------------------------------------------------------------ *)

VAR
  lab: Labyrinth;
  infile, outfile: ARRAY[0..20] OF CHAR;
  eingang : CARDINAL;
  infp, outfp : FILE;

BEGIN
    InitArgs("infile [outfile]");

    IF NOT GetArg(infile) THEN		(* es muss mind. 1 Arg. angeg. sein *)
        Usage; Exit(1);
    END;
    IF NOT GetArg(outfile) THEN
	outfp := stdout;
    END;

    AllArgs;	(* Jetzt darf eigentlich kein Argument mehr kommen *)

    IF ReadLaby(infile, eingang, lab) THEN		(* Laby lesen *)
	IF SucheAusgang(eingang, 0, lab) THEN	(* Ausgang suchen *)
	    IF (outfp<>stdout) AND (Fopen(outfp, outfile, write, TRUE)) THEN
		PrintLaby(outfp, lab);			(* Labyrinth ausgeben *)
	    ELSIF outfp = stdout THEN
		ShowLab(lab);
	    ELSE
		ErrMesg("Kann outfile nicht oeffnen");
	    END;
	ELSE 
	    ErrMesg("Weg nicht gefunden");		(* Kein Weg gefunden *)
	END;
    END;

END laby.

Musterlösung zu Aufgabe 8 || Übungen || Vorlesung || SS 97 || SAI

Franz Schweiggert, 26.06.1997