Code covered by the BSD License  

Highlights from
Best Cribbage Hand

from Best Cribbage Hand by Brandon Armstrong
This function finds the best possible hold cards for a given cribbage hand.

cribbagehand( handstr, iscrib )
function [ handstats ] = cribbagehand( handstr, iscrib )

%The function takes a six card hand you are delt and determines the
%average, low, and high score you can receive after pegging for all
%combinations of plays. It prints out your hands in order from high to low,
%and returns additional statistics for all possible plays in the structure 
%handstats. When returning statistics, the function takes into effect 
%whether or not the crib is yours and how many points the crib can get based on the cards
%you give it and the turnover card.

% An example input would be:

% hand = 'As Ad 2d 4h 5c 10c';

% handstats = cribbagehand(hand, 1); if it is your crib, enter 0 instead of
% 1 if it is not your crib


%   hand is a string where the cards are entered as mystr = 'As 9c 10d Jc
%   8h 7d'

%   iscrib should be 1 if it is your crib and 0 if it is your oppontnets
%   crib. Enter any other number if you don't care about the crib.

%   handstats has the following fields you can explore for all 15 possible
%   plays. 

%   handstats.c1, .c2, .c3, .c4 are the hold cards. 

%   handstats.bestTO are the turnover cards that will give you the maximum
%   possible points for the given hold cards.

%   handstats.avg, .low, .high, and .median are the average, lowest, highest,
%   and median score for the given hold cards. 

%   handstats.ProbAvgOrBetter is probability that you will score higher
%   than the average points

%   handstats.ProbHigh is the probability of getting the maximum possible
%   points for the given hold cards.

deck = {'As', 'Ac', 'Ad', 'Ah', '2s', '2c', '2d', '2h', '3s', '3c', '3d',...
    '3h', '4s', '4c', '4d', '4h', '5s', '5c', '5d', '5h', '6s', '6c',...
    '6d', '6h', '7s', '7c', '7d', '7h', '8s', '8c', '8d', '8h', '9s',...
    '9c', '9d', '9h', '10s', '10c', '10d', '10h', 'Js', 'Jc', 'Jd',...
    'Jh', 'Qs', 'Qc', 'Qd', 'Qh', 'Ks', 'Kc', 'Kd', 'Kh'};

spaces = find(handstr == ' ');

hand = cell(1,6);

hand(1) = {handstr(1:spaces(1)-1)};
hand(2) = {handstr(spaces(1)+1:spaces(2)-1)};
hand(3) = {handstr(spaces(2)+1:spaces(3)-1)};
hand(4) = {handstr(spaces(3)+1:spaces(4)-1)};
hand(5) = {handstr(spaces(4)+1:spaces(5)-1)};
hand(6) = {handstr(spaces(5)+1:end)};
    

%The remaining cards in the deck (rdeck)

rdeck = deck;
indexes = zeros(1,6);

for m = 1:6
    indexes(m) = find(strcmp(deck, hand(m)));
end

rdeck(indexes) = [];

%make a matrix of the different possible hands and our cell of stats for
%each one

phands = nchoosek(hand, 4);
tempcell = cell(15,11);
tempcell(1:15,1:4) = phands;
rowheadings = {'c1', 'c2', 'c3', 'c4', 'bestTO' 'avg', 'low', 'high', 'median', 'ProbAvgOrBetter', 'ProbHigh'};
handstats = cell2struct(tempcell, rowheadings, 2);


%% Start putting together and counting points for each possible hand

for m = 1:15
    
    %Reset the points to zero and get the vectors for counting and runs.
    %Do the switch for the first 4 cards before going into all possible
    %hands so we only do it once for each of the 15 combinations
    
    temphand = phands(m,:);
    points = zeros(1,46);
    vec4runs = zeros(1,5);
    vec15s = zeros(1,5);
    isjack = 0;
    
    
    for k = 1:4
        card = phands{m,k};
        switch card(1)
            case 'A'
                vec4runs(k) = 1;
                vec15s(k) = 1;
        
            case '2'
                vec4runs(k) = 2;
                vec15s(k) = 2;
                
            case '3'
                vec4runs(k) = 3;
                vec15s(k) = 3;
                
            case '4'
                vec4runs(k) = 4;
                vec15s(k) = 4;
                
            case '5'
                vec4runs(k) = 5;
                vec15s(k) = 5;
                
            case '6'
                vec4runs(k) = 6;
                vec15s(k) = 6;
                
            case '7'
                vec4runs(k) = 7;
                vec15s(k) = 7;
                
            case '8'
                vec4runs(k) = 8;
                vec15s(k) = 8;
                 
            case '9' 
                vec4runs(k) = 9;
                vec15s(k) = 9;
            
            case '1'
                vec4runs(k) = 10;
                vec15s(k) = 10;
                
            case 'J'
                vec4runs(k) = 11;
                vec15s(k) = 10;
                isjack = 1;
                
            case 'Q'
                vec4runs(k) = 12;
                vec15s(k) = 10;
                
            case 'K'
                vec4runs(k) = 13;
                vec15s(k) = 10;
                
        end
    
    end
    
    crib = hand;
    cribindex = zeros(1,4);
    crib15s = zeros(1,3);
    cribruns = zeros(1,3);
    
    %Get the crib
    
    for k = 1:4
        
        cribindex(k) = find(strcmp(hand, temphand(k)));
    end
    
    crib(cribindex) = [];
    cribjack = 0;
    
    for k = 1:2
        card = crib{k};
        switch card(1)
            case 'A'
                cribruns(k) = 1;
                crib15s(k) = 1;
        
            case '2'
                cribruns(k) = 2;
                crib15s(k) = 2;
                
            case '3'
                cribruns(k) = 3;
                crib15s(k) = 3;
                
            case '4'
                cribruns(k) = 4;
                crib15s(k) = 4;
                
            case '5'
                cribruns(k) = 5;
                crib15s(k) = 5;
                
            case '6'
                cribruns(k) = 6;
                crib15s(k) = 6;
                
            case '7'
                cribruns(k) = 7;
                crib15s(k) = 7;
                
            case '8'
                cribruns(k) = 8;
                crib15s(k) = 8;
                 
            case '9' 
                cribruns(k) = 9;
                crib15s(k) = 9;
            
            case '1'
                cribruns(k) = 10;
                crib15s(k) = 10;
                
            case 'J'
                cribruns(k) = 11;
                crib15s(k) = 10;
                cribjack = 1;
                
            case 'Q'
                cribruns(k) = 12;
                crib15s(k) = 10;
                
            case 'K'
                cribruns(k) = 13;
                crib15s(k) = 10;
                
        end
    
    end
    
    %Now get the first possible turnover card, finish the crib and start
    %counting points.
    
    for n = 1:46
     
    
    temphand(5) = rdeck(n);
    card = rdeck{n};
    pntscnt = 0;
    cribpnts = 0;
    
    switch card(1)
            case 'A'
                vec4runs(5) = 1;
                vec15s(5) = 1;
                cribruns(3) = 1;
                crib15s(3) = 1;
        
            case '2'
                vec4runs(5) = 2;
                vec15s(5) = 2;
                cribruns(3) = 2;
                crib15s(3) = 2;                
                
            case '3'
                vec4runs(5) = 3;
                vec15s(5) = 3;
                cribruns(3) = 3;
                crib15s(3) = 3;                
                
            case '4'
                vec4runs(5) = 4;
                vec15s(5) = 4;
                cribruns(3) = 4;
                crib15s(3) = 4;                
                
            case '5'
                vec4runs(5) = 5;
                vec15s(5) = 5;
                cribruns(3) = 5;
                crib15s(3) = 5;                
                
            case '6'
                vec4runs(5) = 6;
                vec15s(5) = 6;
                cribruns(3) = 6;
                crib15s(3) = 6;                
                
            case '7'
                vec4runs(5) = 7;
                vec15s(5) = 7;
                cribruns(3) = 7;
                crib15s(3) = 7;                
                
            case '8'
                vec4runs(5) = 8;
                vec15s(5) = 8;
                cribruns(3) = 8;
                crib15s(3) = 8;                
                 
            case '9' 
                vec4runs(5) = 9;
                vec15s(5) = 9;
                cribruns(3) = 9;
                crib15s(3) = 9;                
            
            case '1'
                vec4runs(5) = 10;
                vec15s(5) = 10;
                cribruns(3) = 10;
                crib15s(3) = 10;                
                
            case 'J'
                vec4runs(5) = 11;
                vec15s(5) = 10;
                cribruns(3) = 11;
                crib15s(3) = 10;               
                
            case 'Q'
                vec4runs(5) = 12;
                vec15s(5) = 10;
                cribruns(3) = 12;
                crib15s(3) = 10;                
                
            case 'K'
                vec4runs(5) = 13;
                vec15s(5) = 10;
                cribruns(3) = 13;
                crib15s(3) = 10;                
                
    end    %end switch
    
    
    %% Time to start counting points! First, look at the Jack suit if there
    %is one.
    
    if isjack
         for k = 1:4
             if strcmp(temphand{k}(1),'J')
                 if strcmp(card(end), temphand{k}(2))
                        pntscnt = pntscnt + 1;
                 end
             end
         end
    end   %end searching for Jack
        
    %% Now check for a flush
    
       if strcmp(temphand{1}(end),temphand{2}(end)) && strcmp(temphand{1}(end), ...
            temphand{3}(end)) && strcmp(temphand{1}(end), temphand{4}(end))
        
        pntscnt = pntscnt + 4;
        
         if strcmp(temphand{1}(end),temphand{5}(end))
            
            pntscnt = pntscnt + 1;
            
         end
        
       end  % end checking for flush
       
     %% Get 15s
     
     if 15 <= sum(vec15s)
         
         if isequal(sum(vec15s), 15)
             pntscnt = pntscnt + 2;
         
         else
             twos = nchoosek(vec15s, 2)';
             twostotal = sum(twos);
             twos15 = find(twostotal == 15);
             pntscnt = pntscnt + length(twos15)*2;
             
             threes = nchoosek(vec15s, 3)';
             threestotal = sum(threes);
             threes15 = find(threestotal == 15);
             pntscnt = pntscnt + length(threes15)*2;
             
             fours = nchoosek(vec15s, 4)';
             fourstotal = sum(fours);
             fours15 = find(fourstotal == 15);
             pntscnt = pntscnt + length(fours15)*2;
                 
         end
         
     end   %end summing 15s
     
     %% Get the vector to start looking for runs and pairs
     
     sortedhand = sort(vec4runs);
     pairsorruns = diff(sortedhand);
     
     %Look for pairs
     
     if length(find(pairsorruns == 0)) >= 1
         
         pairs = nchoosek(temphand, 2);
         
         for p = 1:length(pairs(:,1))
             
             if strcmp(pairs{p,1}(1), pairs{p,2}(1))
                 
                 pntscnt = pntscnt + 2;
                 
             end
         end
         
     end   %end looking for pairs
     
     %% Look for runs
         
     num1s = find(pairsorruns == 1);
     num0s = find(pairsorruns == 0);
     
     if length(num1s) >= 2
         
         numrunsof4 = 0;
         numrunsof3 = 0;
         
         if all(pairsorruns == 1)
             
             pntscnt = pntscnt + 5;
             
             
         elseif isequal(length(num1s), 3)
             
             runsof4 = nchoosek(sortedhand, 4)';
             isrunof4 = diff(runsof4);
             
             for p = 1:length(isrunof4(1,:))
                 
                 if all(isrunof4(:,p) == 1)
                     
                     numrunsof4 = numrunsof4 + 1;
                     
                 end
                 
             end
             
             if numrunsof4 ~= 0
                 
                 pntscnt = pntscnt + 4*numrunsof4;
                 
             else 
                 
                 pntscnt = pntscnt + 3;
                 
             end
             
         elseif isequal(length(num1s), 2)
             
             runsof3 = nchoosek(sortedhand, 3)';
             isrunof3 = diff(runsof3);
             
             for p = 1: length(isrunof3(1,:))
                 
                 if all(isrunof3(:,p) == 1)
                     
                     numrunsof3 = numrunsof3 + 1;
                     
                 end
                 
             end
                 
             pntscnt = pntscnt + 3*numrunsof3;
             
         end %end counting points of runs.    
             
         
     end  %end for length(num1s) >= 2
     
    %% Done counting the main hand! Time to count the crib!
     
    if cribjack
         for k = 1:2
             if strcmp(crib{k}(1),'J')
                 if strcmp(card(end), crib{k}(2))
                        cribpnts = cribpnts + 1;
                 end
             end
         end
    end   %end searching for Jack
    
     if 15 <= sum(crib15s)
         
         if isequal(sum(crib15s), 15)
             
             cribpnts = 2;
             
         else
             cribtwos = nchoosek(crib15s, 2)';
             cribtwostotal = sum(cribtwos);
             cribtwos15 = find(cribtwostotal == 15);
             cribpnts = cribpnts + length(cribtwos15)*2;
             
         end
         
     end  %end looking for 15s in the crib
     
    % Find pairs and runs in the crib
    
     sortedcrib = sort(cribruns);
     cribrunsorpairs = diff(sortedcrib);
     
     if all(cribrunsorpairs == 0)
         
         cribpnts = cribpnts + 6;
         
     elseif all(cribrunsorpairs == 1)
         
         cribpnts = cribpnts + 3;
         
     elseif isequal(length(find(cribrunsorpairs == 0)), 1)
         
         cribpnts = cribpnts + 2;
         
     end
     
    % Done counting up all points. Add or subtract the crib from the main
    % hand and put into the 1 x 46 matrix points at position n. If is crib
    % is anything other than 1 or 0, the crib is not counted. Use that
    % option for last hand when you don't care about the crib
    
     if isequal(iscrib, 1)
        
        points(n) = pntscnt + cribpnts;
        
     elseif isequal(iscrib, 0)
        
        points(n) = pntscnt - cribpnts;
        
     else
         
        points(n) = pntscnt;
        
     end
         
    end  %end for 46 count
    
   %% Now let's put together the statistics for the hand before moving 
   % to the next one
   
   bestposition = find(points == max(points));
   bestTOcards = rdeck(bestposition);
   
   handstats(m).bestTO = bestTOcards;
   handstats(m).avg = mean(points);
   handstats(m).low = min(points);
   handstats(m).high = max(points);
   handstats(m).median = median(points);
   handstats(m).ProbHigh = length(bestTOcards)/46;
   
   avgorbetter = find(points >= mean(points));
   handstats(m).ProbAvgOrBetter = length(avgorbetter)/46;
   
   
end   %end for 15 hand count



%% Sort Handstats in order of best average hands


[~, order] = sort([handstats(:).avg]);
handstats = handstats(fliplr(order));


% Will use the highest possible hand as the first tie breaker

ties = find([handstats.avg] == max([handstats.avg]));



if length(ties) > 1
    
    temphandstats = handstats(1:length(ties));
    
    [~, tieindex] = sort([temphandstats(1:length(ties)).high], 'descend');
        
    temphandstats = temphandstats(tieindex);
    
    handstats(1:length(ties)) = temphandstats;
    
end


fprintf('\n\n  Hand Rank         AVG   High  Low  Median  Max%%  >AVG%%\n') 

for m = 1:9
    fprintf('%g) %s %s %s %s     %.2f   %g    %g     %g    %.2f   %.2f\n',...
        m, handstats(m).c1, handstats(m).c2, handstats(m).c3, handstats(m).c4,...
        handstats(m).avg, handstats(m).high, handstats(m).low,...
        handstats(m).median, handstats(m).ProbHigh, handstats(m).ProbAvgOrBetter)
    
end

for m = 10:15
    fprintf('%g)%s %s %s %s     %.2f   %g    %g     %g    %.2f   %.2f\n',...
        m, handstats(m).c1, handstats(m).c2, handstats(m).c3, handstats(m).c4,...
        handstats(m).avg, handstats(m).high, handstats(m).low,...
        handstats(m).median, handstats(m).ProbHigh, handstats(m).ProbAvgOrBetter)
    
end

fprintf('\n\n')

% fprintf('\nYour best possible hand is %s %s %s %s with the following stats:\n'...
%     ,handstats(1).c1,handstats(1).c2, handstats(1).c3, handstats(1).c4)
% fprintf('AVG = %.2f; Low = %.2f; Max = %.2f; Median = %.2f\n',...
%     handstats(1).avg, handstats(1).low, handstats(1).high, handstats(1).median)
% fprintf('Probability of high = %.2f; Probability of beating AVG = %.2f \n',...
%     handstats(1).ProbHigh, handstats(1).ProbAvgOrBetter)
% 
% fprintf('\nYour 2nd best hand is %s %s %s %s with the following stats:\n'...
%     ,handstats(2).c1,handstats(2).c2, handstats(2).c3, handstats(2).c4)
% fprintf('AVG = %.2f; Low = %.2f; Max = %.2f; Median = %.2f\n',...
%     handstats(2).avg, handstats(2).low, handstats(2).high, handstats(2).median)
% fprintf('Probability of high = %.2f; Probability of beating AVG = %.2f\n',...
%     handstats(2).ProbHigh, handstats(2).ProbAvgOrBetter)
% 
% fprintf('\nYour 3rd best hand is %s %s %s %s with the following stats:\n'...
%     ,handstats(3).c1,handstats(3).c2, handstats(3).c3, handstats(3).c4)
% fprintf('AVG = %.2f; Low = %.2f; Max = %.2f; Median = %.2f\n',...
%     handstats(3).avg, handstats(3).low, handstats(3).high, handstats(3).median)
% fprintf('Probability of high = %.2f; Probability of beating AVG = %.2f\n\n',...
%     handstats(3).ProbHigh, handstats(3).ProbAvgOrBetter)




end

Contact us