Playing cards/Ada
Playing cards/Ada is part of Playing Cards. You may find other members of Playing Cards at Category:Playing Cards.
Here is the package specification for a deck of playing cards. <lang ada>package Playing_Cards is
pragma Elaborate_Body(Playing_Cards);
type Card is private; procedure Print(The_Card : Card); type Deck is private; procedure Print(the_Deck : Deck); procedure Deal(From : in out Deck; The_Card : out Card); procedure Shuffle(The_Deck : in out Deck); function New_Deck return Deck; Deck_Empty : exception;
private
type Pips is (Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace); type Suits is (Diamonds, Spades, Hearts, Clubs); type Card is record Pip : Pips; Suit : Suits; end record; type Index is range 1..53; subtype Deck_Index is Index range 1..52; type Deck_Reference is array(Deck_Index) of Deck_Index; type Deck is record Next_Card : Index; Deck_Offsets : Deck_Reference; end record;
end Playing_Cards;</lang> Here is the package body for that same playing card package. This implementation stores one array of cards in sorted order. Each deck contains an array of indices into that one array of cards. Shuffling the deck actually results in randomizing the order of those indices into the array of cards. This approach maximizes shuffling efficiency by only exchanging indices. It also maximizes memory efficiency since an array of cards requires more memory than an array of indices. <lang ada>with Ada.Numerics.Discrete_Random; With Ada.Text_IO;
package body Playing_Cards is
type Internal_Deck is array(Deck_Index) of Card; Base_Deck : Internal_Deck; Base_Index : Index; ---------- -- Deal -- ----------
procedure Deal (From : in out Deck; The_Card : out Card) is begin if From.Next_Card not in Deck_Index then raise Deck_Empty; end if; The_Card := Base_Deck(From.Deck_Offsets(From.Next_Card)); From.Next_Card := From.Next_Card + 1; end Deal;
-------------- -- New_Deck -- --------------
function New_Deck return Deck is Temp : Deck; begin for I in Base_Deck'range loop Temp.Deck_Offsets(I) := I; end loop; Temp.Next_Card := 1; return Temp; end New_Deck;
----------- -- Print -- ----------- procedure Print(The_Card : Card) is package Pip_Io is new Ada.Text_Io.Enumeration_Io(Pips); use Pip_Io; package Suit_Io is new Ada.Text_Io.Enumeration_Io(Suits); use Suit_Io; begin Put(Item => The_Card.Pip, Width => 1); Ada.Text_Io.Put(" of "); Put(Item => The_Card.Suit, Width => 1); Ada.Text_Io.New_Line; end Print; ----------- -- Print -- ----------- procedure Print(The_Deck : Deck) is begin for I in The_Deck.Next_Card..Deck_Index'Last loop Print(Base_Deck(The_Deck.Deck_Offsets(I))); end loop; end Print; ------------- -- Shuffle -- -------------
procedure Shuffle (The_Deck : in out Deck) is procedure Swap(Left, Right : in out Deck_Index) is Temp : Deck_Index := Left; begin Left := Right; Right := Temp; end Swap; Swap_Index : Deck_Index; begin for I in Deck_Index'First..Deck_Index'Pred(Deck_Index'Last) loop declare subtype Remaining_Indices is Deck_Index range I..Deck_Index'Last; package Rand_Card is new Ada.Numerics.Discrete_Random(Remaining_Indices); use Rand_Card; Seed : Generator; begin Reset(Seed); Swap_Index := Random(Seed); Swap(The_Deck.deck_Offsets(I), The_Deck.Deck_Offsets(Swap_Index)); end; end loop; The_Deck.Next_Card := 1; end Shuffle;
begin
Base_Index := 1; for Suit in Suits'range loop for Pip in Pips'range loop Base_Deck(Base_Index) := (Pip, Suit); Base_Index := Base_Index + 1; end loop; end loop;
end Playing_Cards;</lang>