[DELPHI] Kaarten

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Anoniem: 78378

Topicstarter
Ik ben bezig met het maken van een kaartspel in Delphi. Het spel heet bluffen zoals sommige wel zullen kennen onder misschien een andere naam.
Ik ben nu bezig met een kaarten deel functie maar het wil niet echt goed lukken.

Het is de bedoeling dat 4 speler 2 kaarten krijgen. De kaarten die mee doen zijn 7,8,9,10,boer,vrouw,koning,aas.
Eerst krijgt speler 1 , 1 kaart van de stapel, dan speler 2, 1, dan speler 3, 1 en dan krijgt speler 4 nog een kaart. Dan weer speler 1, dan 2, dan 3, en dan 4.
Hoe kan ik dit voor elkaar krijgen zodat er random kaarten worden gekozen en dat kaarten niet meerdere keren voorkomen. Ik heb zelf al een ini bestand toegewezen met de kaart namen onder de strings 1,2,3,4,5......31,32
Nu moet ik dus een functie vinden die als je op een button drukt dat ie speler 1 een random kaart geeft, speler 2 een random kaart,etc... en dan ook nog eens zo dat de kaarten maar een maal voorkomen.

De volgende functie heb ik zelf gemaakt hievoor maar die geeft 2 problemen:

procedure TForm1.Button1Click(Sender: TObject);
var DelphiIni : TInifile;
q : string;
nloop : integer;
begin
q := IntToStr(Random (32));
listbox2.clear;
begin
for nloop := 0 to pred( listbox1.items.count ) do
if q = listbox1.items[ nloop ]
then
listbox2.Items.Add ('bla');
end;
if listbox2.items.count < 1 then
begin
Listbox1.Items.Add (q);
DelphiIni := TIniFile.Create('c:\windows\Kaarten.ini');
Edit1.text := DelphiIni.ReadString ('Kaarten', q, 'BlaBla');
DelphiIni.Free;
end;

Hierbij staat listbox1 voor de gebruikte getalen en listbox2 word bla toegevoegd als het getal al is gebruikt zodat de functie opnieuw zoekt naar een nieuw getal.
Het probleem is dat hoe minder kaarten er nog over zijn hoe langer het gaat duren totdat de random functie dat getal heeft gevonden. De kans dat hij dit getal van de laatste kaart die ngo over is vindt is per keer dus 3% en niet te doen. Er moet dus een andere functie worden bedacht.

Ik dacht zelf aan een aray van de nummers 1 tot 32 die ieder voor een apparte kaart in het ini bestand staan. maar voor zover ik weet is het niet mogelijk om een nummer uit een aray te verwijderen dus zal dit niet lukken.

Wie kan mij hieruit helpen. Het moet namelijk een zeer doordachte functie wezen een echte uitdaging dus!

Acties:
  • 0 Henk 'm!

  • Exirion
  • Registratie: Februari 2000
  • Laatst online: 23:46

Exirion

Gadgetfetisjist

Dit soort dingen behoren tot de basis van datatypen en algoritmen. Ga eerst eens een logische oplossing bedenken voor het kiezen van nummers uit een voorgedefinieerde verzameling, zonder meteen in termen van Delphi functies en componentjes te denken.

"Logica brengt je van A naar B, verbeelding brengt je overal." - Albert Einstein


Acties:
  • 0 Henk 'm!

Anoniem: 78378

Topicstarter
dat heb ik dus gedaan, ik dacht het volgende:
je hebt een verzameling met getallen 1 tot 32. Uit deze verzameling kiest een functie random 2 getallen per speler. Dan worden deze 2 gekozen getallen gewist uit de verzameling en is de volgende speler aan de beurt. Maar ik zou niet weten hoe dit practisch is op te lossen. Ik kan de manier wel bedenken maar niet de uitvoering in code. Moet ik arays gebruiken volgens mij niet namelijk, zulke dingen, daarom vraag ik om help. Ik heb er al een aantal dagen over na gedacht om dit te doen en daarom post ik ook mijn code om zo te laten zien dat ik er serieus mee bezig ben geweest en niet dood leuk een code wil kopieëren van dit forum!

Maar alvast bedankt, kzal mn hersenen zelf ook nog ff laten kraken! Als iemand het antwoord weet zou ik het graag willen horen!

P.S. ik denk dat het iets in de vorm moet zijn van een verzameling die alle namen van kaarten bevat. Er is een functie die random een positie in deze verzameling kiest (dus random(32) bijvoorbeeld bij 1e keer delen) de output krijgt deze kaart en de kaart naam wordt verwijdert uit de verzameling. Dan herhaalt het zich maar dan een random getal uit (random(31)). Hoe krijg ik zoiets voor elkaar?

[ Voor 20% gewijzigd door Anoniem: 78378 op 11-02-2003 12:56 ]


Acties:
  • 0 Henk 'm!

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 23:57

Reptile209

- gers -

Wat een makkelijkere aanpak is, is om een array met al je kaarten te maken en die dan te schudden. Als je dat gedaan hebt, kan je gewoon je array van 1 tot n leegtrekken met random kaarten. Want inderdaad: de wachttijd op de laatste kaart zou met jouw methode wel verschrikkelijk lang kunnen worden, aangezien de kans op dat nummer 1/32 is...

Zo scherp als een voetbal!


Acties:
  • 0 Henk 'm!

Anoniem: 37817

Het kan vrij simpel met een array, een counter en een index:

Je vult het array met 1 t/m32;
Je zet de counter op 32;
je trekt random een index tot max de counter;
De speler krijgt het de kaart array[index];
je verruilt array[index] met array[counter] en je verlaagt counter met 1;

nu krijg je iedere keer in een keer een nog niet gebruikte kaart.
Veel plezier ermee

Acties:
  • 0 Henk 'm!

Anoniem: 78378

Topicstarter
Dat zei ik jah, mijn methode is niet goed. Maar hoe kan je een array een andere volgorde geven aan het begin als hij gedeclareerd wordt dan? Ik heb altijd gedacht dat een array een aantal vaste waarden bevat. Deze zijn niet te veranderen dus ook niet van plaats lijkt mij.

Acties:
  • 0 Henk 'm!

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 23:57

Reptile209

- gers -

Je kan toch een wisselroutine maken: (pseudo-code, geen zin om helemaal uit te schrijven :) )
Delphi:
1
2
3
4
5
6
7
8
9
10
11
procedure Schudden(var Kaarten: TMijnkaartenarray);
begin
  for n:=1 to veel do
  begin
    a := random getal(32);
    b := random getal(32);
    temp := kaarten[a];
    kaarten[a] := kaarten[b];
    kaarten[b] := temp;
  end;
end;

Zo wordt je array geschud en kan je de kaarten er een voor een uithalen. Als je bijv. de 25e kaart gepakt hebt, reset je je teller en schud je opnieuw...

Zo scherp als een voetbal!


Acties:
  • 0 Henk 'm!

Anoniem: 78378

Topicstarter
Ah, ik snap hem, hierbij wordt positie a verwisselt met b en positie b krijgt oude waarde van a. Dit herhaalt zich 'veel' keer zodat je een goed geschud kaarten spel krijgt. In kaarten hoef ik dus alleen maar de kaartnamen te declareren (dat zijn er dus 32) en dan geef ik speler 1 kaart nummer 0 speler 2 nummer 1 etc... Begrijp ik het zo goed?

Alvast bedankt!

Acties:
  • 0 Henk 'm!

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20:02

Tomatoman

Fulltime prutser

De code hierboven kan in theorie bijzonder lang bezig zijn met schudden. Als alleen kaart 25 nog in de stapel te verdelen kaarten werkt, blijft hij net zolang een random getrokken kaart afwijzen omdat die al is uitgegeven totdat hij kaart 25 trekt.

Beter is om met twee lijsten te werken van het type TList of TStringList. Uit de losse pols:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
type
  TForm1 = class(TForm)
  ...
  private
    FOngeschud: TStringList;  // deze lijst verandert nooit
    FGeschud: TStringList;    // deze lijst is voor ieder spel anders
  end;

constructor Form1.Create(AOwner: TComponent);
const
  Kaarten: array[0..31] of string = ('schoppenzeven', 'schoppenacht', ...
    ..., 'hartenaas');
var
  i: Integer;
begin
  inherited Create(AOwner);
  FOngeschud := TStringList.Create;
  for i := 0 to 31 do
    FOngeschud.Add(Kaarten[i]);
  FGeschud := TStringList.Create;
end;

destructor Form1.Destroy;
begin
  FOngeschud.Free;
  FGeschud.Free;
  inherited;
end;

procedure Form1.KaartenSchudden;
var
  TempList: TStringList;
  i: Integer;
begin
  FGeschud.Clear;
  TempList := TStringList.Create;
  try
    { Alle kaarten ongeschud toevoegen aan een tijdelijke lijst }
    TempList.Assign(FOngeschud);
    { Telkens een willekeurige kaart trekken uit de nog overgebleven
      kaarten en deze toevoegen aan de lijst met geschudde kaarten }
    for i := 0 to TempList.Count -1 do
      FGeschud.Add(TempList.Items[Random(TempList.Count)]);
  finally
    TempList.Free;
  end;
end;

procedure Form1.KaartenDelen;
begin
  { speler 1 krijgt de volgende kaarten: FGeschud.Items[0] t/m 7 }
  { speler 2 krijgt de volgende kaarten: FGeschud.Items[8] t/m 15 }
  { enzovoort
end;

procedure TForm1.NieuwSpel;
begin
  KaartenSchudden;
  KaartenDelen;
  { nu het spel spelen }
end;

Een goede grap mag vrienden kosten.


Acties:
  • 0 Henk 'm!

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 23:57

Reptile209

- gers -

Anoniem: 78378 schreef op 11 februari 2003 @ 13:50:
Ah, ik snap hem, hierbij wordt positie a verwisselt met b en positie b krijgt oude waarde van a. Dit herhaalt zich 'veel' keer zodat je een goed geschud kaarten spel krijgt. In kaarten hoef ik dus alleen maar de kaartnamen te declareren (dat zijn er dus 32) en dan geef ik speler 1 kaart nummer 0 speler 2 nummer 1 etc... Begrijp ik het zo goed?
Ja, klopt, zie onder.
tomatoman schreef op 11 February 2003 @ 13:51:
De code hierboven kan in theorie bijzonder lang bezig zijn met schudden. Als alleen kaart 25 nog in de stapel te verdelen kaarten werkt, blijft hij net zolang een random getrokken kaart afwijzen omdat die al is uitgegeven totdat hij kaart 25 trekt.
Ik weet niet of je daarmee mijn "code" bedoelt, maar wat ik met die 25 wilde zeggen is dat je ergens moet bijhouden wanneer de stack kaarten "op" is en er dus opnieuw moet worden geschud.
Volgens mij loopt de code van jou precies zoals die van de TS, tenzij je een geniale Random() hebt die met uitsluiting van eerder getrokken nummers werkt. Mijn "wisseltruuk" is logischer en werkt wèl :P.

code:
1
2
3
4
5
6
7
8
9
10
11
Kaarten.Create();
while (1);
begin
  Kaarten.Schudden();
  while (Kaarten.volgendeKaartDieAanDeBeurtIs < 32) do
    SpeelVolgendeKaartDieAanDeBeurtIs(Kaarten);
end;
Kaarten.Free();

{ SpeelSpeelVolgendeKaartDieAanDeBeurtIs() pakt dus de kaarten 
op (de geschudde) volgorde, één voor één. }

Dit natuurlijk ten overvloede :+. Mag ik in de About / Credits? _/-\o_ :Y)

[ Voor 13% gewijzigd door Reptile209 op 11-02-2003 14:10 ]

Zo scherp als een voetbal!


Acties:
  • 0 Henk 'm!

Anoniem: 78378

Topicstarter
:d, ik maak er een internet spel van. Die je via internet kan spelen. Nu ik dit weet kan ik de rest helemaal zelf doen!

Bedankt!

Acties:
  • 0 Henk 'm!

Anoniem: 78378

Topicstarter
Tomatoman, jouw functie gaat helaas niet op voor dit spel. Er kan ook een combinatie van de kaarten 7/8 voorkomen en dan krijgt de speler nieuwe kaarten uit de stapel die al gebruikt is. Je kan dus niet het aantal kaarten 32/4 doen om per speler een aantal kaarten te krijgen. Maar toch bedankt!
Pagina: 1