Universität Ulm, Fakultät für Mathematik und Wirtschaftswissenschaften, SAI

Lösung zu Blatt 4 --- Allgemeine Informatik II (WS 1999)

5. Just a Soccer Game

MODULE Soccer;

   IMPORT Read, Streams, UnixFiles, Write;

   CONST filename = "cards.txt";

   TYPE Card = RECORD
      colour: ARRAY 4 OF INTEGER; (* 0: yellow, 1: red, 2: blue, 3; black *)
      top: ARRAY 4 OF INTEGER; (* 0 = Body, 1 = Legs *)
      orientation: INTEGER; (* 0 NORTH, 1 EAST, 2 SOUTH, 3 WEST *)
      position: INTEGER; (* -1: not places, 0: NW ... 8: SE *)
	 (* position is not needed - just for output *)
   END;

   VAR
      cards: ARRAY 9 OF Card;    (* nine cards should be placed on 9 spots *)
      board: ARRAY 9 OF INTEGER; (* on the board *)
   
   PROCEDURE PrintBoard(); (* I tried to keep it readable - there are *)
      VAR i, j, k: INTEGER;(* shorter ways to do this *)
   BEGIN
      j := 0;
      WHILE j < 3 DO
	 i := 0;
	 WHILE i < 3 DO
	    Write.String("  ");
	    k := i + 3 * j;
	    Write.Int(cards[board[k]].colour[cards[board[k]].orientation], 1);
	    Write.Int(cards[board[k]].top[cards[board[k]].orientation], 1);
	    Write.String("  ");
	    INC(i);
	 END;
	 Write.Ln;
	 i := 0;
	 WHILE i < 3 DO
	    k := i + 3 * j;
	    Write.Int(cards[board[k]].colour[(cards[board[k]].orientation + 3)
	       MOD 4], 1);
	    Write.Int(cards[board[k]].top[(cards[board[k]].orientation + 3)
	       MOD 4], 1);
	    Write.String("  ");
	    Write.Int(cards[board[k]].colour[(cards[board[k]].orientation + 1)
	       MOD 4], 1);
	    Write.Int(cards[board[k]].top[(cards[board[k]].orientation + 1)
	       MOD 4], 1);
	    INC(i);
	 END;
	 Write.Ln;
	 i := 0;
	 WHILE i < 3 DO
	    k := i + 3 * j;
	    Write.String("  ");
	    Write.Int(cards[board[k]].colour[(cards[board[k]].orientation + 2)
	       MOD 4], 1);
	    Write.Int(cards[board[k]].top[(cards[board[k]].orientation + 2)
	       MOD 4], 1);
	    Write.String("  ");
	    INC(i);
	 END;
	 Write.Ln;
	 INC(j);
      END;
   END PrintBoard;
   
   PROCEDURE Valid(n: INTEGER): BOOLEAN; (* n in -1 .. 8 *)
   BEGIN
      IF n < 1 THEN RETURN TRUE END; (* One or less cards *)
      (* Second and thrid row -> there is a card to the north *)
      (* IF n > 2 & (wrong colour OR wrong body parts) THEN ... *)
      IF (n > 2) & ((cards[board[n]].colour[cards[board[n]].orientation] #
	 cards[board[n - 3]].colour[(cards[board[n - 3]].orientation + 2)
	 MOD 4])
	 OR (cards[board[n]].top[cards[board[n]].orientation] =
	 cards[board[n - 3]].top[(cards[board[n - 3]].orientation + 2) MOD 4]))
	 THEN
	    RETURN FALSE
      END;
      (* And here we will find a card to the left *)
      IF (n MOD 3 # 0) &
	 ((cards[board[n]].colour[(3 + cards[board[n]].orientation) MOD 4] #
	 cards[board[n - 1]].colour[(cards[board[n - 1]].orientation + 1)
	 MOD 4])
	 OR (cards[board[n]].top[(3 + cards[board[n]].orientation) MOD 4] =
	 cards[board[n - 1]].top[(cards[board[n - 1]].orientation + 1) MOD 4]))
	 THEN
	    RETURN FALSE
      END;
      RETURN TRUE;
   END Valid;

   PROCEDURE PlaceCard(n: INTEGER); (* n Cards to be placed *)
      VAR i, j: INTEGER;
   BEGIN
      IF ~Valid(8 - n) THEN RETURN END; (* Check situation *)
      IF n = 0 THEN PrintBoard(); Write.Ln; RETURN END; (* I am done *)
      i := 0;
      WHILE i < 9 DO (* Try to place all nice cards *)
	 IF cards[i].position = -1 THEN (* Card not used *)
	    j := 0;
	    WHILE j < 4 DO (* Test the four orientations *)
	       cards[i].position := 9 - n;
	       cards[i].orientation := j;
	       board[9 - n] := i;
	       PlaceCard(n - 1); (* Recursion *)
	       INC(j);
	    END;
	    cards[i].position := -1; (* Remove Card again *)
	    board[9 - n] := -1;
	 END;
	 INC(i);
      END;
   END PlaceCard;

   PROCEDURE InitCards(): BOOLEAN; (* Read card information *)
      VAR s: Streams.Stream;
	 line: ARRAY 80 OF CHAR;
	 char: CHAR;
	 ok: BOOLEAN;
	 i, j: INTEGER;
   BEGIN
      IF ~UnixFiles.Open(s, filename, UnixFiles.read, Streams.onebuf, NIL) THEN
	 RETURN FALSE
      END;
      ok := TRUE;
      i := 0;
      WHILE i < 9 DO (* Read the nine cards *)
	 j := 0;
	 WHILE j < 4 DO (* read the players' colours *)
	    Read.IntS(s, cards[i].colour[j]);
	    ok := ok & (s.count = 1);
	    Read.CharS(s, char);
	    ok := ok & (char = ",");
	    INC(j);
	 END;
	 j := 0;
	 WHILE j < 4 DO (* legs or no legs ... *)
	    Read.IntS(s, cards[i].top[j]);
	    ok := ok & (s.count = 1);
	    IF j < 3 THEN
	       Read.CharS(s, char);
	       ok := ok & (char = ",");
	    END;
	    INC(j);
	 END;
	 cards[i].orientation := 0;
	 cards[i].position := -1; (* cards are not placed on the board *)
	 INC(i);
	 Read.LnS(s);
      END;
      Streams.Release(s);
      RETURN ok;
   END InitCards;

BEGIN
   IF ~InitCards() THEN Write.String("Could not read file"); Write.Ln; END;
   PlaceCard(9);
END Soccer.

And the cards....

0,1,0,2,0,0,1,1
2,0,1,3,0,0,1,1
2,0,3,0,0,1,1,0
2,1,2,3,0,1,1,0
3,0,2,1,0,0,1,1
3,1,2,0,0,0,1,1
2,0,3,1,0,1,1,0
2,3,0,1,0,0,1,1
2,1,0,3,0,0,1,1

Universität Fakultät SAI

Ingo Melzer, 20. Mai 1999