0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MATLAB言語で学ぶ「Java言語で学ぶデザインパターン入門」ノート #10 Strategy

Posted at

概要

Strategy パターンは、アルゴリズムを容易に入れ替えられる、デザインパターンの一つである。

ソースコード

Hand.m
classdef Hand < handle
    properties (Access = public, Constant)
        HANDVALUE_GUU(1,1) double {mustBeInteger} = 0;
        HANDVALUE_CHO(1,1) double {mustBeInteger} = 1;
        HANDVALUE_PAA(1,1) double {mustBeInteger} = 2;
        hand(1,3) Hand = [...
            Hand(Hand.HANDVALUE_GUU),...
            Hand(Hand.HANDVALUE_CHO),...
            Hand(Hand.HANDVALUE_PAA)...
        ];
    end
    properties (Access = private, Constant)
        name(1,3) cell = {
            'グー',...
            'チョキ',...
            'パー',...
        };
    end
    properties (Access = private)
        handvalue(1,1) double {mustBeInteger};
    end
    methods (Access = private)
        function obj = Hand(handvalue)
            arguments (Input)
                handvalue(1,1) double {mustBeInteger}
            end
            arguments (Output)
                obj(1,1) Hand
            end
            obj.handvalue = handvalue;
        end
        function out = fight(obj, h)
            arguments (Input)
                obj(1,1) Hand
                h(1,1) Hand
            end
            arguments (Output)
                out(1,1) double {mustBeInteger}
            end
            if obj.handvalue == h.handvalue
                out = 0;
            elseif rem((obj.handvalue + 1), 3) == h.handvalue
                out = 1;
            else
                out = -1;
            end
        end
    end
    methods (Access = public, Static)
        function out = getHand(handvalue)
            arguments (Input)
                handvalue(1,1) double {mustBeInteger}
            end
            arguments (Output)
                out(1,1) Hand
            end
            out = Hand.hand(handvalue);
        end
    end
    methods (Access = public)
        function out = isStrongerThan(obj, h)
            arguments (Input)
                obj(1,1) Hand
                h(1,1) Hand
            end
            arguments (Output)
                out(1,1) logical
            end
            out = obj.fight(h) == 1;
        end
        function out = isWeakerThan(obj, h)
            arguments (Input)
                obj(1,1) Hand
                h(1,1) Hand
            end
            arguments (Output)
                out(1,1) logical
            end
            out = obj.fight(h) == -1;
        end
        function out = toString(obj)
            arguments (Input)
                obj(1,1) Hand
            end
            arguments (Output)
                out(1,:) char {mustBeTextScalar}
            end
            out = Hand.name{obj.handvalue};
        end
    end
end
Strategy.m
classdef (Abstract) Strategy < handle
    methods (Access = public, Abstract)
        out = nextHand(obj)
        study(obj, win)
    end
end
WinningStrategy.m
classdef WinningStrategy < Strategy
    properties (Access = private)
        random(1,1) RandStream = matlab.lang.invalidHandle('RandStream')
        won(1,1) logical = false
        prevHand(1,1) Hand = matlab.lang.invalidHandle('Hand')
    end
    methods (Access = public)
        function obj = WinningStrategy(seed)
            arguments (Input)
                seed(1,1) double {mustBeInteger}
            end
            arguments (Output)
                obj(1,1) WinningStrategy
            end
            obj.random = RandStream('twister', 'Seed', seed);
        end
        function out = nextHand(obj)
            arguments (Input)
                obj(1,1) WinningStrategy
            end
            arguments (Output)
                out(1,1) Hand
            end
            if ~obj.won
                obj.prevHand = Hand.getHand(randi(obj.random, length(Hand.hand)));
            end
            out = obj.prevHand;
        end
        function study(obj, win)
            obj.won = win;
        end
    end
end
ProbStrategy.m
classdef ProbStrategy < Strategy
    properties (Access = private)
        random(1,1) RandStream = matlab.lang.invalidHandle('RandStream')
        prevHandValue(1,1) double {mustBeInteger} = 1
        currentHandValue(1,1) double {mustBeInteger} = 1
        history(3,3) double {mustBeInteger} = [...
            [1, 1, 1];...
            [1, 1, 1];...
            [1, 1, 1];...
        ]
    end
    methods (Access = public)
        function obj = ProbStrategy(seed)
            arguments (Input)
                seed(1,1) double {mustBeInteger}
            end
            arguments (Output)
                obj(1,1) ProbStrategy
            end
            obj.random = RandStream('twister', 'Seed', seed);
        end
        function out = nextHand(obj)
            arguments (Input)
                obj(1,1) ProbStrategy
            end
            arguments (Output)
                out(1,1) Hand
            end
            bet = randi(obj.random, obj.getSum(obj.currentHandValue));
            if bet <= obj.history(obj.currentHandValue, 1)
                handvalue = 1;
            elseif bet <= obj.history(obj.currentHandValue, 1) + obj.history(obj.currentHandValue, 2)
                handvalue = 2;
            else
                handvalue = 3;
            end
            obj.prevHandValue = obj.currentHandValue;
            obj.currentHandValue = handvalue;
            out = Hand.getHand(handvalue);
        end
        function study(obj, win)
            if (win)
                obj.history(obj.prevHandValue, obj.currentHandValue) = obj.history(obj.prevHandValue, obj.currentHandValue) + 1;
            else
                obj.history(obj.prevHandValue, rem(obj.currentHandValue, 3) + 1) = obj.history(obj.prevHandValue, rem(obj.currentHandValue, 3) + 1) + 1;
                obj.history(obj.prevHandValue, rem(obj.currentHandValue + 1, 3) + 1) = obj.history(obj.prevHandValue, rem(obj.currentHandValue + 1, 3) + 1) + 1;
            end
        end
    end
    methods (Access = private)
        function out = getSum(obj, hv)
            out = 0;
            for k = 1:3
                out = out + obj.history(hv, k);
            end
        end
    end
end
Player.m
classdef Player < handle
    properties (Access = private)
        name(1,:) char
        strategy %(1,1) Strategy = matlab.lang.invalidHandle('Strategy')
        wincount(1,1) double
        losecount(1,1) double
        gamecount(1,1) double
    end
    methods (Access = public)
        function obj = Player(name, strategy)
            arguments (Input)
                name(1,:) char
                strategy(1,1) Strategy
            end
            arguments (Output)
                obj(1,1) Player
            end
            obj.name = name;
            obj.strategy = strategy;
        end
        function out = nextHand(obj)
            arguments (Input)
                obj(1,1) Player
            end
            arguments (Output)
                out(1,1) Hand
            end
            out = obj.strategy.nextHand();
        end
        function win(obj)
            arguments (Input)
                obj(1,1) Player
            end
            obj.strategy.study(true);
            obj.wincount = obj.wincount + 1;
            obj.gamecount = obj.gamecount + 1;
        end
        function lose(obj)
            arguments (Input)
                obj(1,1) Player
            end
            obj.strategy.study(false);
            obj.losecount = obj.losecount + 1;
            obj.gamecount = obj.gamecount + 1;
        end
        function even(obj)
            arguments (Input)
                obj(1,1) Player
            end
            obj.gamecount = obj.gamecount + 1;
        end
        function out = toString(obj)
            arguments (Input)
                obj(1,1) Player
            end
            arguments (Output)
                out(1,:) char
            end
            out = ['[', obj.name, ':', num2str(obj.gamecount), ' games, ', num2str(obj.wincount), ' win, ', num2str(obj.losecount), ' lose', ']'];
        end
    end
end
main.m
function main(randomseed1, randomseed2)
if nargin ~= 2
    disp('Usage: main randomseed1 randomseed2');
    disp('Example: main 314 15');
    return;
end

seed1 = str2double(randomseed1);
seed2 = str2double(randomseed2);
player1 = Player('Taro', WinningStrategy(seed1));
player2 = Player('Hana', ProbStrategy(seed2));
for k = 1:10000
    nextHand1 = player1.nextHand();
    nextHand2 = player2.nextHand();
    if nextHand1.isStrongerThan(nextHand2)
        disp(['Winner: ', player1.toString()]);
        player1.win();
        player2.lose();
    elseif nextHand2.isStrongerThan(nextHand1)
        disp(['Winner: ', player2.toString()]);
        player1.lose();
        player2.win();
    else
        disp('Even...');
        player1.even();
        player2.even();
    end
end
disp('Total result:');
disp(player1.toString());
disp(player2.toString());

実行結果

>> main 314 15
(中略)
Total result:
[Taro:10000 games, 3153 win, 3565 lose]
[Hana:10000 games, 3565 win, 3153 lose]
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?