
Free Cell is the solitaire card game that Paul Alfille introduced to the PLATO system in 1978. Jim Horne, at Microsoft, changed the name toFreeCell and reimplemented the game forDOS, thenWindows.
This version introduced 32000 numbered deals. (TheFreeCell FAQ tells this history.)
As the game became popular, Jim Horne disclosedthe algorithm, and other implementations of FreeCell began to reproduce the Microsoft deals.
These deals are numbered from 1 to 32000. Newer versions from Microsoft have 1 million deals, numbered from 1 to 1000000; some implementations allow numbers outside that range.
The algorithm uses thislinear congruential generator from Microsoft C:
The algorithm follows:
| Order to deal cards | Game #1 | Game #617 |
|---|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1617 18 19 20 21 22 23 2425 26 27 28 29 30 31 3233 34 35 36 37 38 39 4041 42 43 44 45 46 47 4849 50 51 52 | JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6H | 7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H |
Deals can also be checked againstFreeCell solutions to 1000000 games. (Summon a video solution, and it displays the initial deal.)
Write a program to take a deal number and deal cards in the same order as this algorithm. The program may display the cards with ASCII, with Unicode, by drawing graphics, or any other way.
Related tasks:
F randomGenerator(=seed, n) [Int] r -V max_int32 = 7FFF'FFFF seed = seed [&] max_int32 L r.len < n seed = (seed * 214013 + 2531011) [&] max_int32 r [+]= seed >> 16 R rF deal(seed) V nc = 52 V cards = Array((nc - 1 .< -1).step(-1)) V rnd = randomGenerator(seed, nc) L(r) rnd V j = (nc - 1) - r % (nc - L.index) swap(&cards[L.index], &cards[j]) R cardsF show(cards) V l = cards.map(c -> ‘A23456789TJQK’[Int(c / 4)]‘’‘CDHS’[c % 4]) L(i) (0 .< cards.len).step(8) print((l[i .< i + 8]).join(‘ ’)):start:V seed = I :argv.len == 2 {Int(:argv[1])} E 11982print(‘Hand #.’.format(seed))V deck = deal(seed)show(deck)Hand 11982AH AS 4H AC 2D 6S TS JS3D 3H QS QC 8S 7H AD KSKD 6H 5S 4D 9H JH 9S 3CJC 5D 5C 8C 9D TD KH 7C6C 2C TH QH 6D TC 4S 7SJD 7D 8H 9C 2H QD 4C 5HKC 8D 2S 3S
withAda.Text_IO;useAda.Text_IO;procedureFreeCellistypeStateismod2**31;typeDeckisarray(0..51)ofString(1..2);packageRandomisprocedureInit(Seed:State);functionRandreturnState;endRandom;packagebodyRandomisS:State:=State'First;procedureInit(Seed:State)isbeginS:=Seed;endInit;functionRandreturnStateisbeginS:=S*214013+2531011;returnS/2**16;endRand;endRandom;procedureDeal(num:State)isthedeck:Deck;pick:State;Chars:constantString:="A23456789TJQKCDHS";beginforiinthedeck'Rangeloopthedeck(i):=Chars(i/4+1)&Chars(imod4+14);endloop;Random.Init(num);foriin0..51looppick:=Random.RandmodState(52-i);Put(thedeck(Natural(pick))&' ');if(i+1)mod8=0thenNew_Line;endif;thedeck(Natural(pick)):=thedeck(51-i);endloop;New_Line;endDeal;beginDeal(1);New_Line;Deal(617);endFreeCell;
JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6H7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
FreeCell(num){cards:="A23456789TJQK",suits:="♣♦♥♠",card:=[],Counter:=0loop,parse,cards{ThisCard:=A_LoopFieldloop,parse,suitsCard[Counter++]:=ThisCard.A_LoopField}loop,52{a:=MS(num)num:=a[1]MyCardNo:=mod(a[2],53-A_Index)MyCard:=Card[MyCardNo]Card[MyCardNo]:=Card[52-A_Index]Card.Remove(52-A_Index)Res.=MyCard(Mod(A_Index,8)?" ":"`n")}returnRes}MS(Seed){Seed:=Mod(214013*Seed+2531011,2147483648)return,[Seed,Seed//65536]}
MS() found athttp://rosettacode.org/wiki/Linear_congruential_generator#AutoHotkey
Examples:
Gui,font,s12,CourierGui,add,edit,w320r17-VScroll,%"Game# 1`n"FreeCell(1)"`n`nGame#617`n"FreeCell(617)Gui,showreturnGuiClose:GuiEscape:ExitAppreturn
Outputs:
Game# 1J♦ 2♦ 9♥ J♣ 5♦ 7♥ 7♣ 5♥K♦ K♣ 9♠ 5♠ A♦ Q♣ K♥ 3♥2♠ K♠ 9♦ Q♦ J♠ A♠ A♥ 3♣4♣ 5♣ T♠ Q♥ 4♥ A♣ 4♦ 7♠3♠ T♦ 4♠ T♥ 8♥ 2♣ J♥ 7♦6♦ 8♠ 8♦ Q♠ 6♣ 3♦ 8♣ T♣6♠ 9♣ 2♥ 6♥ Game#6177♦ A♦ 5♣ 3♠ 5♠ 8♣ 2♦ A♥T♦ 7♠ Q♦ A♣ 6♦ 8♥ A♠ K♥T♥ Q♣ 3♥ 9♦ 6♠ 8♦ 3♦ T♣K♦ 5♥ 9♠ 3♣ 8♠ 7♥ 4♦ J♠4♣ Q♠ 9♣ 9♥ 7♣ 6♥ 2♣ 2♠4♠ T♠ 2♥ 5♦ J♣ 6♣ J♥ Q♥J♦ K♠ K♣ 4♥
*FLOAT64hand%=617REM Initialise card library:SYS"LoadLibrary","CARDS.DLL"TOcards%IFcards%=0ERROR100,"No CARDS library"SYS"GetProcAddress",cards%,"cdtInit"TOcdtInit%SYS"GetProcAddress",cards%,"cdtDraw"TOcdtDraw%SYScdtInit%,^dx%,^dy%VDU23,22,8*dx%;5*dy%;8,16,16,128REM Initialise deck:DIMcard&(51)FORI%=0TO51:card&(I%)=I%:NEXTREM Shuffle deck:dummy%=FNrng(hand%)FORI%=51TO0STEP-1C%=FNrng(-1)MOD(I%+1)SWAPcard&(C%),card&(I%)NEXTREM Display deck:FORI%=0TO51C%=card&(51-I%)X%=(I%MOD8)*dx%Y%=(I%DIV8)*dy%*2/3SYScdtDraw%,@memhdc%,X%,Y%,C%,0,0NEXTSYS"InvalidateRect",@hwnd%,0,0*GSAVEfreecellENDDEFFNrng(seed)PRIVATEstate,M%IFseed>=0THENstate=seedELSEstate=(state*214013+2531011)FORM%=52TO31STEP-1IFstate>=2^M%state-=2^M%NEXTENDIF=state>>16
vutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDC>4$0" :rebmun emaG">:#,_$&>55+,>"O?+"**2+*"C4'' "**v>8%!492*+*48*\-,1-:11p0g\0p11g#^_@A23456789TJQKCDHS*^+3:g11,g2+"/"%4,g2+g14/4:-\"v"g0:%g11+*-/2-10-1*<>+>8#8*#4*#::#%*#*/#*:#*0#:\#*`#:8#::#*:#8*#8:#2*#+^#<
Game number: 1JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6H
( ( createArray = array rank ranks suit suits . A 2 3 4 5 6 7 8 9 T J Q K:?ranks & :?array & whl ' ( !ranks:%?rank ?ranks & ♣ ♦ ♥ ♠:?suits & whl ' ( !suits:%?suit ?suits & !array str$(!rank !suit):?array ) ) & !array )& ( deal = A B D L Z pick card dealt deck , i last rand row state . !arg:(?deck:? [?L.?state) & 8:?row & :?dealt & ( pick = sep . ( -1+!row:>0:?row & " ":?sep | \n:?sep&8:?row ) & !dealt !arg !sep:?dealt ) & 2^31:?B & 2^16:?D & " 'Hard code' the numbers B and D into the rand function using macro expansion. (Gives a marginally faster execution speed.) " & ' ( . mod$(!state*214013+2531011.$B):?state & div$(!state.$D) ) : (=?rand) & !L+1:?L & whl ' ( mod$(rand$.!L+-1:?L):?i & !deck:?A [!i %?card ?Z & ( !Z:?Z %@?last&!A !last !Z | !A ) : ?deck & pick$!card ) & pick$\n & str$!dealt )& createArray$:?deck& put$("Game #1\n","dealt.txt",NEW)& put$(deal$(!deck.1),"dealt.txt",APP)& put$("Game #617","dealt.txt",APP)& put$(deal$(!deck.617),"dealt.txt",APP)&)Content ofdealt.txt:
Game #1J♦ 2♦ 9♥ J♣ 5♦ 7♥ 7♣ 5♥K♦ K♣ 9♠ 5♠ A♦ Q♣ K♥ 3♥2♠ K♠ 9♦ Q♦ J♠ A♠ A♥ 3♣4♣ 5♣ T♠ Q♥ 4♥ A♣ 4♦ 7♠3♠ T♦ 4♠ T♥ 8♥ 2♣ J♥ 7♦6♦ 8♠ 8♦ Q♠ 6♣ 3♦ 8♣ T♣6♠ 9♣ 2♥ 6♥ Game #6177♦ A♦ 5♣ 3♠ 5♠ 8♣ 2♦ A♥T♦ 7♠ Q♦ A♣ 6♦ 8♥ A♠ K♥T♥ Q♣ 3♥ 9♦ 6♠ 8♦ 3♦ T♣K♦ 5♥ 9♠ 3♣ 8♠ 7♥ 4♦ J♠4♣ Q♠ 9♣ 9♥ 7♣ 6♥ 2♣ 2♠4♠ T♠ 2♥ 5♦ J♣ 6♣ J♥ Q♥J♦ K♠ K♣ 4♥
#include<stdio.h>#include<stdlib.h>#include<locale.h>wchar_ts_suits[]=L"♣♦♥♠",s_nums[]=L"A23456789TJQK";#define RMAX32 ((1U << 31) - 1)staticintseed=1;intrnd(void){return(seed=(seed*214013+2531011)&RMAX32)>>16;}voidsrnd(intx){seed=x;}voidshow(constint*c){inti;for(i=0;i<52;c++){printf("\033[%dm%lc\033[m%lc",32-(1+*c)%4/2,s_suits[*c%4],s_nums[*c/4]);if(!(++i%8)||i==52)putchar('\n');}}voiddeal(ints,int*t){inti,j;srnd(s);for(i=0;i<52;i++)t[i]=51-i;for(i=0;i<51;i++){j=51-rnd()%(52-i);s=t[i],t[i]=t[j],t[j]=s;}}intmain(intc,char**v){ints,card[52];if(c<2||(s=atoi(v[1]))<=0)s=11982;setlocale(LC_ALL,"");deal(s,card);printf("Hand %d\n",s);show(card);return0;}
Longer than it absolutely needs to be because I split out several independently useful classes.
usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceFreeCellDeals{publicclassRNG{privateint_state;publicRNG(){_state=(int)DateTime.Now.Ticks;}publicRNG(intn){_state=n;}publicintNext(){return((_state=214013*_state+2531011)&int.MaxValue)>>16;}}publicenumRank{Ace,One,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Jack,Queen,King}publicenumSuit{Clubs,Diamonds,Hearts,Spades}publicclassCard{privateconststringRanks="A23456789TJQK";privateconststringSuits="CDHS";privateRank_rank;publicRankRank{get{return_rank;}set{if((int)value<0||(int)value>12){thrownewInvalidOperationException("Setting card rank out of range");}_rank=value;}}privateSuit_suit;publicSuitSuit{get{return_suit;}set{if((int)value<0||(int)value>3){thrownewInvalidOperationException("Setting card rank out of range");}_suit=value;}}publicCard(Rankrank,Suitsuit){Rank=rank;Suit=suit;}publicintNRank(){return(int)Rank;}publicintNSuit(){return(int)Suit;}publicoverridestringToString(){returnnewstring(new[]{Ranks[NRank()],Suits[NSuit()]});}}publicclassFreeCellDeal{publicList<Card>Deck{get;privateset;}publicFreeCellDeal(intiDeal){RNGrng=newRNG(iDeal);List<Card>rDeck=newList<Card>();Deck=newList<Card>();for(intrank=0;rank<13;rank++){for(intsuit=0;suit<4;suit++){rDeck.Add(newCard((Rank)rank,(Suit)suit));}}// Normally we deal from the front of a deck. The algorithm "deals" from the back so we reverse the// deck here to more conventionally deal from the front/start of the array.for(intiCard=51;iCard>=0;iCard--){intiSwap=rng.Next()%(iCard+1);Deck.Add(rDeck[iSwap]);rDeck[iSwap]=rDeck[iCard];}}publicoverridestringToString(){StringBuildersb=newStringBuilder();for(intiRow=0;iRow<6;iRow++){for(intiCol=0;iCol<8;iCol++){sb.AppendFormat("{0} ",Deck[iRow*8+iCol]);}sb.Append("\n");}for(intiCard=48;iCard<52;iCard++){sb.AppendFormat("{0} ",Deck[iCard]);}returnsb.ToString();}}classProgram{staticvoidMain(){Console.WriteLine(newFreeCellDeal(1));Console.WriteLine();Console.WriteLine(newFreeCellDeal(617));}}}
JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6H7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
Shorter than the previous version. Adds a few classes, but stays closer to the gist of the C version.
usingSystem;usingSystem.Text;namespaceFreeCellConsole{publicclassRand{long_seed;publicRand(intseed=1){_seed=seed;}publicintNext(){return(int)((_seed=(_seed*214013+2531011)&int.MaxValue)>>16);}}publicclassCard{privatestaticreadonlystringkSuits="♣♦♥♠";privatestaticreadonlystringkValues="A23456789TJQK";publicintValue{get;set;}publicintSuit{get;set;}publicCard(intrawvalue=0):this(rawvalue/4,rawvalue%4){}publicCard(intvalue,intsuit){Value=value;Suit=suit;}publicoverridestringToString(){returnstring.Format("{0}{1}",kValues[Value],kSuits[Suit]);}}publicclassDeck{publicCard[]Cards;publicDeck(intseed){varr=newRand(seed);Cards=newCard[52];for(inti=0;i<52;i++)Cards[i]=newCard(51-i);for(inti=0;i<51;i++){intj=51-r.Next()%(52-i);Cardtmp=Cards[i];Cards[i]=Cards[j];Cards[j]=tmp;}}publicoverridestringToString(){varsb=newStringBuilder();for(inti=0;i<Cards.Length;i++){sb.Append(Cards[i].ToString());sb.Append(i%8==7?"\n":" ");}returnsb.ToString();}}classProgram{publicstaticvoidMain(string[]args){Console.WriteLine("Deck 1\n{0}\n",newDeck(1));Console.WriteLine("Deck 617\n{0}\n",newDeck(617));}}}
Deck 1J♦ 2♦ 9♥ J♣ 5♦ 7♥ 7♣ 5♥K♦ K♣ 9♠ 5♠ A♦ Q♣ K♥ 3♥2♠ K♠ 9♦ Q♦ J♠ A♠ A♥ 3♣4♣ 5♣ T♠ Q♥ 4♥ A♣ 4♦ 7♠3♠ T♦ 4♠ T♥ 8♥ 2♣ J♥ 7♦6♦ 8♠ 8♦ Q♠ 6♣ 3♦ 8♣ T♣6♠ 9♣ 2♥ 6♥ Deck 6177♦ A♦ 5♣ 3♠ 5♠ 8♣ 2♦ A♥T♦ 7♠ Q♦ A♣ 6♦ 8♥ A♠ K♥T♥ Q♣ 3♥ 9♦ 6♠ 8♦ 3♦ T♣K♦ 5♥ 9♠ 3♣ 8♠ 7♥ 4♦ J♠4♣ Q♠ 9♣ 9♥ 7♣ 6♥ 2♣ 2♠4♠ T♠ 2♥ 5♦ J♣ 6♣ J♥ Q♥J♦ K♠ K♣ 4♥
#include<windows.h>#include<iostream>//--------------------------------------------------------------------------------------------------usingnamespacestd;//--------------------------------------------------------------------------------------------------classfc_dealer{public:voiddeal(intgame){_gn=game;fillDeck();shuffle();display();}private:voidfillDeck(){intp=0;for(intc=0;c<13;c++)for(ints=0;s<4;s++)_cards[p++]=c|s<<4;}voidshuffle(){srand(_gn);intcc=52,nc,lc;while(cc){nc=rand()%cc;lc=_cards[--cc];_cards[cc]=_cards[nc];_cards[nc]=lc;}}voiddisplay(){char*suit="CDHS";char*symb="A23456789TJQK";intz=0;cout<<"GAME #"<<_gn<<endl<<"======================="<<endl;for(intc=51;c>=0;c--){cout<<symb[_cards[c]&15]<<suit[_cards[c]>>4]<<" ";if(++z>=8){cout<<endl;z=0;}}}int_cards[52],_gn;};//--------------------------------------------------------------------------------------------------intmain(intargc,char*argv[]){fc_dealerdealer;intgn;while(true){cout<<endl<<"Game number please ( 0 to QUIT ): ";cin>>gn;if(!gn)break;system("cls");dealer.deal(gn);cout<<endl<<endl;}return0;}//--------------------------------------------------------------------------------------------------
Output:
GAME #1=======================JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6HGAME #617=======================7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
This is written using a more object-oriented approach than the version above.
#include<string> // std::string#include<iostream> // std::cout#include<sstream> // std::stringstream#include<vector> // std::vectorusingnamespacestd;//------------------------------------------------------------------------------classRandom{public:voidinit(uint32_tseed){_seed=seed;}introll(){return(_seed=(_seed*MULT+INCR)&MASK)>>16;}private:int_seed;enum{MULT=214013,INCR=2531011,MASK=(1U<<31)-1};};//------------------------------------------------------------------------------classCard{public:Card(intvalue):_value(value){}intsuit()const{return_value%4;}intrank()const{return_value/4;}stringstr()const{stringstreams;s<<_ranks[rank()]<<_suits[suit()];returns.str();}private:int_value;constchar*_suits="CDHS";constchar*_ranks="A23456789TJQK";};//------------------------------------------------------------------------------classDeck{public:Deck(intseed){_random.init(seed);for(inti=0;i<52;i++)_cards.push_back(Card(51-i));for(inti=0;i<51;i++){intj=51-_random.roll()%(52-i);swap(_cards[i],_cards[j]);}}stringstr()const{stringstreams;for(inti=0;i<_cards.size();i++)s<<_cards[i].str()<<(i%8==7||i==51?"\n":" ");returns.str();}private:vector<Card>_cards;Random_random;};//------------------------------------------------------------------------------intmain(intargc,constchar*argv[]){{Deckdeck(1);cout<<"Deck 1"<<endl<<deck.str()<<endl;}{Deckdeck(617);cout<<"Deck 617"<<endl<<deck.str()<<endl;}return0;}
Deck 1JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6HDeck 6177D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
sharedvoidfreeCellDeal(){//a function that returns a random number generating functionfunctioncreateRNG(variableIntegerstate)=>()=>(state=(214_013*state+2_531_011)%2^31)/2^16;voiddeal(Integernum){// create an array with a list comprehensionvariablevaluedeck=Array{for(rankin"A23456789TJQK")for(suitin"CDHS")"``rank````suit``"};valuerng=createRNG(num);for(iin1..52){valueindex=rng()%deck.size;assert(existslastIndex=deck.lastIndex);//swap the random card with the last onedeck.swap(index,lastIndex);//print the last oneprocess.write("``deck.last else "missingcard"`` ");if(i%8==0){print("");}//and shrink the array to remove the last carddeck=deck[...lastIndex-1];}}deal(1);print("\n");deal(617);}
(defdeck(into[](for[rank"A23456789TJQK"suit"CDHS"](strranksuit))))(defnlcg[seed](map#(bit-shift-right%16)(rest(iterate#(mod(+(*%214013)2531011)(bit-shift-left131))seed))))(defngen[seed](map(fn[rndrng](into[][(modrndrng)(decrng)]))(lcgseed)(range520-1)))(defnxchg[v[srcdst]](assocvdst(vsrc)src(vdst)))(defnshow[seed](map#(println%)(partition88""(reverse(reducexchgdeck(genseed))))))(show1)
(defunmake-rng(seed)#'(lambda()(ash(setfseed(mod(+(*214013seed)2531011)(expt231)))-16)))(defunsplit(s)(map'list#'strings))(defunmake-deck(seed)(let((hand(make-array52:fill-pointer0))(rng(make-rngseed)))(dolist(d(split"A23456789TJQK"))(dolist(s(split"♣♦♥♠"))(vector-push(concatenate'stringds)hand)))(dotimes(i52)(rotatef(arefhand(-51i))(arefhand(mod(funcallrng)(-52i)))))(nreversehand)))(defunshow-deck(seed)(let((hand(make-deckseed)))(formatt"~%Hand ~d~%"seed)(dotimes(i52)(formatt"~A "(arefhandi))(if(=(modi8)7)(write-line"")))))(show-deck1)(show-deck617)
importstd.stdio,std.conv,std.algorithm,std.range;structRandomGenerator{uintseed=1;@propertyuintnext()purenothrow@safe@nogc{seed=(seed*214_013+2_531_011)&int.max;returnseed>>16;}}structDeck{int[52]cards;voiddeal(inuintseed)purenothrow@safe@nogc{enumintnc=cards.length;// Must be signed for iota.nc.iota.retro.copy(cards[]);autornd=RandomGenerator(seed);foreach(immutablei,refc;cards)c.swap(cards[(nc-1)-rnd.next%(nc-i)]);}voidshow()const@safe{writefln("%(%-( %s%)\n%)",cards[].chunks(8).map!(row=>row.map!(c=>only("A23456789TJQK"[c/4],"CDHS"[c%4]))));}}voidmain(instring[]args)@safe{immutableseed=(args.length==2)?args[1].to!uint:11_982;writeln("Hand ",seed);Deckcards;cards.deal(seed);cards.show;}
Hand 11982 AH AS 4H AC 2D 6S TS JS 3D 3H QS QC 8S 7H AD KS KD 6H 5S 4D 9H JH 9S 3C JC 5D 5C 8C 9D TD KH 7C 6C 2C TH QH 6D TC 4S 7S JD 7D 8H 9C 2H QD 4C 5H KC 8D 2S 3S
programDeal_cards_for_FreeCell;{$APPTYPE CONSOLE}usesSystem.SysUtils;typeTRandom=recordSeed:Int64;functionNext:Integer;end;TCard=recordconstkSuits='♣♦♥♠';kValues='A23456789TJQK';varValue:Integer;Suit:Integer;procedureCreate(rawvalue:Integer);overload;procedureCreate(value,suit:Integer);overload;procedureAssign(other:TCard);functionToString:string;end;TDeck=recordCards:TArray<TCard>;procedureCreate(Seed:Integer);functionToString:string;end;{ TRandom }functionTRandom.Next:Integer;beginSeed:=((Seed*214013+2531011)andInteger.MaxValue);Result:=Seedshr16;end;{ TCard }procedureTCard.Create(rawvalue:Integer);beginCreate(rawvaluediv4,rawvaluemod4);end;procedureTCard.Assign(other:TCard);beginCreate(other.Value,other.Suit);end;procedureTCard.Create(value,suit:Integer);beginself.Value:=value;self.Suit:=suit;end;functionTCard.ToString:string;beginresult:=format('%s%s',[kValues[value+1],kSuits[suit+1]]);end;{ TDeck }procedureTDeck.Create(Seed:Integer);varr:TRandom;i,j:integer;tmp:Tcard;beginr.Seed:=Seed;SetLength(Cards,52);fori:=0to51doCards[i].Create(51-i);fori:=0to50dobeginj:=51-(r.Nextmod(52-i));tmp.Assign(Cards[i]);Cards[i].Assign(Cards[j]);Cards[j].Assign(tmp);end;end;functionTDeck.ToString:string;vari:Integer;beginResult:='';fori:=0tolength(Cards)-1dobeginResult:=Result+Cards[i].ToString;ifimod8=7thenResult:=Result+#10elseResult:=Result+' ';end;end;varDeck:TDeck;beginDeck.Create(1);Writeln('Deck 1'#10,Deck.ToString,#10);Deck.Create(617);Writeln('Deck 617'#10,Deck.ToString);readln;end.
Deck 1J♦ 2♦ 9♥ J♣ 5♦ 7♥ 7♣ 5♥K♦ K♣ 9♠ 5♠ A♦ Q♣ K♥ 3♥2♠ K♠ 9♦ Q♦ J♠ A♠ A♥ 3♣4♣ 5♣ T♠ Q♥ 4♥ A♣ 4♦ 7♠3♠ T♦ 4♠ T♥ 8♥ 2♣ J♥ 7♦6♦ 8♠ 8♦ Q♠ 6♣ 3♦ 8♣ T♣6♠ 9♣ 2♥ 6♥Deck 6177♦ A♦ 5♣ 3♠ 5♠ 8♣ 2♦ A♥T♦ 7♠ Q♦ A♣ 6♦ 8♥ A♠ K♥T♥ Q♣ 3♥ 9♦ 6♠ 8♦ 3♦ T♣K♦ 5♥ 9♠ 3♣ 8♠ 7♥ 4♦ J♠4♣ Q♠ 9♣ 9♥ 7♣ 6♥ 2♣ 2♠4♠ T♠ 2♥ 5♦ J♣ 6♣ J♥ Q♥J♦ K♠ K♣ 4♥
global seed .func xrnd . seed = (seed * 214013 + 2531011) mod 0x80000000 return seed div 0x10000.len cards[] 52proc deal game_num . print "hand " & game_num seed = game_num for i = 1 to 52 : cards[i] = 52 - i for i = 1 to 51 j = 52 - xrnd mod (53 - i) swap cards[i] cards[j] ..suits$[] = strchars "CDHS"ranks$[] = strchars "A23456789TJQK"# proc show . for idx = 1 to 52 rank = cards[idx] div 4 + 1 suit = cards[idx] mod 4 + 1 write ranks$[rank] & suits$[suit] & " " if idx mod1 13 = 13 : print "" . print "".deal 1 ; showdeal 617 ; show
hand 1JD 2D 9H JC 5D 7H 7C 5H KD KC 9S 5S AD QC KH 3H 2S KS 9D QD JS AS AH 3C 4C 5C TS QH 4H AC 4D 7S 3S TD 4S TH 8H 2C JH 7D 6D 8S 8D QS 6C 3D 8C TC 6S 9C 2H 6H hand 6177D AD 5C 3S 5S 8C 2D AH TD 7S QD AC 6D 8H AS KH TH QC 3H 9D 6S 8D 3D TC KD 5H 9S 3C 8S 7H 4D JS 4C QS 9C 9H 7C 6H 2C 2S 4S TS 2H 5D JC 6C JH QH JD KS KC 4H
defmoduleFreeCelldoimportBitwise@suits~w( C D H S )@pips~w( A 2 3 4 5 6 7 8 9 T J Q K )@orig_deckforpip<-@pips,suit<-@suits,do:pip<>suitdefdeal(games)dogames=iflength(games)==0,do:[Enum.random(1..32000)],else:gamesEnum.each(games,fnseed->IO.puts"Game##{seed}"Enum.reduce(52..2,{seed,@orig_deck},fnlen,{state,deck}->state=((214013*state)+2531011)&&&0x7fff_ffffindex=rem(state>>>16,len)last=len-1{a,b}={Enum.at(deck,index),Enum.at(deck,last)}{state,deck|>List.replace_at(index,b)|>List.replace_at(last,a)}end)|>elem(1)|>Enum.reverse|>Enum.chunk(8,8,[])|>Enum.each(fnrow->Enum.join(row," ")|>IO.putsend)IO.puts""end)endendSystem.argv|>Enum.map(&String.to_integer/1)|>FreeCell.deal
C:\Elixir>elixir freecell.exs 1 617Game #1JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6HGame #6177D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
PROGRAM FREECELL!$DOUBLEDIM CARDS%[52]PROCEDURE XRANDOM(SEED->XRND) POW31=2^31 POW16=2^16 SEED=SEED*214013+2531011 SEED=SEED-POW31*INT(SEED/POW31) XRND=INT(SEED/POW16)END PROCEDUREPROCEDURE DEAL(CARDS%[],GAME_NUM) LOCAL I%,J%,S% SEED=GAME_NUM FOR I%=1 TO 52 DO CARDS%[I%]=52-I% END FOR FOR I%=1 TO 51 DO XRANDOM(SEED->XRND) J%=52-XRND MOD (53-I%) S%=CARDS%[I%] CARDS%[I%]=CARDS%[J%] CARDS%[J%]=S% END FOREND PROCEDUREPROCEDURE SHOW(CARDS%[]) LOCAL INDEX% FOR INDEX%=1 TO 52 DO PRINT(MID$(SUITS$,CARDS%[INDEX%] MOD 4+1,1);MID$(NUMS$,CARDS%[INDEX%] DIV 4+1,1);" ";) IF INDEX% MOD 8=0 OR INDEX%=52 THEN PRINT END IF END FOREND PROCEDUREBEGIN PRINT(CHR$(12);) SUITS$="♣♦♥♠" NUMS$="A23456789TJQK" GAME_NUM=1982 ! if missing command line IF CMDLINE$<>"" THEN GAME_NUM=VAL(CMDLINE$) END IF SEED=1 DEAL(CARDS%[],GAME_NUM) PRINT("Hand ";GAME_NUM) SHOW(CARDS%[])END PROGRAMHand 1 ♦J ♦2 ♥9 ♣J ♦5 ♥7 ♣7 ♥5 ♦K ♣K ♠9 ♠5 ♦A ♣Q ♥K ♥3 ♠2 ♠K ♦9 ♦Q ♠J ♠A ♥A ♣3 ♣4 ♣5 ♠T ♥Q ♥4 ♣A ♦4 ♠7 ♠3 ♦T ♠4 ♥T ♥8 ♣2 ♥J ♦7 ♦6 ♠8 ♦8 ♠Q ♣6 ♦3 ♣8 ♣T ♠6 ♣9 ♥2 ♥6
Hand 617 ♦7 ♦A ♣5 ♠3 ♠5 ♣8 ♦2 ♥A ♦T ♠7 ♦Q ♣A ♦6 ♥8 ♠A ♥K ♥T ♣Q ♥3 ♦9 ♠6 ♦8 ♦3 ♣T ♦K ♥5 ♠9 ♣3 ♠8 ♥7 ♦4 ♠J ♣4 ♠Q ♣9 ♥9 ♣7 ♥6 ♣2 ♠2 ♠4 ♠T ♥2 ♦5 ♣J ♣6 ♥J ♥Q ♦J ♠K ♣K ♥4
The deal for this one is a little arduous, as we're using a list and maintain an immutable state. Of course, an array could be used, but what's the fun in that?
letmsKindaRandseed=letstate=refseed(fun(_:unit)->state:=(214013*!state+2531011)&&&System.Int32.MaxValue!state/(1<<<16))letunshuffledDeck=[0..51]|>List.map(funn->sprintf"%c%c""A23456789TJQK".[n/4]"CDHS".[n%4])letdealbootidx=let(last,rest)=boot|>List.rev|>funxs->(List.headxs),(xs|>List.tail|>List.rev)ifidx=((List.lengthboot)-1)thenlast,restelserest|>List.mapi(funix->i,x)|>List.partition(fst>>((>)idx))|>fun(xs,ys)->(List.mapsndxs),(List.mapsndys)|>fun(xs,ys)->(List.headys),(xs@last::(List.tailys))letgamegameNo=letrnd=msKindaRandgameNo[52..-1..1]|>List.map(funi->rnd()%i)|>List.fold(fun(dealt,boot)idx->dealbootidx|>fun(x,xs)->(x::dealt,xs))([],unshuffledDeck)|>fst|>List.rev|>List.chunkBySize8|>List.map(String.concat" ")|>String.concat"\n"|>printfn"Game #%d\n%s\n"gameNo[1;617]|>List.itergame
Game #1JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6HGame #6177D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
USING:formattinggroupingiokernelliteralsmakemathmath.functionsnamespacesqwsequencessequences.extras;IN:rosetta-code.freecellCONSTANT:max-rand-ms$[1 15shift1-]CONSTANT:suitsqw{CDHS}CONSTANT:ranksqw{A2 3 4 5 6 7 8 9TJQK}SYMBOL:seed:(random)(n1n2--n3)seedget*+dupseedset;:rand-ms(--n)max-rand-ms2531011 214013(random)-16shiftbitand;:init-deck(--seq)rankssuits[append]cartesian-mapconcatV{}like;:swap-cards(seq--seq')rand-msoverlength[mod][1-]bipickexchange;:(deal)(seq--seq')[[swap-cardsduppop,]until-empty]{}make;:deal(game#--seq)seedsetinit-deck(deal);:.cards(seq--)8group[[writebl]eachnl]eachnl;:.game(game#--)dup"Game #%d\n"printfdeal.cards;:freecell(--)1 617[.game]bi@;MAIN:freecell
Game #1JD 2D 9H JC 5D 7H 7C 5H KD KC 9S 5S AD QC KH 3H 2S KS 9D QD JS AS AH 3C 4C 5C TS QH 4H AC 4D 7S 3S TD 4S TH 8H 2C JH 7D 6D 8S 8D QS 6C 3D 8C TC 6S 9C 2H 6H Game #6177D AD 5C 3S 5S 8C 2D AH TD 7S QD AC 6D 8H AS KH TH QC 3H 9D 6S 8D 3D TC KD 5H 9S 3C 8S 7H 4D JS 4C QS 9C 9H 7C 6H 2C 2S 4S TS 2H 5D JC 6C JH QH JD KS KC 4H
Using the lcgs module fromLinear congruential generator#Fortran:
moduleFreecelluselcgsimplicit nonecharacter(4)::suit="CDHS"character(13)::rank="A23456789TJQK"character(2)::deck(0:51)containssubroutineCreatedeck()integer::i,j,nn=0doi=1,13doj=1,4deck(n)=rank(i:i)//suit(j:j)n=n+1end do end doend subroutinesubroutineFreecelldeal(game)integer,intent(in)::gameinteger(i64)::rnuminteger::i,ncharacter(2)::tmpcallCreatedeck()rnum=msrand(game)doi=51,1,-1n=mod(rnum,i+1)tmp=deck(n)deck(n)=deck(i)deck(i)=tmprnum=msrand()end do write(*,"(a, i0)")"Game #",gamewrite(*,"(8(a, tr1))")deck(51:0:-1)write(*,*)end subroutineend moduleFreecellprogramFreecell_testuseFreecellimplicit none callFreecelldeal(1)callFreecelldeal(617)end program
Game #1JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6H Game #6177D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
' version 04-11-2016' compile with: fbc -s console' to seed ms_lcg(seed > -1)' to get random number ms_lcg(-1) or ms_lcg() or just ms_lcgFunctionms_lcg(seedAsInteger=-1)AsUIntegerStaticAsUIntegerms_stateIfseed<>-1Thenms_state=seedMod2^31Elsems_state=(214013*ms_state+2531011)Mod2^31EndIfReturnms_stateShr16EndFunction' ------=< MAIN >=------DimAsUBytecard(51)DimAsStringsuit="CDHS",value="A23456789TJQK"DimAsLongi,c,s,v,game=1DimAsULonggame_nr(1To2)={1,617}Doms_lcg(game_nr(game))' seed generatorPrint"game #";game_nr(game)game=game+1Fori=0To51' set up the cardscard(i)=iNextFori=51To0Step-1' shufflec=ms_lcgMod(i+1)Swapcard(i),card(c)Nextc=0DoFori=0To7s=card(51-c)Mod4v=card(51-c)\4PrintChr(value[v]);Chr(suit[s]);" ";c=c+1Ifc>51ThenExitDoNextPrintLoopPrint:PrintLoopUntilgame>UBound(game_nr)' empty keyboard bufferWhileInkey<>"":WendPrint:Print"hit any key to end program"SleepEnd
game #1JD 2D 9H JC 5D 7H 7C 5H KD KC 9S 5S AD QC KH 3H 2S KS 9D QD JS AS AH 3C 4C 5C TS QH 4H AC 4D 7S 3S TD 4S TH 8H 2C JH 7D 6D 8S 8D QS 6C 3D 8C TC 6S 9C 2H 6H game #6177D AD 5C 3S 5S 8C 2D AH TD 7S QD AC 6D 8H AS KH TH QC 3H 9D 6S 8D 3D TC KD 5H 9S 3C 8S 7H 4D JS 4C QS 9C 9H 7C 6H 2C 2S 4S TS 2H 5D JC 6C JH QH JD KS KC 4H
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition.
Programs in Fōrmulæ are created/edited online in itswebsite.
Inthis page you can see and run the program(s) related to this task and their results. You can also change either the programs or the parameters they are called with, for experimentation, but remember that these programs were created with the main purpose of showing a clear solution of the task, and they generally lack any kind of validation.
Solution
There is no need to remove from a deal to be added to another one, it can be performed on a single array. It is and iteration from 52 to 1 indicating the end of the first array, and therefore the start of a second one after each swap. The only inconvenience is that second array contains the information in reversed order, but when it is shown it is also read in reversed order.
The number 127,185 is the decimal number of the 🃑 Unicode character.
In the Unicode playing cards characters, there is the Knight, between the Jack and Queen suits, which is not used, so it is skipped in the order.
Test case. The —only— impossible deal #11982 in the original version of FreeCell for windows:
Using FB 7.0.34
//// Dealcards for FreeCell//// FutureBasic 7.0.34, August 2025 R.W.////------------------------------------------dim as long seed // random seeddim cards(52) as long // full deck of cardsCFStringRef ranks (13) = {@"ranks",@"A",@"2",@"3",@"4",@"5", ¬@"6",@"7",@"8",@"9",@"T",@"J",@"Q",@"K"}CFStringRef suits (5) = {@"suits",@"C",@"D",@"H",@"S"}long UniC(5) = {0,127185,127169,127153,127137}Boolean pUni// Convert dec to hex unicodelocal fn DecToHexUni(d as long) as CFStringRef CFStringRef myHexUni myHexUni = hex(d) myHexUni = concat(@"\\U",myHexUni)end fn = myHexUni// display a card at the current position// if "useUni" is true, the emoji icon is used// else the string in variable "card" is usedlocal fn dispC(useUni as boolean, card as CFStringRef) int suite long d, baseN, baseR, rank CFStringRef myUNIcode, disp //, card CFStringRef srank, ssuite srank = left(card,1) // A = 1,2 = 2 ... T = 10, 11 = Q ssuite = right(card,1) //CDHS C=1 D=2 H=3 S=4 suite = 4 Select ssuite case @"C" suite = 1 case @"D" suite = 2 case @"H" suite = 3 end select baseN = uniC (suite) baseR = ucc(srank) - 48 rank = baseR if baseR > 9 select case baseR case 17 rank = 1 case 36 rank = 10 case 26 rank = 11 case 33 rank = 12 case 27 rank = 13 end select else rank = baseR end if if useUni //user wanted in UniCode d = baseN + rank d = d - 1 if (d > BaseN + 10) then d++ // skip the "C" emoji myUNIcode = fn DecToHexUni(d) disp = fn StringByApplyingTransform( myUNIcode, @"Any-Hex", YES ) text @"Menlo", 64 // size to your liking (hard to see if small) print @disp; else text @"Menlo", 12 print @card;" "; end ifend fn// Get a random seed from the generatorlocal fn rndGen as long // RNG seed = (seed * 214013 + 2531011) and 0x7FFFFFFFend fn = int( seed / 65536 )// Deal the deck. At entry gameNum = game numberlocal fn deal(gameNum as long) dim as long i, j // Build a reverse deck seed = gameNum for i = 0 to 51 cards(i) = 52 - i next // deal randomly from seed for i = 1 to 51 dim as long r r = fn rndGen j = 52 - (r mod (53 - i)) Swap cards(i), cards(j) next i // until no moreend fn//// Display the decklocal fn show dim as long idx, rank, suit CFStringRef tmp tmp = @"" for idx = 1 to 52 rank = int(cards(idx) / 4) + 1 suit = (cards(idx) mod 4) + 1 tmp = concat(ranks(rank),suits(suit)) fn dispC(pUni, tmp) if ((idx) mod 8) == 0 then print nextend fn//-------- MAIN ---------window 1,@"Deal cards for FreeCell"dim as long gameNumpUni = _False // default to textprinttext @"Menlo", 12gameNum = 1fn deal(gameNum)print @"Game #"; gameNumfn showprint @print @text @"Menlo", 12gameNum = 617fn deal(gameNum)print @"Game #"; gameNumfn showprint @handleEventsGame #1JD 2D 9H JC 5D 7H 7C 5H KD KC 9S 5S AD QC KH 3H 2S KS 9D QD JS AS AH 3C 4C 5C TS QH 4H AC 4D 7S 3S TD 4S TH 8H 2C JH 7D 6D 8S 8D QS 6C 3D 8C TC 6S 9C 2H 6H Game #6177D AD 5C 3S 5S 8C 2D AH TD 7S QD 6H 6D 8H AS KH TH QC 3H 9D 6S 8D 3D TC KD 5H 9S 3C 8S 7H 4D JS 4C QS 9C 9H 7C 6H 2C 2S 4S TS 2H 5D JC 6C JH QH JD KS KC 4H //==== or if desired, emoji icons
packagemainimport("fmt""math""math/rand""os""strconv""time")constsSuits="CDHS"constsNums="A23456789TJQK"constrMax32=math.MaxInt32varseed=1funcrnd()int{seed=(seed*214013+2531011)&rMax32returnseed>>16}funcdeal(sint)[]int{seed=st:=make([]int,52)fori:=0;i<52;i++{t[i]=51-i}fori:=0;i<51;i++{j:=51-rnd()%(52-i)t[i],t[j]=t[j],t[i]}returnt}funcshow(cs[]int){fori,c:=rangecs{fmt.Printf(" %c%c",sNums[c/4],sSuits[c%4])if(i+1)%8==0||i+1==len(cs){fmt.Println()}}}funcmain(){vargameintswitchlen(os.Args){case1:rand.Seed(time.Now().UnixNano())game=1+rand.Intn(32000)case2:varerrerrorgame,err=strconv.Atoi(os.Args[1])iferr==nil&&game>=1&&game<=32000{break}fallthroughdefault:fmt.Println("usage: deal [game]")fmt.Println(" where game is a number in the range 1 to 32000")return}fmt.Printf("\nGame #%d\n",game)show(deal(game))}
Game #1 JD 2D 9H JC 5D 7H 7C 5H KD KC 9S 5S AD QC KH 3H 2S KS 9D QD JS AS AH 3C 4C 5C TS QH 4H AC 4D 7S 3S TD 4S TH 8H 2C JH 7D 6D 8S 8D QS 6C 3D 8C TC 6S 9C 2H 6HGame #617 7D AD 5C 3S 5S 8C 2D AH TD 7S QD AC 6D 8H AS KH TH QC 3H 9D 6S 8D 3D TC KD 5H 9S 3C 8S 7H 4D JS 4C QS 9C 9H 7C 6H 2C 2S 4S TS 2H 5D JC 6C JH QH JD KS KC 4H
classFreeCell{intseedList<String>createDeck(){List<String>suits=['♣','♦','♥','♠']List<String>values=['A','2','3','4','5','6','7','8','9','10','J','Q','K']return[suits,values].combinations{suit,value->"$suit$value"}}intrandom(){seed=(214013*seed+2531011)&Integer.MAX_VALUEreturnseed>>16}List<String>shuffledDeck(List<String>cards){List<String>deck=cards.clone()(deck.size()-1..1).each{index->intr=random()%(index+1)deck.swap(r,index)}returndeck}List<String>dealGame(intseed=1){this.seed=seedList<String>cards=shuffledDeck(createDeck())(1..cards.size()).each{number->print"${cards.pop()}\t"if(number%8==0)println('')}println('\n')}}deffreecell=newFreeCell()freecell.dealGame()freecell.dealGame(617)
Game #1♦J♦2♥9♣J♦5♥7♣7♥5♦K♣K♠9♠5♦A♣Q♥K♥3♠2♠K♦9♦Q♠J♠A♥A♣3♣4♣5♠10♥Q♥4♣A♦4♠7♠3♦10♠4♥10♥8♣2♥J♦7♦6♠8♦8♠Q♣6♦3♣8♣10♠6♣9♥2♥6Game #617♦7♦A♣5♠3♠5♣8♦2♥A♦10♠7♦Q♣A♦6♥8♠A♥K♥10♣Q♥3♦9♠6♦8♦3♣10♦K♥5♠9♣3♠8♥7♦4♠J♣4♠Q♣9♥9♣7♥6♣2♠2♠4♠10♥2♦5♣J♣6♥J♥Q♦J♠K♣K♥4
importData.IntimportData.BitsimportData.ListimportData.Array.STimportControl.MonadimportControl.Monad.STimportSystem.Environmentsrnd::Int32->[Int]srnd=map(fromIntegral.flipshiftR16).tail.iterate(\x->(x*214013+2531011).&.maxBound)deal::Int32->[String]deals=runST(doar<-newListArray(0,51)$sequence["A23456789TJQK","CDHS"]::STs(STArraysIntString)forM(zip[52,51..1]rnd)$\(n,r)->doletj=r`mod`nvj<-readArrayarjvn<-readArrayar(n-1)writeArrayarjvnreturnvj)wherernd=srndsshowCards::[String]->IO()showCards=mapM_(putStrLn.unwords).takeWhile(not.null).unfoldr(Just.splitAt8)main::IO()main=doargs<-getArgslets=read(headargs)::Int32putStrLn$"Deal "++shows++":"letcards=dealsshowCardscards
Execution:
$ runghc freecell.hs 617Deal 617:7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
proceduremain(A)# freecelldealerfreecelldealer(\A[1]|&null)# seed from command lineendprocedurenewDeck()#: return a new unshuffled deckeveryD:=list(52)&i:=0&r:=!"A23456789TJQK"&s:=!"CDHS"doD[i+:=1]:=r||s# initial deck AC AD ... KSreturnDendprocedurefreecelldealer(gamenum)#: deal a freecell hand/gamenum:=11982returnshowHand(freecellshuffle(newDeck(),gamenum))endprocedureshowHand(D)#: show a freecell handwrite("Hand:\n")everywrites(" ",(1to8)|"\n")everywrites(" ",D[i:=1to*D])doifi%8=0thenwrite()write("\n")returnDendprocedurefreecellshuffle(D,gamenum)#: freecell shufflesrand_freecell(gamenum)# seed random number generatorD2:=[]until*D=0do{# repeat until all dealtD[r:=rand_freecell()%*D+1]:=:D[*D]# swap random & last cardsput(D2,pull(D))# remove dealt card from list}returnD2endproceduresrand_freecell(x)#: seed randomstaticseedreturnseed:=\x|\seed|0# parm or seed or zero if noneendprocedurerand_freecell()#: lcrngreturnishift(srand_freecell((214013*srand_freecell()+2531011)%2147483648),-16)end
Hand: 1 2 3 4 5 6 7 8 JD 2D 9H JC 5D 7H 7C 5H KD KC 9S 5S AD QC KH 3H 2S KS 9D QD JS AS AH 3C 4C 5C TS QH 4H AC 4D 7S 3S TD 4S TH 8H 2C JH 7D 6D 8S 8D QS 6C 3D 8C TC 6S 9C 2H 6H
Paraphrase ofC:
deck=:,/'A23456789TJQK',"0/7u:'♣♦♥♠'srnd=:3:'SEED=:{.y,11982'srnd''seed=:dobind'SEED'rnd=:(2^16)<.@%~(2^31)srnd@|2531011+214013*seedpairs=:<@<@~.@(<:,(|rnd))@>:@i.@-@#NB. indices to swap, for shuffleswaps=:[:>C.&.>/@|.@;NB. implement the specified shuffledeal=:|.@(swapspairs)binddeckshow=:(,"2)@:(_8]\' '&,.)
showdealsrnd1J♦2♦9♥J♣5♦7♥7♣5♥K♦K♣9♠5♠A♦Q♣K♥3♥2♠K♠9♦Q♦J♠A♠A♥3♣4♣5♣T♠Q♥4♥A♣4♦7♠3♠T♦4♠T♥8♥2♣J♥7♦6♦8♠8♦Q♠6♣3♦8♣T♣6♠9♣2♥6♥showdealsrnd6177♦A♦5♣3♠5♠8♣2♦A♥T♦7♠Q♦A♣6♦8♥A♠K♥T♥Q♣3♥9♦6♠8♦3♦T♣K♦5♥9♠3♣8♠7♥4♦J♠4♣Q♠9♣9♥7♣6♥2♣2♠4♠T♠2♥5♦J♣6♣J♥Q♥J♦K♠K♣4♥
importjava.util.Arrays;publicclassShuffler{privateintseed;privateString[]deck={"AC","AD","AH","AS","2C","2D","2H","2S","3C","3D","3H","3S","4C","4D","4H","4S","5C","5D","5H","5S","6C","6D","6H","6S","7C","7D","7H","7S","8C","8D","8H","8S","9C","9D","9H","9S","TC","TD","TH","TS","JC","JD","JH","JS","QC","QD","QH","QS","KC","KD","KH","KS",};privateintrandom(){seed=(214013*seed+2531011)&Integer.MAX_VALUE;returnseed>>16;}//shuffled cards go to the endprivateString[]getShuffledDeck(){String[]deck=Arrays.copyOf(this.deck,this.deck.length);for(inti=deck.length-1;i>0;i--){intr=random()%(i+1);Stringcard=deck[r];deck[r]=deck[i];deck[i]=card;}returndeck;}//deal from end firstpublicvoiddealGame(intseed){this.seed=seed;String[]shuffledDeck=getShuffledDeck();for(intcount=1,i=shuffledDeck.length-1;i>=0;count++,i--){System.out.print(shuffledDeck[i]);if(count%8==0){System.out.println();}else{System.out.print(" ");}}System.out.println();}publicstaticvoidmain(String[]args){Shufflers=newShuffler();s.dealGame(1);System.out.println();s.dealGame(617);}}
JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6H 7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
"use strict";/* * Microsoft C Run-time-Library-compatible Random Number Generator * Copyright by Shlomi Fish, 2011. * Released under the MIT/X11 License * ( http://en.wikipedia.org/wiki/MIT_License ). * *//* This uses Joose 2.x-or-above, an object system for JavaScript - http://code.google.com/p/joose-js/ . */Class('MSRand',{has:{seed:{is:rw,},},methods:{rand:function(){this.setSeed((this.getSeed()*214013+2531011)&0x7FFFFFFF);return((this.getSeed()>>16)&0x7fff);},max_rand:function(mymax){returnthis.rand()%mymax;},shuffle:function(deck){if(deck.length){vari=deck.length;while(--i){varj=this.max_rand(i+1);vartmp=deck[i];deck[i]=deck[j];deck[j]=tmp;}}returndeck;},},});/* * Microsoft Windows Freecell / Freecell Pro boards generation. * * See: * * - http://rosettacode.org/wiki/Deal_cards_for_FreeCell * * - http://www.solitairelaboratory.com/mshuffle.txt * * Under MIT/X11 Licence. * * */functiondeal_ms_fc_board(seed){varrandomizer=newMSRand({seed:seed});varnum_cols=8;var_perl_range=function(start,end){varret=[];for(vari=start;i<=end;i++){ret.push(i);}returnret;};varcolumns=_perl_range(0,num_cols-1).map(function(){return[];});vardeck=_perl_range(0,4*13-1);randomizer.shuffle(deck);deck=deck.reverse()for(vari=0;i<52;i++){columns[i%num_cols].push(deck[i]);}varrender_card=function(card){varsuit=(card%4);varrank=Math.floor(card/4);return"A23456789TJQK".charAt(rank)+"CDHS".charAt(suit);}varrender_column=function(col){return": "+col.map(render_card).join(" ")+"\n";}returncolumns.map(render_column).join("");}
constrank=split("A23456789TJQK","")constsuit=split("♣♦♥♠","")constdeck=Vector{String}()constmslcg=[0]rng()=(mslcg[1]=((mslcg[1]*214013+2531011)&0x7fffffff))>>16initdeck()=forrinrank,sinsuitpush!(deck,"$r$s")endfunctiondeal(num=rand(UInt,1)[1]%32000+1)initdeck()mslcg[1]=numprintln("\nGame # ",num)whilelength(deck)>0choice=rng()%length(deck)+1deck[choice],deck[end]=deck[end],deck[choice]print(" ",pop!(deck),length(deck)%8==4?"\n":"")endenddeal(1)deal(617)deal()
Game # 1
J♦ 2♦ 9♥ J♣ 5♦ 7♥ 7♣ 5♥K♦ K♣ 9♠ 5♠ A♦ Q♣ K♥ 3♥2♠ K♠ 9♦ Q♦ J♠ A♠ A♥ 3♣4♣ 5♣ T♠ Q♥ 4♥ A♣ 4♦ 7♠3♠ T♦ 4♠ T♥ 8♥ 2♣ J♥ 7♦6♦ 8♠ 8♦ Q♠ 6♣ 3♦ 8♣ T♣6♠ 9♣ 2♥ 6♥Game # 617
7♦ A♦ 5♣ 3♠ 5♠ 8♣ 2♦ A♥T♦ 7♠ Q♦ A♣ 6♦ 8♥ A♠ K♥T♥ Q♣ 3♥ 9♦ 6♠ 8♦ 3♦ T♣K♦ 5♥ 9♠ 3♣ 8♠ 7♥ 4♦ J♠4♣ Q♠ 9♣ 9♥ 7♣ 6♥ 2♣ 2♠4♠ T♠ 2♥ 5♦ J♣ 6♣ J♥ Q♥J♦ K♠ K♣ 4♥Game # 20065
7♥ 8♠ T♣ 3♦ T♥ 2♥ 6♥ K♥K♣ A♣ 4♣ 5♥ 9♠ K♠ K♦ J♦8♦ 6♦ J♣ 6♠ T♠ 7♦ 7♠ Q♥7♣ J♠ A♠ 4♦ 5♣ 2♠ A♥ T♦A♦ 6♣ Q♣ 8♥ 3♣ 5♦ 3♠ 3♥9♦ 2♦ Q♦ 4♠ 5♠ 9♥ 8♣ 4♥9♣ 2♣ J♥ Q♠
// version 1.1.3classLcg(vala:Long,valc:Long,valm:Long,vald:Long,vals:Long){privatevarstate=sfunnextInt():Long{state=(a*state+c)%mreturnstate/d}}constvalCARDS="A23456789TJQK"constvalSUITS="♣♦♥♠"fundeal():Array<String?>{valcards=arrayOfNulls<String>(52)for(iin0until52){valcard=CARDS[i/4]valsuit=SUITS[i%4]cards[i]="$card$suit"}returncards}fungame(n:Int){require(n>0)println("Game #$n:")valmsc=Lcg(214013,2531011,1shl31,1shl16,n.toLong())valcards=deal()for(min52downTo1){valindex=(msc.nextInt()%m).toInt()valtemp=cards[index]cards[index]=cards[m-1]print("$temp ")if((53-m)%8==0)println()}println("\n")}funmain(args:Array<String>){game(1)game(617)}
Game #1:J♦ 2♦ 9♥ J♣ 5♦ 7♥ 7♣ 5♥ K♦ K♣ 9♠ 5♠ A♦ Q♣ K♥ 3♥ 2♠ K♠ 9♦ Q♦ J♠ A♠ A♥ 3♣ 4♣ 5♣ T♠ Q♥ 4♥ A♣ 4♦ 7♠ 3♠ T♦ 4♠ T♥ 8♥ 2♣ J♥ 7♦ 6♦ 8♠ 8♦ Q♠ 6♣ 3♦ 8♣ T♣ 6♠ 9♣ 2♥ 6♥ Game #617:7♦ A♦ 5♣ 3♠ 5♠ 8♣ 2♦ A♥ T♦ 7♠ Q♦ A♣ 6♦ 8♥ A♠ K♥ T♥ Q♣ 3♥ 9♦ 6♠ 8♦ 3♦ T♣ K♦ 5♥ 9♠ 3♣ 8♠ 7♥ 4♦ J♠ 4♣ Q♠ 9♣ 9♥ 7♣ 6♥ 2♣ 2♠ 4♠ T♠ 2♥ 5♦ J♣ 6♣ J♥ Q♥ J♦ K♠ K♣ 4♥
; Linear congruential random number generatormake "_lcg_state 0to seed_lcg :seed make "_lcg_state :seedendto sample_lcg make "_lcg_state modulo sum product 214013 :_lcg_state 2531011 2147483648 output int quotient :_lcg_state 65536end; FreeCellto card_from_number :number output word item sum 1 int quotient :number 4 "A23456789TJQK item sum 1 modulo :number 4 "CDHS endto generate_deal :number (local "deck "size "index "deal) seed_lcg :number make "deck [] repeat 52 [ make "deck lput difference # 1 :deck ] make "deck listtoarray :deck make "deal [] repeat 52 [ make "size difference 53 # make "index sum 1 modulo sample_lcg :size make "deal lput item :index :deck :deal setitem :index :deck item :size :deck ] output :dealendto print_deal :number (local "deal "i "j "index) make "deal generate_deal :number repeat 7 [ make "i difference # 1 repeat (ifelse [equal? :i 6] 4 8) [ make "j difference # 1 make "index (sum 1 product :i 8 :j) type (word (card_from_number item :index :deal) "| |) ] print "|| ]endprint [Game #1]print_deal 1print "||print [Game #617]print_deal 617print "||bye
Game #1JD 2D 9H JC 5D 7H 7C 5H KD KC 9S 5S AD QC KH 3H 2S KS 9D QD JS AS AH 3C 4C 5C TS QH 4H AC 4D 7S 3S TD 4S TH 8H 2C JH 7D 6D 8S 8D QS 6C 3D 8C TC 6S 9C 2H 6H Game #6177D AD 5C 3S 5S 8C 2D AH TD 7S QD AC 6D 8H AS KH TH QC 3H 9D 6S 8D 3D TC KD 5H 9S 3C 8S 7H 4D JS 4C QS 9C 9H 7C 6H 2C 2S 4S TS 2H 5D JC 6C JH QH JD KS KC 4H
Uses bit32 library added in Lua 5.2.
deck={}rank={"A","2","3","4","5","6","7","8","9","T","J","Q","K"}suit={"C","D","H","S"}two31,state=bit32.lshift(1,31),0functionrng()state=(214013*state+2531011)%two31returnbit32.rshift(state,16)endfunctioninitdeck()fori,rinipairs(rank)doforj,sinipairs(suit)dotable.insert(deck,r..s)endendendfunctiondeal(num)initdeck()state=numprint("Game #"..num)repeatchoice=rng(num)%#deck+1deck[choice],deck[#deck]=deck[#deck],deck[choice]io.write(" "..deck[#deck])if(#deck%8==5)thenprint()enddeck[#deck]=niluntil#deck==0print()enddeal(1)deal(617)
Game #1 JD 2D 9H JC 5D 7H 7C 5H KD KC 9S 5S AD QC KH 3H 2S KS 9D QD JS AS AH 3C 4C 5C TS QH 4H AC 4D 7S 3S TD 4S TH 8H 2C JH 7D 6D 8S 8D QS 6C 3D 8C TC 6S 9C 2H 6HGame #617 7D AD 5C 3S 5S 8C 2D AH TD 7S QD AC 6D 8H AS KH TH QC 3H 9D 6S 8D 3D TC KD 5H 9S 3C 8S 7H 4D JS 4C QS 9C 9H 7C 6H 2C 2S 4S TS 2H 5D JC 6C JH QH JD KS KC 4H
ModuleFreeCellDeal{deal=lambda->{ms_lcg=lambdams_state=0#(seedAscurrency=-1)->{Ifseed<>-1Thenms_state=seedMod2^31Elsems_state=(214013*ms_state+2531011)Mod2^31EndIf=binary.shift(ms_state,-16)}fillbytes=lambdan=0ud->{=n:n++}dimcards(52)asbyte<<fillbytes()=lambdams_lcg,cards()(gameasinteger)->{callvoidms_lcg(game)dimncards()ncards()=cards()fori=51to0c=ms_lcg()Mod(i+1)Swapncards(i),ncards(c)next=ncards()}}()' execute nowdimdealcards()stringsuit="CDHS",value="A23456789TJQK"aList=(1,617)nList=each(alist)whilenListPrint"Game:"+array(nList)dealcards()=deal(array(nlist))CardDis$=lambda$dealcards(),suit,value(c)->{s=dealcards(51-c)Mod4+1v=dealcards(51-c)div4+1=Mid$(value,v,1)+Mid$(suit,s,1)}c=0DoPrintCardDis$(c);ifcmod8<7then?" ";Else?c++untilc>51?:?endwhile}FreeCellDeal
Game:1JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6HGame:6177D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
next[last_]:=Mod[214013last+2531011,2^31];deal[n_]:=Module[{last=n,idx,deck=StringJoin/@Tuples[{{"A","2","3","4","5","6","7","8","9","T","J","Q","K"},{"C","D","H","S"}}],res={}},While[deck!={},last=next[last];idx=Mod[BitShiftRight[last,16],Length[deck]]+1;deck=ReplacePart[deck,{idx->deck[[-1]],-1->deck[[idx]]}];AppendTo[res,deck[[-1]]];deck=deck[[;;-2]]];res];format[deal_]:=Grid[Partition[deal,8,8,{1,4},Null]];Print[format[deal[1]]];Print[format[deal[617]]];
JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6H7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
importsequtils,strutils,osprocrandomGenerator(seed:int):iterator:int=varstate=seedreturniterator:int=whiletrue:state=(state*214013+2531011)andint32.highyieldstateshr16procdeal(seed:int):seq[int]=constnc=52result=toSeqcountdown(nc-1,0)varrnd=randomGeneratorseedforiin0..<nc:letr=rnd()letj=(nc-1)-rmod(nc-i)swapresult[i],result[j]procshow(cards:seq[int])=varl=newSeq[string]()forcincards:l.add"A23456789TJQK"[cdiv4]&"CDHS"[cmod4]foriincountup(0,cards.high,8):echo" ",l[i..min(i+7,l.high)].join(" ")letseed=ifparamCount()==1:paramStr(1).parseIntelse:11982echo"Hand ",seedletdeck=dealseedshowdeck
Output:
Hand 11982 AH AS 4H AC 2D 6S TS JS 3D 3H QS QC 8S 7H AD KS KD 6H 5S 4D 9H JH 9S 3C JC 5D 5C 8C 9D TD KH 7C 6C 2C TH QH 6D TC 4S 7S JD 7D 8H 9C 2H QD 4C 5H KC 8D 2S 3S
class FreeCell { function : Main(args : String[]) ~ Nil { Deal(1)->PrintLine(); Deal(617)->PrintLine(); } function : Deal(seed : Int) ~ String { deck := Deck->New(seed)->ToString(); return "Game #{$seed}:\n{$deck}\n"; }}class Deck { @cards : Card[]; New(seed : Int) { r := Random->New(seed); @cards := Card->New[52]; for(i := 0; i < 52; i+= 1;) { @cards[i] := Card->New(51 - i); }; for(i := 0; i < 51; i += 1;) { j := 51 - r->Next() % (52 - i); tmp := @cards[i]; @cards[i] := @cards[j]; @cards[j] := tmp; }; } method : public : ToString() ~ String { buffer := ""; each(i : @cards) { buffer += @cards[i]->ToString(); buffer += (i % 8 = 7 ? "\n" : " "); }; return buffer; } }class Random { @seed : Int; New(seed : Int) { @seed := seed; } method : public : Next() ~ Int { @seed := (@seed * 214013 + 2531011) and Int->MaxSize(); return @seed >> 16; }}class Card { @value : Int; @suit : Int; New(value : Int) { @value := value / 4; @suit := value % 4; } method : public : ToString() ~ String { suits := "♣♦♥♠"; values := "A23456789TJQK"; value := values->Get(@value); suit := suits->Get(@suit); return "{$value}{$suit}"; }}Output:
Game #1:J♦ 2♦ 9♥ J♣ 5♦ 7♥ 7♣ 5♥K♦ K♣ 9♠ 5♠ A♦ Q♣ K♥ 3♥2♠ K♠ 9♦ Q♦ J♠ A♠ A♥ 3♣4♣ 5♣ T♠ Q♥ 4♥ A♣ 4♦ 7♠3♠ T♦ 4♠ T♥ 8♥ 2♣ J♥ 7♦6♦ 8♠ 8♦ Q♠ 6♣ 3♦ 8♣ T♣6♠ 9♣ 2♥ 6♥Game #617:7♦ A♦ 5♣ 3♠ 5♠ 8♣ 2♦ A♥T♦ 7♠ Q♦ A♣ 6♦ 8♥ A♠ K♥T♥ Q♣ 3♥ 9♦ 6♠ 8♦ 3♦ T♣K♦ 5♥ 9♠ 3♣ 8♠ 7♥ 4♦ J♠4♣ Q♠ 9♣ 9♥ 7♣ 6♥ 2♣ 2♠4♠ T♠ 2♥ 5♦ J♣ 6♣ J♥ Q♥J♦ K♠ K♣ 4♥
Based on the shorter C# version. Objective-C can use the C code as-is, but this example uses some NS foundation classes. Thelatest clang compiler is assumed withARC enabled. For the sake of clarity & simplicity, method prototypes have been omitted from @interface sections: they are not necessary if everything is in one file.
#define RMAX32 ((1U << 31) - 1)//--------------------------------------------------------------------@interfaceRand :NSObject-(instancetype)initWithSeed:(int)seed;-(int)next;@property(nonatomic)longseed;@end@implementationRand-(instancetype)initWithSeed:(int)seed{if((self=[superinit])){self.seed=seed;}returnself;}-(int)next{return(int)((_seed=(_seed*214013+2531011)&RMAX32)>>16);}@end//--------------------------------------------------------------------@interfaceCard :NSObject-(instancetype)initWithSequence:(int)n;-(instancetype)initWithValue:(int)vsuit:(int)s;@property(nonatomic)intvalue;@property(nonatomic)intsuit;@end@implementationCard-(instancetype)initWithSequence:(int)n{return[selfinitWithValue:n/4suit:n%4];}-(instancetype)initWithValue:(int)vsuit:(int)s{if((self=[superinit])){_value=v;_suit=s;}returnself;}-(NSString*)description{staticNSString*constkSuits=@"♣♦♥♠";staticNSString*constkValues=@"A23456789TJQK";return[NSStringstringWithFormat:@"%C%C",[kValuescharacterAtIndex:_value],[kSuitscharacterAtIndex:_suit]];}@end//--------------------------------------------------------------------@interfaceDeck :NSObject-(instancetype)initWithSeed:(int)seed;@property(nonatomic,strong)NSMutableArray*cards;@end@implementationDeck-(instancetype)initWithSeed:(int)seed{if((self=[superinit])){Rand*r=[[Randalloc]initWithSeed:seed];_cards=[NSMutableArrayarray];for(inti=0;i<52;i++)[_cardsaddObject:[[Cardalloc]initWithSequence:51-i]];for(inti=0;i<51;i++)[_cardsexchangeObjectAtIndex:iwithObjectAtIndex:51-[rnext]%(52-i)];}returnself;}-(NSString*)description{NSMutableString*s=[NSMutableStringstring];for(inti=0;i<[_cardscount];i++){[sappendString:[_cards[i]description]];[sappendString:i%8==7?@"\n":@" "];}returns;}@end//--------------------------------------------------------------------intmain(intargc,constchar*argv[]){@autoreleasepool{NSLog(@"Deck 1\n%@\n",[[Deckalloc]initWithSeed:1]);NSLog(@"Deck 617\n%@\n",[[Deckalloc]initWithSeed:617]);}return0;}
Deck 1J♦ 2♦ 9♥ J♣ 5♦ 7♥ 7♣ 5♥K♦ K♣ 9♠ 5♠ A♦ Q♣ K♥ 3♥2♠ K♠ 9♦ Q♦ J♠ A♠ A♥ 3♣4♣ 5♣ T♠ Q♥ 4♥ A♣ 4♦ 7♠3♠ T♦ 4♠ T♥ 8♥ 2♣ J♥ 7♦6♦ 8♠ 8♦ Q♠ 6♣ 3♦ 8♣ T♣6♠ 9♣ 2♥ 6♥ Deck 6177♦ A♦ 5♣ 3♠ 5♠ 8♣ 2♦ A♥T♦ 7♠ Q♦ A♣ 6♦ 8♥ A♠ K♥T♥ Q♣ 3♥ 9♦ 6♠ 8♦ 3♦ T♣K♦ 5♥ 9♠ 3♣ 8♠ 7♥ 4♦ J♠4♣ Q♠ 9♣ 9♥ 7♣ 6♥ 2♣ 2♠4♠ T♠ 2♥ 5♦ J♣ 6♣ J♥ Q♥J♦ K♠ K♣ 4♥
letsrndx=(* since OCaml's built-in int type is at least 31 (note: not 32) bits wide, and this problem takes mod 2^31, it is just enough if we treat it as an unsigned integer, which means taking the logical right shift *)letseed=refxinfun()->seed:=(!seed*214013+2531011)land0x7fffffff;!seedlsr16letdeals=letrnd=srndsinlett=Array.init52(funi->i)inletcards=Array.init52(funj->letn=52-jinleti=rnd()modninletthis=t.(i)int.(i)<-t.(predn);this)in(cards)letshowcards=letsuits="CDHS"andnums="A23456789TJQK"inArray.iteri(funicard->Printf.printf"%c%c%c"nums.[card/4]suits.[cardmod4](if(imod8)=7then'\n'else' '))cards;print_newline()let()=lets=tryint_of_stringSys.argv.(1)with_->11982inPrintf.printf"Deal %d:\n"s;letcards=dealsinshowcards
$ ocaml freecell.ml 617Deal 617:7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
The use oflocal is critical here, so thatnextrand() has access to the current state unaffected by whatever the user may have stored in the variable'state.
card(n)=concat(["A","2","3","4","5","6","7","8","9","T","J","Q","K"][n\4+1],["C","D","H","S"][n%4+1]);nextrand()={ (state=(214013*state+2531011)%2^31)>>16};deal(seed)={ my(deck=vector(52,n,n-1),t); local(state=seed); forstep(last=52,1,-1, t=nextrand()%last+1; print1(card(deck[t]),if(last%8==5,"\n"," ")); deck[t]=deck[last] )};#!/usr/bin/perlusestrict;usewarnings;useutf8;subdeal{my$s=shift;my$rnd=sub{return(($s=($s*214013+2531011)&0x7fffffff)>>16);};my@d;formy$b(split"","A23456789TJQK"){push@d,map("$_$b",qw/♣ ♦ ♥ ♠/);}formy$idx(reverse0..$#d){my$r=$rnd->()%($idx+1);@d[$r,$idx]=@d[$idx,$r];}return[reverse@d];}my$hand_idx=shift(@ARGV)//11_982;my$cards=deal($hand_idx);my$num_cards_in_height=8;my$string='';while(@$cards){$string.=join(' ',splice(@$cards,0,8))."\n";}binmodeSTDOUT,':encoding(utf-8)';print"Hand $hand_idx\n";print$string;
withjavascript_semanticsatomseedfunctionxrnd()seed=and_bits(seed*214013+2531011,#7FFFFFFF)returnfloor(seed/power(2,16))endfunctionsequencecards=repeat(0,52)proceduredeal(integergame_num)seed=game_numfori=1to52docards[i]=52-iendforfori=1to51dointegerj=52-mod(xrnd(),53-i)integers=cards[i]cards[i]=cards[j]cards[j]=sendforendprocedureconstantsuits="CDHS",ranks="A23456789TJQK"procedureshow()foridx=1to52dointegerrank=floor(cards[idx]/4)+1integersuit=mod(cards[idx],4)+1integereol=remainder(idx-1,13)=12printf(1,"%c%c%s",{ranks[rank],suits[suit],iff(eol?"\n":" ")})endforendprocedureintegergame_num=1--integer game_num=617deal(game_num)printf(1,"hand %d\n",{game_num})show()
hand 1JD 2D 9H JC 5D 7H 7C 5H KD KC 9S 5S ADQC KH 3H 2S KS 9D QD JS AS AH 3C 4C 5CTS QH 4H AC 4D 7S 3S TD 4S TH 8H 2C JH7D 6D 8S 8D QS 6C 3D 8C TC 6S 9C 2H 6Hhand 6177D AD 5C 3S 5S 8C 2D AH TD 7S QD AC 6D8H AS KH TH QC 3H 9D 6S 8D 3D TC KD 5H9S 3C 8S 7H 4D JS 4C QS 9C 9H 7C 6H 2C2S 4S TS 2H 5D JC 6C JH QH JD KS KC 4H
classFreeCell_Deal{protected$deck=array('AC','AD','AH','AS','2C','2D','2H','2S','3C','3D','3H','3S','4C','4D','4H','4S','5C','5D','5H','5S','6C','6D','6H','6S','7C','7D','7H','7S','8C','8D','8H','8S','9C','9D','9H','9S','TC','TD','TH','TS','JC','JD','JH','JS','QC','QD','QH','QS','KC','KD','KH','KS');protected$game;// Freecell Game Numberprotected$state;// Current state of the LCGpublic$deal=array();// Generated card sequence to dealfunction__construct($game){$this->game=max(min($game,32000),1);// seed RNG with game number$this->state=$this->game;while(!empty($this->deck)){// choose random card$i=$this->lcg_rnd()%count($this->deck);// move random card to game deal pile$this->deal[]=$this->deck[$i];// move last card to random card spot$this->deck[$i]=end($this->deck);// remove last card from deckarray_pop($this->deck);}}protectedfunctionlcg_rnd(){return($this->state=($this->state*214013+2531011)%2147483648)>>16;}functionprint($cols=8){echostr_pad(" Game ".$this->game." ",$cols*3-1,'=',STR_PAD_BOTH),PHP_EOL;foreach(array_chunk($this->deal,$cols)as$row){echoimplode(" ",$row),PHP_EOL;}echoPHP_EOL;}}$tests=array(1,617,11982);foreach($testsas$game_num){$deal=newFreeCell_Deal($game_num);$deal->print();}
======= Game 1 ========JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6H====== Game 617 =======7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H===== Game 11982 ======AH AS 4H AC 2D 6S TS JS3D 3H QS QC 8S 7H AD KSKD 6H 5S 4D 9H JH 9S 3CJC 5D 5C 8C 9D TD KH 7C6C 2C TH QH 6D TC 4S 7SJD 7D 8H 9C 2H QD 4C 5HKC 8D 2S 3S
Using the random generator fromLinear congruential generator#PicoLisp:
(setq *MsSeed 11982)(de msRand () (>> 16 (setq *MsSeed (& (+ 2531011 (* 214013 *MsSeed)) `(dec (** 2 31))) ) ) )(let L (make (for Num (range 13 1) (for Suit '((32 . "♠") (31 . "♥") (31 . "♦") (32 . "♣")) (link (cons (get '`(chop "A23456789TJQK") Num) Suit)) ) ) ) (for I 51 (xchg (nth L I) (nth L (- 52 (% (msRand) (- 53 I)))) ) ) (for C L (prin " ^[[" (cadr C) "m" (cddr C) "^[[m" (car C)) (at (0 . 8) (prinl)) ) (prinl) )
#MaxCardNum=51;zero-basedcountofcardsinadeckGlobaldeckSizeGlobalDimcards(#MaxCardNum);cardwithhighestindexisatthetopofdeckProcedureRNG(seed.q=-1)Staticstate.qIfseed>=0state=seedElsestate=(state*214013+2531011)%(1<<31)ProcedureReturnstate>>16EndIfEndProcedureProceduremakeDeck(hand)Protectedi,cFori=0To#MaxCardNum:cards(i)=i:NextRNG(hand);setseedvaluedeckSize=#MaxCardNumWhiledeckSizec=RNG()%(deckSize+1)Swapcards(c),cards(deckSize)deckSize-1WenddeckSize=#MaxCardNumEndProcedureProcedureshowDeck(hand)Protectedi,cPrintN("Hand #"+Str(hand))makeDeck(hand)Fori=0To#MaxCardNumc=cards(#MaxCardNum-i)Print(" "+Mid("A23456789TJQK",(c/4)+1,1)+Mid("CDHS",(c%4)+1,1))If(i+1)%8=0Ori=#MaxCardNum:PrintN(""):EndIfNextEndProcedureIfOpenConsole()showDeck(1)showDeck(617)showDeck(11982)Print(#CRLF$+#CRLF$+"Press ENTER to exit"):Input()CloseConsole()EndIf
Hand #1 JD 2D 9H JC 5D 7H 7C 5H KD KC 9S 5S AD QC KH 3H 2S KS 9D QD JS AS AH 3C 4C 5C TS QH 4H AC 4D 7S 3S TD 4S TH 8H 2C JH 7D 6D 8S 8D QS 6C 3D 8C TC 6S 9C 2H 6HHand #617 7D AD 5C 3S 5S 8C 2D AH TD 7S QD AC 6D 8H AS KH TH QC 3H 9D 6S 8D 3D TC KD 5H 9S 3C 8S 7H 4D JS 4C QS 9C 9H 7C 6H 2C 2S 4S TS 2H 5D JC 6C JH QH JD KS KC 4HHand #11982 AH AS 4H AC 2D 6S TS JS 3D 3H QS QC 8S 7H AD KS KD 6H 5S 4D 9H JH 9S 3C JC 5D 5C 8C 9D TD KH 7C 6C 2C TH QH 6D TC 4S 7S JD 7D 8H 9C 2H QD 4C 5H KC 8D 2S 3S
defrandomGenerator(seed=1):max_int32=(1<<31)-1seed=seed&max_int32whileTrue:seed=(seed*214013+2531011)&max_int32yieldseed>>16defdeal(seed):nc=52cards=list(range(nc-1,-1,-1))rnd=randomGenerator(seed)fori,rinzip(range(nc),rnd):j=(nc-1)-r%(nc-i)cards[i],cards[j]=cards[j],cards[i]returncardsdefshow(cards):l=["A23456789TJQK"[int(c/4)]+"CDHS"[c%4]forcincards]foriinrange(0,len(cards),8):print(" ".join(l[i:i+8]))if__name__=='__main__':fromsysimportargvseed=int(argv[1])iflen(argv)==2else11982print("Hand{}".format(seed))deck=deal(seed)show(deck)
Hand 11982AH AS 4H AC 2D 6S TS JS3D 3H QS QC 8S 7H AD KSKD 6H 5S 4D 9H JH 9S 3CJC 5D 5C 8C 9D TD KH 7C6C 2C TH QH 6D TC 4S 7SJD 7D 8H 9C 2H QD 4C 5HKC 8D 2S 3S
MCR-seed andMCR-rand are defined atLinear congruential generator#Quackery.
[ [ [] 52 times [ i^ join ] ] constant ] is newpack ( --> n ) [ 2dup peek dip [ over -1 peek ] swap 2swap poke -1 poke ] is to-end ( [ n --> [ ) [ [] swap 52 times [ MCR-rand over size mod to-end -1 split swap dip join ] drop ] is mixem ( [ --> [ ) [ 4 /mod $ "A23456789TJQK" rot peek emit $ "CDHS" swap peek emit ] is echocard ( n --> ) [ witheach [ echocard i^ 8 mod 7 = iff cr else sp ] ] is echopack ( [ --> ) [ MCR-seed replace newpack mixem echopack ] is deal ( n --> ) ' [ 1 617 11982 ] witheach [ say "Deal #" dup echo cr deal cr cr ]
Deal #1JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6H Deal #6177D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H Deal #11982AH AS 4H AC 2D 6S TS JS3D 3H QS QC 8S 7H AD KSKD 6H 5S 4D 9H JH 9S 3CJC 5D 5C 8C 9D TD KH 7C6C 2C TH QH 6D TC 4S 7SJD 7D 8H 9C 2H QD 4C 5HKC 8D 2S 3S
## Linear congruential generator code not original -## copied from## http://www.rosettacode.org/wiki/Linear_congruential_generator#R## altered to allow seed as an argumentlibrary(gmp)# for big integersrand_MS<-function(n=1,seed=1){a<-as.bigz(214013)c<-as.bigz(2531011)m<-as.bigz(2^31)x<-rep(as.bigz(0),n)x[1]<-(a*as.bigz(seed)+c)%%mi<-1while(i<n){x[i+1]<-(a*x[i]+c)%%mi<-i+1}as.integer(x/2^16)}## =============================## New code follows:## =============================dealFreeCell<-function(seedNum){deck<-paste(rep(c("A",2,3,4,5,6,7,8,9,10,"J","Q","K"),each=4),c("C","D","H","S"),sep="")cards=rand_MS(52,seedNum)for(iin52:1){cardToPick<-(cards[53-i]%%i)+1# R indexes from 1, not 0deck[c(cardToPick,i)]<-deck[c(i,cardToPick)]}deck<-rev(deck)# flip the deck to dealdeal=matrix(c(deck,NA,NA,NA,NA),ncol=8,byrow=TRUE)# using a matrix for simple printing, but requires filling with NA# if implementing as a game, a list for each pile would make more senseprint(paste("Hand numer:",seedNum),quote=FALSE)print(deal,quote=FALSE,na.print="")}
> dealFreeCell(1)[1] Hand numer: 1 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8][1,] JD 2D 9H JC 5D 7H 7C 5H [2,] KD KC 9S 5S AD QC KH 3H [3,] 2S KS 9D QD JS AS AH 3C [4,] 4C 5C 10S QH 4H AC 4D 7S [5,] 3S 10D 4S 10H 8H 2C JH 7D [6,] 6D 8S 8D QS 6C 3D 8C 10C [7,] 6S 9C 2H 6H > dealFreeCell(617)[1] Hand numer: 617 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8][1,] 7D AD 5C 3S 5S 8C 2D AH [2,] 10D 7S QD AC 6D 8H AS KH [3,] 10H QC 3H 9D 6S 8D 3D 10C [4,] KD 5H 9S 3C 8S 7H 4D JS [5,] 4C QS 9C 9H 7C 6H 2C 2S [6,] 4S 10S 2H 5D JC 6C JH QH [7,] JD KS KC 4H
#langracket(moduleLinear_congruential_generatorracket;; taken from http://rosettacode.org/wiki/Linear_congruential_generator#Racket;; w/o BSD generator(requireracket/generator)(providems-rand)(define(ms-updatestate_n)(modulo(+(*214013state_n)2531011)(expt231)))(define((randupdate->rand)seed)(generator()(letloop([state_nseed])(definestate_n+1(updatestate_n))(yield(->randstate_n+1))(loopstate_n+1))))(definems-rand(randms-update(lambda(x)(quotientx(expt216))))))(require(submod"."Linear_congruential_generator));; Personally I prefer CDHS to the unicode characters (on an aesthetic basis,;; rather than anything else. Plus it helps match with the examples given at the;; head of the task.(definesuits"CDHS")(define(initial-deck)(for*/vector#:length52((face"A23456789TJQK")(suitsuits))(consfacesuit)));; srfi/43 has one of these, but is quick enough to reimplement!(define(vector-swap!vij)(let((t(vector-refvi)))(vector-set!vi(vector-refvj))(vector-set!vjt)))(define(dealhand)(definepack(initial-deck))(definernd(ms-randhand))(define(deal-nth-cardpack-szcard-nodeal)(vector-swap!packcard-no(sub1pack-sz))(cons(vector-refpack(sub1pack-sz))deal))(letinner-deal((pack-sz(vector-lengthpack))(dealnull))(if(zero?pack-sz)(reversedeal);; we accumulated this backwards!(inner-deal(sub1pack-sz)(deal-nth-cardpack-sz(modulo(rnd)pack-sz)deal)))))(define(present-dealhand)(printf"Game #~a~%"hand)(letinner-present-deal((pile0)(deck(dealhand)))(unless(null?deck)(printf"~a~a~a"(caardeck)(cdardeck)(if(or(null?(cdrdeck))(=7(modulopile8)))"\n"" "))(inner-present-deal(add1pile)(cdrdeck)))));; Run it so we get some output:(present-deal1)(newline)(present-deal617)
Game #1JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6HGame #6177D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
(formerly Perl 6)
subdealgame ($game-number =1) {subms-lcg-method($seed =$game-number) { (214013 *$seed +2531011 ) %2**31 }# lazy list of the random sequencemy@ms-lcg = |(&ms-lcg-method ... *).map: * +>16;constantCardBlock ='🂠'.ord;my@deck =gatherforflat(1..11,13,14)X+ (48,32...0) ->$off {takechrCardBlock +$off; }my@game =gatherwhile@deck {@deck[@ms-lcg.shift %@deck,@deck-1] .=reverse;take@deck.pop; }say"Game #$game-number";say@game.splice(0,8min +@game)while@game;}dealgame;dealgame617;
Game #1🃋 🃂 🂹 🃛 🃅 🂷 🃗 🂵🃎 🃞 🂩 🂥 🃁 🃝 🂾 🂳🂢 🂮 🃉 🃍 🂫 🂡 🂱 🃓🃔 🃕 🂪 🂽 🂴 🃑 🃄 🂧🂣 🃊 🂤 🂺 🂸 🃒 🂻 🃇🃆 🂨 🃈 🂭 🃖 🃃 🃘 🃚🂦 🃙 🂲 🂶Game #617🃇 🃁 🃕 🂣 🂥 🃘 🃂 🂱🃊 🂧 🃍 🃑 🃆 🂸 🂡 🂾🂺 🃝 🂳 🃉 🂦 🃈 🃃 🃚🃎 🂵 🂩 🃓 🂨 🂷 🃄 🂫🃔 🂭 🃙 🂹 🃗 🂶 🃒 🂢🂤 🂪 🂲 🃅 🃛 🃖 🂻 🂽🃋 🂮 🃞 🂴
This REXX version supports EBCDIC and ASCII symbols (used for the cards).
It also supports any number for the number of columns (default is 8).
See the discussion page for support for game = ─1 and game= ─2 (minus one and minus two).
/*REXX program deals cards for a specific FreeCell solitaire card game (0 ──► 32767).*/numericdigits15/*ensure enough digits for the random #*/parsearggamecols./*obtain optional arguments from the CL*/ifgame==''|game==","thengame=1/*No game specified? Then use default.*/ifcols==''|cols==","thencols=8/* " cols " " " " */state=game/*seed random # generator with game num*/if8=='f8'xthensuit="cdhs"/*EBCDIC? Then use letters for suits.*/elsesuit="♣♦♥♠"/* ASCII? " " symbols " " */rank='A23456789tJQK'/*t in the rank represents a ten (10).*/pad=left('',13)/*used for indentation for the tableau.*/saycenter('tableau for FreeCell game'game,50,"─")/*show title for FreeCell game #*/say/* [↓] @ is an array of all 52 cards.*/#=-1;dor=1forlength(rank)/*build the deck first by the rank. */dos=1forlength(suit);#=#+1/* " " " secondly " " suit. */@.#=substr(rank,r,1)substr(suit,s,1)/*build the $ array one card at at time*/end/*s*//* [↑] first card is number 0 (zero).*/end/*r*//* [↑] build deck per FreeCell rules. */$=pad/*@: cards to be dealt, eight at a time*/docards=51by-1for52/* [↓] deal the cards for the tableau.*/?=rand()//(cards+1)/*get next rand#; card # is remainder.*/$=$@.?;@.?=@.cards/*swap two cards: use random and last.*/ifwords($)==colsthendo;say$;$=pad/*deal FreeCell cards for the tableau. */endend/*cards*//*normally, 8 cards are dealt to a row.*//* [↓] residual cards may exist. */if$\=''thensay$/*Any residual cards in the tableau ? */exit/*stick a fork in it, we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/rand:state=(214013*state+2531011)//2**31;returnstate%2**16/*FreeCell rand#*/
output when using the default game number: 1
───────────tableau for FreeCell game 1──────────── J♦ 2♦ 9♥ J♣ 5♦ 7♥ 7♣ 5♥ K♦ K♣ 9♠ 5♠ A♦ Q♣ K♥ 3♥ 2♠ K♠ 9♦ Q♦ J♠ A♠ A♥ 3♣ 4♣ 5♣ t♠ Q♥ 4♥ A♣ 4♦ 7♠ 3♠ t♦ 4♠ t♥ 8♥ 2♣ J♥ 7♦ 6♦ 8♠ 8♦ Q♠ 6♣ 3♦ 8♣ t♣ 6♠ 9♣ 2♥ 6♥
output when using the game number: 617
──────────tableau for FreeCell game 617─────────── 7♦ A♦ 5♣ 3♠ 5♠ 8♣ 2♦ A♥ t♦ 7♠ Q♦ A♣ 6♦ 8♥ A♠ K♥ t♥ Q♣ 3♥ 9♦ 6♠ 8♦ 3♦ t♣ K♦ 5♥ 9♠ 3♣ 8♠ 7♥ 4♦ J♠ 4♣ Q♠ 9♣ 9♥ 7♣ 6♥ 2♣ 2♠ 4♠ t♠ 2♥ 5♦ J♣ 6♣ J♥ Q♥ J♦ K♠ K♣ 4♥
« R→B { } 1 13FOR v "A23456789TJQK" v DUP SUB 1 4FOR c SWAP OVER "CDHS" c DUP SUB + + SWAPNEXT DROPNEXT 52 2FOR j DUP j GET SWAP ROT 214013 * 2531011 + # 7FFFFFFFh AND DUP 4 ROLLD SRB SRB B→R j MOD 1 + GET LASTARG 4 ROLL PUT j ROT PUT -1STEP REVLIST SWAP DROP» 'DEAL' STO@ ( game → { "card" .. "card" } )1DEAL617DEAL
2: { "JD" "2D" "9H" "JC" "5D" "7H" "7C" "5H" "KD" "KC" "9S" "5S" "AD" "QC" "KH" "3H" "2S" "KS" "9D" "QD" "JS" "AS" "AH" "3C" "4C" "5C" "TS" "QH" "4H" "AC" "4D" "7S" "3S" "TD" "4S" "TH" "8H" "2C" "JH" "7D" "6D" "8S" "8D" "QS" "6C" "3D" "8C" "TC" "6S" "9C" "2H" "6H" }1: { "7D" "AD" "5C" "3S" "5S" "8C" "2D" "AH" "TD" "7S" "QD" "AC" "6D" "8H" "AS" "KH" "TH" "QC" "3H" "9D" "6S" "8D" "3D" "TC" "KD" "5H" "9S" "3C" "8S" "7H" "4D" "JS" "4C" "QS" "9C" "9H" "7C" "6H" "2C" "2S" "4S" "TS" "2H" "5D" "JC" "6C" "JH" "QH" "JD" "KS" "KC" "4H" }RPL output device is limited to 22 characters per line, which prevents to display the deck as required.
# games = ARGV converted to Integer# No arguments? Pick any of first 32000 games.begingames=ARGV.map{|s|Integer(s)}rescue=>err$stderr.putserr.inspect$stderr.puts"Usage:#{__FILE__} number..."abortendgames.empty?andgames=[rand(32000)]# Create original deck of 52 cards, not yet shuffled.orig_deck=%w{A 2 3 4 5 6 7 8 9 T J Q K}.product(%w{C D H S}).map(&:join)games.eachdo|seed|deck=orig_deck.dup# Shuffle deck with random index from linear congruential# generator like Microsoft.state=seed52.downto(2)do|len|state=((214013*state)+2531011)&0x7fff_ffffindex=(state>>16)%lenlast=len-1deck[index],deck[last]=deck[last],deck[index]enddeck.reverse!# Shuffle did reverse deck. Do reverse again.# Deal cards.puts"Game ##{seed}"deck.each_slice(8){|row|puts" "+row.join(" ")}putsend
$ ruby freecell.rb 1 165 Game #1 JD 2D 9H JC 5D 7H 7C 5H KD KC 9S 5S AD QC KH 3H 2S KS 9D QD JS AS AH 3C 4C 5C TS QH 4H AC 4D 7S 3S TD 4S TH 8H 2C JH 7D 6D 8S 8D QS 6C 3D 8C TC 6S 9C 2H 6HGame #165 2D 2C 2H 5D 3C 6S JC 7S 7H QD 6D KC 3D 9H 8H QC TS 5H JD 7D 6H 7C KH 4D QS 8S QH 9S 8D 3H JS AH AD KS TC KD 9D 4S 2S 3S TH 4C 9C 6C TD 4H 8C AC 5C 5S JH AS
projectDir$= "a_project" ' project directoryimageDir$ = DefaultDir$ + "\projects\" + projectDir$ + "\image\" ' directory of deck imagesimagePath$= "../";projectDir$;"/image/" ' path of deck imagessuite$ = "C,D,H,S" ' Club,Diamond,Heart,Spadescard$ = "A,2,3,4,5,6,7,8,9,T,J,Q,K" ' Cards Ace to Kingdim n(55) ' make ordered deck for i = 1 to 52 ' of 52 cards n(i) = inext ifor i = 1 to 52 * 3 ' shuffle deck 3 times i1 = int(rnd(1)*52) + 1 i2 = int(rnd(1)*52) + 1 h2 = n(i1) n(i1) = n(i2) n(i2) = h2next ifor yy = 1 to 8 ' display 7 across and 8 down for xx = 1 to 7 card = card + 1 s = (n(card) mod 4) + 1 ' determine suite c = (n(card) mod 13) + 1 ' determine card cardId$ = word$(card$,c,",");word$(suite$,s,",");".gif" html "<div style='position: relative; left:";(xx -1) * 80;"px; top:";(yy -1) * 20;"px; height:0px; width:0px;>" html "<div style='width:100px; height:100px; border:solid 0px #000;'>" html "<img src=";imagePath$;cardId$;" width=70px >" html "</div></div>" if card = 52 then end ' out of cards next xxnext yy
Based on JavaScript.
// Code available at https://rosettacode.org/wiki/Linear_congruential_generator#Rustexterncratelinear_congruential_generator;uselinear_congruential_generator::{MsLcg,Rng,SeedableRng};// We can't use `rand::Rng::shuffle` because it uses the more uniform `rand::Rng::gen_range`// (`% range` is subject to modulo bias). If an exact match of the old dealer is not needed,// `rand::Rng::shuffle` should be used.fnshuffle<T>(rng:&mutMsLcg,deck:&mut[T]){letlen=deck.len()asu32;foriin(1..len).rev(){letj=rng.next_u32()%(i+1);deck.swap(iasusize,jasusize);}}fngen_deck()->Vec<String>{constRANKS:[char;13]=['A','2','3','4','5','6','7','8','9','T','J','Q','K'];constSUITS:[char;4]=['C','D','H','S'];letrender_card=|card:usize|{let(suit,rank)=(card%4,card/4);format!("{}{}",RANKS[rank],SUITS[suit])};(0..52).map(render_card).collect()}fndeal_ms_fc_board(seed:u32)->Vec<String>{letmutrng=MsLcg::from_seed(seed);letmutdeck=gen_deck();shuffle(&mutrng,&mutdeck);deck.reverse();deck.chunks(8).map(|row|row.join(" ")).collect::<Vec<_>>()}fnmain(){letseed=std::env::args().nth(1).and_then(|n|n.parse().ok()).expect("A 32-bit seed is required");forrowindeal_ms_fc_board(seed){println!(": {}",row);}}
objectShufflerextendsApp{privatevalsuits=Array("C","D","H","S")privatevalvalues=Array("A","2","3","4","5","6","7","8","9","T","J","Q","K")privatevaldeck=values.flatMap(v=>suits.map(s=>s"$v$s"))privatevarseed:Int=_privatedefrandom()={seed=(214013*seed+2531011)&Integer.MAX_VALUEseed>>16}privatedefgetShuffledDeck={vald=deck.map(c=>c)for(i<-deck.length-1until0by-1){valr=random()%(i+1)valcard=d(r)d(r)=d(i)d(i)=card}d.reverse}defdeal(seed:Int):Unit={this.seed=seedgetShuffledDeck.grouped(8).foreach(e=>println(e.mkString(" ")))}deal(1)printlndeal(617)}
JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6H
7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
$ include "seed7_05.s7i"; include "console.s7i";const string: suits is "♣♦♥♠";const string: nums is "A23456789TJQK";var integer: randomSeed is 1;const func integer: random is func result var integer: rand is 1; begin randomSeed := (randomSeed * 214013 + 2531011) mod 2 ** 31; rand := randomSeed >> 16; end func;const proc: show (in array integer: cards) is func local var integer: index is 0; begin for index range 1 to 52 do write(" " <& suits[succ(cards[index] rem 4)] <& nums[succ(cards[index] div 4)]); if index rem 8 = 0 or index = 52 then writeln; end if; end for; end func;const func array integer: deal (in integer: gameNum) is func result var array integer: cards is 52 times 0; local var integer: i is 0; var integer: j is 0; var integer: s is 0; begin randomSeed := gameNum; for i range 1 to 52 do cards[i] := 52 - i; end for; for i range 1 to 51 do j := 52 - random mod (53 - i); s := cards[i]; cards[i] := cards[j]; cards[j] := s; end for; end func;const proc: main is func local var integer: gameNum is 11982; var array integer: cards is 0 times 0; begin OUT := STD_CONSOLE; if length(argv(PROGRAM)) >= 1 then block gameNum := integer parse (argv(PROGRAM)[1]); exception catch RANGE_ERROR: noop; end block; end if; cards := deal(gameNum); writeln("Hand " <& gameNum); show(cards); end func;Hand 1 ♦J ♦2 ♥9 ♣J ♦5 ♥7 ♣7 ♥5 ♦K ♣K ♠9 ♠5 ♦A ♣Q ♥K ♥3 ♠2 ♠K ♦9 ♦Q ♠J ♠A ♥A ♣3 ♣4 ♣5 ♠T ♥Q ♥4 ♣A ♦4 ♠7 ♠3 ♦T ♠4 ♥T ♥8 ♣2 ♥J ♦7 ♦6 ♠8 ♦8 ♠Q ♣6 ♦3 ♣8 ♣T ♠6 ♣9 ♥2 ♥6
Hand 617 ♦7 ♦A ♣5 ♠3 ♠5 ♣8 ♦2 ♥A ♦T ♠7 ♦Q ♣A ♦6 ♥8 ♠A ♥K ♥T ♣Q ♥3 ♦9 ♠6 ♦8 ♦3 ♣T ♦K ♥5 ♠9 ♣3 ♠8 ♥7 ♦4 ♠J ♣4 ♠Q ♣9 ♥9 ♣7 ♥6 ♣2 ♠2 ♠4 ♠T ♥2 ♦5 ♣J ♣6 ♥J ♥Q ♦J ♠K ♣K ♥4
Swift 4.2. Largely based on the Objective-C example.
enumSuit:String,CustomStringConvertible,CaseIterable{caseclubs="C",diamonds="D",hearts="H",spades="S"vardescription:String{returnself.rawValue}}enumRank:Int,CustomStringConvertible,CaseIterable{caseace=1,two,three,four,five,six,sevencaseeight,nine,ten,jack,queen,kingvardescription:String{letd:[Rank:String]=[.ace:"A",.king:"K",.queen:"Q",.jack:"J",.ten:"T"]returnd[self]??String(self.rawValue)}}structCard:CustomStringConvertible{letrank:Rank,suit:Suitvardescription:String{returnString(describing:self.rank)+String(describing:self.suit)}init(rank:Rank,suit:Suit){self.rank=rank;self.suit=suit}init(sequencen:Int){self.init(rank:Rank.allCases[n/4],suit:Suit.allCases[n%4])}}structDeck:CustomStringConvertible{varcards=[Card]()init(seed:Int){foriin(0..<52).reversed(){self.cards.append(Card(sequence:i))}structMicrosoftLinearCongruentialGenerator{varseed:Intmutatingfuncnext()->Int{self.seed=(self.seed*214013+2531011)%(Int(Int32.max)+1)returnself.seed>>16}}varr=MicrosoftLinearCongruentialGenerator(seed:seed)foriin0..<51{self.cards.swapAt(i,51-r.next()%(52-i))}}vardescription:String{vars=""for(ix,c)inself.cards.enumerated(){s.write(String(describing:c))s.write(ix%8==7?"\n":" ")}returns}}letd1=Deck(seed:1)print(d1)letd617=Deck(seed:617)print(d617)
JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6H
7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
procrnd{{*rseed}}{upvar1${*r}rexpr{[setr[expr{($r*214013+2531011)&0x7fffffff}]]>>16}}procshowcards{setsuits{\u2663\u2666\u2665\u2660}setvalues{A23456789TJQK}for{seti0}{$i<52}{incri}{setc[lindex$cards$i]puts-nonewline[format" \033\[%dm%s\033\[m%s"[expr{32-(1+$c)%4/2}]\[lindex$suits[expr{$c%4}]][lindex$values[expr{$c/4}]]]if{($i&7)==7||$i==51}{puts""}}}procdeal{seed}{for{seti0}{$i<52}{incri}{lappendcards[expr{51-$i}]}for{seti0}{$i<51}{incri}{setj[expr{51-[rnd]%(52-$i)}]settmp[lindex$cards$i]lsetcards$i[lindex$cards$j]lsetcards$j$tmp}return$cards}if{![scan=[lindex$argv0]==%d=s]||$s<=0}{sets11982}setcards[deal$s]puts"Hand $s"show$cards
/* TypeScript code for dealing Microsoft FreeCell / FreeCell Pro deals. * Copyright by Shlomi Fish, 2011. * Released under the MIT/Expat License * ( http://en.wikipedia.org/wiki/MIT_License ). */functionperl_range(start:number,end:number):number[]{constret:number[]=[];for(leti=start;i<=end;++i){ret.push(i);}returnret;}// 33 bitconstMAX_SEED:bigint=(BigInt(1)<<BigInt(31+2))-BigInt(1);constX=BigInt(1)<<BigInt(32);/* * Microsoft C Run-time-Library-compatible Random Number Generator * */classMSRand{privategamenumber:string;private_seed:bigint;private_seedx:bigint;constructor(args){constthat=this;that.gamenumber=args.gamenumber;const_seed=BigInt(that.gamenumber);that._seed=_seed;that._seedx=_seed<X?_seed:_seed-X;return;}publicgetSeed():bigint{constthat=this;returnthat._seed;}privatesetSeed(seed:bigint):void{constthat=this;that._seed=seed;return;}private_rando():bigint{constthat=this;that._seedx=(that._seedx*BigInt(214013)+BigInt(2531011))&MAX_SEED;return(that._seedx>>BigInt(16))&BigInt(0x7fff);}private_randp():bigint{constthat=this;that._seedx=(that._seedx*BigInt(214013)+BigInt(2531011))&MAX_SEED;return(that._seedx>>BigInt(16))&BigInt(0xffff);}publicraw_rand():bigint{constthat=this;if(that._seed<X){constret=that._rando();returnthat._seed<BigInt(0x8)<<BigInt(28)?ret:ret|BigInt(0x8000);}else{returnthat._randp()+BigInt(1);}}publicmax_rand(mymax:bigint):bigint{constthat=this;returnthat.raw_rand()%mymax;}publicshuffle(deck:Array<any>):Array<any>{constthat=this;if(deck.length){leti=deck.length;while(--i){constj=Number(that.max_rand(BigInt(i+1)));consttmp=deck[i];deck[i]=deck[j];deck[j]=tmp;}}returndeck;}}/* * Microsoft Windows Freecell / Freecell Pro boards generation. * * See: * * - http://rosettacode.org/wiki/Deal_cards_for_FreeCell * * - http://www.solitairelaboratory.com/mshuffle.txt * * Under MIT/Expat Licence. * * */exportfunctiondeal_ms_fc_board(gamenumber:string):string{constrandomizer=newMSRand({gamenumber:gamenumber,});constnum_cols:number=8;constcolumns:Array<Array<number>>=perl_range(0,num_cols-1).map(()=>{return[];},);letdeck:Array<number>=perl_range(0,4*13-1);randomizer.shuffle(deck);deck=deck.reverse();for(leti=0;i<52;++i){columns[i%num_cols].push(deck[i]);}functionrender_card(card:number):String{constsuit=card%4;constrank=Math.floor(card/4);return"A23456789TJQK".charAt(rank)+"CDHS".charAt(suit);}functionrender_column(col:Array<number>):String{return": "+col.map(render_card).join(" ")+"\n";}returncolumns.map(render_column).join("");}
test$#-gt0||set--$((RANDOM%32000))forseed;doprintGame$seed:# Shuffle deck.deck=({A,{2..9},T,J,Q,K}{C,D,H,S})foriin{52..1};do((seed=(214013*seed+2531011)&0x7fffffff))((j=(seed>>16)%i+1))t=$deck[$i]deck[$i]=$deck[$j]deck[$j]=$tdone# Deal cards.print-n' 'foriin{52..1};doprint-n' '$deck[$i]((i%8==5))&&print-n$'\n 'doneprintdone
$ zsh freecell.sh 80388Game 80388: QC 5H AS 7H 8S 4S 4H 3H QD 3S 2C 2S 7D AH 6D 3D QS TH QH 3C 2H JS 5D 5C AD TD 6H JD 5S 7S 4D 7C 9S KC TC KH 8C 9D 8D JH KS AC KD 9C 9H 6C JC 2D 4C 8H TS 6S
OptionExplicitPrivatestateMSAsVariantPrivateFunctionms()AsIntegerDimtemp1AsVariant,temp2AsVariant,temp3AsVarianttemp1=CDec(214013*stateMS+2531011)temp2=temp1/2^31temp3=CDec(WorksheetFunction.Floor_Precise(temp2))stateMS=temp1-(2^31)*temp3ms=stateMS\2^16EndFunctionPublicSubmain()DimiAsInteger,jAsInteger,kAsInteger,sAsInteger,vAsInteger,noAsIntegerDimtmpArr(0To51)AsIntegerDimsuitAsString,valueAsString,rowAsStringDimgameNumbersAsVariantsuit="CDHS"value="A23456789TJQK"gameNumbers=Array(1,617)Fori=0ToUBound(gameNumbers)stateMS=CDec(gameNumbers(i))Forj=0To51tmpArr(j)=jNextjForj=51To0Step-1no=msMod(j+1)CallchangePosition(tmpArr(),j,no)NextjDebug.Print"Game "&gameNumbers(i)&":"k=0DoWhilek<52Forj=0To7s=1+tmpArr(51-k)Mod4v=1+tmpArr(51-k)\4row=row&Mid(value,v,1)&Mid(suit,s,1)&IIf(j<7andk<51," ","")k=k+1Ifk>51ThenExitForNextjDebug.Printrowrow=""LoopDebug.PrintNextiEndSubPrivateSubchangePosition(ByRefarr()AsInteger,pos1AsInteger,pos2AsInteger)DimtempPosAsStringtempPos=arr(pos1)arr(pos1)=arr(pos2)arr(pos2)=tempPosEndSub
Game 1:JD 2D 9H JC 5D 7H 7C 5HKD KC 9S 5S AD QC KH 3H2S KS 9D QD JS AS AH 3C4C 5C TS QH 4H AC 4D 7S3S TD 4S TH 8H 2C JH 7D6D 8S 8D QS 6C 3D 8C TC6S 9C 2H 6HGame 617:7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
classLcg{constructnew(a,c,m,d,s){_a=a_c=c_m=m_d=d_s=s}nextInt(){_s=(_a*_s+_c)%_mreturn_s/_d}}varCARDS="A23456789TJQK"varSUITS="♣♦♥♠".toListvardeal=Fn.new{varcards=List.filled(52,null)for(iin0...52){varcard=CARDS[(i/4).floor]varsuit=SUITS[i%4]cards[i]=card+suit}returncards}vargame=Fn.new{|n|if(n.type!=Num||!n.isInteger||n<=0){Fiber.abort("Game number must be a positive integer.")}System.print("Game #%(n):")varmsc=Lcg.new(214013,2531011,1<<31,1<<16,n)varcards=deal.call()for(min52..1){varindex=(msc.nextInt()%m).floorvartemp=cards[index]cards[index]=cards[m-1]System.write("%(temp) ")if((53-m)%8==0)System.print()}System.print("\n")}game.call(1)game.call(617)
Game #1:J♦ 2♦ 9♥ J♣ 5♦ 7♥ 7♣ 5♥ K♦ K♣ 9♠ 5♠ A♦ Q♣ K♥ 3♥ 2♠ K♠ 9♦ Q♦ J♠ A♠ A♥ 3♣ 4♣ 5♣ T♠ Q♥ 4♥ A♣ 4♦ 7♠ 3♠ T♦ 4♠ T♥ 8♥ 2♣ J♥ 7♦ 6♦ 8♠ 8♦ Q♠ 6♣ 3♦ 8♣ T♣ 6♠ 9♣ 2♥ 6♥ Game #617:7♦ A♦ 5♣ 3♠ 5♠ 8♣ 2♦ A♥ T♦ 7♠ Q♦ A♣ 6♦ 8♥ A♠ K♥ T♥ Q♣ 3♥ 9♦ 6♠ 8♦ 3♦ T♣ K♦ 5♥ 9♠ 3♣ 8♠ 7♥ 4♦ J♠ 4♣ Q♠ 9♣ 9♥ 7♣ 6♥ 2♣ 2♠ 4♠ T♠ 2♥ 5♦ J♣ 6♣ J♥ Q♥ J♦ K♠ K♣ 4♥
include c:\cxpl\codes; \intrinsic 'code' declarationsstring 0; \use zero-terminated string conventionint RandState;func Rand; \Random number in range 0 to 32767[RandState:= (214013*RandState + 2531011) & $7FFF_FFFF;return RandState >> 16;];int Card, Deck(52), Size;char Suit, Rank;[RandState:= IntIn(8); \seed RNG with number from command linefor Card:= 0 to 52-1 do Deck(Card):= Card; \create array of 52 cardsRank:= "A23456789TJQK";Suit:= "CDHS";Size:= 52;repeat Card:= rem(Rand/Size); \choose a random card ChOut(0, Rank(Deck(Card)/4)); \deal it by showing it ChOut(0, Suit(rem(0))); if rem(Size/8)=5 then CrLf(0) else ChOut(0, ^ ); Size:= Size-1; \one less card in deck Deck(Card):= Deck(Size); \replace dealt card with last carduntil Size = 0; \all cards have been dealt]
Output:
7D AD 5C 3S 5S 8C 2D AHTD 7S QD AC 6D 8H AS KHTH QC 3H 9D 6S 8D 3D TCKD 5H 9S 3C 8S 7H 4D JS4C QS 9C 9H 7C 6H 2C 2S4S TS 2H 5D JC 6C JH QHJD KS KC 4H
conststd=@import("std");constCard=struct{value:u6=0,pubfnprint(card:Card)void{constn:u8=switch(card.value>>2){0=>'A',1=>'2',2=>'3',3=>'4',4=>'5',5=>'6',6=>'7',7=>'8',8=>'9',9=>'T',10=>'J',11=>'Q',12=>'K',else=>unreachable,};consts:u21=switch(card.value&0x3){0=>'\u{2663}',// Club1=>'\u{2666}',// Diamond2=>'\u{2665}',// Heart3=>'\u{2660}',// Spadeelse=>unreachable,};std.debug.print("{c}{u} ",.{n,s});}};constRand=struct{seed:u31=0,pubfnseed(rand:*Rand,value:u31)void{rand.seed=value;}pubfnnext(rand:*Rand)u16{constnew_seed=rand.seed*%214013+%2531011;rand.seed=new_seed;return@truncate(new_seed>>16);}};pubfndeal(n:u31)void{constprint=std.debug.print;varbuffer:[52]u8=undefined;varfba=std.heap.FixedBufferAllocator.init(&buffer);constallocator=fba.allocator();vardeck=std.ArrayListUnmanaged(Card).initCapacity(allocator,52)catchunreachable;varcard:Card=.{};while(card.value<52):(card.value+=1){deck.appendAssumeCapacity(card);}varcol:usize=0;varrand=Rand{.seed=n};print("Deal {d}:\n",.{n});while(deck.items.len>0){card=deck.swapRemove(rand.next()%deck.items.len);card.print();col=(col+1)%8;if(col==0)print("\n",.{});}print("\n\n",.{});}pubfnmain()!void{deal(1);deal(617);}
Deal 1:J♦ 2♦ 9♥ J♣ 5♦ 7♥ 7♣ 5♥K♦ K♣ 9♠ 5♠ A♦ Q♣ K♥ 3♥2♠ K♠ 9♦ Q♦ J♠ A♠ A♥ 3♣4♣ 5♣ T♠ Q♥ 4♥ A♣ 4♦ 7♠3♠ T♦ 4♠ T♥ 8♥ 2♣ J♥ 7♦6♦ 8♠ 8♦ Q♠ 6♣ 3♦ 8♣ T♣6♠ 9♣ 2♥ 6♥Deal 617:7♦ A♦ 5♣ 3♠ 5♠ 8♣ 2♦ A♥T♦ 7♠ Q♦ A♣ 6♦ 8♥ A♠ K♥T♥ Q♣ 3♥ 9♦ 6♠ 8♦ 3♦ T♣K♦ 5♥ 9♠ 3♣ 8♠ 7♥ 4♦ J♠4♣ Q♠ 9♣ 9♥ 7♣ 6♥ 2♣ 2♠4♠ T♠ 2♥ 5♦ J♣ 6♣ J♥ Q♥J♦ K♠ K♣ 4♥
var suits=T(0x1F0D1,0x1F0C1,0x1F0B1,0x1F0A1); //unicode 🃑,🃁,🂱,🂡var seed=1; const RMAX32=(1).shiftLeft(31) - 1;fcn rnd{ (seed=((seed*214013 + 2531011).bitAnd(RMAX32))).shiftRight(16) }fcn game(n){ seed=n; deck:=(0).pump(52,List,'wrap(n){ if(n>=44) n+=4; // I want JQK, not JCQ (suits[n%4] + n/4).toString(8) }).copy(); // int-->UTF-8 [52..1,-1].pump(Void,'wrap(len){ deck.swap(len-1,rnd()%len); }); deck.reverse(); println("Game #",n); foreach n in ([0..51,8]){ deck[n,8].concat(" ").println(); }}game(1);game(617);Game #1🃋 🃂 🂹 🃛 🃅 🂷 🃗 🂵🃎 🃞 🂩 🂥 🃁 🃝 🂾 🂳🂢 🂮 🃉 🃍 🂫 🂡 🂱 🃓🃔 🃕 🂪 🂽 🂴 🃑 🃄 🂧🂣 🃊 🂤 🂺 🂸 🃒 🂻 🃇🃆 🂨 🃈 🂭 🃖 🃃 🃘 🃚🂦 🃙 🂲 🂶Game #617🃇 🃁 🃕 🂣 🂥 🃘 🃂 🂱🃊 🂧 🃍 🃑 🃆 🂸 🂡 🂾🂺 🃝 🂳 🃉 🂦 🃈 🃃 🃚🃎 🂵 🂩 🃓 🂨 🂷 🃄 🂫🃔 🂭 🃙 🂹 🃗 🂶 🃒 🂢🂤 🂪 🂲 🃅 🃛 🃖 🂻 🂽🃋 🂮 🃞 🂴