this is for MATLAB . thanks ! The main function Blackjack_LastNames.m should ask
ID: 3838195 • Letter: T
Question
this is for MATLAB . thanks !
The main function Blackjack_LastNames.m should ask the user how many chips to play with (default: 100). This is the function that will actually run the program. The program will need to deal cards to each player (yourself and the computer), pause to let the user see the cards. Inside the function, you may want subfunctions that converts a numeric card to a nicely formatted string that the user can understand and can score the hand to determine the winner.
The player should begin the game with a set number of chips and the dealer has an infinite supply of chips. During each round, the player specific tan arbitrary number of chips to bet. All bets are made in whole number of chips. The program should allow the user to double down and/or split.
At every round, the objective of the player is to make the sum of the cards in his/her hand as close to 21 as possible without exceeding 21 (exceeding 21 is a bust)
Cards 2-10 are worth face value. The face cards (Jack, Queen, King) are worth 10 pints. The program should ask the user to decide the value to use for an ACE which can be either 1 point or 11 points.
At every round, the player and dealer are both dealt two cards each. The player is allowed see one of the dealer’s card. The player can choose to either hit (receive one more card) or stay. The may hit repeatedly until they have 5 cards, at which point they must stay. The dealer hits automatically until the dealer’s hand is 17 or higher (or until a bust).
The order of play is important. If a player bust, he/she loses, since the player played first. If the player does not bust but the dealer does, then the player wins. If the player has blackjack and the dealer does not, then the player wins back his/her bet plus 150% of the bet. If the dealer also has blackjack, then it is a tie. If the dealer has blackjack but the player does not the user loses his/her bet.
The program should keep track of the statistic of play, as well as the chip count. Plot the statistics of the game.Also predict the probability of the user winning. The game is over when the user specifies or when the user has no more chips.
The program should be robust to input. If the user specifies an invalid action or invalid chip amount the program should display a warning and ask for an input again.
User defined functions required:
newcard=DrawCard()
this function returns the value of a card drawn from the deck.
ShowCard(card)
This function will display the value of a given card on the screen
Show Hand (hand)
Explanation / Answer
% This is the main process of the game.
% Create figure as our background
handles.hFig = figure('DockControls', 'off', ...
'MenuBar', 'none', ...
'Name', 'BlackJack', ...
'NumberTitle', 'off', ...
'Units', 'pixels', ...
'OuterPosition', [283, 84, 800, 600], ...
'Resize', 'off', ...
'WindowKeyPressFcn', @WindowKeyFcn);
% The first step is creating a welcome screen, let player choose how
% many chips he/she wants to take, and click the 'Start' button.
startChips = StartUI(handles);
% Create the player, dealer and the table
handles.player = ClassPlayer(startChips);
handles.dealer = ClassDealer;
handles.table = ClassTable;
clear startChips
% Shuffle the deck before game starts
handles.table.Shuffle(3);
handles.table.Shuffle(3);
handles.table.GameStatus = 'StartGame';
% Create a new UI
% Do almost everything in it
MainUI(handles);
% End the game
fields = {'table', 'player', 'dealer'};
handles = rmfield(handles, fields);
EndUI(handles);
clear handles
------------------------------------------------------------------------------------
classdef ClassCard
% Class of Cards
properties
% Cards have only two properties, suit and number
suit = '';
number = '';
end% of properties
methods
function card = ClassCard( suit, number )
colors = {'', 'heart', 'spade', 'diamond', 'club'};
ranks = {'', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'};
if (any(ismember(colors, suit)) && any(ismember(ranks, number)))
card.suit = suit;
card.number = number;
else
display('Wrong suit or number');
% Return an empty card as status
card.suit = '';
card.number = '';
end
end% of function
function Logi = EmptyCard(card)
Logi = isempty(card) || (isempty(card.suit) && isempty(card.number));
end% of function
function Logi = eq(card1, card2)
if (card1.suit == card2.suit) && (card1.number == card2.number)
Logi = true;
else
Logi = false;
end
end% of function
end% of methods
methods (Static)
function card = CreateCardSlot()
% Named constructor, used to create an empty card
card = ClassCard('', '');
end
end% of static methods
end% of classdef
--------------------------------------------------------------------------------------------
classdef ClassDealer < ClassPlayer
% class of dealer, inherited from ClassPlayer, because dealer is a special player
properties
%Chips = Inf;
% Chips initialized as infinite
end% of properties
% No special properties
methods
function dealer = ClassDealer
% Constructor of dealer, just construct a player with infinite chips
dealer = dealer@ClassPlayer(2^20-1);
end
end% of methods
end% of classdef
---------------------------------------------------
classdef ClassPlayer < handle
% class of player, a handle class
properties
% Chips initialized when game starts
Chips = 0;
% 5 cards in total, use default initialization: blank str
CardsInHand = repmat(ClassCard.CreateCardSlot, 1, 5);
% Optimal points stored in A, minimum points stored in B
% Player can use button to change AcesAs10
CurrentPointA = 0;
CurrentPointB = 0;
AcesAs10 = 0;
% Point updated after every card dealt
end% of properties
methods
function player = ClassPlayer( Chips )
% player initialization, only initialize chips
player.Chips = Chips;
end% of function
function Status = ChangeChip(player, amount)
% Get chips or bet (use) chips, prevent from negative chips
% Round the amount to integer for robustness
amount = round(amount);
% Add or minus chips with amount
player.Chips = player.Chips + amount;
if player.Chips < 0
% Use returned value to indicate status
Status = -1;
% And prevent negative values at the same time
player.Chips = player.Chips - amount;
elseif player.Chips == 0
% Status 0 indicate "all in"
Status = 0;
else
Status = 1;
end
end% of function
function Status = GetCard(player, card)
% Deal the player a card when hand is not full, card is a ClassCard object as an input
% Status 0 means error, other integers means the position of the dealt card
% Use a flag to indicate hand full, default not full
flag = true;
iter = 1;
while ~(player.CardsInHand(iter).EmptyCard)
iter = iter + 1;
end
if iter >= 6
% iter reaches 6 and no empty slot found, means hand full
disp('get card denied: full hand')
flag = false;
Status = 0;
end
% flag true means hand not full
if flag
player.CardsInHand(iter) = card;
Status = iter;
end
% Update current point every time a card is dealt (even if denied)
player.UpdatePoint;
end% of function
function card = ReturnCard(player)
% Delete the last card from player, return the card (to deck)
if player.EmptyHand
% In the case of empty hand, returns an empty card, use the empty return as a status
card = ClassCard.CreateCardSlot;
else
iter = 5;
while player.CardsInHand(iter).EmptyCard;
iter = iter - 1;
end
% Because hand is not empty, CardsInHand(iter) must correspond to a card in hand
% Give the card to returned value, clear the card in player's hand
card = player.CardsInHand(iter);
player.CardsInHand(iter) = ClassCard.CreateCardSlot;
end
end% of function
function Logi = EmptyHand(player)
% Returns a Logical value indicating if player has no cards
Logi = true;
% Use 'and' to make Logi false any time a card is found
for iter = 1:5
Logi = Logi && player.CardsInHand(iter).EmptyCard;
end
end% of function
function Logi = FullHand(player)
% Returns a Logical value indicating if player has five cards
Logi = true;
% Use 'and' to make Logi false any time an empty slot is found
for iter = 1:5
Logi = Logi && ~(player.CardsInHand(iter).EmptyCard);
end
end% of function
function Logi = BlackJack(player)
% Test if a player has Black Jack
if player.EmptyHand
Logi = false;
else
count = 0;
for iter = 1:5
if ~player.CardsInHand(iter).EmptyCard
count = count + 1;
end
end
if (count == 2) && player.CurrentPointA == 21;
Logi = true;
else
Logi = false;
end
end
end% of function
function Status = UpdatePoint(player, varargin)
% Use current information to calculate current point A
% CurrentPointB saves the minimum possible points
% If any other input is specified, change AcesAs10
if nargin < 2
% Update optimal points, minimum points and AcesAs10
if player.EmptyHand;
% Directly, prevent numberInHand becomes []
player.CurrentPointA = 0;
player.CurrentPointB = 0;
player.AcesAs10 = 0;
Status = 0;
else
% Get all the numbers of cards in hand to make a 'string'
numberInHand = [player.CardsInHand.number];
point = 0;
aces = 0;
for k = numberInHand
% numberInHand should be a string, and k goes through every character
switch k
case 'A'
aces = aces + 1;
point = point + 1;
case {'K', 'Q', 'J'}
point = point + 10;
case '1'% means 10
point = point + 10;
case {'2', '3', '4', '5', '6', '7', '8', '9', '0'}
point = point + str2double(k);
otherwise
disp('Unexpected number in hand')
end
end
% Now we have points without aces and number of aces
player.CurrentPointB = point;
for iter = 0:aces
temppoint = point + iter * 10;
if temppoint > 11
break;
end
end
% No matter how much aces we have, here we get the optimal points
player.CurrentPointA = point + iter * 10;
% And CurrentPointA should equal to CurrentPointB + AcesAs10 * 10
player.AcesAs10 = iter;
Status = 0;
end
else
% Update AcesAs10 only with a new mode
if player.EmptyHand;
% Directly, prevent numberInHand becomes []
player.CurrentPointA = 0;
player.CurrentPointB = 0;
player.AcesAs10 = 0;
Status = 1;
else
% Get all the numbers of cards in hand to make a 'string'
numberInHand = [player.CardsInHand.number];
aces = 0;
for k = numberInHand
% numberInHand should be a string, and k goes through every character
if k == 'A'
aces = aces + 1;
end
% Just get number of A's
end
% Now we have number of aces
if player.AcesAs10 < aces
player.AcesAs10 = player.AcesAs10 + 1;
else
player.AcesAs10 = 0;
end
end
end
end% of function
end% of public methods
%methods (Access = private)
%end% of private methods
%methods (Static)
%function point = totalPoint(numberInHand, mode)
% Totalling points with different modes of counting A
%point = 0;
%aces = 0;
%for k = numberInHand
% numberInHand should be a string, and k goes through every character
%switch k
%case 'A'
%aces = aces + 1;
%point = point + 1;
%case {'K', 'Q', 'J', '10'}
%point = point + 10;
%case {'2', '3', '4', '5', '6', '7', '8', '9'}
%point = point + str2double(k);
%otherwise
%disp('Unexpected number in hand')
%end
%end
% Now we have points without aces and number of aces
%for iter = 0:aces
%temppoint = point + iter * 10;
%if temppoint > 21
%break;
%end
%end
%end% of function
%end% of static methods
end% of classdef
------------------------------------------------------------------
classdef ClassTable < handle
% Class of table, a handle class (in order to manipulate the decks and chips)
properties
% Undealt cards in NewDeck
NewDeck = repmat(ClassCard.CreateCardSlot, 1, 52);
% Discarded cards in DiscardDeck
DiscardDeck = repmat(ClassCard.CreateCardSlot, 1, 52);
% Already bet chips in TableChip
TableChip = 0;
% A special variable who records the current status of game
GameStatus = '';
end% of properties
methods
function table = ClassTable
% Constructor, no input, no output, just create the NewDeck
colors = {'heart', 'spade', 'diamond', 'club'};
ranks = {'A'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9'; '10'; 'J'; 'Q'; 'K'};
suitValues = repmat(colors, 13, 1);
numberValues = repmat(ranks, 1, 4);
suitValues = suitValues(:);
numberValues = numberValues(:);
for iter = 1:52
table.NewDeck(iter) = ClassCard(suitValues{iter}, numberValues{iter});
end
% Create only the NewDeck. At this time, DiscardDeck and TableChip should be the same as the default initializer
end% of function
function card = DrawOne(table, varargin)
% Draw one card from NewDeck. if any other input is specified, draw one card from DiscardDeck
if nargin < 2
iter = 1;
while (iter <= 52) && (table.NewDeck(iter).EmptyCard)
iter = iter + 1;
end
% After while loop, NewDeck(iter) is the first non-empty card in NewDeck, unless iter is 53
if iter <= 52
% Return the card
card = table.NewDeck(iter);
% And delete the drawn card from deck
table.NewDeck(iter) = ClassCard.CreateCardSlot;
else
% iter == 53, means all the deck is empty
% Return an empty card as a status
card = ClassCard.CreateCardSlot;
end
else
% Draw card from DiscardDeck
iter = 1;
while (iter <= 52) && (table.DiscardDeck(iter).EmptyCard)
iter = iter + 1;
end
% After while loop, DiscardDeck(iter) is the first non-empty card in DiscardDeck, unless iter is 53
if iter <= 52
% Return the card
card = table.DiscardDeck(iter);
% And delete the drawn card from deck
table.DiscardDeck(iter) = ClassCard.CreateCardSlot;
else
% iter == 53, means all the deck is empty
% Return an empty card as a status
card = ClassCard.CreateCardSlot;
end
end
end% of function
function Status = ReturnOne(table, card, varargin)
% Return one card to DiscardDeck. if any other input is specified, return one card to NewDeck
if nargin < 3
iter = 1;
while ~(table.DiscardDeck(iter).EmptyCard);
iter = iter + 1;
end
% After while loop, DiscardDeck(iter) is the first empty card in DiscardDeck, unless iter is 53
if iter <= 52
% Return the card
table.DiscardDeck(iter) = card;
Status = 1;
else
% iter == 53, means the deck is full, which is unexpected
display('Unexpected full deck, cannot return');
Status = 0;
end
else
% Return card to NewDeck
iter = 1;
while ~(table.NewDeck(iter).EmptyCard);
iter = iter + 1;
end
% After while loop, NewDeck(iter) is the first empty card in NewDeck, unless iter is 53
if iter <= 52
% Return the card
table.NewDeck(iter) = card;
Status = 1;
else
% iter == 53, means the deck is full, which is unexpected
display('Unexpected full deck, cannot return');
Status = 0;
end
end
end% of function
function Status = Shuffle(table, mode)
% 3 modes of shuffle: 1, NewDeck is empty, shuffle all cards in DiscardDeck and put back to NewDeck; 2, NewDeck is not empty, shuffle all cards in DiscardDeck and NewDeck and put back to NewDeck; 3, DiscardDeck is empty, shuffle all cards in NewDeck only
switch mode
case 1
% Preallocation of tempdeck
tempdeck = repmat(ClassCard.CreateCardSlot, 1, 52);
iter = 1;
% Draw all the cards out from DiscardDeck
tempcard = table.DrawOne(2);
while ~(tempcard.EmptyCard);
tempdeck(iter) = tempcard;
iter = iter + 1;
tempcard = table.DrawOne(2);
end
% Number of cards to be shuffled, iter should be # of cards + 1 after the while loop
nCard = iter - 1;
if nCard > 0;
% Shuffle
shuffledtemp = tempdeck(randperm(nCard));
iter = nCard;
% Return all cards to NewDeck
while (iter > 0) && table.ReturnOne(shuffledtemp(iter), 1);
iter = iter - 1;
end
Status = 1;
else
% DiscardDeck is empty
Status = 0;
end
case 2
% Preallocation of tempdeck
tempdeck = repmat(ClassCard.CreateCardSlot, 1, 52);
iter = 1;
% Draw all the cards out from DiscardDeck
tempcard = table.DrawOne(2);
while ~(tempcard.EmptyCard);
tempdeck(iter) = tempcard;
iter = iter + 1;
tempcard = table.DrawOne(2);
end
% Then draw all the cards out from NewDeck
tempcard = table.DrawOne;
while ~(tempcard.EmptyCard);
tempdeck(iter) = tempcard;
iter = iter + 1;
tempcard = table.DrawOne;
end
% Number of cards to be shuffled, iter should be # of cards + 1 after the while loop
nCard = iter - 1;
if nCard > 0;
% Shuffle
shuffledtemp = tempdeck(randperm(nCard));
iter = nCard;
% Return all cards to NewDeck
while (iter > 0) && table.ReturnOne(shuffledtemp(iter), 1);
iter = iter - 1;
end
Status = 1;
else
% Both NewDeck and DiscardDeck is empty
Status = 0;
end
case 3
% Preallocation of tempdeck
tempdeck = repmat(ClassCard.CreateCardSlot, 1, 52);
iter = 1;
% Draw all the cards out from NewDeck
tempcard = table.DrawOne;
while ~(tempcard.EmptyCard);
tempdeck(iter) = tempcard;
iter = iter + 1;
tempcard = table.DrawOne;
end
% Number of cards to be shuffled, iter should be # of cards + 1 after the while loop
nCard = iter - 1;
if nCard > 0;
% Shuffle
shuffledtemp = tempdeck(randperm(nCard));
iter = nCard;
% Return all cards to NewDeck
while (iter > 0) && table.ReturnOne(shuffledtemp(iter), 1);
iter = iter - 1;
end
Status = 1;
else
% NewDeck is empty
Status = 0;
end
otherwise
display('Shuffle mode error');
Status = 0;
end% of switch
end% of function
function Status = ChangeChip(table, amount)
% Round the amount to integer for robustness
amount = round(amount);
% Check if amount <= 0
if amount <= 0;
Status = 0;
display('Negative bet');
else
table.TableChip = amount;
Status = 1;
end
end% of function
function ClearChips(table)
table.TableChip = 0;
end% of function
function logi = EmptyDeck(table, varargin)
% Test if NewDeck is empty. If any other input is specified, test DiscardDeck
if nargin < 2
iter = 1;
while (iter <= 52) && (table.NewDeck(iter).EmptyCard)
iter = iter + 1;
end
% After while loop, NewDeck(iter) is the first non-empty card in NewDeck, unless iter is 53
if iter <= 52
% Not empty
logi = false;
else
% iter == 53, means all the deck is empty
% Empty NewDeck
logi = true;
end
else
% Test DiscardDeck
iter = 1;
while (iter <= 52) && (table.DiscardDeck(iter).EmptyCard)
iter = iter + 1;
end
% After while loop, DiscardDeck(iter) is the first non-empty card in DiscardDeck, unless iter is 53
if iter <= 52
% Not empty
logi = false;
else
% iter == 53, means all the deck is empty
% Empty DiscardDeck
logi = true;
end
end
end% of function
end% of methods
end% of classdef
--------------------------------------------
function EndUI( handles )
% Display some ending texts on a blank figure
handles.hThank = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [200, 350, 400, 150], ...
'String', 'Thanks for playing!', ...
'FontSize', 30, ...
'FontName', 'Helvetica');
handles.hDeveloper = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [200, 290, 400, 50], ...
'String',
'FontSize', 9, ...
'FontName', 'Helvetica');
handles.hVersion = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [200, 240, 400, 50], ...
'String', 'Black Jack Version 1.10', ...
'FontSize', 12, ...
'FontName', 'Helvetica');
handles.hFrom = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [200, 190, 400, 20], ...
'String', 'Pictures adapted from Internet and Windows Solitaire', ...
'FontSize', 8, ...
'FontName', 'Helvetica');
handles.hQuit = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Visible', 'on', ...
'Units', 'pixels', ...
'Position', [360, 70, 80, 80], ...
'String', 'Quit', ...
'FontSize', 14, ...
'Callback', {@Quit, handles});
uiwait(handles.hFig);
% Clear the figure
tmparray = get(handles.hFig, 'Children');
delete(tmparray(end:-1:1));
clear tmparray;
close(handles.hFig)
end% of function
function Quit( ~, ~, handles )
% Resume, then quit the program
uiresume(handles.hFig);
end% of function
------------------------------------------------------
function MainUI( handles )
% Start again with a blank figure
% Should write the main part of game here
% Create four control buttons for player to use
handles.hHitButton = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Visible', 'off', ...
'Units', 'pixels', ...
'Position', [20, 40, 80, 80], ...
'String', 'Hit', ...
'FontSize', 14, ...
'Callback', {@HitButton, handles});
handles.hStandButton = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Visible', 'off', ...
'Units', 'pixels', ...
'Position', [140, 40, 80, 80], ...
'String', 'Stand', ...
'FontSize', 14, ...
'Callback', {@StandButton, handles});
handles.hSurrenderButton = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Visible', 'off', ...
'Units', 'pixels', ...
'Position', [260, 40, 80, 80], ...
'String', 'Surrender', ...
'FontSize', 12, ...
'Callback', {@SurrenderButton, handles});
%handles.hDoubleButton = uicontrol(handles.hFig, ...
%'Style', 'pushbutton', ...
%'Units', 'pixels', ...
%'Position', [260, 40, 80, 80], ...
%'String', 'Double', ...
%'FontSize', 14);%, ...
%'Callback', {@StartButton, handles.hFig, hStartChips});
%handles.hSplitButton = uicontrol(handles.hFig, ...
%'Style', 'pushbutton', ...
%'Units', 'pixels', ...
%'Position', [380, 40, 80, 80], ...
%'String', 'Split', ...
%'FontSize', 14);%, ...
%'Callback', {@StartButton, handles.hFig, hStartChips});
handles.hQuitButton = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Visible', 'on', ...
'Units', 'pixels', ...
'Position', [500, 40, 80, 80], ...
'String', 'Quit', ...
'FontSize', 14, ...
'Callback', {@QuitButton, handles});
% An area for displaying game log
handles.hLog = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [600, 400, 150, 150], ...
'String', '', ...
'BackgroundColor', [1.0, 1.0, 1.0], ...
'FontSize', 14, ...
'FontName', 'Helvetica');
% Display player's chips in hand and how much wants to bet in this game
handles.hPlayerChip = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [625, 40, 150, 33], ...
'String', num2str(handles.player.Chips), ...
'BackgroundColor', [1.0, 1.0, 1.0], ...
'FontSize', 20, ...
'FontName', 'Helvetica');
handles.hChipText1 = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [625, 75, 150, 30], ...
'String', 'Chips in hand:', ...
'FontSize', 14, ...
'FontName', 'Helvetica');
handles.hBetChips = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [625, 220, 100, 33], ...
'String', '0', ...
'BackgroundColor', [1.0, 1.0, 1.0], ...
'FontSize', 20, ...
'FontName', 'Helvetica');
handles.hBetText = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [625, 255, 150, 30], ...
'String', 'Bet:', ...
'FontSize', 14, ...
'FontName', 'Helvetica');
% Four buttons to modify chips to bet
handles.hBetSmallPlus = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Visible', 'on', ...
'Units', 'pixels', ...
'Position', [725, 238, 20, 15], ...
'String', '+1', ...
'FontSize', 5, ...
'Callback', {@BetSmallPlus, handles});
handles.hBetSmallMinus = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Visible', 'on', ...
'Units', 'pixels', ...
'Position', [725, 220, 20, 15], ...
'String', '-1', ...
'FontSize', 5, ...
'Callback', {@BetSmallMinus, handles});
handles.hBetBigPlus = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Visible', 'on', ...
'Units', 'pixels', ...
'Position', [750, 238, 20, 15], ...
'String', '+10', ...
'FontSize', 5, ...
'Callback', {@BetBigPlus, handles});
handles.hBetBigMinus = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Visible', 'on', ...
'Units', 'pixels', ...
'Position', [750, 220, 20, 15], ...
'String', '-10', ...
'FontSize', 5, ...
'Callback', {@BetBigMinus, handles});
% A button for RoundStart, will start a new round with the betted chips
handles.hRoundStart = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Visible', 'on', ...
'Units', 'pixels', ...
'Position', [660, 120, 80, 80], ...
'String', 'Start!', ...
'FontSize', 14, ...
'Callback', {@RoundStart, handles});
% Display chips on table
handles.hTableChip = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [175, 338, 100, 33], ...
'String', num2str(handles.table.TableChip), ...
'BackgroundColor', [1.0, 1.0, 1.0], ...
'FontSize', 20, ...
'FontName', 'Helvetica');
handles.hChipText2 = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [25, 336, 150, 30], ...
'String', 'Chips on table:', ...
'FontSize', 14, ...
'FontName', 'Helvetica');
% Display current points in hand
handles.hCurrentPoints = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [435, 338, 50, 33], ...
'String', num2str(handles.player.CurrentPointA), ...
'BackgroundColor', [1.0, 1.0, 1.0], ...
'FontSize', 20, ...
'FontName', 'Helvetica');
handles.hPointsText = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'pixels', ...
'Position', [285, 336, 150, 30], ...
'String', 'Current points:', ...
'FontSize', 14, ...
'FontName', 'Helvetica');
handles.hPointsMode = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Visible', 'off', ...
'Units', 'pixels', ...
'Position', [485, 336, 60, 20], ...
'String', 'A=1/11', ...
'FontSize', 10, ...
'Callback', {@PointsMode, handles});
% Create 10 axis for displaying cards
for iter = 1:10
% 1~5 player's cards, 6~10 dealer's cards
xpixel = mod((iter-1),5) * 120 + 5;
ypixel = idivide((iter-1),int32(5)) * 250 + 150;
handles.hA(iter) = axes('Units', 'pixels', ...
'Position', [xpixel, ypixel, 105, 150]);
axis off;
end
clear iter
clear xpixel
clear ypixel
% At this time, all the elements are drawn on the figure
handles.table.GameStatus = 'Wait';
% Wait for RoundStart
uiwait(handles.hFig);
while true
switch handles.table.GameStatus
% GameStatus are 'RoundStart', 'Hit', 'Stand', 'Surrender', 'Bust', 'RoundEnd', 'DealerBust', 'DealerWin', 'Tie', 'Win', 'Quit'
case 'RoundStart'
% 'RoundStart' is only available when a round is over
% After resumed from 'RoundStart' button, first clear log area
set(handles.hLog, 'String', 'RoundStart');
% Get the current bet
currentbet = str2double(get(handles.hBetChips, 'String'));
% Since bet start from 0, must check to avoid player inputting 0 bet
if BetIllegal(currentbet)
set(handles.hLog, 'String', 'Your bet must be at least 1');
handles.table.GameStatus = 'RoundEnd';
else
% Update chips
handles.table.ChangeChip(currentbet);
handles.player.ChangeChip(-currentbet);
% Update chips display
set(handles.hTableChip, 'String', num2str(handles.table.TableChip));
set(handles.hPlayerChip, 'String', num2str(handles.player.Chips));
set(handles.hBetChips, 'String', '0');
% Deal two cards, points in hand is updated automatically
% This block should be used whenever dealing a card
if ~handles.table.EmptyDeck
position = handles.player.GetCard(handles.table.DrawOne);
else
handles.table.Shuffle(1);
position = handles.player.GetCard(handles.table.DrawOne);
end
if ~handles.table.EmptyDeck
position = handles.player.GetCard(handles.table.DrawOne);
else
handles.table.Shuffle(1);
position = handles.player.GetCard(handles.table.DrawOne);
end
% And dealer gets two cards also
if ~handles.table.EmptyDeck
position = handles.dealer.GetCard(handles.table.DrawOne);
else
handles.table.Shuffle(1);
position = handles.dealer.GetCard(handles.table.DrawOne);
end
if ~handles.table.EmptyDeck
position = handles.dealer.GetCard(handles.table.DrawOne);
else
handles.table.Shuffle(1);
position = handles.dealer.GetCard(handles.table.DrawOne);
end
% Display these cards
DispPlayer(handles, [1, 2]);
DispDealer(handles, [1, 2]);
% Update points display
set(handles.hCurrentPoints, 'String', num2str(handles.player.CurrentPointA));
% Make 'Hit', 'Stand', 'Surrender' visible, and 'Start' invisible
set(handles.hHitButton, 'Visible', 'on');
set(handles.hStandButton, 'Visible', 'on');
set(handles.hSurrenderButton, 'Visible', 'on');
set(handles.hQuitButton, 'Visible', 'off');
set(handles.hRoundStart, 'Visible', 'off');
set(handles.hBetSmallPlus, 'Visible', 'off');
set(handles.hBetSmallMinus, 'Visible', 'off');
set(handles.hBetBigPlus, 'Visible', 'off');
set(handles.hBetBigMinus, 'Visible', 'off');
set(handles.hPointsMode, 'Visible', 'on');
uiwait(handles.hFig);
end% of if else
case 'Hit'
% Hit is visible when player does not bust, stand or surrender
% Deal one card
if ~handles.table.EmptyDeck
position = handles.player.GetCard(handles.table.DrawOne);
else
handles.table.Shuffle(1);
position = handles.player.GetCard(handles.table.DrawOne);
end
% Update display of this card
DispPlayer(handles, position);
% Update points display
set(handles.hCurrentPoints, 'String', num2str(handles.player.CurrentPointA));
% Test if the player bust, or get the fifth card but not bust
if handles.player.CurrentPointA > 21
handles.table.GameStatus = 'Bust';
elseif position == 5
handles.table.GameStatus = 'Stand';
else
% Not bust, not five cards stand, just keep waiting
uiwait(handles.hFig);
end
case 'Stand'
% Stand just means it's dealer's turn
% Make player choices invisible
set(handles.hHitButton, 'Visible', 'off');
set(handles.hStandButton, 'Visible', 'off');
set(handles.hSurrenderButton, 'Visible', 'off');
set(handles.hQuitButton, 'Visible', 'off');
% Dealer hit until he has 17 or higher
position = 2;
while position < 5 && handles.dealer.CurrentPointA < 17
% While dealer not bust or stand, draw one card
pause(1);
if ~handles.table.EmptyDeck
position = handles.dealer.GetCard(handles.table.DrawOne);
else
handles.table.Shuffle(1);
position = handles.dealer.GetCard(handles.table.DrawOne);
end
% Update display of this card
DispDealer(handles, position);
% Don't update points display because player doesn't kow
end
if handles.dealer.CurrentPointA > 21
handles.table.GameStatus = 'DealerBust';
elseif handles.dealer.CurrentPointA > handles.player.CurrentPointA
handles.table.GameStatus = 'DealerWin';
elseif handles.dealer.CurrentPointA == handles.player.CurrentPointA
set(handles.hLog, 'String', 'Tie');
handles.table.GameStatus = 'Tie';
elseif handles.dealer.CurrentPointA < handles.player.CurrentPointA
set(handles.hLog, 'String', 'Player Wins');
handles.table.GameStatus = 'Win';
else
set(handles.hLog, 'String', 'Odd case, bug');
end
case 'Surrender'
% Surrender actually ends a round
% Display in log area
set(handles.hLog, 'String', 'Surrender');
pause(1);
% Return half(floor) of the chips on table to player, another half to dealer
currentbet = handles.table.TableChip;
half = floor(currentbet/2);
handles.player.ChangeChip(half);
handles.dealer.ChangeChip(currentbet - half);
handles.table.ClearChips;
% Display in log area how many chips player gets back
if half == 1
set(handles.hLog, 'String', ['You get 1 chip back']);
else
set(handles.hLog, 'String', ['You get ', num2str(half), ' chips back']);
end
% Update chips display
set(handles.hTableChip, 'String', num2str(handles.table.TableChip));
set(handles.hPlayerChip, 'String', num2str(handles.player.Chips));
% Modify GameStatus
handles.table.GameStatus = 'RoundEnd';
case 'Bust'
% When player bust, this round ends
% Display in log area
set(handles.hLog, 'String', 'Bust');
% Make player choices invisible
set(handles.hHitButton, 'Visible', 'off');
set(handles.hStandButton, 'Visible', 'off');
set(handles.hSurrenderButton, 'Visible', 'off');
set(handles.hQuitButton, 'Visible', 'off');
pause(1);
% Return all the chips to dealer
currentbet = handles.table.TableChip;
handles.dealer.ChangeChip(currentbet);
%handles.player.ChangeChip(-currentbet);
handles.table.ClearChips;
% Display in log area how many chips dealer gets
if currentbet == 1
set(handles.hLog, 'String', ['Dealer gets 1 chip']);
else
set(handles.hLog, 'String', ['Dealer gets ', num2str(currentbet), ' chips']);
end
% Update chips display
set(handles.hTableChip, 'String', num2str(handles.table.TableChip));
%set(handles.hPlayerChip, 'String', num2str(handles.player.Chips));
% Modify GameStatus
handles.table.GameStatus = 'RoundEnd';
case 'RoundEnd'
% Return both player's and dealer's cards to DiscardDeck
while ~handles.player.EmptyHand
handles.table.ReturnOne(handles.player.ReturnCard);
end
while ~handles.dealer.EmptyHand
handles.table.ReturnOne(handles.dealer.ReturnCard);
end
% Update cards display, clear all the axes
for iter = 1:10
cla(handles.hA(iter));
end
% Reset BetChips
set(handles.hBetChips, 'String', '0');
% Reset CurrentPoints
set(handles.hCurrentPoints, 'String', '0');
% Reset all the buttons
set(handles.hHitButton, 'Visible', 'off');
set(handles.hStandButton, 'Visible', 'off');
set(handles.hSurrenderButton, 'Visible', 'off');
set(handles.hQuitButton, 'Visible', 'on');
set(handles.hRoundStart, 'Visible', 'on');
set(handles.hBetSmallPlus, 'Visible', 'on');
set(handles.hBetSmallMinus, 'Visible', 'on');
set(handles.hBetBigPlus, 'Visible', 'on');
set(handles.hBetBigMinus, 'Visible', 'on');
set(handles.hPointsMode, 'Visible', 'off');
% If the player has no chips left, quit game
if handles.player.Chips == 0
handles.table.GameStatus = 'Quit';
else
% Wait for RoundStart
uiwait(handles.hFig);
end
case 'DealerBust'
% When dealer bust, this round ends
% Display in log area
set(handles.hLog, 'String', 'Dealer Bust');
pause(1);
% Return double the chips to player
currentbet = handles.table.TableChip;
handles.dealer.ChangeChip(-currentbet);
handles.player.ChangeChip(2*currentbet);
handles.table.ClearChips;
% Display in log area how many chips player gets
set(handles.hLog, 'String', ['You get ', num2str(2*currentbet), ' chips']);
% Update chips display
set(handles.hTableChip, 'String', num2str(handles.table.TableChip));
set(handles.hPlayerChip, 'String', num2str(handles.player.Chips));
% Modify GameStatus
handles.table.GameStatus = 'RoundEnd';
case 'DealerWin'
% Dealer wins when dealer has higher score than player
% Display in log area
set(handles.hLog, 'String', ['Dealer Wins with ', num2str(handles.dealer.CurrentPointA), ' points']);
pause(1);
% Return double the chips to player
currentbet = handles.table.TableChip;
% Win with a Black Jack?
%modifybet = currentbet * (1 + 0.5 * dealer.BlackJack);
handles.dealer.ChangeChip(currentbet);
%handles.player.ChangeChip(-currentbet);
handles.table.ClearChips;
% Display in log area how many chips dealer gets
if currentbet == 1
set(handles.hLog, 'String', ['Dealer gets 1 chip']);
else
set(handles.hLog, 'String', ['Dealer gets ', num2str(currentbet), ' chips']);
end
% Update chips display
set(handles.hTableChip, 'String', num2str(handles.table.TableChip));
%set(handles.hPlayerChip, 'String', num2str(handles.player.Chips));
% Modify GameStatus
handles.table.GameStatus = 'RoundEnd';
case 'Tie'
if handles.player.BlackJack && ~handles.dealer.BlackJack
handles.table.GameStatus = 'Win';
elseif handles.dealer.BlackJack && ~handles.player.BlackJack
handles.table.GameStatus = 'DealerWin';
else
% Genuine 'Tie'
% Display in log area
handles.table.GameStatus = 'Tie';
pause(1);
% Return the chips to player
currentbet = handles.table.TableChip;
%handles.dealer.ChangeChip(currentbet);
handles.player.ChangeChip(currentbet);
handles.table.ClearChips;
% Display in log area how many chips player gets back
if currentbet == 1
set(handles.hLog, 'String', ['You get 1 chip back']);
else
set(handles.hLog, 'String', ['You get ', num2str(currentbet), ' chips back']);
end
% Update chips display
set(handles.hTableChip, 'String', num2str(handles.table.TableChip));
set(handles.hPlayerChip, 'String', num2str(handles.player.Chips));
% Modify GameStatus
handles.table.GameStatus = 'RoundEnd';
end
case 'Win'
% Player wins when player has higher score than dealer
% Display in log area
set(handles.hLog, 'String', 'You Win!');
pause(1);
% Return double the chips to player
currentbet = handles.table.TableChip;
% Win with a Black Jack?
modifybet = floor(currentbet * (1 + 0.5 * handles.player.BlackJack));
handles.dealer.ChangeChip(-modifybet);
handles.player.ChangeChip(currentbet + modifybet);
handles.table.ClearChips;
% Display in log area how many chips player gets
set(handles.hLog, 'String', ['You get ', num2str(currentbet + modifybet), ' chips']);
% Update chips display
set(handles.hTableChip, 'String', num2str(handles.table.TableChip));
set(handles.hPlayerChip, 'String', num2str(handles.player.Chips));
% Modify GameStatus
handles.table.GameStatus = 'RoundEnd';
case 'Quit'
% Clear the figure
% Because 'handles' is copied, not referenced here, all the fields will be automatically deleted except player, table and dealer
tmparray = get(handles.hFig, 'Children');
delete(tmparray(end:-1:1));
clear tmparray;
break;
otherwise
% Unexpected input, keep waiting
uiwait(handles.hFig);
end% of switch
end% of while
end% of function
function BetSmallPlus( ~, ~, handles )
tempnum = str2double(get(handles.hBetChips, 'String'));
% Upper limit is player chips
% All in is allowed
if tempnum <= (handles.player.Chips - 1)
tempnum = tempnum + 1;
set(handles.hBetChips, 'String', num2str(tempnum));
end
end
function BetSmallMinus( ~, ~, handles )
tempnum = str2double(get(handles.hBetChips, 'String'));
% Lower limit 1
if tempnum >= 1
tempnum = tempnum - 1;
set(handles.hBetChips, 'String', num2str(tempnum));
end
end
function BetBigPlus( ~, ~, handles )
tempnum = str2double(get(handles.hBetChips, 'String'));
% Upper limit is player chips
% All in is allowed
if tempnum <= (handles.player.Chips - 10)
tempnum = tempnum + 10;
set(handles.hBetChips, 'String', num2str(tempnum));
end
end
function BetBigMinus( ~, ~, handles )
tempnum = str2double(get(handles.hBetChips, 'String'));
% Lower limit 10
if tempnum >= 10
tempnum = tempnum - 10;
set(handles.hBetChips, 'String', num2str(tempnum));
end
end
function RoundStart( ~, ~, handles )
% Resume, and go on to get the bet chips, then start a new round
handles.table.GameStatus = 'RoundStart';
uiresume(handles.hFig);
end% of function
function HitButton( ~, ~, handles )
% Resume, change the status to 'Hit'
handles.table.GameStatus = 'Hit';
uiresume(handles.hFig);
end% of function
function StandButton( ~, ~, handles )
% Resume, change the status to 'Stand'
handles.table.GameStatus = 'Stand';
uiresume(handles.hFig);
end% of function
function SurrenderButton( ~, ~, handles )
% Resume, change the status to 'Surrender'
handles.table.GameStatus = 'Surrender';
uiresume(handles.hFig);
end% of function
function QuitButton( ~, ~, handles )
% Resume, change the status to 'Quit'
handles.table.GameStatus = 'Quit';
uiresume(handles.hFig);
end% of function
function DispPlayer(handles, numbers)
% Update the cards display according to the current cards in player's hands
for iter = numbers
if (iter >= 1 && iter <= 5)
tempcard = handles.player.CardsInHand(iter);
if ~(EmptyCard(tempcard))
tempstr = ['Library', tempcard.suit(1), tempcard.number, '.jpg'];
axes(handles.hA(iter));
tempC = imread(tempstr);
image(tempC);
axis off;
end
end
end
end% of function
function DispDealer(handles, numbers)
% Update the cards display according to the current cards in dealer's hands
for iter = numbers
if (iter >= 1 && iter <= 5)
tempcard = handles.dealer.CardsInHand(iter);
if (iter == 1 && ~EmptyCard(tempcard))
tempstr = ['Library', tempcard.suit(1), tempcard.number, '.jpg'];
% For dealer, axes number is iter + 5
axes(handles.hA(iter+5));
tempC = imread(tempstr);
image(tempC);
axis off;
elseif (iter > 1 && ~EmptyCard(tempcard))
% Dealer's cards 2~5 are not visible
tempstr = 'Libraryack.jpg';
% For dealer, axes number is iter + 5
axes(handles.hA(iter+5));
tempC = imread(tempstr);
image(tempC);
axis off;
end
end
end
end% of function
function PointsMode( ~, ~, handles )
% Change the mode of displaying points
% Change AcesAs10 first
handles.player.UpdatePoint(2);
% Change display
set(handles.hCurrentPoints, 'String', num2str(handles.player.CurrentPointB + handles.player.AcesAs10 * 10));
end% of function
function logi = BetIllegal(bet)
% Check if bet is 0
logi = ~boolean(bet);
end% of function
---------------------------------------------------------------------
function startChips = StartUI(handles)
% The first step is creating a welcome screen, let player choose how many chips he/she wants to take, and click the 'Start' button.
% Create components on the welcome screen
handles.hStartChips = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'normalized', ...
'Position', [0.35, 0.47, 0.2, 0.055], ...
'String', '100', ...
'BackgroundColor', [1.0, 1.0, 1.0], ...
'FontSize', 20, ...
'FontName', 'Helvetica');
handles.hStartButton = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Units', 'normalized', ...
'Position', [0.4, 0.3, 0.2, 0.1], ...
'String', 'Start!', ...
'FontSize', 15, ...
'Callback', {@StartButton, handles.hFig});
% Give start button a callback function that can record the starting
% chips and remove all UI components, then re-arrange the whole UI.
handles.hWelcomeText = uicontrol(handles.hFig, ...
'Style', 'text', ...
'Units', 'normalized', ...
'Position', [0.3, 0.6, 0.45, 0.055], ...
'String', 'Take Your Starting Chips', ...
'FontSize', 20, ...
'FontName', 'Helvetica');
% Design six buttons that can be used to modify starting chips
handles.hStartSmallPlus = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Units', 'normalized', ...
'Position', [0.58, 0.5, 0.06, 0.04], ...
'String', '+1', ...
'FontSize', 14, ...
'Callback', {@StartSmallPlus, handles.hStartChips});
handles.hStartSmallMinus = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Units', 'normalized', ...
'Position', [0.58, 0.45, 0.06, 0.04], ...
'String', '-1', ...
'FontSize', 14, ...
'Callback', {@StartSmallMinus, handles.hStartChips});
handles.hStartBigPlus = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Units', 'normalized', ...
'Position', [0.66, 0.5, 0.06, 0.04], ...
'String', '+10', ...
'FontSize', 14, ...
'Callback', {@StartBigPlus, handles.hStartChips});
handles.hStartBigMinus = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Units', 'normalized', ...
'Position', [0.66, 0.45, 0.06, 0.04], ...
'String', '-10', ...
'FontSize', 14, ...
'Callback', {@StartBigMinus, handles.hStartChips});
handles.hStartMax = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Units', 'normalized', ...
'Position', [0.74, 0.5, 0.06, 0.04], ...
'String', 'Max', ...
'FontSize', 14, ...
'Callback', {@StartMax, handles.hStartChips});
handles.hStartMin = uicontrol(handles.hFig, ...
'Style', 'pushbutton', ...
'Units', 'normalized', ...
'Position', [0.74, 0.45, 0.06, 0.04], ...
'String', 'Min', ...
'FontSize', 14, ...
'Callback', {@StartMin, handles.hStartChips});
uiwait(handles.hFig);
% record the current value of starting chips
startChips = str2double(get(handles.hStartChips, 'String'));
% delete every UI components
tmparray = get(handles.hFig, 'Children');
delete(tmparray(end:-1:1));
clear tmparray;
% Because 'handles' is copied, not referenced here, all the fields will be automatically deleted
%fields = {'hStartChips', 'hStartButton', 'hWelcomeText', 'hStartSmallPlus', 'hStartBigPlus', 'hStartSmallMinus', 'hStartBigMinus', 'hStartMax', 'hStartMin'};
%handles = rmfield(handles, fields);
end
function StartSmallPlus( ~, ~, hStartChips )
tempnum = str2double(get(hStartChips, 'String'));
% Upper limit 1024
if tempnum <= 1023
tempnum = tempnum + 1;
set(hStartChips, 'String', num2str(tempnum));
end
end
function StartSmallMinus( ~, ~, hStartChips )
tempnum = str2double(get(hStartChips, 'String'));
% Lower limit 1
if tempnum > 1
tempnum = tempnum - 1;
set(hStartChips, 'String', num2str(tempnum));
end
end
function StartBigPlus( ~, ~, hStartChips )
tempnum = str2double(get(hStartChips, 'String'));
% Upper limit 1024
if tempnum <= 1014
tempnum = tempnum + 10;
set(hStartChips, 'String', num2str(tempnum));
end
end
function StartBigMinus( ~, ~, hStartChips )
tempnum = str2double(get(hStartChips, 'String'));
% Lower limit 10
if tempnum > 10
tempnum = tempnum - 10;
set(hStartChips, 'String', num2str(tempnum));
end
end
function StartMax( ~, ~, hStartChips )
% Set to Max 1024
set(hStartChips, 'String', num2str(1024));
end
function StartMin( ~, ~, hStartChips )
% Set to Min 1
set(hStartChips, 'String', num2str(1));
end
function StartButton( ~, ~, hFig )
% The only thing start button does is uiresume
uiresume(hFig);
end
--------------------------------------------------------------------
function WindowKeyFcn( hFig, eventdata )
switch eventdata.Key
case 'escape'
delete(hFig);
clear all
%case 'uparrow'
%Popup;
end
end
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.