290 lines
7.5 KiB
Plaintext
290 lines
7.5 KiB
Plaintext
program Towers_of_Hanoi;
|
|
|
|
uses Crt, Graph, INIFile, BGIP;
|
|
|
|
const { Hmax=5; }
|
|
Gray50: FillPatternType=($AA, $55, $AA, $55, $AA, $55, $AA, $55);
|
|
Sound_ON=false;
|
|
|
|
var xmax, ymax, xmed, ymed: word;
|
|
Code: integer;
|
|
Hanoi: array[1..3,1..100] of byte;
|
|
Item_X: array[1..100] of word;
|
|
Board_Up, Board_Down: word;
|
|
Tower_Y: word;
|
|
Input: char;
|
|
Mv_From, Mv_To: byte;
|
|
Step: longint;
|
|
tmp1,tmp2: string;
|
|
T_Center: array[1..3] of word;
|
|
Hmax: byte;
|
|
Board_X,Board_Middle,Board_Y: word;
|
|
Board_Color: byte;
|
|
Tower_X: word;
|
|
Tower_Color: byte;
|
|
Item_MaxX, Item_MinX, Item_Y: word;
|
|
Item_Color, Text_Color: byte;
|
|
|
|
function V2S(x: longint): string;
|
|
var tmp: string;
|
|
begin
|
|
Str(x:0,tmp);
|
|
V2S := tmp;
|
|
end;
|
|
|
|
function S2V(x: string): integer;
|
|
var tmp,code: integer;
|
|
begin
|
|
Val(x,tmp,code);
|
|
if (code<>0) then begin
|
|
WriteLn('Error while VAL ''',x,''': ',code);
|
|
Halt;
|
|
end else S2V:=tmp;
|
|
end;
|
|
|
|
procedure Init;
|
|
var grDriver, grMode: integer;
|
|
i,j: byte;
|
|
begin
|
|
INIFileDebug := false;
|
|
OpenINI('D:\LANG\src\bp\itg\hanoi.ini');
|
|
Hmax := S2V(INIGet('Hanoi_Main','Items'));
|
|
Board_X := S2V(INIGet('Hanoi_Board','Board_X'));
|
|
Board_Middle := S2V(INIGet('Hanoi_Board','Board_Middle'));
|
|
Board_Y := S2V(INIGet('Hanoi_Board','Board_Y'));
|
|
Board_Color := S2V(INIGet('Hanoi_Board','Board_Color'));
|
|
Tower_X := S2V(INIGet('Hanoi_Poles','Tower_X'));
|
|
Tower_Color := S2V(INIGet('Hanoi_Poles','Tower_Color'));
|
|
Item_MaxX := S2V(INIGet('Hanoi_Coins','Item_MaxX'));
|
|
Item_MinX := S2V(INIGet('Hanoi_Coins','Item_MinX'));
|
|
Item_Y := S2V(INIGet('Hanoi_Coins','Item_Y'));
|
|
Item_Color := S2V(INIGet('Hanoi_Coins','Item_Color'));
|
|
Text_Color := S2V(INIGet('Hanoi_Texts','Text_Color'));
|
|
CloseINI;
|
|
grDriver := VGA;
|
|
grMode := VGAHi;
|
|
InitGraph(grDriver, grMode, BGIPath);
|
|
xmax := GetMaxX+1; { Bildschirmbreite in Pixeln }
|
|
ymax := GetMaxY+1; { Bildschirmh”he in Pixeln }
|
|
xmed := xmax DIV 2;
|
|
ymed := ymax DIV 2;
|
|
T_Center[1] := xmed-(Board_X DIV 4);
|
|
T_Center[2] := xmed;
|
|
T_Center[3] := xmed+(Board_X DIV 4);
|
|
Board_Up := Board_Middle-(Board_Y DIV 2);
|
|
Board_Down := Board_Middle+(Board_Y DIV 2);
|
|
Tower_Y := (Hmax+1)*Item_Y;
|
|
Step := 0;
|
|
for i:=1 to 3 do begin
|
|
for j:=1 to Hmax do begin
|
|
Hanoi[i,j] := 0;
|
|
Hanoi[1,j] := Hmax-j+1;
|
|
Item_X[Hmax-j+1] := Trunc(((Hmax-j)/(Hmax-1))*(Item_MaxX-Item_MinX))+Item_MinX;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure DrawBoard;
|
|
var i,j: byte;
|
|
begin
|
|
ClearDevice;
|
|
for i:=1 to 3 do begin
|
|
SetColor(Tower_Color);
|
|
SetFillPattern(Gray50,Tower_Color);
|
|
Rectangle(T_Center[i]-(Tower_X DIV 2),Board_Up-Tower_Y,T_Center[i]+(Tower_X DIV 2),Board_Up);
|
|
FloodFill(T_Center[i],Board_Middle-(Board_Y DIV 2)-(Tower_Y DIV 2),Tower_Color);
|
|
SetColor(Text_Color);
|
|
SetTextJustify(CenterText, CenterText);
|
|
OutTextXY(T_Center[i],Board_Down+10,V2S(i));
|
|
SetTextJustify(LeftText, TopText);
|
|
end;
|
|
SetColor(Board_Color);
|
|
Rectangle(xmed-(Board_X DIV 2),Board_Up,xmed+(Board_X DIV 2),Board_Down);
|
|
SetFillPattern(Gray50,Board_Color);
|
|
FloodFill(xmed,Board_Middle,Board_Color);
|
|
|
|
for i:=1 to 3 do begin
|
|
for j:=1 to Hmax do begin
|
|
if Hanoi[i,j]<>0 then begin
|
|
SetColor(Item_Color);
|
|
SetFillPattern(Gray50,Item_Color);
|
|
Rectangle(T_Center[i]-(Item_X[Hanoi[i,j]] DIV 2),Board_Up-(Item_Y*(j-1)),T_Center[i]+(Item_X[Hanoi[i,j]] DIV 2),
|
|
Board_Up-(Item_Y*j));
|
|
FloodFill(T_Center[i],Board_Up-(Item_Y*j)+(Item_Y DIV 2),Item_Color);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
function WhatsLast(Tower: byte): byte;
|
|
var i: integer;
|
|
tmp: byte;
|
|
begin
|
|
tmp := 0;
|
|
for i:=Hmax downto 1 do begin
|
|
if Hanoi[Tower,i]<>0 then begin
|
|
tmp := Hanoi[Tower,i];
|
|
Break;
|
|
end;
|
|
end;
|
|
if (tmp=0) then tmp:=255;
|
|
SetTextJustify(CenterText, CenterText);
|
|
OutTextXY(T_Center[Tower],Board_Down+20,V2S(tmp));
|
|
SetTextJustify(LeftText, TopText);
|
|
WhatsLast := tmp;
|
|
end;
|
|
|
|
function TakeLast(Tower: byte): byte;
|
|
var i: integer;
|
|
tmp: byte;
|
|
begin
|
|
for i:=Hmax downto 1 do begin
|
|
if Hanoi[Tower,i]<>0 then begin
|
|
tmp := Hanoi[Tower,i];
|
|
Hanoi[Tower,i] := 0;
|
|
Break;
|
|
end;
|
|
end;
|
|
TakeLast := tmp;
|
|
end;
|
|
|
|
procedure PutOnto(Which,Tower: byte);
|
|
var i: integer;
|
|
begin
|
|
for i:=1 to Hmax do begin
|
|
if Hanoi[Tower,i]=0 then begin
|
|
Hanoi[Tower,i]:=which;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure MoveFromTo(Mv_From, Mv_To: byte);
|
|
var temp: byte;
|
|
begin
|
|
if (WhatsLast(Mv_To)>WhatsLast(Mv_From)) then begin
|
|
PutOnto(TakeLast(Mv_From),Mv_To);
|
|
Inc(Step);
|
|
if (Sound_ON) then begin
|
|
Sound(1200);
|
|
Delay(75);
|
|
NoSound;
|
|
end;
|
|
end else begin
|
|
if (Sound_ON) then begin
|
|
Sound(800);
|
|
Delay(150);
|
|
NoSound;
|
|
end;
|
|
SetTextJustify(CenterText,CenterText);
|
|
SetColor(LightRed);
|
|
OutTextXY(xmed,40,'Can''t move Item on Tower '+V2S(Mv_From)+' to Tower '+V2S(Mv_To)+'.');
|
|
Delay(1000);
|
|
end;
|
|
end;
|
|
|
|
function All(what: byte): word;
|
|
var tmp: word;
|
|
begin
|
|
if what=1 then All:=1 else All:=what+All(what-1);
|
|
end;
|
|
|
|
function CheckWon: boolean;
|
|
var i,j: byte;
|
|
sum: word;
|
|
tmp: boolean;
|
|
begin
|
|
for i:=2 to 3 do begin
|
|
if (WhatsLast(i)=1) then begin
|
|
sum := 0;
|
|
for j:=1 to Hmax do begin
|
|
sum := sum + Hanoi[i,j];
|
|
end;
|
|
if (sum=All(Hmax)) then begin
|
|
tmp:=true;
|
|
Break;
|
|
end;
|
|
end else tmp:=false;
|
|
end;
|
|
CheckWon := tmp;
|
|
end;
|
|
|
|
procedure Outit;
|
|
var i: byte;
|
|
begin
|
|
TextMode(CO80);
|
|
WriteLn('VMode : ',xmax,'x',ymax);
|
|
WriteLn('Center: ',xmed,'x',ymed);
|
|
for i:=1 to Hmax do begin
|
|
WriteLn('Tower_X ',i,': ',Item_X[i]);
|
|
end;
|
|
WriteLn('Steps needed: ',Step:0);
|
|
WriteLn;
|
|
if (CheckWon) then WriteLn('Programm siegreich beendet.') else WriteLn('Programm grundlos beendet.');
|
|
end;
|
|
|
|
begin
|
|
Init;
|
|
repeat
|
|
DrawBoard;
|
|
if (CheckWon) then begin
|
|
if (Sound_ON) then begin
|
|
Sound(1000);
|
|
Delay(100);
|
|
NoSound;
|
|
Delay(200);
|
|
Sound(1000);
|
|
Delay(50);
|
|
NoSound;
|
|
Delay(100);
|
|
Sound(1000);
|
|
Delay(50);
|
|
NoSound;
|
|
Delay(100);
|
|
Sound(1400);
|
|
Delay(750);
|
|
NoSound;
|
|
end;
|
|
Break;
|
|
end;
|
|
SetColor(LightGreen);
|
|
SetTextJustify(CenterText,BottomText);
|
|
OutTextXY(xmed,ymax,'Press X to exit');
|
|
SetTextJustify(LeftText,TopText);
|
|
SetColor(Text_Color);
|
|
Str(Step:3,tmp1);
|
|
OutTextXY(550,10,'Step: '+tmp1);
|
|
tmp1 := 'Move Item from Tower ';
|
|
OutTextXY(10,10,'Press 1, 2 or 3 to select a tower.');
|
|
OutTextXY(10,20,tmp1);
|
|
Input := ReadKey;
|
|
if (Input='1') OR (Input='2') OR (Input='3') then begin
|
|
Val(Input,Mv_From,Code);
|
|
Str(Mv_From:0,tmp2);
|
|
tmp1 := tmp1 + tmp2 + ' to Tower ';
|
|
OutTextXY(10,20,tmp1);
|
|
Input := ReadKey;
|
|
if (Input='1') OR (Input='2') OR (Input='3') then begin
|
|
Val(Input,Mv_To,Code);
|
|
Str(Mv_To:0,tmp2);
|
|
tmp1 := tmp1 + tmp2 + ' ...';
|
|
OutTextXY(10,20,tmp1);
|
|
MoveFromTo(Mv_From,Mv_To);
|
|
end else if (Input<>'x') AND (Input<>'X') then begin
|
|
if (Sound_ON) then begin
|
|
Sound(800);
|
|
Delay(150);
|
|
NoSound;
|
|
end;
|
|
end else Break;
|
|
end else if (Input<>'x') AND (Input<>'X') then begin
|
|
if (Sound_ON) then begin
|
|
Sound(800);
|
|
Delay(150);
|
|
NoSound;
|
|
end;
|
|
end;
|
|
until (Input='x') OR (Input='X');
|
|
Outit;
|
|
end. |