Sprawdzanie układu pięciu "kośtek" do gry.

0

Witam. Wiem, że z sieci można pobrać całkiem fajnie napisaną grę Mega Kości. Jednak ja postanowiłem sam coś
takiego sobie napisać, dla własnej satysfakcji w Delphi. Jednak natrafiłem na problem. W jaki sposób sprawdzać
układ wylosowanych 5 wartości 6 ściennych kości. Zacząłem kombinować z takim układem który wydawał mi się
najprostszy czyli kareta (przynajmniej 4 takie same oczka). I nie wiem jak najlepiej sprawdzić czy wylosowałem
cztery takie same oczka. Póki co założyłem sobie, że wylosowane oczka będą w takiej tablicy jak pokazuję tutaj:

const
  Ile_Kostek = 5;
  public
    OczkaTab : array[1..Ile_Kostek] of Byte;

I teraz jak sprawdzać stany losowań - ja założyłem że zrobię to poprzez dwuwymiarową tablicę prawdy, gdzie
pierwszy wymiar to kolejna kostka (od 1 do 5), a drugi wymiar (od 1 do 6) to wylosowana wartość. Czyli np dla
kombinacji 1 1 1 1 4 (bo wcześniej sortuję tablicę OczkaTab rosnąco) moja tablica prawy będzie wyglądała tak:

Kostka numer 1: prawda fałsz fałsz fałsz fałsz fałsz
Kostka numer 2: prawda fałsz fałsz fałsz fałsz fałsz
Kostka numer 3: prawda fałsz fałsz fałsz fałsz fałsz
Kostka numer 4: prawda fałsz fałsz fałsz fałsz fałsz
Kostka numer 5: fałsz fałsz fałsz prawda fałsz fałsz

I teraz jak ktoś ma pomysł jak prawidłowo zliczyć czy prawda w kolejnych kostkach dla jednej liczby wystąpiła
przynajmniej cztery razy? Może źle się za to zabrałem. Może powinienem użyć innych typów lub metody. Być
może ktoś z Was pisał kiedyś podobną grę jak kości czy poker i ma jakieś przykładowe funkcje sprawdzające
układ kości? Poniżej wklejam póki co zaczętą funkcję przygotowania tablic jakich użyłem i ich sprawdzenie.
Z góry dziękuję za wszelkie sugestie i przykładowe kodu. No i wybaczcie, że znowu się trochę rozpisałem

function WypadlaKareta: boolean;
var
  SL : TStringList;
  I, J : Byte;
  PrawdaTab : array[1..Ile_Kostek, 1..6] of boolean;
begin
  Result := False;
  for I := Low(PrawdaTab) to High(PrawdaTab) do
    for J := Low(PrawdaTab[I]) to High(PrawdaTab[I]) do
    begin
      PrawdaTab[I][J] := False;
    end;
    with MainForm do
    begin
      Sort_Shell(OczkaTab);
      for I := Low(PrawdaTab) to High(PrawdaTab) do
        for J := Low(PrawdaTab[I]) to High(PrawdaTab[I]) do
        begin
          if (OczkaTab[I] = J) then
          begin
            PrawdaTab[I][J] := True;
          end
          else
          begin
            PrawdaTab[I][J] := False;
          end;
        end;
        // ------ sprawdzenie tablicy ------
        SL := TStringList.Create;
        for I := Low(PrawdaTab) to High(OczkaTab) do
        begin
          SL.Add('Kostka numer ' + IntToStr(I) + ':');
          for J := 1 to 6 do
          begin
            if PrawdaTab[I][J] = True then
            begin
              SL[I - 1] := SL[I - 1] +#32+ 'prawda';
            end
            else
            begin
              SL[I - 1] := SL[I - 1] +#32+ 'fałsz';
            end;
          end;
        end;
        ShowMessage(SL.Text);
        SL.Free;
        //----------------------------------
      end;
    end;
0

EDIT: zakładam nowy temat, bo i tak wiele ósob tak robi, a chciałem wyszczegłonić jakoś moją edycję ;P

Już sobie poradziłem, Jak się okazało nie potrzeba wcale żadnej tablicy prawdy, tylko wystarczy że
policzmy ile razy wypadło dane oczko. Nie wiem dlaczego na to wcześniej nie wpadłem, jakiś zastój :)
I teraz mogę sprawdzić czy zgodnie z zasadami gry w kości o nazwie "Yahtzee" opisanych na stronie
http://www.kosteczki.republika.pl/pliki/yahtzee.html mam układ z rodzaju "Szkoła", Trójka, Kareta i Full.
Póki co tyle przetestowałem. Mam nadzieję że ze streetami też mi wyjdzie. A poniżej przykładowy kod
dla sprawdzania czy wypadła kareta. Może komuś szukającemu kiedyś poprzez google czy też tutaj
bezpośtednio się przyda. Ale jak ktoś ma może lepszy pomysł to proszę napiszcie. Z góry dziękuję :)

const
  Ile_Kostek = 5;

var
  MainForm : TMainForm;
  IlosciTab : array[1..6] of Byte;
  OczkaTab : array[1..Ile_Kostek] of Byte;
// ... ciach ...

procedure TMainForm.ZliczanieKosci;
var
  I, J : Byte;
begin
  Sort_Shell(OczkaTab);
  for I := Low(IlosciTab) to High(IlosciTab) do
  begin
    IlosciTab[I] := 0;
  end;
  for I := Low(OczkaTab) to High(OczkaTab) do
    for J := Low(IlosciTab) to High(IlosciTab) do
    begin
      if (OczkaTab[I] = J) then
      begin
        IlosciTab[J] := IlosciTab[J] + 1;
      end;
    end;
  end;
// ... ciach ...

function CzyWypadlaKareta: boolean;
const
  Min_Ilosc = 4;
var
  I : Byte;
begin
  Result := False;
  MainForm.ZliczanieKosci;
  for I := Low(IlosciTab) to High(IlosciTab) do
  begin
    if IlosciTab[I] >= Min_Ilosc then
    begin
      Result := True;
    end;
  end;
end;
// ... ciach ...
0

Zastąp tego słonia:

        begin
          if (OczkaTab[I] = J) then
          begin
            PrawdaTab[I][J] := True;
          end
          else
          begin
            PrawdaTab[I][J] := False;
          end;
        end;

Tym:

        begin
          PrawdaTab[I][J] := OczkaTab[I] = J;
        end;

Poza tym, poprawione:

  1. Po co ciągniesz pętle do końca ? Przerwij ją po uzyskaniu wyniku. (w kodzie w pierwszym poście też należałoby przerwać pętle).
  2. Po co sprawdzasz dwa warunki "x >= 4", lepiej jeden warunek "x > 3".
  3. Zbędne begin/end;
function CzyWypadlaKareta: boolean;
var
  I : Byte;
begin
  Result := False;
  MainForm.ZliczanieKosci;

  for I := Low(IlosciTab) to High(IlosciTab) do
    if IlosciTab[I] > 3 then
    begin
      Result := True;
      Break;
    end;
end;
0

Dzięki za odpowiedź Opi. Tak jak pisałem zrezygnowałem z tablicy prawdy, bo nie jest potrzebna, a co
do pozostałych uwag - zastosowałem je i poniżej umieszczam kompletny moduł. Z tego co sprawdziłem
działa poprawnie. Tam gdzie trzeba dodałem Break i zastosowałem tylko jeden operator przy if-ach :)

unit combos;

interface

const
  Ile_Kostek = 5;
  
var
  OczkaTab : array[1..Ile_Kostek] of Byte;
  function SumaOczek: Byte;
  function WariantSzkola(DlaOczka: Byte): Byte;
  function CzyWypadlaTrojka: boolean;
  function CzyWypadlaKareta: boolean;
  function CzyWypadlFull: boolean;
  function CzyWypadlMalyStrit: boolean;
  function CzyWypadlDuzyStrit: boolean;
  function CzyWypadlYaht: boolean;
  
implementation

var
  IlosciTab : array[1..6] of Byte;

procedure Sort_Shell(var A: array of Byte);
var
  Bis, I, J, K : LongInt;
  H : Byte;
begin
  Bis := High(A);
  K := Bis shr 1;
  while K > 0 do
  begin
    for I := 0 to Bis - K do
    begin
      J := I;
      while (J >= 0) and (A[J] > A[J + K]) do
      begin
        H := A[J];
        A[J] := A[J + K];
        A[J + K] := H;
        if J > K then
          Dec(J, K)
        else
          J := 0;
      end;
    end;
    K := K shr 1;
  end;
end;

procedure ZliczanieKosci;
var
  I, J : Byte;
begin
  Sort_Shell(OczkaTab);
  for I := Low(IlosciTab) to High(IlosciTab) do
  begin
    IlosciTab[I] := 0;
  end;
  for I := Low(OczkaTab) to High(OczkaTab) do
    for J := Low(IlosciTab) to High(IlosciTab) do
    begin
      if (OczkaTab[I] = J) then
      begin
        IlosciTab[J] := IlosciTab[J] + 1;
      end;
    end;
  end;

function SumaOczek: Byte;
var
  I : Byte;
begin
  Result := 0;
  for I := Low(OczkaTab) to High(OczkaTab) do
  begin
    Result := Result + OczkaTab[I];
  end;
end;

function WariantSzkola(DlaOczka: Byte): Byte;
begin
  Result := 0;
  if (DlaOczka < Low(IlosciTab)) or (DlaOczka > High(IlosciTab)) then
  begin
    Exit;
  end;
  ZliczanieKosci;
  Result := IlosciTab[DlaOczka] * DlaOczka;
end;

function CzyWypadlaTrojka: boolean;
const
  Min_Ilosc = 2;
var
  I : Byte;
begin
  Result := False;
  ZliczanieKosci;
  for I := Low(IlosciTab) to High(IlosciTab) do
  begin
    if IlosciTab[I] > Min_Ilosc then
    begin
      Result := True;
      Break;
    end;
  end;
end;

function CzyWypadlaKareta: boolean;
const
  Min_Ilosc = 3;
var
  I : Byte;
begin
  Result := False;
  ZliczanieKosci;
  for I := Low(IlosciTab) to High(IlosciTab) do
  begin
    if IlosciTab[I] > Min_Ilosc then
    begin
      Result := True;
      Break;
    end;
  end;
end;

function CzyWypadlFull: boolean;
const
  Min_Ilosc = 2;
var
  I : Byte;
begin
  Result := False;
  ZliczanieKosci;
  if (CzyWypadlaTrojka = True) then
  begin
    for I := Low(IlosciTab) to High(IlosciTab) do
    begin
      if IlosciTab[I] = Min_Ilosc then
      begin
        Result := True;
        Break;
      end;
    end;
  end;
end;


function CzyWypadlMalyStrit: boolean;
var
  I : Byte;
  A, B, C, D, E, F : Byte;
begin
  Result := False;
  ZliczanieKosci;
  for I := Low(OczkaTab) to High(OczkaTab) do
  begin
    if OczkaTab[I] = 1 then A := 0;
    if OczkaTab[I] = 2 then B := 1;
    if OczkaTab[I] = 3 then C := 2;
    if OczkaTab[I] = 4 then D := 3;
    if OczkaTab[I] = 5 then E := 4;
    if OczkaTab[I] = 6 then F := 5;
  end;

  if ((A = 0) and (B = 1) and (C = 2) and (D = 3)) or
  ((B = 1) and (C = 2) and (D = 3) and (E = 4)) or
  ((C = 2) and (D = 3) and (E = 4) and (F = 5)) then
    Result := True;
end;

function CzyWypadlDuzyStrit: boolean;
const
  Min_Ilosc = 1;
  Przynajmniej = 5;
var
  I, Cnt : Byte;
begin
  Result := False;
  ZliczanieKosci;
  Cnt := 0;
  for I := Low(IlosciTab) to High(IlosciTab) do
  begin
    if IlosciTab[I] = Min_Ilosc then
    begin
      Cnt := Cnt + 1;
    end;
  end;
  if (Cnt = Przynajmniej) then
  begin
    Result := True;
  end;
end;

function CzyWypadlYaht: boolean;
const
  Min_Ilosc = 5;
var
  I : Byte;
begin
  Result := False;
  ZliczanieKosci;
  if (CzyWypadlaTrojka = True) then
  begin
    for I := Low(IlosciTab) to High(IlosciTab) do
    begin
      if IlosciTab[I] = Min_Ilosc then
      begin
        Result := True;
        Break;
      end;
    end;
  end;
end;

end.

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