I'm trying to create a simple game in Pascal. It uses the console. The goal in the game is to collect as many 'apples' as you can in 60 seconds. The game structure is a simple infinite loop. Each iteration, you can make one move. And here's the problem — before you make the move (readKey), time can pass as much as it wants. For example, the user can press a key after 10 seconds! Is there any way to count time? I need the program to know when user plays (before and after a key is pressed), so I don't know how to prevent user from "cheating".
Here's simple structure of my game:
begin
repeat
{* ... *}
case ReadKey of
{* ... *}
end;
{* ... *}
until false;
end.
Full code: http://non.dagrevis.lv/junk/pascal/Parad0x/Parad0x.pas.
As far I know that there are two possible solutions:
getTime (from DOS),
delay (from CRT).
...but I don't know how to use them with my loop.
Check this link. There might be some useful information for you. And here is the same you're asking for. And here's what you're looking for (same as the code below).
var hours: word;
minutes: word;
seconds: word;
milliseconds: word;
procedure StartClock;
begin
GetTime(hours, minutes, seconds, milliseconds);
end;
procedure StopClock;
var seconds_count : longint;
c_hours: word;
c_minutes: word;
c_seconds: word;
c_milliseconds: word;
begin
GetTime(c_hours, c_minutes, c_seconds, c_milliseconds);
seconds_count := c_seconds - seconds + (c_minutes - minutes) * 60 + (c_hours - hours) * 3600;
writeln(inttostr(seconds_count) + ' seconds');
end;
begin
StartClock;
// code you want to measure
StopClock;
end.
Related
I have to find out the biggest number from a txt file. Numbers are for example:
9 8 7 6 5
Someone told me, that it should works, but it didn't, and I have no clue how to work with file bcs.
program file;
uses crt;
var i,count,help:integer;
numb:array [1..9] of integer;
f:text;
begin
clrscr;
assign(f,'file1.txt');
reset(f);
readln(f,count);
for i:=1 to count do
readln(f,numb[i]);
close(f);
for i:=2 to count do
begin
if (numb[i-1] < numb[i]) then
help:=numb[i-1];
numb[i-1]:=numb[i];
numb[i]:=help;
end;
for i:=1 to count do
begin
write(numb[i]);
end;
readln;
end.
If you only want to know the highest number, you can use a running maximum while reading the numbers in the file.
As a user you don't have to know how many numbers there are in the file. The program should determine that.
I wrote a little test file, called file1.txt:
9 8 7 6 3 11 17
32 11 13 19 64 11 19 22
38 6 21 0 37
And I only read the numbers, comparing them with Max. That is all you need.
No need to read the data into an array and
no need to (try to) sort the data. You only want the highest number, right?
And there is also no need for the user to know or enter the number of numbers in the text file.
program ReadMaxNumber;
uses
Crt;
var
Max, Num: Integer;
F: Text;
begin
ClrScr;
Assign(F, 'file1.txt');
Reset(F);
Max := -1;
while not Eof(F) do
begin
Read(F, Num);
if Num > Max then
Max := Num;
end;
Close(F);
Writeln('Maximum = ', Max);
Readln;
end.
When I run this, the output is as expected:
Maximum = 64
There are a few mistakes in the code provided:
The program name is file. The program name cannot be a keyword;
You read from the file the variable count, but the actual value cannot be found in the file, so count=0. For this reason, the for loop which reads the data from the file is never executed. You either read it from a file or from the keyboard (in the solution below, I chose the second option);
You use readln when you read from the file. readln moves the cursor on the next line after it reads the data. This means that only the first number, 9, is stored into numb. Replace readln with read;
At the second for loop, you say that if ... then. If you want all the three instructions to be executed (and I think you do, because it's an exchange of values), put them between begin and end. Otherwise, only the first instruction is executed if the condition is true, the others are always been executed;
The method to determine the maximum is an overkill. Better if you take a variable, max, which initially gets the value of the first element in the array, then you cycle in the remaining values to see if a value is higher than max.
The final code looks like this:
program file1;
uses crt;
var i,count,help, max:integer;
numb:array [1..9] of integer;
f:text;
begin
clrscr;
assign(f,'file1.txt');
reset(f);
writeln('Please input a number for count :');
readln(count);
for i:=1 to count do
read(f,numb[i]);
close(f);
max:=numb[1];
for i:=2 to count do
if numb[i]>max then
max:=numb[i];
write('The result is: ',max);
readln;
end.
PROGRAM approvedapplicants(input,output);
uses crt;
var
applcntname,housingcomm,clarendon_court,providence_gardens,
sangre_grande_villas:string;
slry,spcslry:integer;
c_qual_sal,s_qual_sal,p_qual_sal,qualifying_salary:integer;
BEGIN
writeln('enter applicant name, salary, spouce salary');
readln(applcntname,slry,spcslry);
writeln('enter housing community');
readln(housingcomm);
BEGIN
qualifying_salary:=0;
IF(housingcomm=clarendon_court)
then
qualifying_salary:=$12500;
writeln('you have selected clarendon court!');
readln(c_qual_sal) ;
end if ;
else if(housingcomm=sangre_grande_villas)then
qualifying_salary:=$9500;
writeln('you have selected sangre grande villas!');
readln(s_qual_sal);
end if ;
else(housingcomm=providence_gardens)then;
qualifying_salary:=$7500;
writeln('you have selected providence gardens!');
readln(p_qual_sal);
end if;
END.
Ordinarily, on SO, we don't post answers to homework/coursework, but your code is so far wide of the mark that I think it's ok to make an exception in this case.
Try compiling and running this program, which I think does pretty much what I think you are intending, then I'll explain a few things about it:
program approvedapplicants(input,output);
uses crt;
var
ApplicantName,
HousingCommunity,
ClarendonCourt,
ProvidenceGardens,
SangreGrandVillas :string;
Salary,
SpouseSalary,
QualifyingSalary : Integer;
CQualSal,
PQualSal,
SQualSal : Integer;
slry,spcslry:integer;
begin
ClarendonCourt := 'Clarendon Court';
ProvidenceGardens := 'Providence Gardens';
SangreGrandVillas := 'Sangre Grand Villas';
QualifyingSalary := 0;
writeln('enter applicant name');
readln(ApplicantName);
writeln('enter salary');
readln(Salary);
writeln('enter spouse salary');
readln(SpouseSalary);
writeln('enter housing community');
readln(HousingCommunity);
if (HousingCommunity = ClarendonCourt) then begin
QualifyingSalary := $12500;
writeln('you have selected clarendon court!');
readln(CQualSal);
end
else
if(HousingCommunity = SangreGrandVillas)then begin
QualifyingSalary := $9500;
writeln('you have selected sangre grande villas!');
readln(SQualSal);
end
else
if HousingCommunity = ProvidenceGardens then begin
QualifyingSalary :=$7500;
writeln('you have selected providence gardens!');
readln(CQualSal);
end;
end.
Firstly, notice how much easier it is to read and follow its logic. This is mainly
because of
The use of a layout (including indented blocks) which reflects the logical
structure of the code.
The use of consistent, lower case for keywords like program, begin, end, etc.
Keywords are usually the least interesting contents of source code, and it is distracting
to have them SHOUTing at you.
The avoidance of arbitrarily dropping characters from variable names (like the "i"
and second "a" of "applicant". In the days of interpreted code running on slow machines there was
argubably some justification for this, but not any more imo. Likewise, the avoidance
of underscores in variable names - admittedly this is more of a personal preference, but
why have you used them everywhere except the applicant's name?
Secondly, you still have quite a bit of work to do.
Having 3 different variables for the salary (?) numbers you prompt the user
for, one for each of the 3 communities, is probably a bad idea unless you will
subsequently want to work with all 3 figures at the same time. Also, you haven't provided text prompts to tell the user what information to enter for the readln(c_qual_sal) etc statements. It wasn't obvious to me what you intend, so I have not tried to guess.
The way you echo the user's choice of community is just creating you a maintenance
headache (what if you want to add more communities later?). It would be better
to have a variable which you set to whichever of the community names matches
what the user has entered.
You have 3 statements to execute for each community, which are duplicated for
each community. The only one you actually need is the QualifyingSalary one -
the others can execute regardless of the inputted community.
How would i go about creating a procedure that is a thread which continuously passes automatic random generated data within a specified range.
I currently would have to manually enter in each bit of data in the console using this procedure below. I want to creatre a procedure that when running is able to pass data to this procedure as if it was being typed into the console itself.
procedure Analyse_Data is
Data : Integer;
begin
DT_Put_Line("Data input by user");
loop
DT_Get(Data,"Data must be taken as a whole number");
exit when (Data >=0) and (Data <= Maximum_Data_Possible);
DT_Put("Please input a value between 0 and ");
DT_Put(Maximum_Data_Possible);
DT_Put_Line("");
end loop;
Status_System.Data_Measured := Data_Range(Data);
end Analyse_Data;
I havent included the specification files (.ads)
I am new to Ada and any help would be appreciated.
Use an instance of Discrete_Random to generate some number of random data values in the desired range:
subtype Valid_Range is Natural range 0 .. Maximum_Data_Possible;
package Some_Value is new Ada.Numerics.Discrete_Random(Valid_Range);
G : Some_Value.Generator;
…
procedure Generate is
N : Valid_Range;
begin
for I in 1 .. Count loop
N := Some_Value.Random(G);
Put(N);
end loop;
end;
Save the values to a file:
./generate > test_data.txt
Feed that file to your program using I/O redirection from the command line:
./analyse_data < test_data.txt
The exact details will depend on you actual program. See this related Q&A regarding empty lines in standard input.
This snippet not only causes a runtime error, it makes FPC close if I run it using the debugger.
procedure sortplayersbyscore(var vAux:tplayers);
procedure swap(var a:trplayers;var b:trplayers);
var
rAux:trplayers;
begin
rAux:=a;
a:=b;
b:=rAux;
end;
var
i,j:integer;
sorted:boolean;
begin
vAux:=playersarray;
i:=1;
sorted:=false;
while (i <= MAXPLAYERS -1) and not sorted do
begin
j:=1;
sorted:=true;
while (j <= MAXPLAYERS -i) do
begin
if (vAux[j].score < vAux[j+1].score) then
begin
swap(vAux[j],vAux[j+1]);
sorted:=false;
end;
inc(j);
end;
inc(i);
end;
end;
The code itself is part of a really big source file, I can post the whole thing but the responsible for the error is just that bunch of lines. The debugger terminates at line:
swap(vAux[j],vAux[j+1]);
tplayers is just a type defined as an array of records that contain score (an integer) among a bunch of other variables. trplayers is the type of the aforementioned records. I'm at a total loss; FPC (while not under debugging mode) spits an out-of-range error but under my watches I see that the variables I'm trying to read exist. Any help is really appreciated!
rAux:trplayers; have you typed a wrong symbol or the type here really contains "r" in its name?
It looks valid (other than typos) ... so let's try something simple.
What's the value of "j" when you abort?
If the debugger won't tell you, try adding:
writeln ('j = ', j);
just before the "swap" call.
As Yochai's question implied, your array needs to be dimensioned at least from
1 (or lower) to MAXPLAYERS (or larger). (I.e.: 0..MAXPLAYERS-1 would not work,
but 1..MAXPLAYERS should.)
I have a TMemo on a form which allows users to enter a list of items. People can enter many items here. When they click Save the contents of the TMemo is checked and then added to the database.
I have a second list in a TStringList which I loop over and check to see if any of it's items are contained in the TMemo.
In a nut shell it looks like this
....
//slItems = TStringList
//mItems = TMemo
for i := slItems.Count -1 downto 0 do
begin
if mItems.Lines.IndexOf(slItems[i]) = -1 then
slItems[i].Delete;
end;
----
So stringlist looped, check to see if it exists in memo, if not delete from list.
However, with 200+ items this is starting to slow down a lot, and with 1000 it gets real bad.
Whats the fastest way to search a TMemo?
Read all of TMemo into a local TStringList and work from that. Every time you're accessing TMemo.Lines you're relying on Windows messaging to talk to the windows-provided multi line text box. Anything but efficient!
....
//slItems = TStringList
//mItems = TMemo
//L = TStringList
L.Text := mItems.Text; // edited per David's suggestion.
L.Sorted := True; // per Uwe Raabe's suggestion.
for i := slItems.Count -1 downto 0 do
begin
if L.IndexOf(slItems[i]) = -1 then
slItems[i].Delete;
end;
----