24. november 2003 - 08:58
Der er
4 kommentarer og
1 løsning
Problem med Reset
Jeg har følgende kode, som delphi ikke vil compile fordi den i linie 95 (den hvor jeg har kommenteret med store bogstaver! Der hvor der står Reset(fil)) siger "Missing operator or semicolon".
unit Unit3;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Menus;
type
h = array[0..19,0..19] of string; // Vores highscore array defineres globalt
TForm3 = class(TForm)
ListBox1: TListBox;
ListBox2: TListBox;
MainMenu1: TMainMenu;
Spiligen1: TMenuItem;
Menu1: TMenuItem;
Label1: TLabel;
Label2: TLabel;
procedure Spiligen1Click(Sender: TObject);
procedure Menu1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
hh: h;
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
uses Unit1, Unit2; // Dette gør at vi kan gemme og vise form1 og form2
{$R *.dfm}
// Denne procedure splitter en streng efter en separator op i et array
// Da denne procedure er lånt fra internettet grundet tidsmangel,
// så er den ikke kommenteret, da vi ikke er sikre på hvad der sker hvor!
procedure SplitString(S: String; SplitChar: Char; Strings: TStrings);
var
TmpStr: String;
begin
Strings.Clear;
while Pos(SplitChar, S) > 0 do
begin
TmpStr := Copy(S, 1, Pos(SplitChar, S) - 1);
Delete(S, 1, Pos(SplitChar, S));
if Length(TmpStr) > 0 then // Fjern denne linje hvis du vil acceptere tomme strenge.
Strings.Add(TmpStr);
end;
if Length(S) > 0 then
Strings.Add(S);
end;
procedure TForm3.Spiligen1Click(Sender: TObject); // Denne procedure gemmer highscoren og viser spilleformen
begin
Form3.Hide;
Form2.Show;
end;
procedure TForm3.Menu1Click(Sender: TObject); // Denne procedure gemmer highscoren og viser hovedmenuen
begin
Form3.Hide;
Form1.Show;
end;
// Denne procedure henter highscore information ud af vores textfil,
// sorterer det og sætter det ind i listbokse
procedure TForm3.FormShow(Sender: TObject);
var
Finished : Boolean;
arr: TStringList;
fil: TextFile;
i,j,ii: Integer;
filename,l: string;
begin
ZeroMemory(@hh, SizeOf(hh)); // vores highscore-array nulstilles
filename:= 'highscore.txt'; // Filen vores highscore er gemt i defineres
if fileexists(filename) then // Hvis filen eksisterer så hent navne og score!
begin
// Først bliver indholdet af de 2 listbokse slettet for at undgå at gammelt indhold går igen
form3.listbox1.clear;
form3.listbox2.clear;
arr := TStringList.Create; //
AssignFile(fil,filename); // Vi starter en stream til filen
Reset(fil); // Filen åbnes til læsning. AF EN ELLER ANDEN MÆRKELIG ÅRSAG MENER DELPHI AT DER MANGLER EN "operator or semicolon" HER!
i:=0; // er en nødvendig tæller!
while not EOF(fil) do // Her løbes filen igennem indtil der ikke er flere linier. EOF - End Of File
begin
ReadLn(fil,l); // Linien i filen læses og sættes ind i variablen l
SplitString(l,':',arr); // Her splittes linien op i navn og score
hh[0,i]:= arr[0]; // Navn sættes ind i vores highscore-array
hh[1,i]:= arr[1]; // Score sættes ind i vores highscore
inc(i); // vores tæller i øges med 1
end;
CloseFile(fil); // filen lukkes igen
for j:= 0 to i-1 do // her sættes navn og score så ind i deres respektive listbox
begin
form3.ListBox1.items.Add(hh[0,j]); // Navn bliver sat ind
form3.ListBox2.items.Add(hh[1,j]); // Score bliver sat ind
end;
arr.Free; //
// Start sortering
begin
repeat // Her sorteres vores listbokse
Finished := True; // Vores tjek-variabel
For ii:=1 to Form3.ListBox2.Count-1 do // gør følgende antal gange som der er strenge i listboksen
begin
if (length(form3.ListBox2.Items.Strings[ii]) = 0) then // Hvis strengen løkken er nået til er tom så stoppes løkken
begin
break;
end;
if (StrToInt(Form3.ListBox2.Items.Strings[ii]) > StrToInt(Form3.ListBox2.Items.Strings[ii-1])) then // Her tjekkes om den foregående streng/værdi er mindre end den nuværende
begin
Form3.ListBox2.Items.Move(ii,ii-1); // Score rykkes et tak opad i listboksen
Form3.ListBox1.Items.Move(ii,ii-1); // Det tilhørende navn rykkes et tak opad i listboksen
Finished := False;
break;
end;
end;
until (Finished);
end;
// slut sortering
end; // slut hvis fil eksisterer
end; // slut på procedure
end. // slut på form
24. november 2003 - 10:01
#4
Nu er det til et miniprojekt i Programmering på C niveau på HTX 3. år... Men hvordan er de nye fil håndterings kommandoer ? Har du links til noget dokumentation?
Og det virkeder faktisk med System.Reset... Tak :)
Lige et tillægsspørgsmål:
Vi tegner vores snake på formen og der dukker hvert 10ende sekund en inputboks op med et spørgsmål. Men hvis så inputboksen føres ind over snaken, så forsvinder snaken der hvor inputboksen har været. Vi har prøvet at gentegne slangen, men det virker ikke...
Den kode vi bruger til selve spillet ser således ud:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, Menus;
type
k = array[0..60,0..60] of integer; // Array som gemmer koordinaterne hvor 'snake' har været
TForm2 = class(TForm)
Timer1: TTimer;
Timer2: TTimer;
Timer3: TTimer;
Timer4: TTimer;
Label1: TLabel;
Timer5: TTimer;
MainMenu1: TMainMenu;
Filer1: TMenuItem;
Highscore1: TMenuItem;
procedure Timer1Timer(Sender: TObject);
procedure Timer2Timer(Sender: TObject);
procedure Timer3Timer(Sender: TObject);
procedure Timer4Timer(Sender: TObject);
procedure Timer5Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure Filer1Click(Sender: TObject);
procedure Highscore1Click(Sender: TObject);
private
{ Private declarations }
kk: k; // Arrayet som holder styr på koordinaterne hvor 'snake' har været bliver defineret globalt for hele formen
public
{ Public declarations }
end;
var
Form2: TForm2;
a,b,x,y,p,reset,ts,vej: integer;
kk: k;
implementation
uses Unit1,Unit3; // Her henvises til de to andre forms,
// da vi i denne form gemmer og viser form1 og form 3
{$R *.dfm}
procedure TForm2.FormCreate(Sender: TObject); // Dette i denne procedure bliver udført i det at formen bliver lavet, dvs. som det første.
begin
// Her bliver alle vores variabler og timere lige sat til deres startværdi,
// så vi er sikre på at de har den rigtige værdi inden der sker noget andet i formen
a:= 300; // a sættes til 300 da det er den vertikale position på venstre hjørne af den nyest tegnede kvadrat
b:= 300; // b sættes til 300 da det er den horisontale position på højre hjørne af den nyest tegnede kvadrat
p:= 0;
ts:= 0;
reset:= 1;
// Alle timerne bliver sat til false, så vores orm og pointne ikke begynder,
// at ændre sig før brugeren trykker på en af piltasterne
timer1.enabled:= False;
timer2.enabled:= False;
timer3.enabled:= False;
timer4.enabled:= False;
timer5.enabled:= False;
// I vores pointtavle bliver der skrevet at man har 0 point
label1.caption:= inttostr(p)+' points';
// Vores array der håndterer 'snake's koordinater bliver nulstillet,
// så vi er sikre på at det er helt tomt inden vi starter
ZeroMemory(@kk, SizeOf(kk));
end;
// Denne funktion sætter timerne til enten false eller true,
// afhængig af hvilken piltast brugeren har trykket på.
// Alle timere sættes til false hvis tiden er inde til at der skal stilles et spørgsmål
function timershift(t1,t2,t3,t4,t5: boolean) : boolean;
begin
form2.timer1.enabled:= t1;
form2.timer2.enabled:= t2;
form2.timer3.enabled:= t3;
form2.timer4.enabled:= t4;
form2.timer5.enabled:= t5;
end;
// Denne funktion stiller et spørgsmål til brugeren
function question(count: integer) : integer;
type // Lokalt defineres 2 arrays som indeholder henholdsvis spørgsmål og svar
q = array[0..5] of string;
a = array[0..5] of string;
var
que:q; // Lokale variabler defineres
ans:a;
iii,i,j,i1,j1:integer;
query,a1:string;
begin
timershift(False,False,False,False,False); // Alle timere stoppes vha. førnævnte funktion
// Her definerer vi vores spørgsmål
que[0] := 'Hvad er 8*4?';
que[1] := 'Hvem byggede rundetårn?';
que[2] := 'Hvilket land ligger nord for Danmark?';
que[3] := 'I hvilket årstal faldt Berlinmuren?';
que[4] := 'Hvilket grundstof har nr. 26?';
que[5] := 'Hvad er molmassen af vand (H2O)?';
// Og her defineres de tilhørende svar
ans[0] := '32';
ans[1] := 'Christian den 4.';
ans[2] := 'Norge';
ans[3] := '1989';
ans[4] := 'Jern';
ans[5] := '18,016';
randomize; // For at vi ikke får det samme tal hver gang
iii:= random(5); // Der vælges et tilfældigt nummer, som så har et spørgsmål tilknyttet, jævnfør vores array ovenfor
query:= que[iii];
a1:= InputBox('Dit svar',query,''); // Der laves en inputboks med spørgsmålet, og brugeren skriver sit svar og trykker ok
if (LowerCase(a1) = LowerCase(ans[iii])) then // Her tjekkes om brugerens svar og det korrekte svar stemmer overens, begge sættes i LowerCase, da delphis variabler er case-sensitive
begin
p := p+1000; // Brugeren får 1000 point hvis svaret er korrekt
end
else
begin
p := p; // Brugeren får ingen point ved forkert svar
end;
// Nedenstående lykker er et forsøg på at gentegne 'snake'en der hvor inputboksen kommer frem, men det virker ikke efter hensigten !
for i:= 0 to 60 do
begin
for j:= 0 to 60 do
begin
if (kk[i,j] = 1) then
begin
i1:= i*10;
j1:= j*10;
form2.canvas.Brush.color:= clblue;
form2.canvas.pen.color:= clblue;
form2.canvas.rectangle(i1,j1,i1+10,j1+10);
end;
end;
end;
// Slut på lykker der ikke virker
// Her tjekkes den variabel der er sendt til funktionen (count)
// som angiver hvilken vej slangen var på vej hen da spørgsmålet blev stillet, og denne startes så igen!
case count of
1 : timershift(True,False,False,False,True);
2 : timershift(False,True,False,False,True);
3 : timershift(False,False,True,False,True);
4 : timershift(False,False,False,True,True);
end;
end;
// Nedenstående funktion bliver kørt når brugeren dør. Funktionen returnerer ingen værdier!
function dead(n1: integer) : integer;
var
hs: TextFile;
v: Integer;
name,filename: string;
begin
timershift(False,False,False,False,False); // Alle timere stoppes
// Brugeren bliver spurgt om han vil gemme sin score
v:= MessageDlg('Du er død. Vil du gemme din score?',mtConfirmation,
[mbYes,mbNo],0);
if (v = 6) then // Hvis brugeren svarer ja!
begin
repeat // Vi bliver ved med at vise inputboksen hvor brugeren skal skrive sit navn til han har skrevet noget
name:= InputBox('Dit navn','Skriv dit navn','Mit navn!'); // Inputboks til brugerens navn
until name <> '';
filename:= 'highscore.txt'; // Filnavnet på den fil vi gemmer highscoren i
AssignFile(hs,filename); // Her åbner vi en stream til filen
if not FileExists(filename) then // Hvis filen ikke eksisterer så
begin
Rewrite(hs); // Filen bliver oprettet og åbnet
WriteLn(hs,name+':'+inttostr(p)); // Brugerens navn og point bliver skrevet som første linie i filen
CloseFile(hs); // Filen lukkes igen
end
else // Hvis filen eksisterer
begin
Append(hs); // Filen åbnes så vi kan tilføje linier uden at slette eksisterende linier
WriteLn(hs,name+':'+inttostr(p)); // Brugerens navn og point bliver skrevet i filen efter allered eksisterende linier
CloseFile(hs); // Filen lukkes igen
end;
end;
// Første firkant til vores slange tegnes i midten af formen
form2.canvas.brush.Color:= clTeal;
form2.canvas.pen.color:= clTeal;
form2.canvas.Rectangle(0,0,600,600);
a:= 300; // a sættes igen til vores startkoordinat
b:= 300; // b sættes igen til vores startkoordinat
p:= 0; // Pointsne nulstilles
reset:=1;
form2.label1.caption:= inttostr(p)+' points'; // Point skrives i pointtavlen
ZeroMemory(@kk, SizeOf(kk)); // Vores array der holder styr på slangens koordinater nulstilles
end;
// Denne procedure starter og stopper de respektive timere afhængig af hvilken piltast der trykkes på
procedure TForm2.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
// Hvis brugeren trykker på venstre piltast, så startes timer1, da vi så får slangen til at bevæge sig til venstre
// Samtidig sættes vej til 1 da det er denne værdi der sendes til funktionen question, så denne ved hvilken timer der skal startes igen efter spørgsmål
if (key = VK_LEFT) then
begin
vej:= 1;
timershift(True,False,False,False,True);
end;
// Hvis brugeren trykker på højre piltast, så startes timer2, da vi så får slangen til at bevæge sig til højre
// Samtidig sættes vej til 2 da det er denne værdi der sendes til funktionen question, så denne ved hvilken timer der skal startes igen efter spørgsmål
if (key = VK_RIGHT) then
begin
vej:= 2;
timershift(False,True,False,False,True);
end;
// Hvis brugeren trykker på nedad piltast, så startes timer3, da vi så får slangen til at bevæge sig til nedad
// Samtidig sættes vej til 3 da det er denne værdi der sendes til funktionen question, så denne ved hvilken timer der skal startes igen efter spørgsmål
if (key = VK_DOWN) then
begin
vej:= 3;
timershift(False,False,True,False,True);
end;
// Hvis brugeren trykker på opad piltast, så startes timer4, da vi så får slangen til at bevæge sig til opad
// Samtidig sættes vej til 4 da det er denne værdi der sendes til funktionen question, så denne ved hvilken timer der skal startes igen efter spørgsmål
if (key = VK_UP) then
begin
vej:= 4;
timershift(False,False,False,True,True);
end;
end;
procedure TForm2.Timer1Timer(Sender: TObject); // Timer som tegner kvadrater til venstre
begin
if (reset = 1) then // Denne if nulstiller lige arrayet 1 gang til, da vi har oplevet fejl uden denne!
begin
ZeroMemory(@kk, SizeOf(kk));
reset:=0;
end;
if (a < 0) then // Hvis man kommer ud over kanten i venstre side
begin
dead(a); // Så dør man, og dead funktionen køres
end
else // ellers
begin
a:= a-10; // så trækkes der 10 fra a da slangen jo rykker 1 kvadrat længere mod venstre
x:=a div(10); // a og b divideres med 10 for at vi kan have dem i vores array
y:=b div(10);
if (kk[x,y] = 1) then // Der tjekkes i arrayet om slangen har været i det punkt før
begin
dead(a); // Hvis slangen har været der før, så køres dead funktionen
end
else // ellers
begin
kk[x,y]:=1; // så sættes det punkt slangen er på til værdien 1 i arrayet
end;
end;
canvas.Brush.color:= clblue; // Slangens farve er blå
canvas.pen.color:= clblack; // Slangens kant er sort
canvas.rectangle(a,b,a+10,b+10); // den nye kvadrat tegnes og slangens længde øges
end;
procedure TForm2.Timer2Timer(Sender: TObject); // Timer som tegner kvadrater til højre
begin
if (reset = 1) then // Denne if nulstiller lige arrayet 1 gang til, da vi har oplevet fejl uden denne!
begin
ZeroMemory(@kk, SizeOf(kk));
reset:=0;
end;
if (a > 580) then // Hvis man kommer ud over kanten i højre side
begin
dead(a); // Så dør man, og dead funktionen køres
end
else // ellers
begin
a:= a+10; // så adderes 10 til a da slangen jo rykker 1 kvadrat længere mod højre
x:=a div(10); // a og b divideres med 10 for at vi kan have dem i vores array
y:=b div(10);
if (kk[x,y] = 1) then // Der tjekkes i arrayet om slangen har været i det punkt før
begin
dead(a); // Hvis slangen har været der før, så køres dead funktionen
end
else // ellers
begin
kk[x,y]:=1; // så sættes det punkt slangen er på til værdien 1 i arrayet
end;
end;
canvas.Brush.color:= clblue; // Slangens farve er blå
canvas.pen.color:= clblack; // Slangens kant er sort
canvas.rectangle(a,b,a+10,b+10); // den nye kvadrat tegnes og slangens længde øges
end;
procedure TForm2.Timer3Timer(Sender: TObject); // Timer som tegner kvadrater til opad
begin
if (reset = 1) then // Denne if nulstiller lige arrayet 1 gang til, da vi har oplevet fejl uden denne!
begin
ZeroMemory(@kk, SizeOf(kk));
reset:=0;
end;
if (b > 580) then // Hvis man kommer ud over kanten i bunden
begin
dead(a); // Så dør man, og dead funktionen køres
end
else // ellers
begin
b:= b+10; // så adderes 10 til b da slangen jo rykker 1 kvadrat længere nedad
x:=a div(10); // a og b divideres med 10 for at vi kan have dem i vores array
y:=b div(10);
if (kk[x,y] = 1) then // Der tjekkes i arrayet om slangen har været i det punkt før
begin
dead(a); // Hvis slangen har været der før, så køres dead funktionen
end
else // ellers
begin
kk[x,y]:=1; // så sættes det punkt slangen er på til værdien 1 i arrayet
end;
end;
canvas.Brush.color:= clblue; // Slangens farve er blå
canvas.pen.color:= clblack; // Slangens kant er sort
canvas.rectangle(a,b,a+10,b+10); // den nye kvadrat tegnes og slangens længde øges
end;
procedure TForm2.Timer4Timer(Sender: TObject); // Timer som tegner kvadrater til nedad
begin
if (reset = 1) then // Denne if nulstiller lige arrayet 1 gang til, da vi har oplevet fejl uden denne!
begin
ZeroMemory(@kk, SizeOf(kk));
reset:=0;
end;
if (b < 10) then // Hvis man kommer ud over kanten i toppen
begin
dead(a); // Så dør man, og dead funktionen køres
end
else // ellers
begin
b:= b-10; // så trækkes der 10 fra b da slangen jo rykker 1 kvadrat længere opad
x:=a div(10); // a og b divideres med 10 for at vi kan have dem i vores array
y:=b div(10);
if (kk[x,y] = 1) then // Der tjekkes i arrayet om slangen har været i det punkt før
begin
dead(a); // Hvis slangen har været der før, så køres dead funktionen
end
else // ellers
begin
kk[x,y]:=1; // så sættes det punkt slangen er på til værdien 1 i arrayet
end;
end;
canvas.Brush.color:= clblue; // Slangens farve er blå
canvas.pen.color:= clblack; // Slangens kant er sort
canvas.rectangle(a,b,a+10,b+10); // den nye kvadrat tegnes og slangens længde øges
end;
// Denne timer adderer 1 point op hvert 50. ms
procedure TForm2.Timer5Timer(Sender: TObject);
begin
inc(p); // p som er antal points øges med 1
inc(ts); // ts som er vores tidstæller øges også med 1, og når ts er øget til 200 (så er der gået 10 sekunder), så stilles et spørgsmål
label1.Caption:= inttostr(p)+' points'; // Points skrives til pointtavlen
if (ts = 200) then
begin
question(vej); // Spørgsmål stilles
ts:= 0; // Tidstælleren nulstilles
end;
end;
// Dette er menuen i toppen af formen, som sender en tilbage til hovedmenuen
procedure TForm2.Filer1Click(Sender: TObject);
begin
Form2.Hide; // Spilformen gemmes
Form1.Show; // Hovedmenuen vises
end;
// Dette er menuen i toppen af formen, som sender en til highscoren
procedure TForm2.Highscore1Click(Sender: TObject);
begin
Form2.Hide; // Spilformen gemmes
Form3.Show; // Highscoren vises
end;
end.