It's been years since I've played blackjack, so I had to read up on the rules.
I agree with @mkeintz regarding why you were skipping cards, but think that the way you were dealing cards was correct.
The following runs correctly, but I haven't tested it for either efficiency, completeness, or correctness. I modified your code to allow how many decks of cards would be included in any run, as well as how many players there would be, and how many hands would be dealt.
I played around with how to handle aces, set rules for whether any player or the dealer would take a hit, incorporated decision making based on dealer's facecard, and shortened the game if a dealer got a blackjack. I didn't expand on the code to allow for splitting or doubling down, or when to reshuffle the card deck.
%macro deal(games=3,decks=6,players=3);
/* create deck */
data cards (drop=decks face suit);
length card $5 face $2;
do decks=1 to &decks.;
do suit = "C", "D", "H", "S";
do c2= 1 to 13;
if c2 eq 1 then value = 11;
else if c2 in (11, 12, 13) then value = 10;
else value = c2;
if c2 = 11 then face = "J";
else if c2 = 12 then face = "Q";
else if c2 = 13 then face = "K";
else if c2 = 1 then face = "A";
else face=put(c2,2.);
card=cats(face,"-",suit);
output;
end;
end;
end;
run;
/* shuffle deck */
proc sql noprint;
create table shuffled as
select * from cards
order by rand("uniform")
;
quit;
data deal (drop=_: card c2 value stop_value total);
/* last hand is dealers hand */
array hands(&players.,11) _temporary_ ;
array values(&players.,11) _temporary_ ;
array cardsdealt(&players.,11) $ _temporary_;
array hand(&players.) $24.;
retain stop_value hand;
/* deal one card to each player until all players have 2 cards */
do _g=1 to &games.;
call missing(of hands{*});
call missing(of values{*});
call missing(of cardsdealt{*});
_c=0;
_done=0;
do _p=1 to (2*&players.);
if _c lt (&players*2) then do;
set shuffled;
_c+1;
if _c le &players. then do;
hands{&players.-mod(_c,&players),1} = c2;
values{&players.-mod(_c,&players),1} = value;
cardsdealt{&players.-mod(_c,&players),1} = card;
end;
else do;
hands{&players.-mod(_c,&players),2} = c2;
values{&players.-mod(_c,&players),2} = value;
cardsdealt{&players.-mod(_c,&players),2} = card;
end;
end; /* if _c lt (&players*2) then do */
end; /* do _p=1 to (2*&players.) */
/* Check to see if dealer has blackjack and, if not, deal rest of cards*/
if sum(of values{&players,1},
values{&players,2}) ne 21 then do;
/* if necessary deal rest of cards for all players */
do _p=1 to &players.;
/* check dealers face card to set stop_value */
if _p eq &players. then do;
if sum(values{&players.,1},values{&players.,2}) eq 17 and
values{&players.,1} in (6,11) then stop_value=18;
else stop_value=17;
end;
else do;
select (values{&players.,1});
when (in (4,5,6)) stop_value=12;
when (in (2,3)) stop_value=13;
otherwise stop_value=17;
end;
end;
_c=2;
do until (total ge stop_value);
total=sum(of values{_p,1},
values{_p,2},
values{_p,3},
values{_p,4},
values{_p,5},
values{_p,6},
values{_p,7},
values{_p,8},
values{_p,9},
values{_p,10},
values{_p,11});
if total gt 21 then do;
do _t=1 to 11;
if values{_p,_t} eq 11 then values{_p,_t}=1;
end;
total=sum(of values{_p,1},
values{_p,2},
values{_p,3},
values{_p,4},
values{_p,5},
values{_p,6},
values{_p,7},
values{_p,8},
values{_p,9},
values{_p,10},
values{_p,11});
end; /* if total gt 21 then do; */
if total lt stop_value then do;
set shuffled;
_c+1;
hands{_p,_c} = c2;
values{_p,_c} = value;
cardsdealt{_p,_c} = card;
total=sum(of values{_p,1},
values{_p,2},
values{_p,3},
values{_p,4},
values{_p,5},
values{_p,6},
values{_p,7},
values{_p,8},
values{_p,9},
values{_p,10},
values{_p,11});
if total gt 21 and value eq 11 then do;
values{_p,_c} = 1;
total=sum(of values{_p,1},
values{_p,2},
values{_p,3},
values{_p,4},
values{_p,5},
values{_p,6},
values{_p,7},
values{_p,8},
values{_p,9},
values{_p,10},
values{_p,11});
end; /* if total gt 21 and value eq 11 then do */
if stop_value eq 18 then stop_value=17;
end; /* if total lt stop_value then do */
end; /* do until (total ge stop_value) */
end; /* do _p=1 to &players.; */
end; /* if not sum(of values{&players,1},
values{&players,2}) eq 21 then do */
call missing(of hand{*});
do _p=1 to &players.;
do _d=1 to dim(hand);
if not missing(cardsdealt{_p,_d}) then
hand{_p}=catx(',',hand{_p},cardsdealt{_p,_d});
end; /* _d=1 to dim(hand) */
end; /* do _p=1 to &players. */
output;
if _g eq &games. then stop;
end; /* do _g=1 to &games. */
run;
%mend deal;
%deal;
Art, CEO, AnalystFinder.com
... View more