unit raetselunit; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Forms, Spin, Controls, StdCtrls, ExtCtrls; type tAlphabetFunktion = function(i: longint): string; tRaetsel = class private besitzer: tForm; zeichenflaeche: tImage; function besitzerHoehe: longint; dynamic; function besitzerBreite: longint; dynamic; procedure zeichenFlaecheNeuKreieren; public constructor create(aOwner: tForm); destructor destroy; override; procedure zeichnen; dynamic; abstract; end; tFelderRaetsel = class(tRaetsel) spinEdits: array of tSpinEdit; diagonalenCB: tCheckBox; groeszen: array of longint; felder,rand: array of longint; dim,schriftGroesze: longint; zellGroesze: extended; uebersetze: tAlphabetFunktion; procedure anzSEsOnChange(sender: tObject); procedure aktualisiereGroesze; procedure aktualisiereZeichenflaechenGroesze; function besitzerHoehe: longint; override; function besitzerBreite: longint; override; procedure schreibeZentriert(x,y,i: longint); public constructor create(aOwner: tForm; anzInhTypen: longint; alphabetFunktion: tAlphabetFunktion); destructor destroy; override; procedure zeichnen; override; end; tBuchstabenRaetsel = class(tFelderRaetsel) private public constructor create(aOwner: tForm); destructor destroy; override; end; tHochhausRaetsel = class(tFelderRaetsel) private public constructor create(aOwner: tForm); destructor destroy; override; end; const spacing = 2; function buchstabenAlphabetFunktion(i: longint): string; function zahlenAlphabetFunktion(i: longint): string; implementation uses math; // tRaetsel ******************************************************************** constructor tRaetsel.create(aOwner: tForm); begin inherited create; besitzer:=aOwner; zeichenflaeche:=tImage.create(besitzer); zeichenflaeche.parent:=besitzer; end; destructor tRaetsel.destroy; begin zeichenflaeche.free; inherited destroy; end; function tRaetsel.besitzerHoehe: longint; begin result:=zeichenflaeche.height+zeichenflaeche.top+spacing; end; function tRaetsel.besitzerBreite: longint; begin result:=zeichenflaeche.width+zeichenflaeche.left+spacing; end; procedure tRaetsel.zeichenFlaecheNeuKreieren; var i: tImage; begin i:=tImage.create(besitzer); i.parent:=zeichenflaeche.parent; i.left:=zeichenflaeche.left; i.top:=zeichenflaeche.top; i.width:=zeichenflaeche.width; i.height:=zeichenflaeche.height; i.canvas.font.size:=zeichenflaeche.canvas.font.size; zeichenflaeche.free; zeichenflaeche:=i; end; // tFelderRaetsel ************************************************************** constructor tFelderRaetsel.create(aOwner: tForm; anzInhTypen: longint; alphabetFunktion: tAlphabetFunktion); var i: longint; begin inherited create(aOwner); uebersetze:=alphabetFunktion; setlength(spinEdits,anzInhTypen+1); setlength(groeszen,length(spinEdits)-1); for i:=0 to length(spinEdits)-1 do begin spinEdits[i]:=tSpinEdit.create(besitzer); with spinEdits[i] do begin parent:=besitzer; top:=spacing; if i>0 then left:=spinEdits[i-1].left + spinEdits[i-1].width; left:=left+spacing; onChange:=@anzSEsOnChange; tag:=i; end; if i>0 then groeszen[i-1]:=-1; end; spinEdits[0].showHint:=true; spinEdits[0].hint:='Schriftgröße'; spinEdits[0].value:=7; diagonalenCB:=tCheckBox.create(besitzer); diagonalenCB.parent:=besitzer; diagonalenCB.caption:='Diagonalen'; diagonalenCB.top:=spacing; diagonalenCB.left:=spinEdits[length(spinEdits)-1].left+spinEdits[length(spinEdits)-1].width+spacing; zeichenflaeche.left:=spacing; zeichenflaeche.top:=diagonalenCB.top+diagonalenCB.height+spacing; aktualisiereGroesze; end; destructor tFelderRaetsel.destroy; begin inherited destroy; end; procedure tFelderRaetsel.anzSEsOnChange(sender: tObject); begin if ((sender as tSpinEdit).tag = 0) and ((sender as tSpinEdit).value <> schriftGroesze) then begin schriftGroesze:=(sender as tSpinEdit).value; aktualisiereZeichenflaechenGroesze end else if (sender as tSpinEdit).value <> groeszen[(sender as tSpinEdit).tag-1] then aktualisiereGroesze; end; procedure tFelderRaetsel.aktualisiereGroesze; var i: longint; begin dim:=0; schriftGroesze:=spinEdits[0].value; for i:=0 to length(groeszen)-1 do begin groeszen[i]:=spinEdits[i+1].value; dim:=dim+groeszen[i]; end; setlength(felder,dim*dim); for i:=0 to length(felder)-1 do felder[i]:=random(dim+1)-1; // 0; setlength(rand,4*dim); for i:=0 to length(rand)-1 do rand[i]:=random(dim+1)-1; // 0; aktualisiereZeichenflaechenGroesze; end; procedure tFelderRaetsel.aktualisiereZeichenflaechenGroesze; begin zeichenflaeche.canvas.font.size:=schriftGroesze; zellGroesze:= 2*spacing + zeichenflaeche.canvas.pen.width + max( zeichenflaeche.canvas.textWidth(uebersetze(dim)), zeichenflaeche.canvas.textHeight(uebersetze(dim)) ); zeichenflaeche.height:=(dim+2)*round(2*zellGroesze); zeichenflaeche.width:=zeichenflaeche.height; zeichenFlaecheNeuKreieren; besitzer.height:=besitzerHoehe; besitzer.width:=besitzerBreite; zeichnen; end; function tFelderRaetsel.besitzerHoehe: longint; var i: longint; begin result:=max(inherited besitzerHoehe,diagonalenCB.top+diagonalenCB.height+spacing); for i:=0 to length(spinEdits)-1 do result:=max(result,spinEdits[i].top+spinEdits[i].height+spacing); end; function tFelderRaetsel.besitzerBreite: longint; var i: longint; begin result:=max(inherited besitzerBreite,diagonalenCB.left+diagonalenCB.width+spacing);; for i:=0 to length(spinEdits)-1 do result:=max(result,spinEdits[i].left+spinEdits[i].width+spacing); end; procedure tFelderRaetsel.schreibeZentriert(x,y,i: longint); var br,ho: longint; s: string; begin s:=uebersetze(i); with zeichenflaeche.canvas do begin br:=textWidth(s); ho:=textHeight(s); textOut( round(2*(x+1.5)*zellGroesze-br/2), round(2*(y+1.5)*zellGroesze-ho/2), s ); end; end; procedure tFelderRaetsel.zeichnen; var i: longint; begin zeichenflaeche.canvas.brush.color:=$ffffff; zeichenflaeche.canvas.rectangle(-10,-10,zeichenflaeche.width+10,zeichenflaeche.height+10); zeichenflaeche.canvas.pen.width:=3; for i:=0 to dim do with zeichenflaeche.canvas do begin moveTo(round((i+1)*2*zellGroesze),round(2*zellGroesze)); lineTo(round((i+1)*2*zellGroesze),round((dim+1)*2*zellGroesze)); moveTo(round(2*zellGroesze),round((i+1)*2*zellGroesze)); lineTo(round((dim+1)*2*zellGroesze),round((i+1)*2*zellGroesze)); end; for i:=0 to dim-1 do begin schreibeZentriert(i,-1,rand[i]); schreibeZentriert(dim,i,rand[dim+i]); schreibeZentriert(i,dim,rand[2*dim+i]); schreibeZentriert(-1,i,rand[3*dim+i]); end; for i:=0 to length(felder)-1 do schreibeZentriert(i mod dim,i div dim,felder[i]); end; // tBuchstabenRaetsel ********************************************************** constructor tBuchstabenRaetsel.create(aOwner: tForm); begin inherited create(aOwner,2,@buchstabenAlphabetFunktion); spinEdits[1].showHint:=true; spinEdits[1].hint:='Anzahl Buchstaben'; spinEdits[1].value:=5; spinEdits[2].showHint:=true; spinEdits[2].hint:='Anzahl Leerfelder'; spinEdits[2].value:=1; aktualisiereGroesze; end; destructor tBuchstabenRaetsel.destroy; begin inherited destroy; end; // tHochhausRaetsel ************************************************************ constructor tHochhausRaetsel.create(aOwner: tForm); begin inherited create(aOwner,1,@zahlenAlphabetFunktion); spinEdits[1].showHint:=true; spinEdits[1].hint:='Anzahl Spalten'; spinEdits[1].value:=5; aktualisiereGroesze; end; destructor tHochhausRaetsel.destroy; begin inherited destroy; end; // allgemeine Funktionen ******************************************************* function buchstabenAlphabetFunktion(i: longint): string; begin if i<0 then result:='' else if i=0 then result:='-' else begin result:=''; while i>0 do begin dec(i); result:=char(ord('A')+(i mod 26))+result; i:=i div 26; end; end; end; function zahlenAlphabetFunktion(i: longint): string; begin if i<0 then result:='' else if i=0 then result:='-' else result:=inttostr(i); end; end.