PDA

View Full Version : I need a little help with this.



nicostream
09-03-2011, 10:15 AM
Hi everyone! I'm new here. I've been doing Pascal for a little while, and it's become very interesting to me recently. This program I'm working on at the moment however has confused me. It's a program that is supposed to help you with learning vocabularly. The idea is as follows: The words will be records stored in a binary file, with variables of meaning, english tally, and the position of the record in the file. There are 3 functions. First you can add new words. No problem with that. Second you can correct already added words. Works fine. And third comes the real use of the program. It asks you randomly a chosen number of questions and checks if your answer is correct. The problem is,since it randoms which number to go to, there is a decent possibility for one or two words being asked more than once. I had an idea to solve this: Let's collect the numbers of the already asked words into an array, and keep randoming until the random number isn't in that array. But this just doesn't work. I'm stuck. I don't know what is wrong, the procedure or the function. I'll give the related parts of the code here. Thanks in advance, have a nice day everyone!



Type szo=record
hun:string;
eng:string;
num:integer; {This variable is only needed for the correction function}

Var
f: file of szo;
ticked:array[1..1000] of integer;

Function is_in_arr(testval,max,arr):boolean;
var count,i:integer;
begin
count:=0;
for i:=1 to max do if testval=arr[i] then inc(count);
if count>0 then is_in_arr:=true else is_in_arr:=false;
end;

Procedure quest(numofquest:integer);

var
ans:string;
posvar,j:integer;
tempw:szo;
begin

reset(f)

for j:=1 to numofquest do

begin

repeat
posvar:=random(filesize(f));
Until is_in_arr(posvar,numofquest,ticked)=false;

ticked[j]:=posvar;
seek(f,posvar);
read(f,tempw);

Writeln('Hungarian: ',tempw.hun);
Write('English: ');
Readln(ans);

If ans=tempw.eng then
writeln('Congratulations!')
else writeln('Wrong! The correct answer is: ',tempw.eng);
end;

Close(f);
menu; {This calls the menu procedure}
end;
{Randomize, and Assign are called in the main program}
Note: When I get really good at this I'm looking forward to try myself out and write a game, but there is a lot to practise yet. Object pascal and SDL are both quite new to me :)

WILL
09-03-2011, 09:15 PM
Hi and welcome to PGD! :)

I would try to make a check-list of what values have been chosen to keep track of what's been used. It would look something like this...


var WordCheckList: Array[0 .. MaxWords] of Boolean;

Then each time a word in your array is randomly chosen for your question, you would mark the check-list array as true to signify that it has been indeed chosen. It would work something like this...


//Random Word Selection
Repeat
i := random(MaxWords);
Until(not WordCheckList[i]);

//Indicating on the checklist
WordCheckList[i] := true;

// the rest of your code

There is a few things you want to make sure of when using this method 1) your not using more words than you have in your array. If you do want to do more you'll have to count your usage so that once you hit the max number of words you reset the check-list. and of course 2) there is a slim chance that not all the values in your check-list array will be false so for safe coding practices you should make a function that sets all the elements of this array to false, just to be sure. But that part is as easy as a simple for loop. ;)

If you need any more help please don't hesitate to ask there are lots of knowledgeable people here who like to help.

As for making a game, awesome choice! Just start slow. ;) I highly recommend SDL for graphics and game input (keyboard, mouse, joystick, etc), especially when just starting out. I also recommend you check out both the PPS (http://www.pp4s.co.uk/) and Free Pascal Meets SDL (http://www.freepascal-meets-sdl.net/) sites as shown on the front page. Both are a great resource for learning various aspects of Object Pascal and SDL.

nicostream
09-03-2011, 09:56 PM
Hello Will! An array of boolean... what an elegant and easy way. Thanks a lot. But there is a small technical thing with that. The number, Maxwords may change since there is always the possibility of adding new words to the database and as far as I know I can't use a variable as a length of an array. I think I'll do the following: Set the Maxwords constant to 1000, and for the until conditions, I'll add that the random number shouldn't be bigger than the size of the binary file.

As for the game I was thinking about a chess game for two players. Writing a chess AI is way above my level, but a chess game has easy graphics. And for two players it would be challenging, but also possible. I already have some things in my mind about it. The board would be a 8x8 matrix. The values in the matrix would indicate what piece is on the square, and whether the square is attacked or not. The players would be objects, I think that's the simplest way for calculating checks, mates, stalemates etc. A drawing procedure would be called after every move. It would draw according to the values of the matrix, and according to which player is on move(it would reverse after every move to make it convenient for both players) But before that I'd like to master my pascal skills :)

Carver413
10-03-2011, 01:36 PM
actual a better method would be to have two arrays of record. one for the records that have not been called and one for the ones that have. as you access the records move them to the second array. the reason you would want to do this is if the list is very long it will take longer to find a new record each time do to all the misses. be sure to update your random number to the current size of the array.

nicostream
10-03-2011, 04:05 PM
Hi Carver. Thanks but I think I'll stick with this one. But instead of adding the condition to the Until section I just changed the randomization. It is now random(filesize(f)-1)+1 (This makes sure that the random number is not bigger than the filesize and is not zero) Yes it takes more time but the difference can be defined in miliseconds. I'm finished with it. It works fine. There is just a minor error left to fix. If I run the program for the first time, I add some words to the database but I need to exit the program before it can do something with it because something creates a disk read error if I call the question or correct procedures. (Interesting that it only occurs for the first run... But I checked it and each time the file was reset or rewritten it was also closed, so that's not the problem currently I have no idea but I will look at it more deeply with some breakpoints and watches tonight)

User137
11-03-2011, 06:57 PM
Hello Will! An array of boolean... what an elegant and easy way. Thanks a lot. But there is a small technical thing with that. The number, Maxwords may change since there is always the possibility of adding new words to the database and as far as I know I can't use a variable as a length of an array. I think I'll do the following: Set the Maxwords constant to 1000, and for the until conditions, I'll add that the random number shouldn't be bigger than the size of the binary file.
You can make the boolean array dynamic.

var WordCheckList: Array of Boolean;
...
Setlength(WordCheckList, NumOfRecords);

Another way i can think of is also using dynamic array but it consist of numbers, indexes to the record. Make them run from 0 to last index and then randomize the whole array. Finally start reading from start towards end however many you want to pick.