Database
 sql >> Baza danych >  >> RDS >> Database

Co mają wspólnego poker, blackjack, Belot i Préférence z bazami danych?

Jak zaprojektować bazę danych wystarczająco elastyczną, aby pomieścić kilka bardzo różnych gier karcianych.

Niedawno pokazaliśmy, jak można wykorzystać bazę danych do przechowywania wyników gier planszowych. Gry planszowe są fajne, ale nie są jedyną dostępną wersją klasycznych gier online. Bardzo popularne są również gry karciane. Wprowadzają do rozgrywki element szczęścia, a w dobrej grze karcianej nie chodzi tylko o szczęście!

W tym artykule skupimy się na budowaniu modelu danych do przechowywania meczów, wyników, graczy i wyników. Głównym wyzwaniem jest tutaj przechowywanie danych związanych z wieloma różnymi grami karcianymi. Możemy również rozważyć analizę tych danych, aby określić zwycięskie strategie, poprawić własne umiejętności gry lub zbudować lepszego przeciwnika AI.

Cztery gry karciane, których użyjemy w naszej bazie danych

Ponieważ gracze nie mogą kontrolować rozdania, w których są rozdawane, gry karciane łączą strategię, umiejętności i szczęście. Ten czynnik szczęścia daje początkującemu szansę na pokonanie doświadczonego gracza i sprawia, że ​​gry karciane są uzależniające. (Różni się to od gier takich jak szachy, które w dużej mierze opierają się na logice i strategii. Słyszałem od wielu graczy, że nie są zainteresowani grą w szachy, ponieważ nie mogą znaleźć przeciwników na ich poziomie umiejętności.)

Skoncentrujemy się na czterech dobrze znanych grach karcianych:pokerze, blackjacku, belot (lub belote) i préférence. Każda z nich ma stosunkowo złożone zasady i wymaga trochę czasu do opanowania. Stosunek szczęścia do wiedzy jest również inny dla każdej gry.

Przyjrzymy się pokrótce uproszczonym zasadom i szczegółom wszystkich czterech poniższych gier. Opisy gier są dość rzadkie, ale zamieściliśmy wystarczająco dużo, aby pokazać różne tryby rozgrywki i różnorodne zasady, które napotkamy podczas procesu projektowania bazy danych.

Blackjack:

  • Pokład: Od jednej do ośmiu talii po 52 karty każda; bez kart jokera
  • Gracze: Krupier i 1 lub więcej przeciwników
  • Używana jednostka: Zwykle pieniądze
  • Podstawowe zasady: Gracze otrzymują 2 karty, które tylko oni widzą; krupier otrzymuje dwie karty, jedną odkrytą, a drugą zakrytą; każdy gracz decyduje się dobrać więcej kart (lub nie); krupier dobiera ostatni. Karty mają przypisane wartości punktowe od 1 do 11.
  • Możliwe działania gracza: Uderz, stój, podziel, poddaj się
  • Warunek celu i zwycięstwa: Suma kart gracza jest większa niż krupiera; jeśli któryś z graczy przekroczy 21, ten gracz przegrywa.

Poker (Texas Hold’Em):

  • Pokład: Standardowa (znana również jako kolor francuski) talia 52 kart; bez kart jokera. Karty są najczęściej w kolorze czerwonym i czarnym.
  • Gracze: Dwa do dziewięciu; gracze na zmianę rozdają
  • Używana jednostka:zwykle żetony
  • Podstawowe zasady: Każdy gracz zaczyna od otrzymania dwóch kart; gracze stawiają zakłady; trzy karty są odkryte na środku stołu; gracze ponownie stawiają swoje zakłady; czwarta karta jest umieszczana na środku i gracze ponownie obstawiają; następnie kładzie się piątą i ostatnią kartę i kończy się ostatnia runda licytacji.
  • Możliwe działania gracza: Pas, sprawdzenie, podbicie, mała ciemna, duża ciemna, przebicie
  • Cel: Połącz najlepszą możliwą rękę z pięciu kart (z dwóch kart w ręce gracza i pięciu kart na środku stołu)
  • Warunek zwycięstwa:zwykle wygranie wszystkich żetonów na stole

Belot (chorwacka odmiana Belote):

  • Pokład: Zwykle tradycyjna niemiecka lub węgierska talia 32-kartowa; bez kart jokera
  • Gracze: Dwa do czterech; zwykle czterech graczy w parach po dwie
  • Używana jednostka: Punkty
  • Podstawowe zasady: W grze czteroosobowej każdy gracz otrzymuje sześć kart w ręce i dwie karty zakryte; gracze jako pierwszy licytują kolor atutowy; po ustaleniu atu, biorą dwie zakryte karty i kładą je na ręce; następuje runda deklaracji, podczas której określone kombinacje kart są ogłaszane za dodatkowe punkty; gra jest kontynuowana, dopóki wszystkie karty nie zostaną wykorzystane.
  • Możliwe działania gracza: Podaj, licytuj, deklaruj, rzuć kartę
  • Cel dla ręki: Aby zdobyć więcej niż połowę punktów
  • Stan zwycięstwa: Bądź pierwszą drużyną, która zdobędzie 1001 punktów lub więcej

Preferencje:

  • Pokład: Najczęściej tradycyjna niemiecka lub węgierska talia 32-kartowa; bez kart jokera
  • Gracze: trzy
  • Jednostki: Punkty
  • Podstawowe zasady: Wszyscy gracze otrzymują 10 kart; dwie karty „kotek” lub „szpon” kładzie się na środku stołu; gracze decydują, czy chcą licytować kolor; gracze decydują się grać, czy nie.
  • Możliwe działania gracza: Podaj, licytuj, graj, nie graj, rzucaj kartą
  • Cel: Zależy od odtwarzanego wariantu Préférence; w wersji standardowej licytujący musi wygrać łącznie sześć lew.
  • Stan zwycięstwa: Gdy suma wyników wszystkich trzech graczy wynosi 0, wygrywa gracz z najmniejszą liczbą punktów.

Po co łączyć bazy danych i gry karciane?

Naszym celem tutaj jest zaprojektowanie modelu bazy danych, który mógłby przechowywać wszystkie istotne dane dla tych czterech gier karcianych. Baza danych może być wykorzystywana przez aplikację internetową jako miejsce do przechowywania wszystkich istotnych danych. Chcemy przechowywać początkowe ustawienia gry, uczestników gry, działania podjęte podczas gry oraz wynik pojedynczej rozdania, rozdania lub lewy. Musimy również pamiętać, że z meczem może być powiązana jedna lub więcej transakcji.

Z tego, co przechowujemy w naszej bazie danych, powinniśmy być w stanie odtworzyć wszystkie akcje, które miały miejsce podczas gry. Użyjemy pól tekstowych do opisania warunków zwycięstwa, działań w grze i ich wyników. Są one specyficzne dla każdej gry, a logika aplikacji internetowej zinterpretuje tekst i przekształci go w razie potrzeby.

Szybkie wprowadzenie do modelu




Ten model pozwala nam przechowywać wszystkie istotne dane gry, w tym:

  • Właściwości gry
  • Lista gier i meczów
  • Uczestnicy
  • Działania w grze

Ponieważ gry różnią się pod wieloma względami, często używamy varchar(256) typ danych do opisu właściwości, ruchów i wyników.

Gracze, mecze i uczestnicy

Ta sekcja modelu składa się z trzech tabel i służy do przechowywania danych o zarejestrowanych graczach, rozegranych meczach i graczach, którzy brali udział.

player tabela przechowuje dane o zarejestrowanych graczach. username i email atrybuty są unikalnymi wartościami. nick_name atrybut przechowuje nazwy ekranowe graczy.

match tabela zawiera wszystkie istotne dane meczowe. Ogólnie mecz składa się z jednej lub więcej rozdań kart (znanych również jako rundy, ręce lub lewy). Wszystkie mecze mają ustalone zasady przed rozpoczęciem gry. Atrybuty są następujące:

  • game_id – odwołuje się do tabeli zawierającej listę gier (w tym przypadku poker, blackjack, belot i préférence).
  • start_time i end_time to rzeczywiste godziny rozpoczęcia i zakończenia meczu. Zauważ, że end_time może być NULL; nie będziemy mieli jego wartości, dopóki gra się nie skończy. Ponadto, jeśli dopasowanie zostanie porzucone przed zakończeniem, end_time wartość może pozostać NULL.
  • number_of_players – czy liczba uczestników jest wymagana do rozpoczęcia gry
  • deck_id – odnosi się do talii używanej w grze.
  • decks_used – to liczba talii używanych do gry. Zwykle wartość ta wynosi 1, ale w niektórych grach używa się wielu talii.
  • unit_id – czy jednostka (punkty, żetony, pieniądze itp.) użyta do zdobycia punktów w grze.
  • entrance_fee – liczba jednostek potrzebnych do dołączenia do gry; może to być NULL, jeśli gra nie wymaga od każdego gracza rozpoczęcia z określoną liczbą jednostek.
  • victory_conditions – określa, który zawodnik wygrał mecz. Użyjemy varcharu typ danych, aby opisać warunki zwycięstwa w każdej grze (tj. pierwsza drużyna, która zdobędzie 100 punktów) i pozostawić aplikacji, aby to zinterpretowała. Ta elastyczność pozostawia miejsce na dodawanie wielu gier.
  • match_result – przechowuje wynik meczu w formacie tekstowym. Tak jak w przypadku victory_conditions , pozwolimy aplikacji zinterpretować wartość. Ten atrybut może mieć wartość NULL, ponieważ wypełnimy tę wartość w tym samym czasie, w którym wstawimy end_time wartość.

participant tabela przechowuje dane o wszystkich uczestnikach meczu. match_id i player_id atrybuty są odniesieniami do match i player tabele. Razem te wartości tworzą klucz alternatywny tabeli.

Większość gier zmienia się, który gracz licytuje lub gra jako pierwszy. Zwykle w pierwszej rundzie gracz, który gra jako pierwszy (gracz otwierający), jest określony przez zasady gry. W następnej rundzie gracz po lewej (lub czasami po prawej) od pierwszego gracza otwierającego będzie pierwszy. Użyjemy initial_player_order atrybut do przechowywania liczby porządkowej gracza otwierającego pierwszą rundę. match_id i initial_player_order atrybuty tworzą kolejny klucz alternatywny, ponieważ dwóch graczy nie może grać jednocześnie.

score atrybut jest aktualizowany, gdy gracz kończy mecz. Czasami będzie to miało miejsce w tym samym momencie dla wszystkich graczy (np. w belot lub préférence), a czasami, gdy mecz jest nadal w toku (np. poker lub blackjack).

Akcje i typy akcji

Kiedy myślimy o działaniach, które gracze mogą wykonywać w grze karcianej, zdajemy sobie sprawę, że musimy przechowywać:

  • Jaka była akcja
  • Kto wykonał to działanie
  • Kiedy (w której rozdaniu) miała miejsce akcja
  • Które karty zostały użyte w tej akcji

action_type table to prosty słownik, który zawiera nazwy działań graczy. Niektóre możliwe wartości obejmują dobranie karty, zagranie karty, przekazanie karty innemu graczowi, sprawdzenie i podbicie.

W action tabeli, będziemy przechowywać wszystkie zdarzenia, które miały miejsce podczas transakcji. deal_id , card_id , participant_id i action_type_id są odniesieniami do tabel, które zawierają wartości deal, card part i action_type. Zauważ, że participant_id i card_id mogą być wartościami NULL. Wynika to z faktu, że niektóre akcje nie są wykonywane przez graczy (np. krupier dobiera kartę i kładzie ją odkrytą), a niektóre nie zawierają kart (np. podbicie w pokerze). Musimy zapisać wszystkie te działania, aby móc odtworzyć całe dopasowanie.

action_order atrybut przechowuje liczbę porządkową akcji w grze. Na przykład oferta otwierająca otrzyma wartość 1; następna oferta miałaby wartość 2 itd. W tym samym czasie nie może być wykonywana więcej niż jedna akcja. Dlatego deal_id i action_order atrybuty razem tworzą klucz alternatywny.

action_notation atrybut zawiera szczegółowy opis akcji. Na przykład w pokerze możemy zapisać podbicie działanie i dowolną kwotę. Niektóre działania mogą być bardziej skomplikowane, więc dobrze jest przechowywać te wartości jako tekst i pozostawić aplikacji do ich interpretacji.

Okazy i zamówienia

Mecz składa się z co najmniej jednego rozdania kart. Omówiliśmy już participant i match tabele, ale uwzględniliśmy je na obrazku, aby pokazać ich związek z deal i deal_order tabele.

deal tabela przechowuje wszystkie potrzebne nam dane dotyczące pojedynczej instancji dopasowania.

match_id atrybut wiąże tę instancję z odpowiednim dopasowaniem, podczas gdy start_time i end_time wskaż dokładny czas rozpoczęcia i zakończenia tej instancji.

move_time_limit i deal_result atrybuty to zarówno pola tekstowe używane do przechowywania limitów czasowych (jeśli ma to zastosowanie), jak i opis wyniku tej transakcji.

W participant tabela, initial_player_order atrybut przechowuje kolejność graczy dla instancji meczu otwierającego. Przechowywanie zamówień na kolejne tury wymaga zupełnie nowej tabeli – deal_order tabela.

Oczywiście deal_id i participant_id są odniesieniami do instancji meczu i uczestnika. Razem tworzą pierwszy klucz alternatywny w deal_order stół. player_order atrybut zawiera wartości oznaczające rozkazy, jakie gracze uczestniczyli w danej instancji meczu. Wraz z deal_id , tworzy drugi klucz alternatywny w tej tabeli. deal_result atrybut to pole tekstowe opisujące wynik meczu dla pojedynczego gracza. score atrybut przechowuje wartość liczbową związaną z wynikiem transakcji.

Garnitury, rangi i karty

Ta sekcja modelu opisuje karty, których będziemy używać we wszystkich obsługiwanych grach. Każda karta ma kolor i rangę.

suit_type table to słownik zawierający wszystkie używane przez nas typy kolorów. Dla suit_type_name , użyjemy wartości takich jak „Garnitury francuskie”, „Garnitury niemieckie”, „Garnitury szwajcarsko-niemieckie” i „Garnitury łacińskie”.

suit tabela zawiera nazwy wszystkich kolorów zawartych w poszczególnych typach talii. Na przykład francuska talia ma kolory o nazwach „Spades”, „Hearts”, „Diamonds” i „Clubs”.

W rank słownika, znajdziemy dobrze znane wartości kart, takie jak „As”, „Król”, „Dama” i „Walet”.

card tabela zawiera listę wszystkich możliwych kart. Każda karta pojawi się w tej tabeli tylko raz. To jest powód, dla którego suit_id i rank_id atrybuty tworzą klucz alternatywny tej tabeli. Wartości obu atrybutów mogą być NULL, ponieważ niektóre karty nie mają koloru lub rangi (np. karty jokera). is_joker_card to oczywista wartość logiczna. card_name Atrybut opisuje kartę tekstem:„As pik”.

Karty i talie

Karty należą do talii. Ponieważ jedna karta może występować w wielu taliach, będziemy potrzebować n:n relacja między card i deck tabele.

W deck tabeli, będziemy przechowywać nazwy wszystkich talii kart, których chcemy użyć. Przykład wartości przechowywanych w deck_name atrybutami są:„Standardowa talia 52-kartowa (francuska)” lub „Talia 32-kartowa (niemiecka)”.

card_in_deck Relacja służy do przypisywania kart do odpowiednich talii. card_iddeck_id para jest alternatywnym kluczem deck stół.

Dopasuj właściwości, używane talie i jednostki

Ta sekcja modelu zawiera kilka podstawowych parametrów do rozpoczęcia nowej gry.

Główną częścią tej sekcji jest game stół. Ta tabela przechowuje dane o grach obsługiwanych przez aplikacje. game_name atrybut zawiera wartości takie jak „poker”, „blackjack”, „belot” i „préférence”.

min_number_of_players i max_number_of_players to minimalna i maksymalna liczba uczestników meczu. Te atrybuty służą jako granice gry i są wyświetlane na ekranie na początku meczu. Osoba inicjująca dopasowanie musi wybrać wartość z tego zakresu.

min_entrance_fee i max_entrance_fee atrybuty oznaczają zakres opłat za wstęp. Ponownie, jest to oparte na rozgrywanej grze.

W possible_victory_condition , zachowamy wszystkie warunki zwycięstwa, które można przypisać do meczu. Wartości są oddzielone ogranicznikiem.

unit Słownik służy do przechowywania każdej jednostki używanej we wszystkich naszych grach. unit_name atrybut będzie zawierał wartości takie jak „punkt”, „dolar”, „euro” i „chip”.

game_deck i game_unit tabele używają tej samej logiki. Zawierają one listę wszystkich talii i jednostek, których można użyć w meczu. Dlatego game_iddeck_id para i game_idunit_id sparuj klucze alternatywne w odpowiednich tabelach.

Wyniki

W naszej aplikacji będziemy chcieli przechowywać wyniki wszystkich graczy, którzy brali udział w naszych grach karcianych. Dla każdej gry obliczana i zapisywana jest pojedyncza wartość liczbowa. (Obliczenia są oparte na wynikach gracza we wszystkich grach jednego typu.) Ten wynik gracza jest podobny do rangi; pozwala użytkownikom z grubsza wiedzieć, jak dobry jest gracz.

Wróćmy do procesu kalkulacji. Utworzymy n:n relacja między player i game tabele. To jest player_score stół w naszym modelu. player_id i score_id ” razem tworzą alternatywny klucz tabeli. „score atrybut jest używany do przechowywania wspomnianej wcześniej wartości liczbowej.

Istnieje wiele gier karcianych, które wykorzystują bardzo różne zasady, karty i talie. Aby stworzyć bazę danych przechowującą dane dla więcej niż jednej gry karcianej, musimy dokonać pewnych uogólnień. Jednym ze sposobów, w jaki możemy to zrobić, jest użycie opisowych pól tekstowych i pozwolenie aplikacji na ich interpretację. Moglibyśmy wymyślić sposoby na pokrycie najczęstszych sytuacji, ale to wykładniczo skomplikowałoby projekt bazy danych.

Jak pokazał ten artykuł, możesz używać jednej bazy danych dla wielu gier. Dlaczego miałbyś to zrobić? Trzy powody:1) możesz ponownie wykorzystać tę samą bazę danych; 2) uprościłoby analitykę; a to doprowadziłoby do 3) budowania lepszych przeciwników AI.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak używać klauzuli ORDER BY w SQL?

  2. Część 2 – Jak zorganizować duży diagram bazy danych

  3. Schemat płatka śniegu

  4. Model bazy danych dla ankiety online. Część 2

  5. Korzystanie z ODBC z Salesforce i OneLogin Single Sign On (SSO)