1

I would like to create a card-deck class in MatLAB. This is my first time experiencing OOP with MatLAB, and I'm fairly new to MatLAB. I'm thinking of having 2 classes:

  1. card (properties: type [1-4], value [1-13])
  2. deck (containing a list/vector of the cards in the deck, I will later define methods for this class; shuffle, drawCard, etc.)

card.m:

classdef card
   properties
      type;    % number: 1-4
      value;   % number: 1-13
   end
   methods
      function obj = card(type, value)
         % some code to check [type, value] should be inserted here
         obj.type = type;
         obj.value = value;
      end
   end
end

This being a raw structure of my class, functionality will come later. Now - how do I define the deck class?

I would also like to be able to let my deck class communicate with my card instances (to make sure I call the right cards: [card(1,1), card(1,2), card(1,3), ..., card(4, 13)], for example.

Any suggestions? Thanks in advance!

casparjespersen
  • 3,460
  • 5
  • 38
  • 63
  • You probably want to use a [cell-array](http://www.mathworks.com/help/matlab/ref/cell.html). – Isaac Nov 17 '12 at 00:31
  • 2
    @Isaac huh? why that? object arrays are just fine to use – Gunther Struyf Nov 17 '12 at 00:42
  • 2
    It will be wildly inefficient. You can do anything if you want, but for any type of dealing tool you will need to generate thousands or millions of samples. (This said by someone who has written his own dealer tools.) –  Nov 17 '12 at 02:55
  • @woodchips you mean [this kind of behaviour](http://stackoverflow.com/a/7727501/1162609) ? Didn't know about that.. but it also depends on what OP wants to do. And on a sidenote, I'm hoping Mathworks fixes these object-related quirks in the future.. – Gunther Struyf Nov 17 '12 at 12:28

2 Answers2

1

You need to implement a subsref function to handle indexing a deck object if you want to address directly into a deck, ie:

d = deck();
d(33)

or add a function with indexing parameters:

d = deck();
d.getCard(33)

The last one seems more appropriate, and also easier to implement:

classdef deck
    properties
        cardstack=card;
    end
    methods(Static)
        function obj = deck()
            obj.cardstack(1:52) = card(); % array creation, will fail if card has no parameterless constructor
            for ii=1:4
                for jj=1:13
                    obj.cardstack((ii-1)*13+jj) = card(ii,jj);
                end
            end
        end
    end
    methods
        function crd = getCard(obj, idx)
            if idx>=1 && idx<=52
                crd = obj.cardstack(idx);
            else
                error('Deck:getCard','Index out of range');
            end
        end
    end
end

or just use:

d.cardstack(33)

which is just the same, without the explicit error checking.

Also add an parameter-less constructor to card, so you can easily create card arrays:

function obj = card(type, value)
    if nargin==0
        % eg:
        type=NaN;
        value=NaN;
    end
    % some code to check [type, value] should be inserted here
    obj.type = type;
    obj.value = value;
end
Gunther Struyf
  • 11,158
  • 2
  • 34
  • 58
0

Maybe you don't need the deck to be a class because you can do most of the operations with an array of Card objects. Here is an example.

classdef Card < handle
   properties
      type    % number: 1-4
      value   % number: 1-13
   end
   methods
      function obj = Card(type, value)
         % some code to check [type, value] should be inserted here
         obj.type = type;
         obj.value = value;
      end
      function c = get_card(obj, t, v)
          c = obj([obj.type] == t & [obj.value] == v);
      end
      function c_arr = get_cards_array(obj, t, v)
          c_arr = obj(ismember([obj.type], t) & ismember([obj.value], v));
      end      
      function print(obj)
          for k = 1 : numel(obj)
              fprintf('Card type = %g; value = %g\n', obj(k).type, obj(k).value);
          end
      end
   end
end

And the usage:

%% build array
deck = Card.empty();
for type = 1 : 4
    for value = 1 : 13
        deck(end + 1, 1) = Card(type, value);
    end
end
%% if needed, you can reshape it into 4x13
deck = reshape(deck, 4, 13);
%% you can also use Card's methods from array:
>> deck.print
Card type = 1; value = 1
Card type = 1; value = 2
Card type = 1; value = 3
...
%% get certain card
c = deck([deck.type] == 3 & [deck.value] == 10);
c.print
%% shuffle 
idx = randperm(numel(deck));
deck = deck(idx);

update: added get_card() to Card's methods (see implementation):

>> c = deck.get_card(3, 10)    
c = 

  Card handle

  Properties:
     type: 3
    value: 10

  Methods, Events, Superclasses

Two remarks:

1) if this is your first experience with MatLAB's OOP it might be very useful to understand the meaning of classdef Card < handle.

2) Here is a question regarding initialization of objects array: Matlab's arrayfun for uniform output of class objects

update 2: added get_cards_array() method. Usage:

%% get array of cards
t = [1, 2];
v = [5, 6, 12];
c = deck.get_cards_array(t, v);
>> c.print
Card type = 1; value = 5
Card type = 1; value = 6
Card type = 1; value = 12
Card type = 2; value = 5
Card type = 2; value = 6
Card type = 2; value = 12
Community
  • 1
  • 1
Serg
  • 13,470
  • 8
  • 36
  • 47