home *** CD-ROM | disk | FTP | other *** search
- {************************************************}
- { }
- { Turbo Pascal 6.0 }
- { Turbo Vision Demo }
- { Copyright (c) 1990 by Borland International }
- { }
- {************************************************}
-
- unit Puzzle;
-
- {$F+,O+,S-,D-}
-
- { Simple puzzle object. See TVDEMO.PAS for an example
- program that uses this unit.
- }
-
-
- interface
-
- uses views, Drivers, Objects, Crt;
-
- const
- CPuzzleView = #6#7;
-
- type
-
- TBoard = array[0..5,0..5] of Char;
- PPuzzleView = ^TPuzzleView;
- TPuzzleView = object(TView)
- Board: TBoard;
- Moves: Word;
- Solved: Boolean;
- constructor Init(Bounds: TRect);
- constructor Load(var S: TStream);
- procedure HandleEvent(var Event: TEvent); Virtual;
- procedure Draw; Virtual;
- function GetPalette: PPalette; virtual;
- procedure MoveKey(Key: Word);
- procedure MoveTile(Point: TPoint);
- procedure Scramble;
- procedure Store(var S: TStream);
- procedure WinCheck;
- end;
-
- PPuzzleWindow = ^TPuzzleWindow;
- TPuzzleWindow = object(TWindow)
- constructor Init;
- end;
-
- const
- RPuzzleView: TStreamRec = (
- ObjType: 10010;
- VmtLink: Ofs(TypeOf(TPuzzleView)^);
- Load: @TPuzzleView.Load;
- Store: @TPuzzleView.Store
- );
- RPuzzleWindow: TStreamRec = (
- ObjType: 10011;
- VmtLink: Ofs(TypeOf(TPuzzleWindow)^);
- Load: @TPuzzleWindow.Load;
- Store: @TPuzzleWindow.Store
- );
-
- procedure RegisterPuzzle;
-
- implementation
-
- { TPuzzleWindow }
-
- constructor TPuzzleWindow.Init;
- var
- R: TRect;
- begin
- R.Assign(1, 1, 21, 7);
- TWindow.Init(R, 'Puzzle', 0);
- Flags := Flags and not (wfZoom + wfGrow);
- GrowMode := 0;
- GetExtent(R);
- R.Grow(-1, -1);
- Insert(New(PPuzzleView, Init(R)));
- end;
-
- { TPuzzleView }
-
- constructor TPuzzleView.Init(Bounds: TRect);
- type
- TBoardValue = array[1..16] of Char;
- const
- SBoardValue: TBoardValue =
- ('A','B','C','D',
- 'E','F','G','H',
- 'I','J','K','L',
- 'M','N','O',' ');
- var
- I, J: Integer;
- begin
- TView.Init(Bounds);
- Randomize;
- Options := Options or ofSelectable;
- FillChar(Board, SizeOf(Board), '?');
- for I := 0 to 3 do
- for J := 0 to 3 do
- Board[I+1, J+1] := SBoardValue[I*4 + J+1];
- Scramble;
- end;
-
- constructor TPuzzleView.Load(var S: TStream);
- begin
- TView.Load(S);
- S.Read(Board, SizeOf(Board) + Sizeof(Moves) + SizeOf(Solved));
- end;
-
- Procedure TPuzzleView.Draw;
- var
- I, J, K: Integer;
- B: array[0..17] of word;
- S1: String[3];
- Color: array[0..1] of byte;
- ColorBack: Byte;
- const
- Map: array['A'..'O'] of Byte =
- (0, 1, 0, 1,
- 1, 0, 1, 0,
- 0, 1, 0, 1,
- 1, 0, 1);
- begin
- Color[0] := GetColor(1);
- Color[1] := GetColor(2);
- ColorBack := GetColor(1);
- if Solved then Color[1] := Color[0]
- else Color[1] := GetColor(2);
- for I := 1 to 4 do
- begin
- MoveChar(B, ' ', ColorBack, 18);
- if I = 2 then MoveStr(B[13], 'Move', ColorBack);
- if I = 3 Then
- begin
- Str(Moves: 3, S1);
- MoveStr(B[14], S1, ColorBack);
- end;
- for J := 1 to 4 do
- begin
- S1 := ' ' + Board[I, J] + ' ';
- K := (Byte(Board[I, J]) mod 2) +1;
- if Board[I, J] = ' ' then MoveStr(B[(J - 1) * 3], S1, Color[0])
- else
- MoveStr(B[(J - 1) * 3], S1, Color[Map[Board[I, J]]]);
- end;
- WriteLine(0, I - 1, 18, 1, B);
- end;
- end;
-
- function TPuzzleView.GetPalette: PPalette;
- const
- P: String[Length(CPuzzleView)] = CPuzzleView;
- begin
- GetPalette := @P;
- end;
-
- procedure TPuzzleView.HandleEvent(var Event: TEvent);
- begin
- TView.HandleEvent(Event);
- if Solved and (Event.What and (evKeyDown + evMouseDown) <> 0) then
- begin
- Scramble;
- ClearEvent(Event);
- end;
- case Event.What of
- evMouseDown: MoveTile(Event.Where);
- evKeyDown: MoveKey(Event.KeyCode);
- else
- Exit;
- end;
- ClearEvent(Event);
- WinCheck;
- end;
-
- procedure TPuzzleView.MoveKey(Key: Word);
- var
- X, Y, I, J: Integer;
- begin
- for I:=1 To 4 do
- for J:=1 To 4 do
- if Board[i,j] = ' ' then
- begin
- Y:=I;
- X:=J;
- end;
-
- case Key of
- kbDown:
- if Y > 1 then
- begin
- Board[Y, X] := Board[Y-1, X];
- Board[Y-1, X] := ' ';
- Inc(moves, Byte(moves<1000));
- end;
- kbUp:
- if Y < 4 then
- begin
- Board[Y, X] := Board[Y+1, X];
- Board[Y+1, X] := ' ';
- Inc(moves, Byte(moves<1000));
- end;
- kbRight:
- if X > 1 then
- begin
- Board[Y, X] := Board[Y, X-1];
- Board[Y, X-1] := ' ';
- Inc(moves, Byte(moves<1000));
- end;
- kbLeft:
- if X < 4 then
- begin
- Board[Y, X] := Board[Y, X+1];
- Board[Y, X+1] := ' ';
- Inc(moves,Byte(moves<1000));
- end;
- end;
- DrawView;
- end;
-
- procedure TPuzzleView.MoveTile(Point: TPoint);
- var
- P: TPoint;
- X, Y: Word;
- begin
- MakeLocal(Point, P);
- X := ((P.X + 3) div 3);
- Y := P.Y + 1;
- if (X > 0) and (X < 5) and (Y > 0) and (Y < 5) Then
- begin
- if Board[Y, X-1] = ' ' then
- begin
- Board[Y, X-1] := Board[Y, X];
- Board[Y, X] := ' ';
- Inc(moves, Byte(moves<1000));
- end;
- if Board[Y-1, X] = ' ' then
- begin
- Board[Y-1, X] := Board[Y, X];
- Board[Y, X] := ' ';
- Inc(moves, Byte(moves<1000));
- end;
- if Board[Y, X+1] = ' ' then
- begin
- Board[Y, X+1] := Board[Y, X];
- Board[Y, X] := ' ';
- Inc(moves, Byte(moves<1000));
- end;
- if Board[Y+1, X] = ' ' then
- begin
- Board[Y+1, X] := Board[Y, X];
- Board[Y, X] := ' ';
- Inc(moves, Byte(moves<1000));
- end;
- DrawView;
- end;
- end;
-
- procedure TPuzzleView.Scramble;
- begin
- Moves := 0;
- Solved := False;
- repeat
- case Random(4) of
- 0: MoveKey(kbUp);
- 1: MoveKey(kbDown);
- 2: MoveKey(kbRight);
- 3: MoveKey(kbLeft);
- end;
- until Moves=500;
- Moves := 0;
- DrawView;
- end;
-
- procedure TPuzzleView.Store(var S: TStream);
- begin
- TView.Store(S);
- S.Write(Board, SizeOf(Board) + Sizeof(Moves) + SizeOf(Solved));
- end;
-
- procedure TPuzzleView.WinCheck;
- type
- BoardStr = array [0..35] of Char;
- const
- FBoard: BoardStr = '???????ABCD??EFGH??IJKL??MNO ???????';
- var
- I: Integer;
- begin
- Solved := BoardStr(Board) = FBoard;
- DrawView;
- end;
-
- procedure RegisterPuzzle;
- begin
- RegisterType(RPuzzleView);
- RegisterType(RPuzzleWindow);
- end;
-
- end.
-