/* 01 */ {--------------------------------------------------------------------- /* 02 */ { /* 03 */ Unit Name: AmpariForm /* 04 */ Purpose : Nesteen kaataminen ämäristä toiseen /* 05 */ Author : Vesa Lappalainen /* 06 */ Date : 6.12.2000 /* 07 */ Changed : /* 08 */ /* 09 */ Pelillä demonstroidaan/harjoitellaan miten voidaan kahdella astiall /* 10 */ 5 l ja 8 l, muodostaa kaikki mahdolliset tilavuudet 1-13 l. /* 11 */ Pelissä on kaksi varsinaista astiaa: a5 ja a8, sekä kolmas apuastia /* 12 */ a0. Nestettä voidaan kerrallaan kaataa yhdestä astiasta toiseen /* 13 */ joko siten, että astian koko sisältö tyhjennetään jos se mahtuu /* 14 */ tai astista kaadetaan sen verran että toinen astia tulee täyteen. /* 15 */ /* 16 */ Ensin klikataan sitä astiaa, josta kaadetaan ja sitten sitä /* 17 */ astiaa, johon kaadetaan. /* 18 */ /* 19 */ Peli kirjoittaa "siirroista" logia teksti-ikkunaan MemoOhjeet. /* 20 */ Esim. 3 litraa saadaan "ohjeikkunan syntaksin" mukaisesti kuvattuna /* 21 */ a0 -> a8: 0.0 8.0 /* 22 */ a8 -> a5: 5.0 3.0 /* 23 */ Eli kaadetaan a0 astiasta (tyhjään) a8 astiaan niin että a8 tulee /* 24 */ täyteen. Tällöin astioissa a5 ja a8 on 0 ja 8 l nestettä. /* 25 */ Sitten kaadetaan a8 astiasta a5 astia täyteen, jolloin a8 astiaan /* 26 */ jää kaivattu 3 l nestettä. /* 27 */ /* 28 */ Pelissä on myös nappulat, joissa on tekstit 1,2,3...,12,13. /* 29 */ Aina kun jokin nestemäärä on joko astiassa a5 tai a8 tai /* 30 */ nestemäärä on yhteensä astioissa a5 ja a8, saa vastaavan nappulan /* 31 */ "klikata" pois. Edellisessä esimerkissä saisi painaa nappuloita /* 32 */ 3, 5 ja 8 (kaikki em. nestemäärät on saatavissa /* 33 */ /* 34 */ Tehtäviä: /* 35 */ 0) Kommentoi tarkasti metodit AstiaClick, ButtonClick ja /* 36 */ FormCreate /* 37 */ 1) Lisää peliin loppumisen tarkistus, eli kun kaikki nappulat /* 38 */ on merkitty (enabled := false), niin tulee ilmoitus pelin /* 39 */ loppumisesta ja siirtojen määrästä ( MemoOhjeet.Lines.Count). /* 40 */ 2) Lisää peliin käyttäytyminen, jossa kaikki oikeatkin nappulat /* 41 */ muuttuvat takaisin aktiivisiksi jos kerrankin painetaan /* 42 */ väärää nappulaa. Esim. jos astioiden tilavuudet ovat 3 ja 5 /* 43 */ ja painetaan nappulaa 4, niin kaille nappuloille tulee /* 44 */ Enabled := True. /* 45 */ 3) Nyt nappulat on sijoitettu formin luonnissa kaikki rinnakkain. /* 46 */ Mitä koodista pitäisi muuttaa ja miten, jos nappulat olisikin /* 47 */ sijoitettu paikalleen jo suunnitteluaikana "raahaamalla"? /* 48 */ 4) Kuinka montaa riviä pelissä pitäisi nyt muuttaa, jotta /* 49 */ voitaisiin "leikkiä" astoilla 2l ja 3l? /* 50 */ 5) Muuta peli automaattiseksi siten, ettei nappuloita tarvitse /* 51 */ itse käydä painelemassa, vaan nappulat tarkistetaan /* 52 */ "automaattisesti" kunkin siirron jälkeen. /* 53 */ /* 54 */ } /* 55 */ {--------------------------------------------------------------------- /* 56 */ /* 57 */ unit AmpariForm; /* 58 */ /* 59 */ interface /* 60 */ /* 61 */ uses /* 62 */ Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dia /* 63 */ astia, ExtCtrls, StdCtrls; /* 64 */ /* 65 */ type /* 66 */ TFormAmpari = class(TForm) /* 67 */ PanelButtons: TPanel; /* 68 */ MemoOhjeet: TMemo; /* 69 */ LabelA5: TLabel; /* 70 */ LabelA8: TLabel; /* 71 */ LabelA0: TLabel; /* 72 */ procedure FormCreate(Sender: TObject); /* 73 */ private /* 74 */ { Private declarations } /* 75 */ a5 : TAstia; /* 76 */ a8 : TAstia; /* 77 */ a0 : TAstia; /* 78 */ MistaOtetaan : TAstia; /* 79 */ btns : array of TButton; /* 80 */ procedure AstiaClick(Sender: TObject); /* 81 */ procedure ButtonClick(Sender: TObject); /* 82 */ procedure AstiaEvent(sender:TAstia; const viesti:string); /* 83 */ function GetAineetAsString: string; /* 84 */ public /* 85 */ property AineetAsString : string read GetAineetAsString; /* 86 */ end; /* 87 */ /* 88 */ var /* 89 */ FormAmpari: TFormAmpari; /* 90 */ /* 91 */ implementation /* 92 */ /* 93 */ {$R *.DFM} /* 94 */ /* 95 */ procedure TFormAmpari.AstiaClick(Sender: TObject); /* 96 */ var KlikattuAstia : TAstia; /* 97 */ begin /* 98 */ if not ( Sender is TAstia ) then exit; /* 99 */ KlikattuAstia := TAstia(sender); /* 100 */ if ( MistaOtetaan = nil ) then begin /* 101 */ MistaOtetaan := KlikattuAstia; /* 102 */ exit; /* 103 */ end; /* 104 */ /* 105 */ KlikattuAstia.Kaada(MistaOtetaan); /* 106 */ MistaOtetaan := nil; /* 107 */ end; /* 108 */ /* 109 */ /* 110 */ procedure TFormAmpari.AstiaEvent(sender: TAstia; const viesti: string) /* 111 */ begin /* 112 */ MemoOhjeet.Lines.Add(viesti + ': ' + AineetAsString); /* 113 */ end; /* 114 */ /* 115 */ procedure TFormAmpari.ButtonClick(Sender: TObject); /* 116 */ var b : TButton; /* 117 */ function Tutki(d:double):boolean; /* 118 */ begin /* 119 */ Result := false; /* 120 */ if not ( eq(b.Tag,d) ) then exit; /* 121 */ b.Enabled := false; /* 122 */ Result := true; /* 123 */ end; /* 124 */ begin /* 125 */ if not ( sender is TButton ) then exit; /* 126 */ b := TButton(sender); /* 127 */ if ( tutki(a5.Ainetta) ) then exit; /* 128 */ if ( tutki(a8.Ainetta) ) then exit; /* 129 */ if ( tutki(a5.Ainetta+a8.Ainetta) ) then exit; /* 130 */ /* 131 */ end; /* 132 */ /* 133 */ procedure TFormAmpari.FormCreate(Sender: TObject); /* 134 */ // Kun lomake luodaan, luodaan dynaamisesti astiat ja nappulat. /* 135 */ var i,max_tilavuus:integer; /* 136 */ /* 137 */ function LuoAstia(V:double; lab : TLabel) : TAstia; /* 138 */ var h : integer; a : TAstia; /* 139 */ begin /* 140 */ a := TAstia.Create(self); a.Parent := self; /* 141 */ a.Name := Format('a%1.0f',[V]); // => esim. a.Name := 'a5'; /* 142 */ lab.Caption := a.Name; /* 143 */ if ( V = 0 ) then V := max_tilavuus+1; /* 144 */ h := Round(V*10); /* 145 */ a.SetBounds(lab.Left,lab.Top-h,lab.Width,h); /* 146 */ a.Tilavuus := V; /* 147 */ a.OnClick := AstiaClick; /* 148 */ a.OnFull := AstiaEvent; /* 149 */ a.OnEmpty := AstiaEvent; /* 150 */ Result := a; /* 151 */ end; /* 152 */ /* 153 */ begin /* 154 */ a5 := LuoAstia(5,LabelA5); /* 155 */ a8 := LuoAstia(8,LabelA8); /* 156 */ max_tilavuus := Round(a5.Tilavuus + a8.Tilavuus); /* 157 */ /* 158 */ a0 := LuoAstia(0,LabelA0); /* 159 */ a0.Ainetta := max_tilavuus; /* 160 */ SetLength(btns,max_tilavuus+1); /* 161 */ /* 162 */ for i:=1 to max_tilavuus do begin /* 163 */ btns[i] := TButton.Create(self); btns[i].Parent := PanelButtons; /* 164 */ btns[i].Caption := IntToStr(i); /* 165 */ btns[i].Width := 30; btns[i].Left := 1000; btns[i].Align := alLef /* 166 */ btns[i].OnClick := ButtonClick; /* 167 */ btns[i].Tag := i; /* 168 */ end; /* 169 */ /* 170 */ end; /* 171 */ /* 172 */ function TFormAmpari.GetAineetAsString: string; /* 173 */ // Palauttaa astoiden sisällön merkkijonona, esim: 3.0 5.0 /* 174 */ begin /* 175 */ Result := Format('%3.1f %3.1f',[a5.Ainetta,a8.Ainetta]); /* 176 */ end; /* 177 */ /* 178 */ end.