RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 559101
Accepted
smellyshovel
smellyshovel
Asked:2020-08-25 03:19:13 +0000 UTC2020-08-25 03:19:13 +0000 UTC 2020-08-25 03:19:13 +0000 UTC

如何在代码中正确描述牌组中牌的关系?

  • 772

假设扑克牌的每个值都由一个单独的类描述:

class Jack {
    ...
}

class Queen {
    ...
}

还有一个单独的甲板类:

class Deck {
    ...
}

对如何正确描述卡资历关系感兴趣。例如,在任何纸牌游戏中(实际上,但这无关紧要)皇后比杰克年长,而平手比国王年轻。另外,不要忘记在某些游戏中有王牌,因此任何王牌都会比任何非王牌更老。

据我了解,这应该在每个类(对于每种类型的地图)中进行描述。但是怎么办?是否有必要列出所有比这张牌更老(和更小)的牌?如果我的推理正确,如何用 Ruby 语言做到这一点?还是应该在整个牌组的层面上描述关系?

ruby
  • 3 3 个回答
  • 10 Views

3 个回答

  • Voted
  1. anoam
    2020-08-25T15:49:24Z2020-08-25T15:49:24Z

    尽管表面上显而易见,但我认为继承在这里毫无用处。最起码会有很多类,每个类不仅要定义,还要初始化。具体来说,要确定优先级,定义一个属性seniority(precedence)和一个方法就可以了can_hit?。这足以确定资历,并重新定义(同一个例子,当 2 可以击败 ace 时)。

    class Card
      attr_reader :name, :seniority, :hitable_seniorities
    
      def initialize(name, seniority, hitable_seniorities)
        @name = name
        @seniority = seniority
        @hitable_seniorities = hitable_seniorities
      end
    
      def can_hit?(other_card)
        hitable_seniorities.include?(other_card.seniority)
      end
    end
    

    例如,这就是我们确定 2 可以击败 A 的方式:

    Card.new("two", 2, [14])
    

    好吧,仍然需要定义工厂:

    def build_deck(cards_params)
      cards_params.map { |card_params| Card.new(*card_params) }
    end
    

    使用示例:

    build_deck([
      ["three", 3, [2]],
      ["seven", 7, [2, 3, 4, 5, 6]],
      ["ace", 14, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]]
    ])
    

    我故意没有考虑示例中的花色。问题中没有关于他们的任何内容。要使用花色(尤其是像小丑这样的牌),您很可能需要使用组合(请参阅Ruby 中的实用面向对象设计,第 1章Combining Objects with Composition)。但我希望,思想的总体方向是明确的。

    更新:

    做了个小例子。花色也有长短之分,但为了使例子​​更完整,以“传统”方式进行比较。

    class Suit
    
      attr_reader :name, :seniority
    
      def intialize(name, seniority)
        @name = name
        @seniority = seniority
        @trump = false
      end
    
      def trump!
        @trump = true
      end
    
      def trump?
        @trump
      end
    
      def same?(other_suit)
        seniority == other_suit.seniority
      end
    
      def highter?(other_suit)
        return false if same?(other_suit)
        return true if trump?
    
        seniority > other_suit.seniority
      end
    end
    
    class Card
      attr_reader :name, :seniority, :hitable_seniorities, :suit
    
      def initialize(name, seniority, hitable_seniorities, suit)
        @name = name
        @seniority = seniority
        @hitable_seniorities = hitable_seniorities
        @suit = suit
      end
    
      def can_hit?(other_card)
        #hitable_seniorities.include?(other_card.seniority)
        return true if suit_highter?(other_card)
        return false unless same_suit?(other_card)
    
        seniority_highter?(other_card)
      end
    
      private
    
      def suit_highter?(other_card)
        suit.highter?(other_card.suit)
      end
    
      def same_suit?(other_card)
        suit.same?(other_card.suit)
      end
    
      def seniority_highter?(other_card)
        hitable_seniorities.include?(other_card.seniority)
      end
    end
    
    class Game
      attr_reader :suits_factory, :deck_factory
      attr_reader :suits, :deck
    
      def initialize(suits_factory, deck_factory)
        @suits_factory = suits_factory
        @deck_factory = deck_factory
      end
    
      def new_game!
        build_deck!
        choose_tramp!
      end
    
      private
    
      def build_deck!
        @suits = suits_factory.build
        @deck = deck_factory.build(suits)
      end
    
      def choose_tramp!
        @suits.example.trump!
      end
    end
    
    class SuitsFactory
    
      attr_reader :suits_data
    
      def initialize(suits_data)
        # возможные масти в игре
        @suits_data = suits_data
      end
    
      def build
        suits_data.map do |suit_data|
          Suit.new(*suit_data)
        end
      end
    
    end
    
    class DesckFactory
    
      attr_reader :cards_data
    
      def initialize(cards_data)
        # возможные в игре достоинства карт
        @cards_data = cards_data
      end
    
      def build(suits)
        suits.map { |suits| build_for_suit(suit) }.flatten
      end
    
      private
    
      def build_for_suit(suit)
        cards_data.map do |card_data|
          Suit.new(*card_data, suit)
        end
      end
    end
    
    
    suits_factory = SuitsFactory.new([
      ["Clubs", 1],
      ["Diamonds", 2],
      ["Hearts", 3],
      ["Diamonds", 4]
    ])
    
    desk_factory = DesckFactory.new([
      ["three", 3, [2]],
      ["seven", 7, [2, 3, 4, 5, 6]],
      ["ace", 14, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]]
    ])
    

    使用示例:

    game = Game.new(suits_factory, desk_factory)
    game.new_game!
    
    • 7
  2. Best Answer
    cheops
    2020-08-25T04:05:36Z2020-08-25T04:05:36Z

    我建议从基类继承所有类型的卡片Card,例如,在其中使用内部数组,TYPES我将设置卡片“类型”的顺序。这种数组的索引将决定类型之间的优先级。构造函数可以通过花色suit和这张牌是否是王牌trump。

    为了让类对象可以相互比较,我们使用includemodule Comparable,然后我们重新定义了 <=> 运算符。

    class Card
      include Comparable
    
      # Массив-константа типов карт в порядке убывания значения    
      TYPES = %w(Jocker Ace King Queen Jack Ten Nine Eight Seven Six).freeze
    
      # Конструктор принимает масть suit и признак является ли карта козырем trump
      def initialize(suit, trump = false)
        @suit = suit
        @trump = trump
      end
    
      # Вес мастей относительно друг друга
      def weight
        TYPES.find_index(self.class.name)
      end
    
      # Козырь или нет?
      def trump
        @trump
      end
    
      # Масть
      def suit
        @suit
      end
    
      # Переопределение оператора сравнения <=>
      def <=>(other)
        if other.trump == @trump
          other.weight <=> weight
        else
          (other.trump && !@trump) ? -1 : 1
        end
      end
    end
    

    之后,您可以从基类显式继承地图类Card

    class Jocker < Card
    end
    
    class Ace < Card
    end
    
    class King < Card
    end
    
    class Queen < Card
    end
    
    class Jack < Card
    end
    
    ...
    
    class Six < Card
    end
    

    或者使用元编程工具创建它们(无论如何它们都是相同的类型)。在一个循环中,我们遍历映射数组Card::TYPES并动态创建从类继承的同名类Card

    Card::TYPES.each do |klass|
      Kernel.const_set(klass, Class.new(Card))
    end
    

    因此,这些类的对象可以相互比较。给定王牌花色,要将牌标记为王牌,将 true 作为第二个参数传递给构造函数。

    jack = Jack.new(:hearts)
    ace = Ace.new(:clubs)
    
    p ace < jack # false
    p ace > jack # true
    p ace == ace # true
    
    jack = Jack.new(:hearts, true)
    ace = Ace.new(:clubs)
    trump = Ace.new(:clubs, true)
    
    p ace < jack # true
    p ace > jack # false
    p ace == trump # false
    

    因此,无论您组成什么样的套牌,Deck都可以将其正确排序并将每张牌与另一张牌进行比较,同时考虑到当前的王牌花色。

    • 6
  3. Ivan Ignatiev
    2020-08-25T03:45:38Z2020-08-25T03:45:38Z

    我怀疑资历关系可以用一些属性,值/权重来描述,其中会包含一个数字。

    2 = 2
    ...
    A = 14
    // либо туз может быть младшим
    

    那么卡片之间的所有关系都可以用数学或逻辑表达式的形式来描述。

    如果花色是王牌,那么您可以为相同花色的所有牌增加一些值。

    • 4

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5