Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi random zahl genau 2 mal (https://www.delphipraxis.net/4415-random-zahl-genau-2-mal.html)

wo0zy 28. Apr 2003 14:40


random zahl genau 2 mal
 
hallo, ich hab eine form mit 36 buttons und ich will das in der caption der buttons eine zahl steht. hierbei besteht nun mein problem, ich will eine art memory machen und dazu brauch ich also 18 zahlen, jede aber 2 mal. und damit das spiel nicht langweilig ist, sollen die zahlen zufällig angeordnet werden.

das mit dem zufall is nich das problem, sondern das die zahl genau 2mal vorkommt, nicht weniger und nicht mehr

Mirilin 28. Apr 2003 14:56

Könntest ein Array nehmen, das die 36 Werte enthält und dann durchmischeln...

wo0zy 28. Apr 2003 14:57

hmm...wie geht das denn??

oki 28. Apr 2003 15:23

Hi,

noch ne Lösung:

Ermittel 16 Zufallszahlen und verteile diese incl. ihrer Duplikate per Zufallsgenerator auf die 32 Buttons.

So nach dem Motto wenn erst mal die 16 Zufallszahlen ermittelt sind (und zwischenspeichern; Array ist da eine Lösung) dann nächste Schleife (Anzahl 32 für die Buttons) und 32 Zufallszahlen zwischen 1 und 32 ermitteln und Werte zuweisen. hierbei prüfen, dass ein Button nicht zweimal belegt wird.

Gruß oki

MrSpock 28. Apr 2003 15:29

Hallo wo0zy,

wir hatten ähnliche Fragen schon mal in der Vergangenheit diskutiert. Suche mal in unserem Forum nach "Zufall". Dieser Thread scheint auf dein Problem zu passen!?

ssach 29. Apr 2003 22:02

loesung
 
hy,

denke auch du nimmst 16 zufallszahlen + 16 dublikate und daach mir random jede zahl 2mal versenden!

und beim random schleisst du jedes mal 2 buttons aus die du rausschreeiwst oder si einfach deaktiviert, so kannst du ne if abfrage starten mir
:
Delphi-Quellcode:
if (btnX.Enabled = true) then
   btnX.Caption := ZAHL;
ciao :P

[edit=Daniel B]BB-Code wieder eingeschaltet, damit die Tags funktionieren. MfG Daniel B.[/edit]

Specialwork 30. Apr 2003 01:07

Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Woozy,

Versuchs doch mal so:

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
end;

procedure TForm1.Button1Click(Sender: TObject);
var Values: TStringList;
    x, y: Integer;
    Rnd: Integer;
    CurrentIndex, NewIndex: Integer;
begin
  Values:=TStringList.Create;
  Values.Duplicates:=dupIgnore;

  // Zufallswerte erzeugen
  While Values.Count < 32 do begin
    Rnd:=random(60);
    Values.Add(inttostr(rnd));
    Values.Add(inttostr(rnd));
  end;

  // Zufallswerte mischen
  y:=random(9999);
  for x:=1 to y do begin
    CurrentIndex:=random(Values.Count);
    NewIndex:=random(Values.Count);
    While CurrentIndex=NewIndex do begin
      CurrentIndex:=random(Values.Count);
      NewIndex:=random(Values.Count);
    end;
    Values.Move(CurrentIndex, NewIndex);
  end;

  // Zufallswerte zuweisen
  for x:=0 to ComponentCount-1 do begin
    if Components[x].ClassType =TSpeedButton then begin
      (Components[x] as TSpeedButton).Tag:=strtoint(Values.Strings[x]);
      if CheckBox1.Checked then begin
        (Components[x] as TSpeedButton).Glyph:=nil;
        (Components[x] as TSpeedButton).Caption:='';
        ImageList1.GetBitmap(strtoint(values.Strings[x]), (Components[x] as TSpeedButton).Glyph);
      end else begin
        (Components[x] as TSpeedButton).Glyph:=nil;
        (Components[x] as TSpeedButton).Caption:=Values.Strings[x];
      end;
    end;
  end;

  Values.Free;
end;
Einziger Nachteil, es werden mehrere gleiche Paare angezeigt.

Gruß, Tom

Jens Schumann 30. Apr 2003 07:48

Hallo,
ich würde das Problem so lösen:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons;

const

  MaxMemoryArray = 32;

type

  TMemoryArray = Array[1..MaxMemoryArray] of Integer;

  TForm1 = class(TForm)
    Button1: TButton;
    SpeedButton1: TSpeedButton;
    SpeedButton2: TSpeedButton;
    SpeedButton3: TSpeedButton;
    SpeedButton4: TSpeedButton;
    SpeedButton5: TSpeedButton;
    SpeedButton6: TSpeedButton;
    SpeedButton7: TSpeedButton;
    SpeedButton8: TSpeedButton;
    SpeedButton9: TSpeedButton;
    SpeedButton10: TSpeedButton;
    SpeedButton11: TSpeedButton;
    SpeedButton12: TSpeedButton;
    SpeedButton13: TSpeedButton;
    SpeedButton14: TSpeedButton;
    SpeedButton15: TSpeedButton;
    SpeedButton16: TSpeedButton;
    SpeedButton17: TSpeedButton;
    SpeedButton18: TSpeedButton;
    SpeedButton19: TSpeedButton;
    SpeedButton20: TSpeedButton;
    SpeedButton21: TSpeedButton;
    SpeedButton22: TSpeedButton;
    SpeedButton23: TSpeedButton;
    SpeedButton24: TSpeedButton;
    SpeedButton25: TSpeedButton;
    SpeedButton26: TSpeedButton;
    SpeedButton27: TSpeedButton;
    SpeedButton28: TSpeedButton;
    SpeedButton29: TSpeedButton;
    SpeedButton30: TSpeedButton;
    SpeedButton31: TSpeedButton;
    SpeedButton32: TSpeedButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
    FMemoryArray : TMemoryArray;
    procedure FillArray;
    procedure Scramble;
    procedure SetSpeedButtons;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Randomize; // Zufallsgenerator initialisieren
  FillArray;
  Scramble;
  SetSpeedButtons;
end;

procedure TForm1.FillArray;
var
  iCnt : Integer;
  jCnt : Integer;
  Ok  : Boolean;
begin
  {Die Schleife muss nur über das halbe Array laufen, da ja Paare im Array
   stehen sollen.}
  For iCnt:=Low(FMemoryArray) to High(FMemoryArray) div 2 do
    begin
    Repeat
      Ok:=True;
      FMemoryArray[iCnt]:=Random(100); // liefere Zahlen im Bereich 0 bis 99
      //Prüfe, ob die Zahl im Array vorhanden ist
      For jCnt:=Low(FMemoryArray) to iCnt-1 do
        begin
        If FMemoryArray[iCnt]=FMemoryArray[jCnt] then
          begin
          Ok:=False; // Wenn vorhanden, dann Ok:=False damit neue Zahl "gezogen wird"
          Break;
          end; // If FMemoryArray[iCnt]=FMemoryArray[jCnt] then
        end; // For jCnt:=Low(FMemoryArray) to iCnt-1 do
    Until Ok;
    {Schreibe den "Partner" an die Stelle iCnt+High(FMemoryArray) div 2 im Array.
     Dadurch wird das Paar erzeugt.}
    FMemoryArray[iCnt+High(FMemoryArray) div 2]:=FMemoryArray[iCnt];
    end; // For iCnt:=Low(FMemoryArray) to High(FMemoryArray) div 2 do
end;

procedure TForm1.Scramble;
var
  iCnt : Integer;
  jCnt : Integer;
  Swap : Integer;
begin
  For iCnt:=Low(FMemoryArray) to High(FMemoryArray) do
    begin
    jCnt:=Random(High(FMemoryArray))+1; // wähle einen zufälligen Index in FMemoryArray
    Swap:=FMemoryArray[iCnt];
    FMemoryArray[iCnt]:=FMemoryArray[jCnt];
    FMemoryArray[jCnt]:=Swap;
    end;
end;

procedure TForm1.SetSpeedButtons;
var
  iCnt            : Integer;
  SpeedButton     : TSpeedButton;
begin
  For iCnt:=Low(FMemoryArray) to High(FMemoryArray) do
    begin
    SpeedButton:=TSpeedButton(FindComponent('SpeedButton'+IntToStr(iCnt)));
    SpeedButton.Caption:=IntToStr(FMemoryArray[iCnt]);
    end; // For iCnt:=Low(FMemoryArray) to High(FMemoryArray) div 2 do
end;

end.
Achtung: Die Größe des Array korespondiert mit der Anzahl der TSpeedButtons

wo0zy 30. Apr 2003 10:31

ich hab das ganze jetzt mal gemacht wie jens, und das funzt auch, doch nun wollte ich das spiel erweitern, undzwar sollen immer dann die letzen beiden buttons verschwinden, wenn diese die gleich caption haben. das ganze hab ich so gemacht
Code:
procedure TForm1.OnBtnClick(Sender: TObject);
var
 Sender1:TObject;
  begin
    If Sender is TFlatBtn then
      count:=count+1;
    if count=1 then
      Sender1:=Sender;
    if count=2 then begin
      count:=0;
        if (Sender1 as TFlatBtn).Caption=(Sender as TFlatBtn).Caption then begin
          //(Sender as TFlatBtn).Color:=clRed;
          (Sender as TFlatBtn).hide;
          //(Sender1 as TFlatBtn).Color:=clRed;
          (Sender1 as TFlatBtn).hide;
        end;
    end;
  end;
doch
Code:
if (Sender1 as TFlatBtn).Caption=(Sender as TFlatBtn).Caption
wird nie erreicht, vor dem erreichen bekomme ich immer folgenden fehler
Zitat:

Im Projekt Memory.exe ist eine Exception der Klasse EAccesViolation aufgetreten. Meldung:'Zugriffsverletzung bei Adresse 004032E8 in Modul 'MEMORY.EXE'. LEsen von Adresse 66D88B2F'...
woran liegt das??

Jens Schumann 30. Apr 2003 10:39

Hallo,
das liegt daran, das Du Sender1 als lokale Variable deklariert hast.
Wenn Du aus Sender1 ein Formularfeld machst sollte es klappen.

wo0zy 30. Apr 2003 10:54

Zitat:

Zitat von Jens Schumann
...
Wenn Du aus Sender1 ein Formularfeld machst sollte es klappen.

is das ein anderer begriff für globale variablen? damit hats nämlich geplappt

danke

Jens Schumann 30. Apr 2003 11:03

Hallo

Zitat:

Zitat von wo0zy
is das ein anderer begriff für globale variablen? damit hats nämlich geplappt

NEIN !!!

Bei einem Formularfeld handelt es sich um eine "Variable" innerhalb des Formularobjektes. Eine globale Variable wir innerhalb des Interface-Abschnittes einer Unit mit var deklariert.

Beispiel:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private-Deklarationen }
    FVariable : TObject; // Dies ist ein Formularfeld
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  Variable : TObject; // Dies ist eine globale Variable

implementation

{$R *.dfm}

end.
Jetzt stellt sich die Frage, welcher Denkschule man angehört. Ich vertrete die Denkschule, dass eine globale Variable eine Designschwäche anzeigt. D.h. verwende globale Variabeln nur, wenn Dir absolut nichts besseres einflällt und rede nicht darüber.

wo0zy 30. Apr 2003 12:29

ich hab da mal noch eine frage, wie bekomme ich raus ob auf btn32 oder btn2 geklickt wurde, also ich brauch die zahl hinter btn, kann ich tobject einfach in einen string umwandeln oder wie muss ich das machen??

Jens Schumann 30. Apr 2003 12:39

Hallo,
welcher Button angeklickt wurde verrät dir der Parameter Sender.

wo0zy 30. Apr 2003 12:40

is mir schon klar, aber ich muss wissen welche nummer der hat

Jens Schumann 30. Apr 2003 12:42

Hallo,
Du kannst in der SetSpeedButton Methode die Tag-Property der
SpeedButtons auf iCnt setzen. Im OnClick-Handler kannst Du dann
über TControl(Sender).Tag darauf zugreiffen.

Touchdown 30. Apr 2003 13:57

Willst du viele Buttons auf eine Methode laufen lassen willst, dann nimm besser Tags dafür, die natürlich von Hand vergeben werden müssen.

Delphi-Quellcode:
case TButton(Sender).Tag of
  0 : result := 'ein schöner Tag';
  1 : Result := 'ein wundervoller Tag';
end;
PS: Nicht Tag und Tag verwechseln :mrgreen:

Specialwork 30. Apr 2003 14:56

Hallo Woozy,

Schau Dir doch einfach mal mein Beispiel an, da ist das mit den Tags schon umgesetzt.

Gruß, Tom


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:22 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz