logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Pascal] Jak uniknąć powtórzeń kart przy rozdawaniu w Pascalu?

musiek123 28 Mar 2008 00:15 5471 8
  • #1 4963597
    musiek123
    Poziom 10  
    Posty: 29
    Mam taki problem, mam do napisania prace zaliczeniową w pascalu, mianowicie mam napisac progeam rozdajacy karty dla 4 graczy, i blądze bo pascala ucze sie od niedawna.
    Program który juz mam rozdaje karty 4 graczom ale niestety karty sie powtarzaja nie wiem jak zrobic by uniknac powtórzen, być moze kod moj jest sporym chaosem a moze ktos sie polapie, nizej zamieszczam jego tresc, prosze o pomoc.

    uses crt;
    const karty='23456789DJQKA';
    const kolory=#3#4#5#6;
    
    function f_23(x:integer):char;
    begin
    f_23:=karty[x mod 13+1];
    end;
    
    function f_13(x:integer):char;
    begin
    f_13:=kolory[x div 13+1];
    end;
    
    var k,i,a,b,c:integer;
    talia:array[1..52] of integer;
    begin
    clrscr;
    randomize;
    writeln('gracz1');
    for i:=1 to 13 do
     begin
     k:=random(52);
     write(f_23(k),f_13(k),' ');
     end;
     writeln;
     writeln('gracz2');
     for a:=1 to 13 do
      begin
      k:=random(52);
      if k=k then k:=k+1;
      write(f_23(k),f_13(k),' ');
      end;
      writeln;
      writeln('gracz3');
      for b:=1 to 13 do
       begin
       k:=random(52);
       if k=k then k:=k+1;
       write(f_23(k),f_13(k),' ');
       end;
       writeln;
       writeln('gracz4');
       for c:=1 to 13 do
        begin
        k:=random(52);
        if k=k then k:=k+1;
        write(f_23(k),f_13(k),' ');
        end;
     readkey;
    { clrscr;
     randomize;
     for i:=1 to 52 do talia[i]:=i-1;
     for i:=1 to 4 do
      for k:=1 to 13 do
      begin
      gotoxy(k*4,i*2);
      write(f_23(talia[(i-1)*13+k]),f_13(talia[(i-1)*13+k]));
      end; }
      readkey;
    end.
    


    Moderowany przez Marek_Skalski:

    Temat zamykam.

  • #2 4963635
    webmortiz
    Poziom 20  
    Posty: 467
    Pomógł: 24
    Ocena: 15
    Nie wnikam w kod, ale ogolnie losowanie bez powtorzen to banalne zadanie, moge podpowiedzic ze mozna skorzystac ze zbiorow lub poprostu tablic. Losujemy i dodajemy wylosowane do zbioru. Przy kolejnym losowaniu sprawdzamy czy w zbiorze mamy juz taki element, jak mamy to losujemy dalej a jak nie to dodajemy do zbioru. Dodanie do zbioru oznacza jednoczesnie ze tej karty wczesniej nie bylo.

    P.S. A tego kodu zgrabniej sie nie da?
    Powodzenia ;)
  • #3 4963691
    musiek123
    Poziom 10  
    Posty: 29
    Może dla Ciebie to banalne ale ja jestem początkujący...
    Przykłady mile widziane ;>
    co do kodu to pisałem ze chaotyczny, taki sam chaos mam w głowie.
  • #4 4963744
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 241
    Ja bym to zrobił przy pomocy tablicy boolean gdzie jeden element oznacza że określona karta byłą już wylosowana albo nie. Do tego licznik ile zostało kart i za każdym razem losujesz liczbę z zakresu 1 do "licznik" i wybierasz n-tą kartę która jeszcze istnieje do rozdania. Powinno to działać znacznie wydajniej niż algorytm losujący do oporu.
  • #5 4963835
    ed-ek
    Poziom 34  
    Posty: 1814
    Pomógł: 275
    Ocena: 43
    Kiedyś komuś pisałem taki prog. Załączam kod, ale można to napisać bez używania instrukcji GoTo
    
     uses Crt;
    
     var i,j:integer;
         los:array[1..6]of byte;
         label powt;
     begin
        clrscr;
      Randomize;
    
     powt:   for i:=1 to 6 do begin
           j:=Random(49)+1;
           los[i]:=j;
           if i>=2 then begin
           for j:=i-1 downto 1 do
           if los[i]=los[j] then GoTo powt;
       end;
    
       end;
       gotoxy(5,5);write('LICZBY WYLOSOWANE PRZEZ KOMPUTER:');
       gotoxy(19,8);
       for i:=1 to 6 do
       write(los[i],' ');
       gotoxy(15,15);write('press any key');
         readKey;
    
     end.
    
  • #6 4964173
    Xitami
    Poziom 29  
    Posty: 1130
    Pomógł: 118
    Ocena: 31
    Trzeba potasować karty.
    Mam talię "N" kart.
    Rozłożę je.
    Zaczynając od pierwszej, wezmę po kolei kolejne N-1 kart, i zamienię tą którą mam w ręce z którąś losowo wybraną z pozostałych/kolejnych.
    Gdzieś widziałem dowód, że to dobry sposób.
  • #7 4964262
    musiek123
    Poziom 10  
    Posty: 29
    No ok a jak to podzielic na 4 graczy?
    Albo 4 oddzielne losowania gdzie liczby nie mogą sie w zadnym zbiorze powtarzac albo 1 losowanie tak by po 13 liczbach jakos je oddzielac od siebie.
  • #8 4966132
    ed-ek
    Poziom 34  
    Posty: 1814
    Pomógł: 275
    Ocena: 43
    Podałem przykład losowania bez powtórzeń. Jednak jak mu się przyjrzałem, nie jest optymalny. Dlatego napisałem prog. rozdziału 52 kart dla 4 graczy.
    
    uses crt;
    type tab=array[1..13]of integer;
         tab1=array[1..52]of string;
    
    const talia1:tab1=('2C','2D','2H','2S','3C','3D','3H','3P','4C','4D','4H',
         '4S','5C','5D','5H','5S','6C','6D','6H','6S','7C','7D','7H','7S','8C',
         '8D','8H','8S','9C','9D','9H','9S','10C','10D','1OH','1OS','WC','WD',
         'WH','WS','DC','DD','DH','DS','KC','KD','KH','KS',
          'AC','AD','AH','AS');
    const mx=52;
    var gracz1,gracz2,gracz3,gracz4:tab;
    label powt;
    var i,j,n,k,liczba,g1,g2,g3,g4:integer;
        los:array[1..mx]of integer;
    
    begin
        for i:=1 to mx do los[i]:=0;
        clrscr;
    
       k:=0;
        Randomize;
    
     powt: repeat
            k:=k+1;
            liczba:=Random(mx)+1;
            if k=1 then begin los[1]:=liczba;end;
            if k>1 then
            begin
             for n:=k-1 downto 1 do
             begin
                 if los[n]=liczba then begin k:=k-1;GoTo powt;end;
              end;
            end;
                  los[k]:=liczba;
            until k=mx;
       n:=0;g1:=0;g2:=0;g3:=0;g4:=0;
       repeat
           g1:=g1+1;n:=n+1;
         gracz1[g1]:=los[n];
            g2:=g2+1;n:=n+1;
         gracz2[g2]:=los[n];
         n:=n+1;g3:=g3+1;
         gracz3[g3]:=los[n];
         n:=n+1;g4:=g4+1;
         gracz4[g4]:=los[n];
        until n=52;
        writeln('C clabs - trefle');
        writeln('D diamonds - kara');
        writeln('H hearts - kiery');
        writeln('S spades - piki');
        writeln('np. 5C to 5 trefl, AH to as kier');
        writeln;
        writeln('gracz 1');
       for i:=1 to 13 do
        write(talia1[gracz1[i]],'  '); writeln;
            writeln('gracz 2');
         for i:=1 to 13 do
        write(talia1[gracz2[i]],'  '); writeln;
            writeln('gracz 3');
         for i:=1 to 13 do
        write(talia1[gracz3[i]],'  '); writeln;
            writeln('gracz 1');
         for i:=1 to 13 do
        write(talia1[gracz4[i]],'  '); writeln;
        writeln('press any key');
      readkey;
       end.
    
  • #9 4975452
    x3r
    Poziom 18  
    Posty: 126
    Pomógł: 32
    Ocena: 2
    Losowanie bez powtórzeń często kończy się długim oczekiwaniem. Możliwości wylosowania nowej karty wysycają się, im dalej losujesz tym trudniej trafić w kartę której jeszcze nie miałeś. Na Twoim miejscu "ułożyłbym" karty w tablicy(obojętne w jakiej kolejności), przemieszał ją (powiedzmy 50 razy wylosowałbym parę liczb oznaczających pozycje kart które bym ze sobą zamienił miejscami w tablicy) i rozdzielił talię na 4 po równo dla każdego gracza. Kodu nie załącze bo nie znam składni pascala ale nie powinien zbyt skomplikowany.

    pozdrawiam

Podsumowanie tematu

LABEL_AI_GENERATED
Dyskusja dotyczy problemu unikania powtórzeń kart podczas losowego rozdawania talii 52 kart czterem graczom w języku Pascal. Główne wyzwanie to zapewnienie, aby każda karta pojawiła się tylko raz. Proponowane rozwiązania obejmują: wykorzystanie zbiorów lub tablic do śledzenia już wylosowanych kart i ponowne losowanie w przypadku powtórzeń; zastosowanie tablicy typu boolean do oznaczania kart już rozdanych oraz efektywne losowanie z uwzględnieniem pozostałych kart; implementację algorytmu tasowania talii (np. metoda Fishera-Yatesa), który polega na wielokrotnym zamienianiu miejscami kart w tablicy, a następnie podziale talii na cztery równe części dla graczy. Przykładowy kod w Pascalu pokazuje implementację losowania bez powtórzeń z użyciem pętli i kontroli powtórzeń, choć wskazano, że można to zrobić bardziej elegancko bez instrukcji GoTo. Podkreślono, że losowanie bez powtórzeń metodą ciągłego sprawdzania może być nieefektywne, dlatego lepszym podejściem jest wcześniejsze potasowanie talii i podział na graczy.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA