如何描述三个项目之间的剪刀石头布关系? [英] How can one describe a rock-paper-scissors relationship between 3 items?

查看:195
本文介绍了如何描述三个项目之间的剪刀石头布关系?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我具有以下结构:

abstract class Hand {}

class Rock extends Hand {}
class Paper extends Hand {}
class Scissors extends Hand {}

目标是制作一个函数(或方法)Hand::compareHands(Hand $hand1, Hand $hand2),该函数将在剪刀石头布的比赛中返回获胜的手.

The goal is to make a function (or a method) Hand::compareHands(Hand $hand1, Hand $hand2), which would return the winning hand in a rock-paper-scissors match.

用一堆if会很容易,但是重点是要有一个更健壮的结构,即依靠多态而不是过程代码.

That would be very easy with a bunch of ifs, but the point is to have a more robust structure, that's relying on polymorphism rather than on procedural code.

P.S.如果有人问,这是在实际的生产代码中完成的.这不是某种挑战或作业. (这不是真正的剪刀布,但您明白了.)

P.S. this is done in actual production code, if someone is asking. This isn't some sort of challenge or homework. (It's not really rock-paper-scissors, but you get the point).

推荐答案

您的手的唯一性质是它在击败另一只手.

The sole nature of your hand is that it is beating one single other one.

然后,您不希望在重复使用每种手工形式具有一种具体类型的同时重复代码,因此您需要进行参数设置.根据您允许的自由级别,这可以像受保护成员一样简单:

Then you want to not repeat the code while having one concrete type per hand-form, so you need to parametrize. Depending on the level of freedom you can allow, this can be as simple as a protected member:

abstract class Hand {

    protected $beats;

    final public function beats(Hand $opponent) {

        return $opponent instanceof $this->beats;
    }
}

class Rock extends Hand {

    protected beats = 'Scissors';
}

class Paper extends Hand {

    protected beats = 'Rock';
}

class Scissors extends Hand {

    protected beats = 'Paper';
}

我认为这是标准的模板方法模式,形式非常简单.

I think this is the standard template method pattern here, in a very simple form.

将此与 Lusitanian的答案进行比较,谁应该获得实际代码的信用,我只是将其重新排序为一点.但只有很少.

Compare this with Lusitanian's answer who should get the credits for the actual code, I just have re-sorted it a little bit. But only a very little.

另外,我需要感谢 @Leigh,以提供更好的功能和参数命名.这样可以减少评论的需要.

Additionally I need to give credits to @Leigh for the far better function and parameter naming. This should reduce the need of comments.

Lusistanian建议的第二种选择可以用策略模式表示.这也有些直截了当:

The second alternative that Lusistanian suggests can be represented with the strategy pattern. It is also somewhat straight forward:

class EvaluateHands
{
    private $rules;

    public function __construct(array $rules)
    {
        $this->rules = $rules;
    }

    public function compareHands(Hand $hand1, Hand $hand2)
    {
        return $this->rules[get_class($hand1)] === get_class($hand2) ? $hand1 : $hand2;
    }
}

new EvaluateHands(
    array(
        'Rock' => 'Scissors',
        'Paper' => 'Rock',
        'Scissor' => 'Paper'
    )
);

两只手之间的比较已完全封装为EvaluateHands类型,甚至可以配置(如果游戏规则发生变化),而两只手则保持不变:

The comparison between two hands has been fully encapsulated into the EvaluateHands type which is even configureable (if the rules of the game change), while the hands would stay the same:

abstract class Hand {}

class Rock extends Hand {}

class Paper extends Hand {}

class Scissors extends Hand {}

此代码的信用转到 gordon (Lusistanian旁边).

Credits for this code go to gordon (next to Lusistanian).

这篇关于如何描述三个项目之间的剪刀石头布关系?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆