Commande random() [Résolu]

NivekR 87 Messages postés mercredi 1 octobre 2008Date d'inscription 28 avril 2009 Dernière intervention - 9 avril 2009 à 20:53 - Dernière réponse : Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention
- 10 avril 2009 à 17:27
Bonsoir à tous et à toute,

Voilà, je suis en 1ère année de DEUST Informatique à Orsay et je dois créer une application (celle que l'on veut) avec DELPHI.

Je me suis donc lancé dans la création d'un programme regroupant plusieurs jeux de hasard.
Pour le moment je planche sur le 421 et le poker.
Pour commencer, je suis sous VISTA Pro et je programme sous DELPHI 6.

Et voilà mes deux soucis du moment :

- Pour le 421, la commande 'random()', me donne bien des nombres aléatoires dans l'intervalle que je veux, mais toujours dans un même ordre.
Je m'explique, je clique sur le bouton 'Lancé n°1', il me sort 3 chiffres au hasard, je quitte l'application, je reviens et je clique de nouveau sur le bouton, et les 3 mêmes chiffres réapparaissent. Et cela à chaque fois...
En gros, ce sont les même séries de chiffres qui se suivent dans un même ordre.
Comment éviter cela???
C'est le seul soucis que j'ai sur ce jeu

- Pour le poker, c'est plus délicat (enfin je crois)
Comment peut-on éviter les doublons?
Je m'explique, dans un jeu de carte il n'y a pas 2 cartes ayant même valeur ET même couleur mais la commande 'random()' s'en fiche...
Comment éviter cela?

N'hésitez pas à me poser des questions pour de plus amples informations.

Je vous remercie d'avance.
Bonne soirée.

Cordialement,
Kevin.

PS : Si vous ne voyez pas trop de quoi je parle, je peux vous envoyer l'exécutable pour que vous fassiez le test.
       Si vous désirez voir les lignes de commande, je ne peux le faire sur le forum car il y a beaucoup de lignes :S (En comptant toutes les lignes, j'en ai 275
Afficher la suite 

31 réponses

Répondre au sujet
Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention - 9 avril 2009 à 21:27
+3
Utile
Utilise randomize dans le OnCreate de ta fiche pour initialiser le générateur de nombres aléatoires. Et tu verras ça marchera directement beaucoup plus aléatoirement :)

Cordialement, Bacterius !
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Bacterius
Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention - 9 avril 2009 à 21:31
0
Utile
Et pour ta seconde question, il faudra utiliser un tri sélectif :

1. Tu fais une liste d'éléments contenant toutes les cartes du jeu.
2. Tu en tires une au hasard dans la liste.
3. Tu la retire de la liste (on ne la tirera plus).
4. Recommencer à partir de l'étape 2 jusqu'à la fin de la liste.

Cordialement, Bacterius !
Commenter la réponse de Bacterius
NivekR 87 Messages postés mercredi 1 octobre 2008Date d'inscription 28 avril 2009 Dernière intervention - 9 avril 2009 à 21:37
0
Utile
Merci beaucoup Bacterius :)

Je connaissais la commande 'randomize()' mais je ne savais pas où la mettre, je n'avais pas pensé à la création de la fiche^^ C'est nickel!!!!!

Thank you :P

Pour le poker, la 1ère étape est faite.
Par contre je ne sais pas comment retirer un élément d'un tableau/d'une liste, comment fait-on?
Commenter la réponse de NivekR
Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention - 9 avril 2009 à 21:40
0
Utile
Ben tu peux par exemple utiliser une TList (et à la place des pointeurs, mettre des nombres, utiliser la fonction Ptr pour convertir en pointeur), puis quand tu veux supprimer un élément de la liste du fais List.Delete(Index), puis List.Pack pour supprimer les nils. List.Count donne le nombre d'éléments, donc pour boucler sur la liste, for I := 0 to List.Count - 1 do ...

Cordialement, Bacterius !
Commenter la réponse de Bacterius
NivekR 87 Messages postés mercredi 1 octobre 2008Date d'inscription 28 avril 2009 Dernière intervention - 9 avril 2009 à 21:50
0
Utile
D'accord, je vais regarder tout cela :)

Mais, est-ce possible de supprimer une 'case' à un tableau?
Car voici le code que j'ai pour le moment :

Le 1er, avec 2 tableaux :
Désolé si je répète certaines choses, mais je m'y repère mieux :)

"var
  SecondJeu: TSecondJeu;
  Valeur: Array [0..12] of String;
  Couleur: Array [0..3] of String;

procedure TSecondJeu.Tirage1Click(Sender: TObject);
begin
Valeur[0]:='As';
Valeur[1]:='Deux';
Valeur[2]:='Trois';
Valeur[3]:='Quatre';
Valeur[4]:='Cinq';
Valeur[5]:='Six';
Valeur[6]:='Sept';
Valeur[7]:='Huit';
Valeur[8]:='Neuf';
Valeur[9]:='Dix';
Valeur[10]:='Valet';
Valeur[11]:='Dame';
Valeur[12]:='Roi';
edVal1.Text:=Valeur[random(13)];
edVal2.Text:=Valeur[random(13)];
edVal3.Text:=Valeur[random(13)];
edVal4.Text:=Valeur[random(13)];
edVal5.Text:=Valeur[random(13)];
Couleur[0]:='Coeur';
Couleur[1]:='Carreau';
Couleur[2]:='Trèfle';
Couleur[3]:='Pique';
edCoul1.Text:=Couleur[random(4)];
edCoul2.Text:=Couleur[random(4)];
edCoul3.Text:=Couleur[random(4)];
edCoul4.Text:=Couleur[random(4)];
edCoul5.Text:=Couleur[random(4)];
Tirage1.Enabled:=false;
end;

procedure TSecondJeu.Tirage2Click(Sender: TObject);
begin
Valeur[0]:='As';
Valeur[1]:='Deux';
Valeur[2]:='Trois';
Valeur[3]:='Quatre';
Valeur[4]:='Cinq';
Valeur[5]:='Six';
Valeur[6]:='Sept';
Valeur[7]:='Huit';
Valeur[8]:='Neuf';
Valeur[9]:='Dix';
Valeur[10]:='Valet';
Valeur[11]:='Dame';
Valeur[12]:='Roi';
if Garder1.Checked=true
then edVal1.Enabled:=false
else edVal1.Text:=Valeur[random(13)];
if Garder2.Checked=true
then edVal2.Enabled:=false
else edVal2.Text:=Valeur[random(13)];
if Garder3.Checked=true
then edVal3.Enabled:=false
else edVal3.Text:=Valeur[random(13)];
if Garder4.Checked=true
then edVal4.Enabled:=false
else edVal4.Text:=Valeur[random(13)];
if Garder5.Checked=true
then edVal5.Enabled:=false
else edVal5.Text:=Valeur[random(13)];
Couleur[0]:='Coeur';
Couleur[1]:='Carreau';
Couleur[2]:='Trèfle';
Couleur[3]:='Pique';
if Garder1.Checked=true
then edCoul1.Enabled:=false
else edCoul1.Text:=Couleur[random(4)];
if Garder2.Checked=true
then edCoul2.Enabled:=false
else edCoul2.Text:=Couleur[random(4)];
if Garder3.Checked=true
then edCoul3.Enabled:=false
else edCoul3.Text:=Couleur[random(4)];
if Garder4.Checked=true
then edCoul4.Enabled:=false
else edCoul4.Text:=Couleur[random(4)];
if Garder5.Checked=true
then edCoul5.Enabled:=false
else edCoul5.Text:=Couleur[random(4)];
Tirage2.Enabled:=false;
end;"

Le 2nd, avec un seul :
Seul une carte est tirée, mais la suite du code ressemblera au premier :)

"var
  Form1: TForm1;
  Carte : Array [0..51] of String;

procedure TForm1.Button1Click(Sender: TObject);
begin
Carte[0]:='As de Carreau';
Carte[1]:='Deux de Carreau';
Carte[2]:='Trois de Carreau';
Carte[3]:='Quatre de Carreau';
Carte[4]:='Cinq de Carreau';
Carte[5]:='Six de Carreau';
Carte[6]:='Sept de Carreau';
Carte[7]:='Huit de Carreau';
Carte[8]:='Neuf de Carreau';
Carte[9]:='Dix de Carreau';
Carte[10]:='Valet de Carreau';
Carte[11]:='Dame de Carreau';
Carte[12]:='Roi de Carreau';
Carte[13]:='As de Coeur';
Carte[14]:='Deux de Coeur';
Carte[15]:='Trois de Coeur';
Carte[16]:='Quatre de Coeur';
Carte[17]:='Cinq Coeur';
Carte[18]:='Six de Coeur';
Carte[19]:='Sept de Coeur';
Carte[20]:='Huit de Coeur';
Carte[21]:='Neuf de Coeur';
Carte[22]:='Dix de Coeur';
Carte[23]:='Valet de Coeur';
Carte[24]:='Dame de Coeur';
Carte[25]:='Roi de Coeur';
Carte[26]:='As de Pique';
Carte[27]:='Deux de Pique';
Carte[28]:='Trois de Pique';
Carte[29]:='Quatre de Pique';
Carte[30]:='Cinq de Pique';
Carte[31]:='Six de Pique';
Carte[32]:='Sept de Pique';
Carte[33]:='Huit de Pique';
Carte[34]:='Neuf de Pique';
Carte[35]:='Dix de Pique';
Carte[36]:='Valet de Pique';
Carte[37]:='Dame de Pique';
Carte[38]:='Roi de Pique';
Carte[39]:='As de Trefle';
Carte[40]:='Deux de Trefle';
Carte[41]:='Trois de Trefle';
Carte[42]:='Quatre de Trefle';
Carte[43]:='Cinq de Trefle';
Carte[44]:='Six de Trefle';
Carte[45]:='Sept de Trefle';
Carte[46]:='Huit de Trefle';
Carte[47]:='Neuf de Trefle';
Carte[48]:='Dix de Trefle';
Carte[49]:='Valet de Trefle';
Carte[50]:='Dame de Trefle';
Carte[51]:='Roi de Trefle';
Edit1.Text:=Carte[random(52)];"
Commenter la réponse de NivekR
Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention - 9 avril 2009 à 21:57
0
Utile
Ben regarde ce que je te propose, moi, une technique que tu pourrais utiliser (pas trop difficile à mettre en oeuvre !) :

procedure Shuffle(List: TList);
Var
I: Integer;
begin
{ Il faut avoir appellé randomize avant ! }
for I := 0 to List.Count - 1 do
List.Exchange(random(List.Count), random(List.Count));
{ On effectue une sorte de mélange ... }
end;

function Tirage(var Position: Integer; List: TList): TCarte;
begin
if Position => List.Count then Exit;
Result := TCarte(List.Items[Position]);
Inc(Position);
end;

Position est une valeur que tu dois initialiser au début.

Et TCarte est enregistré ainsi :

type
TCarte=record
Groupe: Byte; {1 pour trefle, 2 pour carreau, etc ... }
Couleur: Byte; { 1 pour noir, 2 pour rouge par exemple }
Nom: Byte; { 1 pour 1, 2 pour 2, 11 pour valet, 12 pour reine, etc ... }
end;

Le principe ici est de mélanger la liste, puis de tirer les cartes 1 par 1 (en gardant une variable pour se souvenir de la position actuelle du tirage).
Pour nouveau tirage, appeller Shuffle, puis tirer les cartes avec Tirage :)
Dis-moi ce que tu penses de cette méthode ?

Cordialement, Bacterius !
Commenter la réponse de Bacterius
NivekR 87 Messages postés mercredi 1 octobre 2008Date d'inscription 28 avril 2009 Dernière intervention - 9 avril 2009 à 22:06
0
Utile
Je vais essayer^^
Je suis novice en Delphi et programmation :(
J'apprends vite mais j'ai beaucoup de chose à apprendre :p
Commenter la réponse de NivekR
NivekR 87 Messages postés mercredi 1 octobre 2008Date d'inscription 28 avril 2009 Dernière intervention - 9 avril 2009 à 22:25
0
Utile
Et bien, c'est un échec :(

Je comprends où tu veux en venir, mais je ne vois pas le plan que je dois suivre et je ne sais pas ce que je dois mettre :(
Désolé...

Merci de m'avoir aidé^^
Commenter la réponse de NivekR
Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention - 9 avril 2009 à 22:30
0
Utile
Imagine une liste de nombres (pour l'explication, on ne parlera pas de cartes). Pour obtenir une liste aléatoire, je te propose de mélanger la liste. D'abord, tu remplis ta liste avec des nombres aléatoires, puis tu appelles Shuffle.
Puis, tu remplis une ListBox de tous les nombres de la liste, un par un (ils seront mélangés).
Voilà en fait le principe. Tu as peut-être oublié de remplir la liste avant ?

Cordialement, Bacterius !
Commenter la réponse de Bacterius
NivekR 87 Messages postés mercredi 1 octobre 2008Date d'inscription 28 avril 2009 Dernière intervention - 9 avril 2009 à 22:32
0
Utile
Et bien, en fait, que veux-tu dire par List? Dans les menus de Delphi je ne voie que la ListBox :( C'est celle-là dont tu parles?
Commenter la réponse de NivekR
Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention - 9 avril 2009 à 22:37
0
Utile
Ah non non en fait je parles de la TList (ce n'est pas un composant mais une classe).

Tu fais comme ça (mais il faudra déclarer en local) :

procedure TestList;
var
List: TList;
begin
List := TList.Create;
List.Add(Ptr(7));
ShowMessage(IntToStr(Longword(List.Items[0])));
List.Free;
end;

Ici, on crée la liste, on ajoute le nombre 7 dans le premier élément de la liste, on affiche un message contenant le premier nombre de la liste (normalement 7), puis on libère la liste.

Cordialement, Bacterius !
Commenter la réponse de Bacterius
NivekR 87 Messages postés mercredi 1 octobre 2008Date d'inscription 28 avril 2009 Dernière intervention - 9 avril 2009 à 22:45
0
Utile
Aaaah, lOl :P
Désolé, je suis sur ce projet depuis quelques heures déjà (plus d'une dizaine d'un coup :) ) et j'ai un peu de mal :p

Est-ce cela que tu voulais?
procedure List1;
var Val: TList;
begin
Val := TList.Create;
Val.Add(Ptr(1));
Val.Add(Ptr(2));
Val.Add(Ptr(3));
Val.Add(Ptr(4));
Val.Add(Ptr(5));
Val.Add(Ptr(6));
Val.Add(Ptr(7));
Val.Add(Ptr(8));
Val.Add(Ptr(9));
Val.Add(Ptr(10));
Val.Add(Ptr(11));
Val.Add(Ptr(12));
Val.Add(Ptr(13));
end;

procedure List2;
var Coul: TList;
begin
Coul := TList.Create;
Coul.Add(Ptr(1));
Coul.Add(Ptr(2));
Coul.Add(Ptr(3));
Coul.Add(Ptr(4));
Commenter la réponse de NivekR
f0xi 4304 Messages postés samedi 16 octobre 2004Date d'inscription 9 mars 2018 Dernière intervention - 10 avril 2009 à 02:31
0
Utile
voici comment utiliser random :

aprés avoir initialisé Randomise dans le create de la fiche ou l'initialization de l'unité,

il faut utiliser un comme comme ceci :

var
  OldRandom : integer;

function UnicRand(const R: integer): integer;
begin
  Result := Random(R);
  while Result = OldRandom do
    Result := Random(R);
end;

pour les boolean dans les conditions il n'est pas necessaire de faire ceci :

if Booleen = true then
ou
if Booleen = false then

mais faire :

if Booleen then
et
if not Booleen then

pour les tableaux tu peux les initialiser dans la declaration (const ou var) :

var
  Couleur : array[0..3] of string = ('pic', 'coeur', 'trefle', 'carreau');

pour ensuite appeler un valeur aleatoirement choisie de ce tableau fait :

V := Couleur[ UnicRandom( Length(Couleur) ) ];

Length(couleur) renverra 4, qui est le nombre d'element dans le tableau (de 0 a 3)
Random renvoyant des nombres entre 0 et X-1 nous aurons bien les chiffres aleatoire de 0 a 3 a chaque fois.
de plus, il n'y aura jamais deux couleur identique a la suite grace a la fonction UnicRandom.
donc impossible de tomber sur une suite : 0 2 0 3 3 0 2 0 1 1 1 3 0 1

Commenter la réponse de f0xi
JulioDelphi 2354 Messages postés dimanche 5 octobre 2003Date d'inscription 18 novembre 2010 Dernière intervention - 10 avril 2009 à 08:00
0
Utile
Je ne suis pas d'accord avec ton random pour lancer un dé ni tirer une carte :
1) Tu peux lancer 2/3/4... dés et faire 2 fois de suite le même chiffre, c'est normal et largement possible.
2) Si il n'utilise que ce random pour tirer des cartes, si il en tire au moins 3, il peut se retrouver avec 2 cartes identiques
ps : je parle de ce random :
var
  OldRandom : integer;

function UnicRand(const R: integer): integer;
begin
  Result := Random(R);
  while Result = OldRandom do
    Result := Random(R);
end;
Commenter la réponse de JulioDelphi
Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention - 10 avril 2009 à 14:40
0
Utile
Moi je trouve que ma solution est pas trop mal, mélanger les cartes et les tirer 1 par 1. C'est comme ça qu'on fait au poker et si on a pas changé c'est que ça marche ?

Cordialement, Bacterius !
Commenter la réponse de Bacterius
JulioDelphi 2354 Messages postés dimanche 5 octobre 2003Date d'inscription 18 novembre 2010 Dernière intervention - 10 avril 2009 à 14:54
0
Utile
Pour les cartes, il existe des milliers de sources quasi identiques et utilisent une Card.DLL donc "yakaregarder"
Commenter la réponse de JulioDelphi
Caribensila 2671 Messages postés jeudi 15 janvier 2004Date d'inscription 18 janvier 2018 Dernière intervention - 10 avril 2009 à 16:13
0
Utile
Salut,

Pour un tirage aléatoire sans doublon, je fais comme ça :

{Cette procédure mélange aléatoirement n'importe quel
tableau. Ici, ce sont des chaînes, mais la procedure
serait la même pour un tableau de n'importe quel autre Type.
Il suffirait de changer « var Tab : array of MonType »}
procedure GetRandomArray(var Tab : array of string);
var RandomIndex, LastIndex : Integer;
TempVal : Variant;
begin
LastIndex := length(Tab);
while LastIndex>1 do begin
RandomIndex := Random(LastIndex);
TempVal := Tab[RandomIndex];
Tab[RandomIndex] := Tab[LastIndex-1];
Tab[LastIndex-1] := TempVal;
Dec(LastIndex);
end;
end;

{Exemple d'utilisation.}
procedure TForm1.Button1Click(Sender: TObject);
var i : Integer;
Tab : array of String;
begin
SetLength(Tab, 5);
for i := 0 to High(Tab) do Tab[i] := IntToStr(i);// -->[0,1,2,3,4]
GetRandomArray(Tab); //-->[1,3,2,4,0], par exemple.
for i := 0 to High(Tab) do Memo1.Lines.Add(Tab[i]);//Vérification.
end;


On pourrait ainsi mélanger aléatoirement sans doublon n'importe quel type, pas forcément ordinal.
Commenter la réponse de Caribensila
Caribensila 2671 Messages postés jeudi 15 janvier 2004Date d'inscription 18 janvier 2018 Dernière intervention - 10 avril 2009 à 16:19
0
Utile
Tiens?!
On dirait que ça beugue...
Nouvel essai:

{Cette procédure mélange aléatoirement n'importe quel
tableau. Ici, ce sont des chaînes, mais la procedure
serait la même pour un tableau de n'importe quel autre Type.
Il suffirait de changer « var Tab : array of MonType »}
procedure GetRandomArray(var Tab : array of string);
var RandomIndex, LastIndex : Integer;
TempVal : Variant;
begin
LastIndex := length(Tab);
while LastIndex>1 do begin
RandomIndex := Random(LastIndex);
TempVal := Tab[RandomIndex];
Tab[RandomIndex] := Tab[LastIndex-1];
Tab[LastIndex-1] := TempVal;
Dec(LastIndex);
end;
end;

{Exemple d'utilisation.}
procedure TForm1.Button2Click(Sender: TObject);
var i : Integer;
Tab : array of String;
begin
//Randomize;
SetLength(Tab, 5);
for i := 0 to High(Tab) do Tab[i] := IntToStr(i);// -->[0,1,2,3,4]
GetRandomArray(Tab); //-->[1,3,2,4,0], par exemple.
for i := 0 to High(Tab) do Memo1.Lines.Add(Tab[i]);//Vérification.
end;


On pourrait mélanger aléatoirement sans doublon n'importe quel type, pas forcément ordinal.
Commenter la réponse de Caribensila
Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention - 10 avril 2009 à 16:26
0
Utile
Oh c'est l'idée que je proposais il y a 5 posts dites-donc ! Mélanger le tableau puis tirer comme d'habitude (0 .. Count - 1) ...
Parfois j'ai l'impression que mon avatar n'est pas assez visible ... ^^

Cordialement, Bacterius !
Commenter la réponse de Bacterius
Caribensila 2671 Messages postés jeudi 15 janvier 2004Date d'inscription 18 janvier 2018 Dernière intervention - 10 avril 2009 à 16:33
0
Utile
:)))

Si tu regardes mieux, Bacterius, tu verras que je ne mélange pas comme toi. ^^
Commenter la réponse de Caribensila

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.

Commande random() - page 2