Poker klasyczny - uporządkowanie kodu

0

Witam. Piszę klasycznego pokera dobieranego. Napisałem zestaw funkcji sprawdzających układy kart i sprawdzającego zwycięzcę - Jakoś działają. Chciałem trochę skrócić/uporządkować kod, więc co mogę zrobić? W szczególności funkcja 'KtoWygrał' wydaje się skomplikowana.

Function Kareta(K:TReka):Boolean;
Begin

 SortujKarty(K);

 Kareta:=((K[1].Figura=K[2].Figura) And (K[2].Figura=K[3].Figura) And
    (K[3].Figura=K[4].Figura) Or ((K[2].Figura=K[3].Figura) And (K[3].Figura=K[4].Figura) And
    (K[4].Figura=K[5].Figura)));

End;  {------------------------Karteta-}



Function Para(K:TReka):Boolean;
Begin

 SortujKarty(K);

 Para:=((K[1].Figura=K[2].Figura) Or (K[2].Figura=K[3].Figura) Or (K[3].Figura=K[4].Figura) Or
    (K[4].Figura=K[5].Figura));

End;  {-------------------------Para-}


Function Full(K:TReka):Boolean;
Begin

 SortujKarty(K);

 Full:=((K[1].Figura=K[2].Figura) And (K[3].Figura=K[4].Figura) And
    (K[4].Figura=K[5].Figura) Or ((K[4].Figura=K[5].Figura) And (K[1].Figura=K[2].Figura) And
    (K[2].Figura=K[3].Figura)));

End;  {-----------------------------Full-}


Function TrzyFigury(K:TReka):Boolean;
Begin

 SortujKarty(K);

 TrzyFigury:=((K[1].Figura=K[2].Figura) And (K[2].Figura=K[3].Figura) Or
    (K[2].Figura=K[3].Figura) And (K[3].Figura=K[4].Figura) Or
    (K[3].Figura=K[4].Figura) And (K[4].Figura=K[5].Figura));

End;


Function DwiePary(K:TReka):Boolean;
Begin

 SortujKarty(K);

 DwiePary:=((K[1].Figura=K[2].Figura) And ((K[3].Figura=K[4].Figura) Or (K[4].Figura=K[5].Figura))
    Or (K[2].Figura=K[3].Figura) And (K[4].Figura=K[5].Figura) And (Not Kareta(K)));

End;  {------------------------Dwie_Pary-}


Function Kolor(K:TReka):Boolean;
Begin

 SortujKarty(K);

 Kolor:=((K[1].Kolor=K[2].Kolor) And (K[2].Kolor=K[3].Kolor) And
     (K[3].Kolor=K[4].Kolor) And (K[4].Kolor=K[5].Kolor));

 End;  {--------------------------Kolor-}


Function Strit(K:TReka):Boolean;
Var

L:Integer;

Begin

 Strit:=True;

 SortujKarty(K);

 For L:= 1 To 4 Do
   If (Abs(Ord(K[L].Figura)-Ord(K[L+1].Figura)) <> 1) Then Strit:=False;


End;  {-------------------------Strit-}


Function Poker(K:TReka):Boolean;
Begin

 Poker:=(Strit(K) And Kolor(K));

End;  {-------------------------Poker-}


Function PokerKrolewski(K:TReka):Boolean;
Begin

 PokerKrolewski:=(Poker(K) And (K[5].Figura=ASY));

End;  {-------------------------PokerKrolewski-}


Function WartoscUkladuKart(K:TReka):Integer;
Begin

WartoscUkladuKart:=0;

 If (PokerKrolewski(K)) Then WartoscUkladuKart:=9
  else If (Poker(K))  Then WartoscUkladuKart:=8
    else If (Kareta(K))  Then WartoscUkladuKart:=7
     else If (Full(K))  Then WartoscUkladuKart:=6
      else If (TrzyFigury(K))  Then WartoscUkladuKart:=5
       else If (Strit(K))  Then WartoscUkladuKart:=4
        else If (Kolor(K))  Then WartoscUkladuKart:=3
         else If (DwiePary(K))  Then WartoscUkladuKart:=2
          else If (Para(K))  Then WartoscUkladuKart:=1 

End;



Function KtoWygral(G:TGraczRodzaj):TTypGracza;
Var
Pom, Pom2, I:Integer;
Poz, Poz2:array[1..3] of Integer;
P: TTypGracza;
Begin

P:=KOMPUTER;

 If (WartoscUkladuKart(G[CZLOWIEK].Reka) > WartoscUkladuKart(G[KOMPUTER].Reka))
   Then P:=CZLOWIEK
     else

       If (WartoscUkladuKart(G[CZLOWIEK].Reka) = WartoscUkladuKart(G[KOMPUTER].Reka))  Then
       Begin
        {Jeli ukady sĽ takie same}
         If (WartoscUkladuKart(G[CZLOWIEK].Reka) = 9)  AND
             (Ord(G[CZLOWIEK].Reka[1].Kolor) > Ord(G[KOMPUTER].Reka[1].Kolor))
             Then  P:=CZLOWIEK

                       { Poker Krolewski}

         else If (WartoscUkladuKart(G[CZLOWIEK].Reka) = 8)  AND
                   (Ord(G[CZLOWIEK].Reka[5].Figura) > Ord(G[KOMPUTER].Reka[5].Figura))
                   Then  P:=CZLOWIEK

                         { poker }


         else If (WartoscUkladuKart(G[CZLOWIEK].Reka) = 7)  AND
                   (Ord(G[CZLOWIEK].Reka[2].Figura) > Ord(G[KOMPUTER].Reka[2].Figura))
                   Then  P:=CZLOWIEK

                         { Kareta }

         else If (WartoscUkladuKart(G[CZLOWIEK].Reka) = 6)  AND
                   (Ord(G[CZLOWIEK].Reka[3].Figura) > Ord(G[KOMPUTER].Reka[3].Figura))
                   Then  P:=CZLOWIEK

                         { Full }

         else If (WartoscUkladuKart(G[CZLOWIEK].Reka) = 5)  AND
                   (Ord(G[CZLOWIEK].Reka[3].Figura) > Ord(G[KOMPUTER].Reka[3].Figura))
                   Then  P:=CZLOWIEK

                         { Trojka }

         else If (WartoscUkladuKart(G[CZLOWIEK].Reka) = 4)  AND
                   (Ord(G[CZLOWIEK].Reka[5].Figura) > Ord(G[KOMPUTER].Reka[5].Figura))
                   Then  P:=CZLOWIEK

                         { Strit }

         else If (WartoscUkladuKart(G[CZLOWIEK].Reka) = 3)  AND
                   (Ord(G[CZLOWIEK].Reka[5].Figura) > Ord(G[KOMPUTER].Reka[5].Figura))
                   Then  P:=CZLOWIEK

                         { Kolor }

         else If (WartoscUkladuKart(G[CZLOWIEK].Reka) = 2)  AND
                   (Ord(G[CZLOWIEK].Reka[4].Figura) > Ord(G[KOMPUTER].Reka[4].Figura))
                   Then  P:=CZLOWIEK
                   else  If (WartoscUkladuKart(G[CZLOWIEK].Reka) = 2)  AND (
                   (Ord(G[CZLOWIEK].Reka[4].Figura) = Ord(G[KOMPUTER].Reka[4].Figura)) AND
                   (Ord(G[CZLOWIEK].Reka[2].Figura) > Ord(G[KOMPUTER].Reka[2].Figura)))
                   Then  P:=CZLOWIEK
                   else  If (WartoscUkladuKart(G[CZLOWIEK].Reka) = 2)  AND (
                   (Ord(G[CZLOWIEK].Reka[4].Figura) = Ord(G[KOMPUTER].Reka[4].Figura)) AND
                   (Ord(G[CZLOWIEK].Reka[2].Figura) = Ord(G[KOMPUTER].Reka[2].Figura)))    { Dwie Pary }
                          Then Begin
                                IF  (Ord(G[CZLOWIEK].Reka[1].Figura) = Ord(G[CZLOWIEK].Reka[2].Figura))
                                 AND (Ord(G[CZLOWIEK].Reka[4].Figura) = Ord(G[CZLOWIEK].Reka[5].Figura))
                                  Then Pom:=Ord(G[CZLOWIEK].Reka[3].Figura);
                                 IF  (Ord(G[CZLOWIEK].Reka[2].Figura) = Ord(G[CZLOWIEK].Reka[3].Figura))
                                 AND (Ord(G[CZLOWIEK].Reka[4].Figura) = Ord(G[CZLOWIEK].Reka[5].Figura))
                                  Then Pom:=Ord(G[CZLOWIEK].Reka[1].Figura);
                                 IF  (Ord(G[CZLOWIEK].Reka[1].Figura) = Ord(G[CZLOWIEK].Reka[2].Figura))
                                 AND (Ord(G[CZLOWIEK].Reka[3].Figura) = Ord(G[CZLOWIEK].Reka[4].Figura))
                                  Then Pom:=Ord(G[CZLOWIEK].Reka[5].Figura);

                                 IF  (Ord(G[KOMPUTER].Reka[1].Figura) = Ord(G[KOMPUTER].Reka[2].Figura))
                                 AND (Ord(G[KOMPUTER].Reka[4].Figura) = Ord(G[KOMPUTER].Reka[5].Figura))
                                  Then Pom2:=Ord(G[KOMPUTER].Reka[3].Figura);
                                 IF  (Ord(G[KOMPUTER].Reka[2].Figura) = Ord(G[KOMPUTER].Reka[3].Figura))
                                 AND (Ord(G[KOMPUTER].Reka[4].Figura) = Ord(G[KOMPUTER].Reka[5].Figura))
                                  Then Pom2:=Ord(G[KOMPUTER].Reka[1].Figura);
                                 IF  (Ord(G[KOMPUTER].Reka[1].Figura) = Ord(G[KOMPUTER].Reka[2].Figura))
                                 AND (Ord(G[KOMPUTER].Reka[3].Figura) = Ord(G[KOMPUTER].Reka[4].Figura))
                                  Then Pom2:=Ord(G[KOMPUTER].Reka[5].Figura);

                               IF Pom > Pom2 Then P:=CZLOWIEK;
                               End

                         { Dwie Pary }

          else   If (WartoscUkladuKart(G[CZLOWIEK].Reka) = 1)
                 Then Begin
                      SortujKarty(G[CZLOWIEK].Reka);
                      SortujKarty(G[KOMPUTER].Reka);

                      IF  (Ord(G[CZLOWIEK].Reka[1].Figura) = Ord(G[CZLOWIEK].Reka[2].Figura)) Then
                      Begin Pom:=Ord(G[CZLOWIEK].Reka[1].Figura); Poz[1]:=Ord(G[CZLOWIEK].Reka[3].Figura);
                      Poz[2]:=Ord(G[CZLOWIEK].Reka[4].Figura);
                      Poz[3]:=Ord(G[CZLOWIEK].Reka[5].Figura); end;
                      IF  (Ord(G[CZLOWIEK].Reka[2].Figura) = Ord(G[CZLOWIEK].Reka[3].Figura)) Then
                       Begin Pom:=Ord(G[CZLOWIEK].Reka[2].Figura); Poz[1]:=Ord(G[CZLOWIEK].Reka[1].Figura);
                      Poz[2]:=Ord(G[CZLOWIEK].Reka[4].Figura);
                      Poz[3]:=Ord(G[CZLOWIEK].Reka[5].Figura); end;
                      IF  (Ord(G[CZLOWIEK].Reka[3].Figura) = Ord(G[CZLOWIEK].Reka[4].Figura)) Then
                       Begin Pom:=Ord(G[CZLOWIEK].Reka[3].Figura); Poz[1]:=Ord(G[CZLOWIEK].Reka[1].Figura);
                      Poz[2]:=Ord(G[CZLOWIEK].Reka[2].Figura);
                      Poz[3]:=Ord(G[CZLOWIEK].Reka[5].Figura); end;
                      IF  (Ord(G[CZLOWIEK].Reka[4].Figura) = Ord(G[CZLOWIEK].Reka[5].Figura)) Then
                      Begin Pom:=Ord(G[CZLOWIEK].Reka[4].Figura); Poz[1]:=Ord(G[CZLOWIEK].Reka[1].Figura);
                      Poz[2]:=Ord(G[CZLOWIEK].Reka[2].Figura);
                      Poz[3]:=Ord(G[CZLOWIEK].Reka[3].Figura); end;

                      IF  (Ord(G[KOMPUTER].Reka[1].Figura) = Ord(G[KOMPUTER].Reka[2].Figura)) Then
                      Begin Pom2:=Ord(G[KOMPUTER].Reka[1].Figura); Poz2[1]:=Ord(G[KOMPUTER].Reka[3].Figura);
                      Poz2[2]:=Ord(G[KOMPUTER].Reka[4].Figura);
                      Poz2[3]:=Ord(G[KOMPUTER].Reka[5].Figura); end;
                      IF  (Ord(G[KOMPUTER].Reka[2].Figura) = Ord(G[KOMPUTER].Reka[3].Figura)) Then
                       Begin Pom2:=Ord(G[KOMPUTER].Reka[2].Figura); Poz2[1]:=Ord(G[KOMPUTER].Reka[1].Figura);
                      Poz2[2]:=Ord(G[KOMPUTER].Reka[4].Figura);
                      Poz2[3]:=Ord(G[KOMPUTER].Reka[5].Figura); end;
                      IF  (Ord(G[KOMPUTER].Reka[3].Figura) = Ord(G[KOMPUTER].Reka[4].Figura)) Then
                       Begin Pom2:=Ord(G[KOMPUTER].Reka[3].Figura); Poz2[1]:=Ord(G[KOMPUTER].Reka[1].Figura);
                      Poz2[2]:=Ord(G[KOMPUTER].Reka[2].Figura);
                      Poz2[3]:=Ord(G[KOMPUTER].Reka[5].Figura); end;
                      IF  (Ord(G[KOMPUTER].Reka[4].Figura) = Ord(G[KOMPUTER].Reka[5].Figura)) Then
                      Begin Pom2:=Ord(G[KOMPUTER].Reka[4].Figura); Poz2[1]:=Ord(G[KOMPUTER].Reka[1].Figura);
                      Poz2[2]:=Ord(G[KOMPUTER].Reka[2].Figura);
                      Poz2[3]:=Ord(G[KOMPUTER].Reka[3].Figura); end;

                                IF Pom > Pom2 Then P:=CZLOWIEK
                                 else If Pom = Pom2 Then
                                   Begin
                                    I:=3;

                                    While (I>0) AND (P=KOMPUTER) do
                                      Begin
                                      If Poz[I] > Poz2[I] Then  P:=CZLOWIEK;
                                      I:=I-1;
                                      End;
                                   End


                 End

                   { Para }

            else  If (WartoscUkladuKart(G[CZLOWIEK].Reka) = 0 )
                 Then Begin
                         I:=5;                        SortujKarty(G[CZLOWIEK].Reka);
                      SortujKarty(G[KOMPUTER].Reka);
                                    While (I>0) AND (P=KOMPUTER) do
                                      Begin
                                      If Ord(G[CZLOWIEK].Reka[I].Figura) > Ord(G[KOMPUTER].Reka[I].Figura) Then  P:=CZLOWIEK;
                                      I:=I-1;
                                      End;



                      End;


       end;
   KtoWygral:=P;

end;
0

Nie podałeś deklaracji typów danych, więc trudno cokolwiek doradzić.

Jeśli chodzi o funkcję KtoWygral to tak się nie robi… Nie chodzi mi tu o drabinkę if-ów (bo tę można w każdej chwili zamienić na coś sensownego), ale o wywoływanie funkcji WartoscUkladuKart w kółko dla każdego warunku. W całej tej funkcji wartość układu nie zmienia się, więc powinieneś pobrać wartość układu do zmiennej (na początku ciała funkcji) i tę zmienną później używać. A do tego w kółko P ustawiasz na CZLOWIEK.

Kolejna rzecz – funkcja WartoscUkladuKart zwraca gołe liczby, które nie wiadomo co oznaczają, dopóki nie sprawdzi się ciała tej funkcji. Tak więc zadeklaruj sobie typ wyliczeniowy i zwracaj czytelne enum-y.

Dalej szkoda patrzeć – popraw to o czym napisałem wyżej i się zobaczy co jeszcze. Na pewno do poprawy jest formatowanie kodu (wcięcia są tragiczne) oraz polskie identyfikatory (pisz kod po angielsku, w razie czego użyj translatora).

0

Nazywaj zmienne sensownie, czasy gdy ilość znaków, jaką może zawierać identyfikator, jest ograniczona minęły bezpowrotnie jakieś 40 lat temu jak nie wcześniej.

0

Co do deklaracji - faktycznie zapomniałem. Już daje:

Type
    TFigury = (DWOJKA, TROJKA, CZWORKA, PIATKA, SZOSTKA, SIODEMKA, OSEMKA,
    DZIEWIATKA, DZIESIATKA, WALET, DAMA, KROL, ASY, NIEOKR);

    TKolory = (PIK, TREFL, KARO, KIER, NIEOKR);


    TTekstKarty = String[2];

    TKarta = record
             Figura:Tfigury;
             Kolor:TKolory;
             TekstKarty:TTekstKarty;
             end;

    TReka = array[1..5] of TKarta;

    TDecyzja = (WYCOFAJ, PAS, CZEKAJ, WEJDZ, SPRAWDZ, PODBIJ, VABANK, NIEOKR);

    TTypGracza = (CZLOWIEK, KOMPUTER);
    TDoWymiany = array[1..5] of Boolean;
    TGracz = record
             Reka:TReka;
             Pieniadze:Integer;
             Decyzja:TDecyzja;
             DoWymiany:TDoWymiany;
             end;
    TGraczRodzaj = array[CZLOWIEK..KOMPUTER] of TGracz;

Co do funkcji WartoscUkladuKart - o to Ci chodziło?

Type
    TUkladKart = (NIC, PARA, DWIEPARY, KOLOR, STRIT, TROJKA, FULL, KARETA, POKER, POKERKROLEWSKI);
.
.
.
Function WartoscUkladuKart(K:TReka):TUkladKart;
Begin



 If (PokerKrolewski(K)) Then WartoscUkladuKart:=POKERKROLEWSKI
  else If (Poker(K))  Then WartoscUkladuKart:=POKER
    else If (Kareta(K))  Then WartoscUkladuKart:=KARETA
     else If (Full(K))  Then WartoscUkladuKart:=FULL
      else If (TrzyFigury(K))  Then WartoscUkladuKart:=TROJKA
       else If (Strit(K))  Then WartoscUkladuKart:=STRIT
        else If (Kolor(K))  Then WartoscUkladuKart:=KOLOR
         else If (DwiePary(K))  Then WartoscUkladuKart:=DWIEPARY
          else If (Para(K))  Then WartoscUkladuKart:=PARA
           else  WartoscUkladuKart:=NIC;

End;

Jeśli chodzi o funkcję KtoWygral - założyłem na początku, że komputer ma lepszy układ. Potem sprawdzałem kolejne warianty wygranej człowieka i dlatego dużo powtarzania tego P. Najgorzej jest w przypadku pary, bo jest wiele przypadków - stąd te ify

Pozbyłem się ciągłego wywoływania funkcji, tak jak chciałeś i wygląda to tak:

Function KtoWygral(G:TGraczRodzaj):TTypGracza;
Var
Pom, Pom2, I:Integer;
Poz, Poz2:array[1..3] of Integer;
P: TTypGracza;
SilaRekiKomputer, SilaRekiCzlowiek: TUkladKart;
Begin

P:=KOMPUTER;

SilaRekiKomputer:=WartoscUkladuKart(G[KOMPUTER].Reka);
SilaRekiCzlowiek:=WartoscUkladuKart(G[CZLOWIEK].Reka);


 If (SilaRekiCzlowiek > SilaRekiKomputer)
   Then P:=CZLOWIEK
     else

       If (SilaRekiCzlowiek = SilaRekiKomputer)  Then
       Begin
        {Jeli ukady sĽ takie same}
         If (SilaRekiCzlowiek = POKERKROLEWSKI)  AND
             (Ord(G[CZLOWIEK].Reka[1].Kolor) > Ord(G[KOMPUTER].Reka[1].Kolor))
             Then  P:=CZLOWIEK

                       { Poker Krolewski}

         else If (SilaRekiCzlowiek = POKER)  AND
                   (Ord(G[CZLOWIEK].Reka[5].Figura) > Ord(G[KOMPUTER].Reka[5].Figura))
                   Then  P:=CZLOWIEK

                         { poker }


         else If (SilaRekiCzlowiek = KARETA)  AND
                   (Ord(G[CZLOWIEK].Reka[2].Figura) > Ord(G[KOMPUTER].Reka[2].Figura))
                   Then  P:=CZLOWIEK

                         { Kareta }

         else If (SilaRekiCzlowiek = FULL)  AND
                   (Ord(G[CZLOWIEK].Reka[3].Figura) > Ord(G[KOMPUTER].Reka[3].Figura))
                   Then  P:=CZLOWIEK

                         { Full }

         else If (SilaRekiCzlowiek = TROJKA)  AND
                   (Ord(G[CZLOWIEK].Reka[3].Figura) > Ord(G[KOMPUTER].Reka[3].Figura))
                   Then  P:=CZLOWIEK

                         { Trojka }

         else If (SilaRekiCzlowiek = STRIT)  AND
                   (Ord(G[CZLOWIEK].Reka[5].Figura) > Ord(G[KOMPUTER].Reka[5].Figura))
                   Then  P:=CZLOWIEK

                         { Strit }

         else If (SilaRekiCzlowiek = KOLOR)  AND
                   (Ord(G[CZLOWIEK].Reka[5].Figura) > Ord(G[KOMPUTER].Reka[5].Figura))
                   Then  P:=CZLOWIEK

                         { Kolor }

         else If (SilaRekiCzlowiek = DWIEPARY)  AND
                   (Ord(G[CZLOWIEK].Reka[4].Figura) > Ord(G[KOMPUTER].Reka[4].Figura))
                   Then  P:=CZLOWIEK
                   else  If (SilaRekiCzlowiek = DWIEPARY)  AND (
                   (Ord(G[CZLOWIEK].Reka[4].Figura) = Ord(G[KOMPUTER].Reka[4].Figura)) AND
                   (Ord(G[CZLOWIEK].Reka[2].Figura) > Ord(G[KOMPUTER].Reka[2].Figura)))
                   Then  P:=CZLOWIEK
                   else  If (SilaRekiCzlowiek = DWIEPARY)  AND (
                   (Ord(G[CZLOWIEK].Reka[4].Figura) = Ord(G[KOMPUTER].Reka[4].Figura)) AND
                   (Ord(G[CZLOWIEK].Reka[2].Figura) = Ord(G[KOMPUTER].Reka[2].Figura)))    { Dwie Pary }
                          Then Begin
                                IF  (Ord(G[CZLOWIEK].Reka[1].Figura) = Ord(G[CZLOWIEK].Reka[2].Figura))
                                 AND (Ord(G[CZLOWIEK].Reka[4].Figura) = Ord(G[CZLOWIEK].Reka[5].Figura))
                                  Then Pom:=Ord(G[CZLOWIEK].Reka[3].Figura);
                                 IF  (Ord(G[CZLOWIEK].Reka[2].Figura) = Ord(G[CZLOWIEK].Reka[3].Figura))
                                 AND (Ord(G[CZLOWIEK].Reka[4].Figura) = Ord(G[CZLOWIEK].Reka[5].Figura))
                                  Then Pom:=Ord(G[CZLOWIEK].Reka[1].Figura);
                                 IF  (Ord(G[CZLOWIEK].Reka[1].Figura) = Ord(G[CZLOWIEK].Reka[2].Figura))
                                 AND (Ord(G[CZLOWIEK].Reka[3].Figura) = Ord(G[CZLOWIEK].Reka[4].Figura))
                                  Then Pom:=Ord(G[CZLOWIEK].Reka[5].Figura);

                                 IF  (Ord(G[KOMPUTER].Reka[1].Figura) = Ord(G[KOMPUTER].Reka[2].Figura))
                                 AND (Ord(G[KOMPUTER].Reka[4].Figura) = Ord(G[KOMPUTER].Reka[5].Figura))
                                  Then Pom2:=Ord(G[KOMPUTER].Reka[3].Figura);
                                 IF  (Ord(G[KOMPUTER].Reka[2].Figura) = Ord(G[KOMPUTER].Reka[3].Figura))
                                 AND (Ord(G[KOMPUTER].Reka[4].Figura) = Ord(G[KOMPUTER].Reka[5].Figura))
                                  Then Pom2:=Ord(G[KOMPUTER].Reka[1].Figura);
                                 IF  (Ord(G[KOMPUTER].Reka[1].Figura) = Ord(G[KOMPUTER].Reka[2].Figura))
                                 AND (Ord(G[KOMPUTER].Reka[3].Figura) = Ord(G[KOMPUTER].Reka[4].Figura))
                                  Then Pom2:=Ord(G[KOMPUTER].Reka[5].Figura);

                               IF Pom > Pom2 Then P:=CZLOWIEK;
                               End

                         { Dwie Pary }

          else   If (SilaRekiCzlowiek = PARA)
                 Then Begin
                      SortujKarty(G[CZLOWIEK].Reka);
                      SortujKarty(G[KOMPUTER].Reka);

                      IF  (Ord(G[CZLOWIEK].Reka[1].Figura) = Ord(G[CZLOWIEK].Reka[2].Figura)) Then
                      Begin Pom:=Ord(G[CZLOWIEK].Reka[1].Figura); Poz[1]:=Ord(G[CZLOWIEK].Reka[3].Figura);
                      Poz[2]:=Ord(G[CZLOWIEK].Reka[4].Figura);
                      Poz[3]:=Ord(G[CZLOWIEK].Reka[5].Figura); end;
                      IF  (Ord(G[CZLOWIEK].Reka[2].Figura) = Ord(G[CZLOWIEK].Reka[3].Figura)) Then
                       Begin Pom:=Ord(G[CZLOWIEK].Reka[2].Figura); Poz[1]:=Ord(G[CZLOWIEK].Reka[1].Figura);
                      Poz[2]:=Ord(G[CZLOWIEK].Reka[4].Figura);
                      Poz[3]:=Ord(G[CZLOWIEK].Reka[5].Figura); end;
                      IF  (Ord(G[CZLOWIEK].Reka[3].Figura) = Ord(G[CZLOWIEK].Reka[4].Figura)) Then
                       Begin Pom:=Ord(G[CZLOWIEK].Reka[3].Figura); Poz[1]:=Ord(G[CZLOWIEK].Reka[1].Figura);
                      Poz[2]:=Ord(G[CZLOWIEK].Reka[2].Figura);
                      Poz[3]:=Ord(G[CZLOWIEK].Reka[5].Figura); end;
                      IF  (Ord(G[CZLOWIEK].Reka[4].Figura) = Ord(G[CZLOWIEK].Reka[5].Figura)) Then
                      Begin Pom:=Ord(G[CZLOWIEK].Reka[4].Figura); Poz[1]:=Ord(G[CZLOWIEK].Reka[1].Figura);
                      Poz[2]:=Ord(G[CZLOWIEK].Reka[2].Figura);
                      Poz[3]:=Ord(G[CZLOWIEK].Reka[3].Figura); end;

                      IF  (Ord(G[KOMPUTER].Reka[1].Figura) = Ord(G[KOMPUTER].Reka[2].Figura)) Then
                      Begin Pom2:=Ord(G[KOMPUTER].Reka[1].Figura); Poz2[1]:=Ord(G[KOMPUTER].Reka[3].Figura);
                      Poz2[2]:=Ord(G[KOMPUTER].Reka[4].Figura);
                      Poz2[3]:=Ord(G[KOMPUTER].Reka[5].Figura); end;
                      IF  (Ord(G[KOMPUTER].Reka[2].Figura) = Ord(G[KOMPUTER].Reka[3].Figura)) Then
                       Begin Pom2:=Ord(G[KOMPUTER].Reka[2].Figura); Poz2[1]:=Ord(G[KOMPUTER].Reka[1].Figura);
                      Poz2[2]:=Ord(G[KOMPUTER].Reka[4].Figura);
                      Poz2[3]:=Ord(G[KOMPUTER].Reka[5].Figura); end;
                      IF  (Ord(G[KOMPUTER].Reka[3].Figura) = Ord(G[KOMPUTER].Reka[4].Figura)) Then
                       Begin Pom2:=Ord(G[KOMPUTER].Reka[3].Figura); Poz2[1]:=Ord(G[KOMPUTER].Reka[1].Figura);
                      Poz2[2]:=Ord(G[KOMPUTER].Reka[2].Figura);
                      Poz2[3]:=Ord(G[KOMPUTER].Reka[5].Figura); end;
                      IF  (Ord(G[KOMPUTER].Reka[4].Figura) = Ord(G[KOMPUTER].Reka[5].Figura)) Then
                      Begin Pom2:=Ord(G[KOMPUTER].Reka[4].Figura); Poz2[1]:=Ord(G[KOMPUTER].Reka[1].Figura);
                      Poz2[2]:=Ord(G[KOMPUTER].Reka[2].Figura);
                      Poz2[3]:=Ord(G[KOMPUTER].Reka[3].Figura); end;

                                IF Pom > Pom2 Then P:=CZLOWIEK
                                 else If Pom = Pom2 Then
                                   Begin
                                    I:=3;

                                    While (I>0) AND (P=KOMPUTER) do
                                      Begin
                                      If Poz[I] > Poz2[I] Then  P:=CZLOWIEK;
                                      I:=I-1;
                                      End;
                                   End


                 End

                   { Para }

            else  If (SilaRekiCzlowiek = NIC )
                 Then Begin
                         I:=5;
		      SortujKarty(G[CZLOWIEK].Reka);
                      SortujKarty(G[KOMPUTER].Reka);
                                    While (I>0) AND (P=KOMPUTER) do
                                      Begin
                                      If Ord(G[CZLOWIEK].Reka[I].Figura) > Ord(G[KOMPUTER].Reka[I].Figura) Then  P:=CZLOWIEK;
                                      I:=I-1;
                                      End;



                      End;


       end;
   KtoWygral:=P;

end;

Co do nazw zmiennych - najwyżej przepisze od nowa z angielskimi nazwami jak całość będzie działać.

0

Kod nadal jest po polsku… :(

Biały Rower napisał(a):

Co do deklaracji - faktycznie zapomniałem. Już daje:

Type
    TFigury = (DWOJKA, TROJKA, CZWORKA, PIATKA, SZOSTKA, SIODEMKA, OSEMKA,
    DZIEWIATKA, DZIESIATKA, WALET, DAMA, KROL, ASY, NIEOKR);

    TKolory = (PIK, TREFL, KARO, KIER, NIEOKR);

Identyfikatory składające się z samych dużych liter zarezerwowane są wyłącznie dla stałych. Dla enumów przyjęło się, aby stosować notację węgierską w stylu camelCase, bez podkreślników.

Poza tym, enum określający że czegoś brak, powinien być zadeklarowany jako pierwszy w zbiorze – czyli Twój NIEOKR powinien być na początku. Natomiast karta z literką A to As, nie Asy – on jest jeden.

Co do funkcji WartoscUkladuKart - o to Ci chodziło?

Czy Ty programujesz w jakimś archaicznym środowisku, jak TP7? Jeśli nie, to do zwracania rezultatu z funkcji używaj niejawnej zmiennej Result. Poza tym Twoja drabinka i tak mimo wszystko wykonywana jest w całości, bo po spełnieniu któregoś z nich, ustawiasz wartość rezultatu i nie przerywasz działania funkcji. Tu przyda się Exit z parametrem:

type
  TUkladKart = (ukNic, ukPara, ukDwiePary, ukKolor, ukStrit, ukTrojka, ukFull, ukKareta, ukPoker, ukPokerKrolewski);

  function WartoscUkladuKart(AReka: TReka): TUkladKart;
  begin
    if PokerKrolewski(AReka) then Exit(ukPokerKrolewski);
    if Poker(AReka)          then Exit(ukPoker);
    if Kareta(AReka)         then Exit(ukKareta);
    if Full(AReka)           then Exit(ukFull);
    if Trojka(AReka)         then Exit(ukTrojka);
    if Strit(AReka)          then Exit(ukStrit);
    if Kolor(AReka)          then Exit(ukKolor);
    if DwiePary(AReka)       then Exit(ukDwiePary);
    if Para(AReka)           then Exit(ukPara);
    
    Result := ukNic;
  end;

Jeśli chodzi o formatowanie kodu, to:

  • nie pisz słów kluczowych z dużych liter,
  • nie używaj jednoliterowych identyfikatorów nigdzie (ew. z wyjątkiem iteratorów pętli, takich jak np. I, X czy Y),
  • stosuj dwuznakowe wcięcie dla bloków kodu,
  • używaj prefiksu A dla argumentów.

Jeśli chodzi o funkcję KtoWygral - założyłem na początku, że komputer ma lepszy układ. Potem sprawdzałem kolejne warianty wygranej człowieka i dlatego dużo powtarzania tego P. Najgorzej jest w przypadku pary, bo jest wiele przypadków - stąd te ify

Ale po co w ogóle te warunki, skoro już na samym początku funkcji wiesz kto wygrał? Ten kod to robi:

SilaRekiKomputer:=WartoscUkladuKart(G[KOMPUTER].Reka);
SilaRekiCzlowiek:=WartoscUkladuKart(G[CZLOWIEK].Reka);
 
If (SilaRekiCzlowiek > SilaRekiKomputer)

Więc po co one są?

Co do nazw zmiennych - najwyżej przepisze od nowa z angielskimi nazwami jak całość będzie działać.

Nie musisz tego robić!

Każde normalne środowisko programistyczne posiada narzędzia do zmiany identyfikatorów – umieszczasz kursor (tekstowy) na danym identyfikatorze, wciskasz np. F2, podajesz nową nazwę i akceptujesz. Natomiast do ogólnego bałaganu są formattery, również wbudowane w środowiska.

0

Ale po co w ogóle te warunki, skoro już na samym początku funkcji wiesz kto wygrał? Ten kod to robi:

SilaRekiKomputer:=WartoscUkladuKart(G[KOMPUTER].Reka);
SilaRekiCzlowiek:=WartoscUkladuKart(G[CZLOWIEK].Reka);
 
If (SilaRekiCzlowiek > SilaRekiKomputer)

Więc po co one są?

Ale co w przypadku, jak gracz i komputer będą mieli np. po stricie? Trzeba dalej sprawdzać, kto ma lepszy układ. Ten warunek sprawdza, czy gracz ma inny (większy) układ od komputera. Chyba, że podpowiesz, jak to lepiej rozwiązać.

Kiedyś pisałem w TP7 i taki nawyk mam z tymi funkcjami. Po latach chciałem coś dla siebie napisać i wybrałem środowisko freepascal. Poprawiłem kod (oprócz funkcji KtoWygral). Jak to teraz wygląda?

type
  TFigures = (fiNone, fiTwo, fiThree, fiFour, fiFive, fiSix, fiSeven, fiEight,
  fiNine, fiTen, fiJack, fiQueen, fiKing, fiAce);

  TColors = (coNone, coSpade, coClub, coDiamond, coHeart);

  TCardLabel = String[2];

  TCard = record
            Figure     : TFigures;
            Color      : TColors;
            CardLabel  : TCardLabel;
          end;

  THand = array[1..5] of TCard;

  TDecision = (deNone, deFold, dePass, deCheck, deBet, deRaise, deAllIn);

  TPlayerType = (plHuman, plComputer);

  TChangeCard = array[1..5] of Boolean;

  TPlayer = record
               Hand       : THand;
               Money      : Integer;
               Decision   : TDecision;
               ChangeCard : TChangeCard;
            end;

  TPlayerData = array[plHuman..plComputer] of TPlayer;

  TCardLayer = (caNone, caPair, caTwoPairs, caFlush, caStraight, caThreeOfAKind, caFull, caFourOfAKind, caStraightFlush, caRoyalFlush);

  TGameLogs=Array[1..50] of String;


procedure SortCards(var AHand : THand);
  var
    I, J       : Byte;
    HelpFigure : TFigures;
    HelpColor  : TColors;
    HelpText   : TCardLabel;

  begin
    for I := 1 to 4 do
      for J := I+1 to 5 do
        if (AHand[I].Figure > AHand.Figure) then
          begin
            HelpFigure:=AHand[I].Figure;
            AHand[I].Figure:=AHand[J].Figure;
            AHand[J].Figure:=HelpFigure;
            HelpColor:=AHand[I].Color;
            AHand[I].Color:=AHand[J].Color;
            AHand[J].Color:=HelpColor;
            HelpText:=AHand[I].CardLabel;
            AHand[I].CardLabel:=AHand[J].CardLabel;
            AHand[J].CardLabel:=HelpText;
          end;

  end;

function FourOfAKind(AHand : THand): Boolean;
  begin

    SortCards(AHand);

    FourOfAKind := ((AHand[1].Figure=AHand[2].Figure) and (AHand[2].Figure=AHand[3].Figure) and
    (AHand[3].Figure=AHand[4].Figure) or ((AHand[2].Figure=AHand[3].Figure) and (AHand[3].Figure=AHand[4].Figure) and
    (AHand[4].Figure=AHand[5].Figure)));

  end; 



function Pair(AHand : THand): Boolean;
  begin

    SortCards(AHand);

    Pair := ((AHand[1].Figure=AHand[2].Figure) or (AHand[2].Figure=AHand[3].Figure) or (AHand[3].Figure=AHand[4].Figure) or
    (AHand[4].Figure=AHand[5].Figure));

  end; 


function Full(AHand : THand): Boolean;
  begin

    SortCards(AHand);

    Full := ((AHand[1].Figure=AHand[2].Figure) and (AHand[3].Figure=AHand[4].Figure) and
    (AHand[4].Figure=AHand[5].Figure) or ((AHand[4].Figure=AHand[5].Figure) and (AHand[1].Figure=AHand[2].Figure) and
    (AHand[2].Figure=AHand[3].Figure)));

  end;  


function ThreeOfAKind(AHand : THand): Boolean;
  begin

    SortCards(AHand);

    ThreeOfAKind := ((AHand[1].Figure=AHand[2].Figure) and (AHand[2].Figure=AHand[3].Figure) or
    (AHand[2].Figure=AHand[3].Figure) and (AHand[3].Figure=AHand[4].Figure) or
    (AHand[3].Figure=AHand[4].Figure) and (AHand[4].Figure=AHand[5].Figure));

  end;


function TwoPairs(AHand : THand): Boolean;
  begin

    SortCards(AHand);

    TwoPairs := ((AHand[1].Figure=AHand[2].Figure) and ((AHand[3].Figure=AHand[4].Figure) or (AHand[4].Figure=AHand[5].Figure))
    or (AHand[2].Figure=AHand[3].Figure) and (AHand[4].Figure=AHand[5].Figure) and (not FourOfAKind(AHand)));

  end; 


function Flush(AHand : THand): Boolean;
  begin

    SortCards(AHand);

    Flush := ((AHand[1].Color=AHand[2].Color) and (AHand[2].Color=AHand[3].Color) and
    (AHand[3].Color=AHand[4].Color) and (AHand[4].Color=AHand[5].Color));

 end; 


 function Straight(AHand : THand): Boolean;
   var

    I : Byte;

    begin

      Straight := True;
      SortCards(AHand);

     for I := 1 To 4 do
       if (abs(ord(AHand[I].Figure) - ord(AHand[I+1].Figure)) <> 1) then Straight := False;

  end; 


function StraightFlush(AHand : THand): Boolean;
  begin

    RoyalFlush := (Straight(AHand) and Flush(AHand));

  end;  


function RoyalFlush(AHand : THand): Boolean;
  begin

   RoyalFlush:=(StraightFlush(AHand) and (AHand[5].Figure=fiAce));

  end; 

function HandStrength(AHand: THand): TCardLayer
  begin

    if RoyalFlush(AHand)    then Exit(caRoyalFlush);
    if StraightFlush(AHand) then Exit(caStraightFlush);
    if FourOfAKind(AHand)   then Exit(caFourOfAKind);
    if Full(AHand)          then Exit(caFull);
    if ThreeOfAKind(AHand)  then Exit(caThreeOfAKind);
    if Straight(AHand)      then Exit(caStraight);
    if Flush(AHand)         then Exit(caFlush);
    if TwoPairs(AHand)      then Exit(caTwoPairs);
    if Pair(AHand)          then Exit(caPair);
 
    Result := caNone;

  end;

0
Biały Rower napisał(a):

Ale co w przypadku, jak gracz i komputer będą mieli np. po stricie? Trzeba dalej sprawdzać, kto ma lepszy układ. Ten warunek sprawdza, czy gracz ma inny (większy) układ od komputera.

Moje przeoczenie.

Chyba, że podpowiesz, jak to lepiej rozwiązać.

Nom – napisz sobie zestaw funkcji określających siłę kart dla danego układu, czyli:

  • PowerOfPair,
  • PowerOfTwoPairs,
  • PowerOfFlush,
  • PowerOfStraight,
  • PowerOfThreeOfAKind,
  • PowerOfFull,
  • PowerOfFourOfAKind,
  • PowerOfStraightFlush,
  • PowerOfRoyalFlush.

Słówko Power może akurat być nieadekwatne, jak chcesz to użyć innego, np. Value. Te funkcje pozwolą określić wartość konkretnego układu, podczas gdy ten jest znany – a jest, bo pobierasz typ układu na początku funkcji.

Teraz jak już jest zestaw funkcji pobierających wartość układu, należy napisać kolejny zestaw funkcji, tym razem porównujących dwa układy i zwracających typ gracza, którego układ ma wyższą wartość. Czyli według nowego nazewnictwa, ma zwrócić wartość typu TPlayerType. Każda z tych funkcji powinna pobierać w argumentach układ gracza i układ komputera.

Owe funkcje to:

  • PlayerWithStrongerPair,
  • PlayerWithStrongerTwoPairs,
  • PlayerWithStrongerFlush,
  • PlayerWithStrongerStraight,
  • PlayerWithStrongerThreeOfAKind,
  • PlayerWithStrongerFull,
  • PlayerWithStrongerFourOfAKind,
  • PlayerWithStrongerStraightFlush,
  • PlayerWithStrongerRoyalFlush.

Jak sobie je zdefiniujesz, to funkcja WhoWon (czyli Twoja dawna KtoWygral) uprości się do takiej postaci:

function WhoWon(const AHumanHand, ACpuHand: THand): TPlayerType;
var
  HumanLayer, CpuLayer: TCardLayer;
begin
  Result := plNone;

  HumanLayer := HandStrength(AHumanHand);
  CpuLayer := HandStrength(CpuHand);

  case Math.CompareValue(Byte(HumanLayer), Byte(CpuLayer)) of
    LessThanValue:    Result := plComputer;
    GreaterThanValue: Result := plHuman;
    EqualsValue:
    case HumanLayer of
      caPair:          Result := PlayerWithStrongerPair(AHumanHand, ACpuHand);
      caTwoPairs:      Result := PlayerWithStrongerTwoPairs(AHumanHand, ACpuHand);
      caFlush:         Result := PlayerWithStrongerFlush(AHumanHand, ACpuHand);
      caStraight:      Result := PlayerWithStrongerStraight(AHumanHand, ACpuHand);
      caThreeOfAKind:  Result := PlayerWithStrongerThreeOfAKind(AHumanHand, ACpuHand);
      caFull:          Result := PlayerWithStrongerFull(AHumanHand, ACpuHand);
      caFourOfAKind:   Result := PlayerWithStrongerFourOfAKind(AHumanHand, ACpuHand);
      caStraightFlush: Result := PlayerWithStrongerStraightFlush(AHumanHand, ACpuHand);
      caRoyalFlush:    Result := PlayerWithStrongerRoyalFlush(AHumanHand, ACpuHand);
    end;
  end;
end;

Wygląda nieźle, o niebo lepiej niż to co miałeś na początku.

Natomiast jeśli chodzi o procedurę SortCards, to niepotrzebnie przepisujesz poszczególne pola – możesz przepisać od razu całe struktury:

procedure SortCards(var AHand: THand);
var
  Card: TCard;
  I, J: UInt8;
begin
  for I := Low(AHand) to High(AHand) - 1 do
    for J := I + 1 to High(AHand) do
      if AHand[I].Figure > AHand[J].Figure then
      begin
        Card := AHand[I];
        AHand[I] := AHand[J];
        AHand[J] := Card;
      end;
end;

Zwróć uwagę na indeksowanie pętli – Low i High zwraca indeksy,więc nie trzeba używać nic nie mówiących literałów). Poprawiłem też warunek, bo masz w nim bubel – AHand.Figure nie jest poprawny, bo AHand to macierz.

Kiedyś pisałem w TP7 i taki nawyk mam z tymi funkcjami. Po latach chciałem coś dla siebie napisać i wybrałem środowisko freepascal. Poprawiłem kod (oprócz funkcji KtoWygral). Jak to teraz wygląda?

O wiele lepiej – widać, że czujesz bluesa. Choć co nieco bym zmienił. ;)

  • nazwy typów wyliczeniowych są dobre, choć jeśli nazwa typu zawiera jedno słowo, to ustaliłbym nieco dłuższy prefiks (wielkiego znaczenia by to nie miało) – np.:
    • TFigures – prefiks fig,
    • TColors – prefiks col lub clr,
    • TDecision – prefiks dec,
    • TCardLayer – prefiks cl, clay lub lay,
  • w strukturze TCard są pola o mylących nazwach:
    • Figure – jest typu TFigures, więc pole powinno nosić nazwę Figures,
    • Color – jest typu TColors, więc powinno mieć nazwę Colors,
  • macierze indeksujemy od 0, więc deklaracja THand do poprawy,
  • typ TPlayerType trzeba wzbogacić o nowy enum plNone, bo gracze mogą mieć układ o takiej samej sile i wtedy nie dałoby się prawidłowo okreslić zwycięzcy (to zrobiłem podając przykład funkcji WhoWon ekran wyżej),
  • typ TPlayerData służy do przechowywania danych o dwóch graczach, więc powinien posiadać nazwę TPlayersData,
  • jeśli chodzi o wcięcia – lokalne dla funkcji bloki kodu (var, const i para begin end) powinny być wyrównane maksymalnie do lewej, na równo z nagłówkiem funkcji – tutaj przykład,
  • jeśli chodzi o puste linie – nie powinny być używane przed właściwą częścią kodu i po niej,
  • operatory powinny być rozsunięte jedną spacją od identyfikatorów/literałów.

Ale to już kwestia stylistyki, więc jak kto woli.

0

Też zauważyłem błąd w SortCards. Poprawiłem już i przyjąłem Twoją wersję.
plNone dodałem.

Co do formatowania - skoro twierdzisz, że to kwestia stylistyki i 'jak to woli', to ja już bym nie ruszał tych typów porządkowych i deklaracji. Macierz TCard jest dla mnie czytelniejsza niż jakby miało być 0..4 (Trochę kiepsko brzmi 'wymień 0-rową kartę).

Funkcje obliczające siłę układu zrobiłem w taki sposób, że użyłem jakby wag, w zależności od sytuacji

  • ValueOfRoyalFlush - układ o lepszym kolorze ma większą wartość (wybór dowolnej karty)
  • ValueOfStraightFlush - układ ze stritem (wartość najwyżej 5 karty*10)+wartość koloru (jakby strity były takie same)
  • ValueOfFourOfAKind - wartość wybrana ze wspólnych części kombinacji układu (AAAAx i xAAAA) - wybrana 3 karta
  • ValueOfFull - 3 karta, bo fuli też są 2 możliwości (AAABB i BBAAA - 3 karta z 'trójki' jest wspólna)
  • ValueOfThreeOfAKind - 3 kombinacje (AAAxx, xAAAx, xxAAA - 3 karta z 'trójki' jest wspólna)
  • ValueOfStraight - to samo co ValueOfStraightFlush
  • ValueOfFlush - kolor z odpowiednią wagą + wartość najwyższej figury
  • ValueOfTwoPairs - 3 kombinacje (AABBx, xAABB, AAxBB) - Waga większego układu B (4 karta) potem waga mniejszego A (2 karta). Jakby były 2 te same '2 pary', to dodaje jeszcze wartość z karty 1,3,5 (w zależności od wariantu)
  • ValueOfPairs - tego nie napisałem jeszcze, bo tu już będzie trochę ifów (może lepiej się da to napisać). Kombinacje AAxxx, xAAxx, xxAAx, xxxAA. Jak będą te same pary, to trzeba chyba w pętli szukać z wagami pozostałych trzech kart?
  • ValueOfNone - jest też do napisania.

Kod funkcji:

function ValueOfRoyalFlush(AHand : THand): UInt8;
begin

  SortCards(AHand);
  Result := ord(AHand[1].Color);

end;


function ValueOfStraightFlush(AHand : THand): UInt8;
begin

  SortCards(AHand);
  Result := ((10 * ord(AHand[5].Figure)) + ord(AHand[5].Color));

end;


function ValueOfFourOfAKind(AHand : THand): UInt8;
begin

  SortCards(AHand);
  Result := ord(AHand[3].Figure);

end;


function ValueOfFull(AHand : THand): UInt8;
begin

  SortCards(AHand);
  Result := ord(AHand[3].Figure);

end;

function ValueOfThreeOfAKind(AHand : THand): UInt8;
begin

  SortCards(AHand);
  Result := ord(AHand[3].Figure);

end;


function ValueOfStraight(AHand : THand): UInt8;
begin

  SortCards(AHand);
  Result := ((10 * ord(AHand[5].Figure)) + ord(AHand[5].Color));

end;


function ValueOfFlush(AHand : THand): UInt8;
begin

  SortCards(AHand);
  Result := ((20 * ord(AHand[5].Color)) + ord(AHand[5].Figure));

end;


function ValueOfTwoPairs(AHand : THand): UInt8;
var
  Score : UInt8;

begin

  SortCards(AHand);
  
  Score := ((30 * ord(AHand[4].Figure)) + (20 * ord(AHand[2].Figure)));

  if ((AHand[2].Figure = AHand[3].Figure) and (AHand[4].Figure = AHand[5].Figure)) 
    then Score := Score + ord (AHand[1].Figure);
  if ((AHand[1].Figure = AHand[2].Figure) and (AHand[3].Figure = AHand[4].Figure)) 
    then Score := Score + ord (AHand[5].Figure);
  if ((AHand[1].Figure = AHand[2].Figure) and (AHand[4].Figure = AHand[5].Figure)) 
    then Score := Score + ord (AHand[3].Figure);

  Result := Score;
  
end;

Ps. nie kasuj tematu, jak będą nieaktywny lub długo nie odpowiadał (mało czasu) :)

0
Biały Rower napisał(a):

Co do formatowania - skoro twierdzisz, że to kwestia stylistyki i 'jak to woli', to ja już bym nie ruszał tych typów porządkowych i deklaracji.

Możesz zostawić jak jest – złe nie są.

Macierz TCard jest dla mnie czytelniejsza niż jakby miało być 0..4 (Trochę kiepsko brzmi 'wymień 0-rową kartę).

No jak to… przecież podczas wyświetlania danych możesz dodać 1 do indeksu i wyjdzie na to samo. Pamiętaj, że tylko ciągi znaków indeksowane są od 1 (przez wsteczną kompatybilność z typem ShortString), wszystko inne jest od 0.

Funkcje obliczające siłę układu zrobiłem w taki sposób, że użyłem jakby wag, w zależności od sytuacji

Wyglądają w porządku, ale słówka then nie przenoś na początek nowej linii, bo to wprowadza w błąd. ;)

Ps. nie kasuj tematu, jak będą nieaktywny lub długo nie odpowiadał (mało czasu) :)

Tutaj wątków się nie usuwa, nie ma się czego obawiać.

0

Zmieniłem TCard na 0..4 zgodnie z Twoją sugestią.

Dodałem te 2 brakujące funkcje ValueOfPair ValueOfHighCard

function ValueOfPair(AHand : THand): UInt8;
var
  Score, I   : UInt8;
  OtherCards : array [0..2] of UInt8;

begin

  SortCards(AHand);

  Score := 0;

  if ((AHand[0].Figure = AHand[1].Figure)) then 
  begin

    Score := Score + (1000 * (ord(AHand[0].Figure)+1))
    OtherCards[0] := ord(AHand[2].Figure);
    OtherCards[1] := ord(AHand[3].Figure);
    OtherCards[2] := ord(AHand[4].Figure);
   
    for I := 0 to 2 do
      Score := Score + ((100 * (I + 1)) * OtherCards[I]);
   end; 

  if ((AHand[1].Figure = AHand[2].Figure)) then 
  begin

    Score := Score + (1000 * (ord(AHand[1].Figure)+1))
    OtherCards[0] := ord(AHand[0].Figure);
    OtherCards[1] := ord(AHand[3].Figure);
    OtherCards[2] := ord(AHand[4].Figure);
   
    for I := 0 to 2 do
      Score := Score + ((100 * (I + 1)) * OtherCards[I]);
   end;  

  if ((AHand[2].Figure = AHand[3].Figure)) then 
  begin

    Score := Score + (1000 * (ord(AHand[3].Figure)+1))
    OtherCards[0] := ord(AHand[0].Figure);
    OtherCards[1] := ord(AHand[1].Figure);
    OtherCards[2] := ord(AHand[4].Figure);
   
    for I := 0 to 2 do
      Score := Score + ((100 * (I + 1)) * OtherCards[I]);
   end;

  if ((AHand[3].Figure = AHand[4].Figure)) then 
  begin

    Score := Score + (1000 * (ord(AHand[3].Figure)+1))
    OtherCards[0] := ord(AHand[0].Figure);
    OtherCards[1] := ord(AHand[1].Figure);
    OtherCards[2] := ord(AHand[2].Figure);
   
    for I := 0 to 2 do
      Score := Score + ((100 * (I + 1)) * OtherCards[I]);
   end;

  Result := Score;
  
end;


function ValueOfHighCard(AHand : THand): UInt8;
var
  Score, I : UInt8;

begin

  SortCards(AHand);
  
  Score := 0

 for I := Low(AHand) to High(AHand) do
      Score := Score + ((100 * (I + 1)) * (ord(AHand[I].Figure)+1))

  Result := Score;
  
end;

Co do kolejnego zestawu funkcji - skleciłem coś takiego (1 funkcja na razie). Pozostałe będą (poza nazwami wywoływanych funkcji) takie same.

function PlayerWithStrongerRoyalFlush(APlayerHand, AComputerHand : THand) : TPlayerType;
begin

  if (ValueOfRoyalFlush(APlayerHand) > ValueOfRoyalFlush(AComputerHand)) then exit(plHuman)
    else if (ValueOfRoyalFlush(APlayerHand) < ValueOfRoyalFlush(AComputerHand)) then exit(plComputer);

  Result := plNone;
  
end;
0

Funkcję ValueOfPair trzeba jakoś skrócić – ciągle powtarza się ten sam schemat, tylko indeksy się zmieniają. Zwróć uwagę na to, że wewnątrz funkcji ValueOfPair wiadome jest, że karty zawierają parę, a ta została określona na podstawie posortowanych kart, więc już nie musisz kolejny raz sortować. Zamiast wołać SortCards, wywołaj funkcję która przesunie karty pary na początek, tak aby można było od razu policzyć wartość kart pary (dwie pierwsze, indeksy 0 i 1) i trzech pozostałych (indeksy 2, 3, 4).

Natomiast w funkcji PlayerWithStrongerRoyalFlush znów popełniasz ten sam błąd co wcześniej – zamiast wywołać dwa razy funkcje ValueOf*, zapisać ich wynik do zmiennych i ich używać do warunków, Ty wołasz te funkcje tyle razy, ile jest warunków (po razy dwie w każdym z nich).

Powinieneś zrobić w ten sposób:

function PlayerWithStrongerRoyalFlush(APlayerHand, AComputerHand: THand): TPlayerType;
var
  PlayerValue, ComputerValue: Integer;
begin
  PlayerValue   := ValueOfRoyalFlush(APlayerHand);
  ComputerValue := ValueOfRoyalFlush(AComputerHand);
  
  if PlayerValue > ComputerValue then
    Result := plPlayer
  else
    if PlayerValue < ComputerValue then
      Result := plComputer
    else
      Result := plNone;
end;

Ew. możesz wspomóc się instrukcją wyboru – wyjdzie krócej, choć niekoniecznie szybciej:

function PlayerWithStrongerRoyalFlush(APlayerHand, AComputerHand: THand): TPlayerType;
var
  PlayerValue, ComputerValue: Integer;
begin
  PlayerValue   := ValueOfRoyalFlush(APlayerHand);
  ComputerValue := ValueOfRoyalFlush(AComputerHand);
  
  case CompareValue(PlayerValue, ComputerValue) of
    LessThanValue:     Result := plComputer;
    EqualsValue:       Result := plNone;
    GreatherThanValue: Result := plPlayer;
  end;
end;

Kolejna rzecz to funkcja ValueOfHighCard – skoro używasz zmiennej Result, to po co Ci zmienna Score?

function ValueOfHighCard(AHand: THand): UInt8;
var
  Score, I: UInt8;
begin
  Result := 0
  SortCards(AHand);
 
  for I := Low(AHand) to High(AHand) do
    Result := Result + ((100 * (I + 1)) * (Ord(AHand[I].Figure)+1))
end;

Tu kilka informacji – jeśli do pisania tego programu używasz Lazarusa to możesz skorzystać z operatora +=:

function ValueOfHighCard(AHand: THand): UInt8;
var
  I: UInt8;
begin
  Result := 0
  SortCards(AHand);
 
  for I := Low(AHand) to High(AHand) do
    Result += (100 * (I + 1)) * (Ord(AHand[I].Figure) + 1);
end;

Jeśli chodzi o rzeczy mniej znaczące – używasz mnóstwa nadmiarowych nawiasów, komplikując kod i sprawiając, że trudniej jest go analizować (i zrozumieć). Nawiasy umieszczaj wyłącznie tam, gdzie jest to konieczne i tylko tam.

0

Pozostałe będą (poza nazwami wywoływanych funkcji) takie same.

To gdzieś masz błąd projektowy. Skoro jest kilka funkcji różniących się jedną nazwą to można zrobić z nich jedną.

0
babubabu napisał(a):

Pozostałe będą (poza nazwami wywoływanych funkcji) takie same.

To gdzieś masz błąd projektowy. Skoro jest kilka funkcji różniących się jedną nazwą to można zrobić z nich jedną.

Mi chodziło, że zestaw funkcji PlayerWithStronger..... zaproponowanych przez @furious programming będą podobnej konstrukcji.

Jeśli chodzi o poprawę ValueOfPair to zrobiłem dodatkową procedurę PairOnFirstIndex , gdzie użyłem pomocniczej tablicy rekordów. W 1 pętli para jest ustawiana na pierwszych indeksach, a 2 dokleja pozostałe karty. Faktycznie, sporo kodu ubyło.

procedure PairOnFirstIndex(var AHand : THand);
var
  AuxiliaryArray :THand;
  I, N :IUint8;

begin

  SortCards(AHand);
  N := 0;
  for I := Low(THand) to High(AHand) -1 do
    if THand[I].Figure = THand[I+1].Figure then
      begin
        AuxiliaryArray[N].Figure := THand[I].Figure;
        AuxiliaryArray[N+1].Figure := THand[I+1].Figure;
      end;
  N := N + 2;
  for I := Low(THand) to High(AHand)-1 do
    if THand[I].Figure <> THand[I+1].Figure then
      begin
        AuxiliaryArray[N].Figure := THand[I+1].Figure;
        N := N + 1;
      end; 

  AHand := AuxiliaryArray;

end;

Dzięki temu, sama funkcja ValueOfPair skróciła się do postaci:

function ValueOfPair(AHand : THand): UInt8;
var
  I   : UInt8;

begin

  PairOnFirstIndex(AHand);

  Result := 1000 * ord(AHand[0].Figure) +1 ;
    for I := Low(AHand) +2 to High(AHand) do
     Result := Result + (100*(I+1)) * ord(AHand[I].Figure)+1;
  
end;

Resztę funkcji PlayerWithStronger...... dopisałem i skorzystałem z Twojej funkcji WhoWon. Mam pytanie do konstrukcji Math.CompareValue(Byte(HumanLayer), Byte(CpuLayer)). Dobrze rozumiem, że zwraca ona 3 argumenty LessThanValue, GreaterThanValue, EqualsValue? Pytam, bo w klasycznym pascalu nie spotkałem się z tym. To samo z byte. Czy do tego Math. potrzebna jest jakaś deklaracja w Uses? Używam freepascala.

0

for I := Low(THand) to High(AHand) -1 do . Literówka - Zamiast THand jest AHand.

0
Biały Rower napisał(a):

Mam pytanie do konstrukcji Math.CompareValue(Byte(HumanLayer), Byte(CpuLayer)). Dobrze rozumiem, że zwraca ona 3 argumenty LessThanValue, GreaterThanValue, EqualsValue?

Nie, funkcja CompareValue zwraca jedną z trzech możliwych wartości typu TValueRelationship-1, 0 lub 1. Natomiast te trzy nazwy to zwykłe stałe:

  • LessThanValue – stała o wartości -1 (zwracana gdy A < B),
  • EqualsValue – stała o wartości 0 (zwracana gdy A = B),
  • GreatherThanValue – stała o wartości 1 (zwracana gdy A > B).

Jak chcesz wiedzieć czym jest dana nazwa to wciśnij lewy Ctrl, najedź kursorem myszy na daną nazwę i wciśnij lewy przycisk myszy – zostaniesz przeniesiony w miejsce deklaracji tego elementu. Można też umieścić kursor tekstowy na danym słowie i wcisnąć kombinację Alt+Up.

Pytam, bo w klasycznym pascalu nie spotkałem się z tym.

W klasycznym Pascalu też istnieje instrukcja wyboru, też istnieje możliwość definiowania własnych typów liczbowych (o innych zakresach wartości) i też istnieją stałe. ;)

To samo z byte.

To jest zwykłe rzutowanie – jest ono konieczne ze względu na bardzo silne typowanie w Pascalu. Typ wyliczeniowy, pomimo tego że jest liczbą, nie może zostać bezpośrednio przekazany w liczbowym argumencie funkcji (ani w niczym innym o typie innym niż ten enum). Rzutowanie też istnieje w klasycznym Pascalu.

Czy do tego Math. potrzebna jest jakaś deklaracja w Uses? Używam freepascala.

Math to nazwa modułu, który zawiera funkcję CompareValue i musi być dodany do listy uses. Tę linijkę napisałem w ten sposób, abyś wiedział, że ta funkcja znajduje się w tym module i że trzeba go dodać do listy – ale nie zrozumiałeś zapisu.

Jak dodasz sobie ten moduł to możesz napisać samą nazwę funkcji – prefiks modułu nie jest wymagany.


Ogólnie to widzę pewien problem – masz jakieś podstawy Pascala, jednak tego klasycznego, który jest 100 lat za murzynami. Jeśli używasz Free Pascala to zapoznaj się z jego możliwościami, bo ma o wiele większe niż klasyczna wersja. I mam nadzieję, że do pisania tego programu używasz Lazarusa, a nie tego konsolowego pseudo-edytora.

0

W klasycznym Pascalu też istnieje instrukcja wyboru, też istnieje możliwość definiowania własnych typów liczbowych (o innych zakresach wartości) i też istnieją stałe. ;)

To akurat wiedziałem :) Chodziło mi o same math

To jest zwykłe rzutowanie – jest ono konieczne ze względu na bardzo silne typowanie w Pascalu. Typ wyliczeniowy, pomimo tego że jest liczbą, nie może zostać bezpośrednio przekazany w liczbowym argumencie funkcji (ani w niczym innym o typie innym niż ten enum). Rzutowanie też istnieje w klasycznym Pascalu.

Właśnie sprawdziłem w starej książce od TurboPascala i jest byte. Nie miałem okazji skorzystać z niej i dlatego stąd brak wiedzy.

Ogólnie to widzę pewien problem – masz jakieś podstawy Pascala, jednak tego klasycznego, który jest 100 lat za murzynami. Jeśli używasz Free Pascala to zapoznaj się z jego możliwościami, bo ma o wiele większe niż klasyczna wersja. I mam nadzieję, że do pisania tego programu używasz Lazarusa, a nie tego konsolowego pseudo-edytora.

Ostatni programik napisałem gdzieś 10 lat temu w TurboPascalu i od tamtego czasu z programowaniem nie miałem do czynienia. Ostatnio wziąłem z nudów książkę o TP i naszła mnie myśl "a może coś napisać?". 10 lat w IT to przepaść i nie interesowałem się rozwojem Pascala. Cieszy mnie fakt, że jakaś tam moja wiedza po tych latach została. Pozostało mi poprawić kod losowania kart i będę miał tyle, co w starym kodzie. Potem jeszcze sama rozgrywka i obsługa gracza-komputera.

Właśnie używałem tego konsolowego edytorka, ale już ściągnąłem Lazarusa. Muszę się przyzwyczaić i obcykać.

0

Przerobiłem funkcje odpowiedzialne za losowanie kart (Skoro ktoś mi pomógł, to może ja komuś pomogę udostępniając kod).

procedure DeckInit(var ADeck :TDeckOfCard);
var

  I       : Integer;
  CardFigure  : TFigures;
  CardColor  : TColors;

begin

  CardFigure := fiTwo;
  CardColor := coSpade;

  for I := 1 to 52 do
  begin
    ADeck[I-1].Figure := CardFigure;
    ADeck[I-1].Color := CardColor;
    if (I mod 4 = 0) and (I<>52) then
      Inc(CardFigure);
    if CardColor <> coHeart then
      Inc(CardColor)
    else
      CardColor := coSpade;
  end;
end;


procedure DeckShuffle(var ADeck : TDeckOfCard);
var
  TemporaryDeck: TCard;
  I, J         : Integer;

begin
  for I := 0 to 51 do
  begin
    J := Random(52);
    TemporaryDeck := ADeck[J];
    ADeck[J] := ADeck[I];
    ADeck[I] := TemporaryDeck;
  end;
    CardsInDeck := 52;
end;


function DealCard(ADeck : TDeckOfCard): TCard;
begin

  Dec(CardsInDeck);
  Result := ADeck[CardsInDeck];

end;


function CardToString(ACard : TCard): String;
const

  FiguresStr = '23456789TJQKA';
  ColorsStr  = #6#5#4#3;


begin

  Result := FiguresStr[ord(ACard.Figure)] + ColorsStr[ord(ACard.Color)];

end;

Chociaż mam mały problem funkcją CardToString. Funkcja działa normalnie, jak będę wyświetlał w ColorsStr litrowych symboli kart SCDH, ale chcę zrobić to bardziej elegancko i wyświetlić symbole ♠♣♥♦. Na konsoli Windows są wyświetlane poprawnie, a na linuksowej są krzaczki. Kombinowałem z ustawieniami kodowania znaków terminala, ale bez rezultatu. Jak to obejść?

Pozostało mi już do napisania samą rozgrywkę i Sztuczną inteligencje. Kolejne pytanie : Jak uporządkować główny blok begin...end tzn co ma w nim być? Myślałem żeby tam zostawić główną pętle gry i zastosować ze 2 procedury (powiedzmy) init, onepokergame.

0

Jest dobrze, choć nadal gdzieniegdzie widzę używanie zmiennych globalnych – wymień je na dodatkowe parametry.

Biały Rower napisał(a):

Funkcja działa normalnie, jak będę wyświetlał w ColorsStr litrowych symboli kart SCDH, ale chcę zrobić to bardziej elegancko i wyświetlić symbole ♠♣♥♦. Na konsoli Windows są wyświetlane poprawnie, a na linuksowej są krzaczki. […] Jak to obejść?

Ustawić kodowanie w konsoli na unikod i skorzystać z symboli unikodowych. Pod Windows, symbole te wyświetlane są zamiast znaków kontrolnych (co wykorzystałeś). W innych wersjach systemu i innych systemach może się wyświetlać coś innego – i tak też się dzieje pod Linuksem.

Symbole które wkleiłeś do posta, nie są jednobajtowe. To znaki unikodowe, których rozmiar jest inny niż zakładasz. Zróbmy mały test:

Write('♠♣♥♦'.Length);

Jak myślisz, co zostanie wyświetlone w konsoli? 4, bo cztery znaki? Nie – wyświeli się 12, bo każdy z tych znaków w natywnym kodowaniu (czyli w UTF-8) zajmuje po trzy bajty. Jeśli spróbujesz je wyświetlić jako literał:

Write('♠♣♥♦');

W konsoli pojawią się krzaczki:

ÔÖáÔÖúÔÖąÔÖŽ

Dlatego też trzeba zmienić kodowanie konsoli, tak aby obsługiwała unikod. Spróbuj w ten sposób:

uses
  {$IF DEFINED(UNIX)}
  cwstring;
  {$ELSEIF DEFINED(WINDOWS)}
  Windows;
  {$ENDIF}
begin
  {$IFDEF WINDOWS}
  SetConsoleOutputCP(CP_UTF8);
  {$ENDIF}
  Write('♠♣♥♦');

Pod Linuksami konsola domyślnie obsługuje unikod, więc znaki unikodowe można wyświetlać bezpośrednio. Pod Windows trzeba ustawić odpowiednie kodowanie. Powyższy sposób nie działa pod Windows XP, ale można inaczej:

Write(LazUTF8.UTF8ToSys('♠♣♥♦'));

Dla tych znaków powinno działać. Tyle że do projektu trzeba dodać pakiet LCL, a do uses moduł LazUTF8.

Trzeba też zwrócić uwagę na to, że font w konsoli musi posiadać wymagane znaki. Jeśli nie posiada ich to trzeba się pobawić i ustawić inny – taki, który je zawiera.

Jak uporządkować główny blok begin...end tzn co ma w nim być? Myślałem żeby tam zostawić główną pętle gry i zastosować ze 2 procedury (powiedzmy) init, onepokergame.

Póki co nie wiem co w niej masz, więc mogę doradzić tyle, że powinna mieć góra kilkanaście linijek kodu i ograniczać się wyłącznie do wywoływania innych procedur/funkcji.

0

w procedurze DeckShuffle zmienna TemporaryDeck powinna nazywać się TemporaryCard skoro jest typu TCard. Taka moja sugestia.

0
furious programming napisał(a):

Dlatego też trzeba zmienić kodowanie konsoli, tak aby obsługiwała unikod. Spróbuj w ten sposób:

uses
  {$IF DEFINED(UNIX)}
  cwstring;
  {$ELSEIF DEFINED(WINDOWS)}
  Windows;
  {$ENDIF}
begin
  {$IFDEF WINDOWS}
  SetConsoleOutputCP(CP_UTF8);
  {$ENDIF}
  Write('♠♣♥♦');

Pod Linuksami konsola domyślnie obsługuje unikod, więc znaki unikodowe można wyświetlać bezpośrednio.

Też to nie działa pod linuxem. Już ze 3h się z tym męczę. W konsoli tak wyświetla:
screenshot-20180208205220.png

0

Dodam jeszcze procedurke wyświetlające karty, bo to może mieć wpływ.

Procedure DrawCard(APosX, APosY : Integer; ACard : String);
begin

  GotoXY(APosX, APosY);    write('.-.');
  GotoXY(APosX, APosY+1);  write('|',ACard[1],'|');
  GotoXY(APosX, APosY+2);  write('|',ACard[2],'|');
  GotoXY(APosX, APosY+3);  write('`-`');

end;

Testową procedurę

procedure Test;
begin

  ResetLogs;
  ResetComputerPlayer;
  ResetHumanPlayer;
  Pot := 0;

  Clrscr;
  DeckInit(Deck);

  DrawPokerTable;    AddLog(GameLogs, LogCounter, 'Inicjalizacja stolu...');
  DeckShuffle(Deck,CardsInDeck); AddLog(GameLogs, LogCounter, 'Tasowanie kart...');
  Delay(2000);

  Clrscr;
  Pot := Pot + EnterPot;
  Player[plComputer].Money := Player[plComputer].Money - EnterPot;
  DrawPokerTable;
  AddLog(GameLogs, LogCounter, 'Komputer dal 5 zl.');
  Delay(1000);

  Clrscr;
  Pot := Pot + EnterPot;
  Player[plHuman].Money := Player[plHuman].Money - EnterPot;
  DrawPokerTable;
  AddLog(GameLogs, LogCounter, 'Gracz dal 5 zl.');
  Delay(1000);

  for I:=1 to 10 do
  begin
    if (I mod 2) = 1 then
    begin
      Card := DealCard(Deck,CardsInDeck);
      Player[plComputer].Hand[trunc(i/2)] := Card;
      DrawHideCard(9+(trunc(i/2)*3),8);
     end
       else
       begin
         Card := DealCard(Deck,CardsInDeck);
         Player[plHuman].Hand[trunc(i/2)-1] := Card;
         DrawCard(9+(Trunc((i/2)-1)*3),13,CardToString(Card));
       end;
         Delay(500);
   end;
  AddLog(GameLogs, LogCounter, 'Rozdano karty.');


end;
0
Procedure DrawCard(APosX, APosY : Integer; ACard : String);
begin
  GotoXY(APosX, APosY);    write('.-.');
  GotoXY(APosX, APosY+1);  write('|',ACard[1],'|');
  GotoXY(APosX, APosY+2);  write('|',ACard[2],'|');
  GotoXY(APosX, APosY+3);  write('`-`');
end;

A co zawiera ACard[2] – jak myślisz?

Jeden jednobajtowy znak, podczas gdy każdy symbol – np. – nie jest znakiem, a trzybajtowym ciągiem, więc nie możesz do tego celu używać dwubajtowego String[2], bo symbol się w nim nie zmieści.

Zrób mały test pod Linuksem, odpal poniższy kod (przekopiuj go do edytora) i zrób fotkę konsoli:

uses
  cwstring;
begin
  Write('♠♣♥♦');

Jeśli konsola obsługuje natywnie unikod, to zobaczysz symbole, a jeśli nie to krzaczki.

Najpierw skup się na rozwiązaniu problemu z kodowaniem, a dopiero jak już ten problem uda się rozwiązać to wtedy popraw kod swojego projektu.

0

Rozwiązałem problem z kodowaniem :)

  1. Wkleiłem znaczki ♠♣♦♥ do kodu w edytorze gedit. Wyskoczył komunikat, że nie można zapisać bez zmiany kodowania. Była możliwość zmiany na UTF-8 i tak zrobiłem (nie wiem, czy to ma do znaczenia).

  2. We funkcji CardToString zmieniłem ColorsStr = #6#5#4#3; na ColorsStr = '♠♣♦♥';

  3. Przerobiłem procedurę DrawCard

procedure DrawCard(APosX, APosY : Integer; ACard : String);
var
  ColorStr : String;

begin

  ColorStr := copy(ACard, 2, length(ACard));

  GotoXY(APosX, APosY);    write('.-.');
  GotoXY(APosX, APosY+1);  write('|',ACard[1],'|');
  GotoXY(APosX, APosY+2);  write('|',ColorStr,'|');
  GotoXY(APosX, APosY+3);  write('`-`');

end;
  1. Dodałem dyrektywę kompilatora (znalazłem w necie) {$codepage utf8} na początku programu i dopiero zadziałało :)

Dodam też, że zastosowanie starej wersji procedury DrawCard z ACards[2] po użyciu tej dyrektywy kompilatora też wywalało krzaczki.

Efekt w konsoli

screenshot-20180209210906.png

0
Biały Rower napisał(a):
  1. Wkleiłem znaczki ♠♣♦♥ do kodu w edytorze gedit. Wyskoczył komunikat, że nie można zapisać bez zmiany kodowania. Była możliwość zmiany na UTF-8 i tak zrobiłem (nie wiem, czy to ma do znaczenia).

Toż pisałem Ci kilka razy w poprzednich swoich postach, żebyś skorzystał ze znaków unikodowych, a nie liczył, że akurat zadziała ze znakami kontrolnymi. Oczywiście że ma to znaczenie.

  1. We funkcji CardToString zmieniłem ColorsStr = #6#5#4#3; na ColorsStr = '♠♣♦♥';

Nie powinieneś do tego celu używać jednego ciągu znaków.

  1. Przerobiłem procedurę DrawCard
ColorStr := copy(ACard, 2, length(ACard));

Ta linijka jest tak dziwna, że sam nawet nie wiem jak ona może działać…

Jeśli plik z kodem źródłowym (który zawiera powyższą linijkę) zapisany jest jako UTF-8, to ta linijka pakuje do zmiennej kupę śmieci. Kopiujesz zawsze od drugiego bajtu (czyli od środkowego bajtu pierwszego znaku) i zawsze tyle bajtów, ile zajmuje ten ciąg (czyli 12).

Prawidłowe skopiowanie ciągu na podstawie enuma – jeśli o UTF-8 chodzi – wygląda tak (w postaci helpera, więc wymaga dyrektywy {$MODESWITCH TYPEHELPERS}):

type
  TCardColor = (ccNone, ccSpade, ccClub, ccDiamond, ccHeart);

type
  TCardColorHelper = type helper for TCardColor
  public
    function ToString(): String;
  end;

  function TCardColorHelper.ToString(): String;
  const
    SYMBOL: String = '♠';
    SYMBOLS: String = '♠♣♦♥';
  begin
    if Self <> ccNone then
      Result := Copy(SYMBOLS, (Ord(Self) - 1) * SYMBOL.Length + 1, SYMBOL.Length)
    else
      Result := '';
  end;

Ewentualnie możesz użyć krótszej wersji, jeśli nigdy nie będziesz próbował przekonwertować enuma ccNone:

function TCardColorHelper.ToString(): String;
begin
  Result := Copy('♠♣♦♥', (Ord(Self) - 1) * '♠'.Length + 1, '♠'.Length);
end;

Od tej pory możesz używać zapisu CardColor.ToString (czy nawet z poziomu wartości – ccSpade.ToString), więc znacznie krótszego.

  1. Dodałem dyrektywę kompilatora (znalazłem w necie) {$codepage utf8} na początku programu i dopiero zadziałało :)

Sprawdź lepiej jakie kodowanie masz ustawione w edytorze kodu dla tego pliku źródłowego – PPM w edytorze, w menu opcja File Settings i dalej Encoding. Domyślnie powinna być zaznaczona ta na samej górze, czyli UTF-8.


Przy okazji – skoro i tak używasz w konsoli znaków unikodowych, to skorzystaj też z wielu innych do rysowania interfejsu. Np. do malowania kart możesz użyć znaków ┌ ┐└ ┘─│, dzięki czemu karta na ekranie może wyglądać tak:

┌─┐
│A│
│♣│
└─┘

W konsoli ramka będzie wyglądać jak prostokąt, bez przerw. Do rysowania ramek jest o wiele więcej znaków – z grubszą linią, bloków, krzyżaków, łączników itd. itd.

0

Mam pytanie do tego kodu:

function TCardColorHelper.ToString(): String;
begin
  Result := Copy('♠♣♦♥', (Ord(Self) - 1) * '♠'.Length + 1, '♠'.Length);
end;

Czym by się różniła od :

function CardColorToString(AColor : TColor): String;
begin

  Result := Copy('♠♣♦♥', (Ord(AColor) -1) * length('♠')+1, length('♠'));

end;

Bo w zasadzie obie funkcje kopiują ze stringa ♠♣♦♥ od pozycji (Ord(ACard.Color) -1) * length('♠')+1 o długości length('♠')? Inne wywołanie tylko CardColorToString(coSpade)

Sprawdź lepiej jakie kodowanie masz ustawione w edytorze kodu dla tego pliku źródłowego – PPM w edytorze, w menu opcja File Settings i dalej Encoding. Domyślnie powinna być zaznaczona ta na samej górze, czyli UTF-8.

Jest UTF-8.

Przy okazji – skoro i tak używasz w konsoli znaków unikodowych, to skorzystaj też z wielu innych do rysowania interfejsu. Np. do malowania kart możesz użyć znaków ┌ ┐└ ┘─│, dzięki czemu karta na ekranie może wyglądać tak(...)

Myślałem już od dawna o tym. Za czasów starego pascala tak sobie rysowałem. Poprawie stół i inne elementy interfejsu.

0
Biały Rower napisał(a):

Czym by się różniła od :

Jedyną różnicą jest składnia. Moja propozycja operuje na metodach pochodzących z helperów, m.in. redukując liczbę potrzebnych nawiasów, co upraszcza zapis i sprawia, że łatwiej się go analizuje. To tylko cukier składniowy.

Bo w zasadzie obie funkcje kopiują ze stringa ♠♣♦♥ od pozycji (Ord(ACard.Color) -1) * length('♠')+1 o długości length('♠')?

Tak. Literał ♠♣♦♥ zawiera cztery znaki, z których każdy opisany jest na trzech bajtach – to daje łącznie dwanaście bajtów. Lewa część konwertuje enum na liczbę i odejmuje od niej 1 – musi, aby dla pierwszego enuma z kolorem (ccNone jest ignorowany) zwróciła 0. Następnie pobierany jest z literału rozmiar jednego znaku (czyli 3) i wykonywane jest mnożenie. Na koniec dodawane jest 1, bo ciągi znaków indeksowane są od 1.

Inne wywołanie tylko CardColorToString(coSpade)

Służy do tego samego, tyle że to zwykła funkcja, która enum koloru pobiera w parametrze. Jednak najprzyjemniejsza dla oka wersja to ta używająca metody helpera, więc taką też zaproponowałem.

Przy okazji – wbudowane helpery typów prostych znajdują się w module SysUtils i oprócz metod (statycznych i instancyjnych) posiadają jeszcze stałe i właściwości. Tak na przyszłość, abyś nie musiał mordować się z IntToStr i podobnymi.

0

Zrobiłem tak:

Usunąłem funkcje CardToString. Zamiast jej, 2 funkcje:

function GetStringCardFigure(AFigure : TFigures): String;
begin

  Result := Copy('23456789TJQKA', ord(AFigure), 1);

end;


function GetStringCardColor(AColor : TColors): String;
begin

  Result := Copy('♠♣♦♥', (Ord(AColor) -1) * length('♠')+1, length('♠'));

end;

a w samej procedurze DrawCard zmieniłem argument ze string na TCard

procedure DrawCard(APosX, APosY : Integer; ACard : TCard);
var
  Color, Figure : String;

begin

  Color := GetStringCardColor(ACard.Color);
  Figure := GetStringCardFigure(ACard.Figure);
 

  GotoXY(APosX, APosY);    write('┌─┐');
  GotoXY(APosX, APosY+1);  write('│',Figure,'│');
  GotoXY(APosX, APosY+2);  write('│',Color,'│');
  GotoXY(APosX, APosY+3);  write('└─┘');

end;

Też działa i chyba dla mnie czytelniejsze, niż te helpery i poprzednia wersja.

0

Helpery dla typów prostych to dość młody ficzer – pomysł zassany z C# czy Javy – w każdym razie bardzo przydatny. Niektórzy jednak wolą zwykłe funkcje – każdy znajdzie coś dla siebie. ;)

Jeśli chodzi o same literały łańcuchowe, to nie należy ich nadużywać. W Twoich funkcjach z powyższego posta mogą zostać, jednak jeśli jakaś stała wartość używana jest w kodzie w wielu miejscach, to warto wrzucić ją do stałej i z tej stałej korzystać.

Jak będziesz chciał zmienić/poprawić tę wartość to wystarczy modyfikacja stałej, bez szukania wszystkich wystąpień – reszta kodu sama się dostosuje.

0

Myślałem, jak zrobić wymianę kart przez komputer. Więc wymyśliłem mniej więcej tak:

  1. Jeśli jest poker królewski, kolor, strit, full - to nie wymieniamy kart
  2. Jeśli jest kareta, to będą 2 opcje:
  • nie wymieniamy kart, jeśli los(1-10)>3
  • w przeciwnym przypadku wymieniamy 1 kartę (taki element blefu)
  1. Jeśli jest trójka - 2 karty do wymiany
  2. Jeśli są 2 pary - 1 karta do wymiany
  3. Jeśli jest para to:)
  • Sprawdzamy, czy mamy 4 karty tego samego koloru
  • jeśli tak to los(1-100)
  • jeśli los(1-100)>30 to wymieniamy 3 karty
  • w przeciwnym wypadku liczymy na szczęście i wymieniamy 1 kartę
  • Sprawdzamy, czy mamy 4 karty z tym samym kolorem
  • jeśli tak to los(1-100)
  • jeśli los(1-100)>30 to wymieniamy 3 karty
  • w przeciwnym wypadku liczymy na szczęście i wymieniamy 1 kartę
  1. Jeśli nic nie mamy to:
  • Sprawdzamy, czy mamy 4 karty tego samego koloru
  • jeśli tak to los(1-100)
  • jeśli los(1-100)>20 to wymieniamy 4 karty, pozostawiając najwyższą
  • w przeciwnym wypadku liczymy na szczęście i wymieniamy 1 kartę
  • Sprawdzamy, czy mamy 4 karty z tym samym kolorem
  • jeśli tak to los(1-100)
  • jeśli los(1-100)>20 to wymieniamy 4 karty, pozostawiając najwyższą
  • w przeciwnym wypadku liczymy na szczęście i wymieniamy 1 kartę

Do zrealizowania tego algorytmu napisałem kilka funkcji pomocniczych, które określą, na których pozycjach są poszczególne układy lub niepasujące karty:

function FindPairPos(AHand : THand):Integer;
var
  I : Integer;

begin
  
  SortCards(AHand);
  for I :=0 to 3 do
    if AHand[I].Figure = AHand[I+1].Figure then exit(I); 

  Result := -1; 

end;


function FindThreeOfAKindPos(AHand : THand):Integer;
var
  I : Integer;

begin
  
  SortCards(AHand);
  for I :=0 to 2 do
    if (AHand[I].Figure = AHand[I+1].Figure) and (AHand[I+1].Figure = AHand[I+2].Figure) then exit(I);  

  Result := -1;

end;


function FindFourOfAKindPos(AHand : THand):Integer;
var
  I : Integer;

begin
  
  SortCards(AHand);
  for I :=0 to 1 do
    if (AHand[I].Figure = AHand[I+1].Figure) and (AHand[I+1].Figure = AHand[I+2].Figure)
    and (AHand[I+2].Figure = AHand[I+3].Figure) then exit(I);  

  Result := -1;

end;


function FindFreeCardInTwoPairs(AHand : THand):Integer;
begin
  
  SortCards(AHand);
  
  if (AHand[0].Figure = AHand[1].Figure) and (AHand[2].Figure = AHand[3].Figure) and 
     (not FourOfAKind(AHand)) then exit(4);
  if (AHand[1].Figure = AHand[2].Figure) and (AHand[3].Figure = AHand[4].Figure) and 
     (not FourOfAKind(AHand)) then exit(0);
  if (AHand[0].Figure = AHand[1].Figure) and (AHand[3].Figure = AHand[4].Figure) and 
     (not FourOfAKind(AHand)) then exit(2);

  Result := -1;

end;


function FindFreeCardToStraight(AHand : THand):Integer;
begin
  
  SortCards(AHand);

  if (abs(ord(AHand[0].Figure) - ord(AHand[1].Figure)) = 1) and 
     (abs(ord(AHand[1].Figure) - ord(AHand[2].Figure)) = 1) and
     (abs(ord(AHand[2].Figure) - ord(AHand[3].Figure)) = 1) then exit(4);

  if (abs(ord(AHand[0].Figure) - ord(AHand[1].Figure)) = 1) and 
     (abs(ord(AHand[1].Figure) - ord(AHand[2].Figure)) = 1) and
     (abs(ord(AHand[2].Figure) - ord(AHand[4].Figure)) = 2) then exit(3);

  if (abs(ord(AHand[0].Figure) - ord(AHand[1].Figure)) = 1) and 
     (abs(ord(AHand[1].Figure) - ord(AHand[3].Figure)) = 2) and
     (abs(ord(AHand[3].Figure) - ord(AHand[4].Figure)) = 1) then exit(2);

  if (abs(ord(AHand[0].Figure) - ord(AHand[2].Figure)) = 2) and 
     (abs(ord(AHand[2].Figure) - ord(AHand[3].Figure)) = 1) and
     (abs(ord(AHand[3].Figure) - ord(AHand[4].Figure)) = 1) then exit(1)

  if (abs(ord(AHand[1].Figure) - ord(AHand[2].Figure)) = 1) and 
     (abs(ord(AHand[2].Figure) - ord(AHand[3].Figure)) = 1) and
     (abs(ord(AHand[3].Figure) - ord(AHand[4].Figure)) = 1) then exit(0);

  Result := -1;
         

end;


function FindFourColorsPos(AHand : THand):Integer;
var
  SpadesCount, ClubsCount, DiamondsCount, HeartsCount, I : Integer;

begin
  
  SortCards(AHand);
  SpadesCount := 0;
  ClubsCount := 0;
  DiamondsCount := 0;
  HeartsCount := 0;

  for I := Low(AHand) to High(AHand) do
    case AHand[I].Color of
      coSpade : Inc(SpadesCount);
      coClub : Inc(ClubsCount);
      coDiamond : Inc(DiamondsCount);
      coHeart : Inc(HeartsCount);
    end;

  if (SpadesCount = 4) or (ClubsCount = 4) or (DiamondsCount = 4) or (HeartsCount = 4) then
    begin
      if (AHand[0].Color = AHand[1].Color) and (AHand[2].Color = AHand[3].Color) then exit(4)
      else
        if (AHand[0].Color = AHand[1].Color) and (AHand[2].Color = AHand[4].Color) then exit(3)
        else
          if (AHand[0].Color = AHand[1].Color) and (AHand[3].Color = AHand[4].Color) then exit(2)
          else
            if (AHand[0].Color = AHand[3].Color) and (AHand[4].Color = AHand[5].Color) then exit(1)
            else
             if (AHand[1].Color = AHand[2].Color) and (AHand[3].Color = AHand[4].Color) then exit(0);
    end;

  Result := -1;

end;

Trochę niechlujnie przez te ify - w szczególności w FindFreeCardToStraight.

0

Witam po dłuższej przerwie.

Zaimplementowałem algorytm wymiany kart przez komputer. Jakoś działa. Pierw procedura pomocnicza zaznaczająca karty do wymiany SelectedCards

procedure SelectedCards(var AHand : TChangeCard; A0Card, A1Card, A2Card, A3Card, A4Card : Boolean);
begin

  AHand[0] := A0Card;
  AHand[1] := A1Card;
  AHand[2] := A2Card;
  AHand[3] := A3Card;
  AHand[4] := A4Card;

end;

Potem główna funkcja z algorytmem CpuSearchCardsToDiscard

function CpuSearchCardsToDiscard(AHand : THand) : TChangeCard;
var

  Rank : TCardLayer;
  Rnd, Pos  : Integer;
  Hand : TChangeCard;

begin

  Rank := HandStrength(AHand);
   
  Case Rank of
    caStraight, caRoyalFlush, caFlush, caFull : SelectedCards(Hand, False, False, False, False, False);
    caFourOfAKind : begin
                      Rnd := Random(100);
                      if Rnd > 70 then 
                      begin 
                        Pos := FindFourOfAKindPos(AHand);
                        case Pos of
                          0: SelectedCards(Hand, False, False, False, False, True);
                          1: SelectedCards(Hand, True, False, False, False, False);
                        end
                      end
                      else SelectedCards(Hand, False, False, False, False, False);
                    end; 

    caThreeOfAKind : begin 
                       Pos := FindThreeOfAKindPos(AHand);
                       case Pos of
                         0: SelectedCards(Hand, False, False, False, True, True);
                         1: SelectedCards(Hand, True, False, False, False, True);
                         2: SelectedCards(Hand, True, True, False, False, False);
                       end
                     end; 

    caTwoPairs : begin 
                   Pos := FindFreeCardInTwoPairs(AHand);
                   case Pos of
                     0: SelectedCards(Hand, True, False, False, False, False);
                     2: SelectedCards(Hand, False, False, True, False, False);
                     4: SelectedCards(Hand, False, False, False, False, True);
                   end
                 end;  
                                             
    caPair: begin
              Rnd := Random(100);
              if Rnd < 30 then
              begin
                Pos := FindPairPos(AHand);
                case Pos of
                  0: SelectedCards(Hand, False, False, True, True, True);
                  1: SelectedCards(Hand, True, False, False, True, True);
                  2: SelectedCards(Hand, True, True, False, False, True);
                  3: SelectedCards(Hand, True, True, True, False, False);
                end
               end
               else
               begin
                 Pos := FindFourColorsPos(AHand);
                 if Pos >= 0 then
                 begin
                   case Pos of
                     0: SelectedCards(Hand, True, False, False, False, False);
                     1: SelectedCards(Hand, False, True, False, False, False);
                     2: SelectedCards(Hand, False, False, True, False, False);
                     3: SelectedCards(Hand, False, False, False, True, False);
                     4: SelectedCards(Hand, False, False, False, False, True);
                   end
                 end
                 else
                 begin
                   Pos := FindPairPos(AHand);
                   case Pos of
                     0: SelectedCards(Hand, False, False, True, True, True);
                     1: SelectedCards(Hand, True, False, False, True, True);
                     2: SelectedCards(Hand, True, True, False, False, True);
                     3: SelectedCards(Hand, True, True, True, False, False);
                   end
                 end
               end;
                     
               Pos := FindFreeCardToStraight(AHand);
               if Pos >= 0 then
               begin
                 case Pos of
                   0: SelectedCards(Hand, True, False, False, False, False);
                   1: SelectedCards(Hand, False, True, False, False, False);
                   2: SelectedCards(Hand, False, False, True, False, False);
                   3: SelectedCards(Hand, False, False, False, True, False);
                   4: SelectedCards(Hand, False, False, False, False, True);
                 end
               end
               else
               begin
                 Pos := FindPairPos(AHand);
                 case Pos of
                   0: SelectedCards(Hand, False, False, True, True, True);
                   1: SelectedCards(Hand, True, False, False, True, True);
                   2: SelectedCards(Hand, True, True, False, False, True);
                   3: SelectedCards(Hand, True, True, True, False, False);
                 end
               end
             end;

    caNone: begin
              Rnd := Random(100);
              if Rnd < 30 then SelectedCards(Hand, True, True, True, True, False)
              else
              begin
                Pos := FindFourColorsPos(AHand);
                if Pos >= 0 then
                begin
                  case Pos of
                    0: SelectedCards(Hand, True, False, False, False, False);
                    1: SelectedCards(Hand, False, True, False, False, False);
                    2: SelectedCards(Hand, False, False, True, False, False);
                    3: SelectedCards(Hand, False, False, False, True, False);
                    4: SelectedCards(Hand, False, False, False, False, True);
                  end
                end
                else SelectedCards(Hand, True, True, True, True, False);
                  Pos := FindFreeCardToStraight(AHand);
                  if Pos >= 0 then
                  begin
                    case Pos of
                      0: SelectedCards(Hand, True, False, False, False, False);
                      1: SelectedCards(Hand, False, True, False, False, False);
                      2: SelectedCards(Hand, False, False, True, False, False);
                      3: SelectedCards(Hand, False, False, False, True, False);
                      4: SelectedCards(Hand, False, False, False, False, True);
                    end
                end            
                else SelectedCards(Hand, True, True, True, True, False);
              end
            end
  end;

Result := Hand;

end;

I sama procedura wymieniająca CpuDiscardCards

procedure CpuDiscardCards(ACpuHand : THand);
var
 I : Integer;
 DiscardCard : TChangeCard;
 
begin
 
  DiscardCard := CpuSearchCardsToDiscard(ACpuHand);

  for I := Low(ACpuHand) to High(ACpuHand) do
    if DiscardCard[I] then 
    begin
     Card := DealCard(Deck,CardsInDeck);
     Player[plComputer].Hand[I] := Card;
    end;

end;

1 użytkowników online, w tym zalogowanych: 0, gości: 1