Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Randomising with no repeats?

Status
Not open for further replies.

Pleco

Programmer
Mar 26, 2003
9
GB
Okay, without necessarily wanting to shoot all my problems here, solving this should put me on track for the rest of this application. [wink]


I have a button that places one random letter in turn across a series of labels. At present I'm randomising the letters from an array using the Randomise/Random function but ideally I want to make it so that a letter is not repeated twice across the set of labels. Any ideas on how this is possible?
 
Check the caption of the labels already assigned a letter, and if used, generate the next 'random' value.

HTH
TonHu
 
I assume you mean Randseed or RandomRange? How might I implement that? Sorry I'm not all that experienced.

This is what I'm using to generate a random letter:

var

letter: array [0..5] of string;
currentletter: integer;

begin

letter[0] := 'A';
letter[1] := 'E';
letter[2] := 'I';
letter[3] := 'O';
letter[4] := 'U';


with (GrpBoxLetters.Controls[GrpBoxLetters.Tag] as TLabel) do
begin
Randomize;
currentletter := Random(5);

Caption := letter[currentletter];


GrpBoxLetters.Tag := GrpBoxLetters.Tag + 1;



Would something along the lines of this work or am I way off?

if LblLetter1.Caption = 'A' then
begin
Randseed := currentletter
end;
 
Here is one way to do what I think you are trying to accomplish:
Code:
function RandomizeString( AString:string ): string;
var
  cTemp: char;
  i,j: integer;
begin
  Randomize;
  for i := 1 to Length(AString) do
    begin
      j := Random( Length(AString) ) + 1;
      cTemp := AString[i];
      AString[i] := AString[j];
      AString[j] := cTemp;
    end;
  Result := AString;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  sLetters: string;
  i: integer;
begin
  sLetters := RandomizeString( 'AEIOU' );
  for i := 0 to 4 do
    TLabel(grpBoxLetters.Controls[i]).Caption
             := Copy(sLetters,i+1,1);
end;
I'm not sure what you are doing with GrpBoxLetters.Tag so I left that part out.
 
From what I understand, each time you call randomize, you put all of the numbers back into play. I'm pretty sure that you should call randomize only once while the application runs, or when you want to start all over. Brian
"There are 2 kinds of people in the world, those that divide people into two groups and those that don't. I belong to the second group." - tag line I stole
 
Okay I'm rethinking a few things here. But typically something else has cropped up. Surely I can use the Tag property to record how many times a button has been clicked, right? I want to be able to click a button five times, after which it disables. This is what I'm trying but it won't work:

if (Btn1.Tag = 6) then
begin
Btn1.Enabled := false;
 
Hmmm I' too lazy to actually check in Delphi right now, but I'm pretty sure the Tag property is a String.

That means that adding "1" to it 5 times yields '11111' rather than 5...

Work around it with nested IntToStr and StrToInt functions...
 
Or you could just cheapskate and have your condition check on '11111' instead of 5 :D
 
Code:
if (Btn1.Tag = 6) then
  begin
    Btn1.Enabled := false;
should work ok. (the Tag is a 32-bit longint), but being somewhat paranoid, I would use
Code:
if (Btn1.Tag >= 6) then
  begin
    Btn1.Enabled := false;
If it still doesn't work, breakpoint it and see what value is actually in the tag.

As for Randomize, it generates a new starting point based on the system clock. Brian may be thinking of the variable RandSeed which can be set by the application instead of calling Randomize. This is sometimes desired if the same sequence of pseudo-random numbers is wanted for testing.
 
I can't seem to get it to function. The button will continue to be enabled no matter how many times I click. I tried breakpoint and it indicates the correct value (if I used it correctly, that is).

I set up an extra application to test it out, to ensure there was no conflict with the other code I had written and still it didn't work. So, I'm at a loss...
 
You haven't given me enough clues to go on to determine why you code isn't working as you expect.

I modified the code posted above by adding three lines:
Code:
procedure TForm1.Button3Click(Sender: TObject);
var
  sLetters: string;
  i: integer;
begin
  sLetters := RandomizeString( 'AEIOU' );
  for i := 0 to 4 do
    TLabel(grpBoxLetters.Controls[i]).Caption
             := Copy(sLetters,i+1,1);
Code:
  Button3.Tag := Button3.Tag + 1;
  if (Button3.Tag >= 6) then
    Button3.Enabled := false;
Code:
end;
After clicking the button six times, it becomes grayed out. Your original post was incrementing the tag of the group box, while the last post was testing the tag of the button. You need to be consistent.
 
Ah I see, I was just missing that line of code.

I didn't mean to include the GroupBox Tag reference before, it just got caught up in the paste. That's so I can generate a random letter across the labels in sequence as the button is clicked rather than give all the labels random letters simultaneously or just one label.

Anyway it's all working now. Muchos gracious amigo.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top