Переменные частного экземпляра Ruby, за исключением - PullRequest
4 голосов
/ 04 марта 2010

Я делаю карточную игру в рубине.

У меня есть класс Game, в котором есть массив объектов Player.

 array_of_players = Array[
  Player.new("Ben"),
  Player.new("Adam"),
  Player.new("Peter"),
  Player.new("Fred"),
 ]
 my_game = Game.new(array_of_players)

 puts my_game.players[2].name #=> Peter

Каждый игрок также имеет доступ к Игре, так что он может получить доступ к важным частям игры, как, например,

self.game.last_card_dealt

У каждого игрока также есть карты (Player.cards), и я хочу убедиться, что игроки не могут получить доступ к картам друг друга. Однако игре необходим доступ к карточкам, поэтому я не думаю, что использование private целесообразно, а игрокам нужен доступ к некоторой информации друг друга, поэтому я не думаю, что это будет private либо ...

По сути, я хочу, чтобы они работали.

self.cards #where self is a Player object
self.players[0].cards #where self is the Game
self.game.players[0].name #where self is a Player object

И это не получится:

self.hand.players[0].cards  #=> Nice try sucker! Cheating is for losers.

Как обрабатываются более сложные разрешения, подобные этому? Спасибо.

Ответы [ 4 ]

3 голосов
/ 04 марта 2010

Это более практично, чем мой другой ответ, и использует объект Game в качестве делегата для всей информации в самой игре (игроки, карты и т. Д.). Обратите внимание, что вы все еще должны доверять звонящему, чтобы передать себя, но серьезно, где вы проводите черту?

class Player
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

class Cards
  attr_accessor :cards
end

class Game
  attr_reader :name, :players

  def initialize(players)
    @name = "Game Master"
    @hands = []
    @players = players.each do |p|
      puts "Added %s to game." % p.name
      @hands << {:player => p, :cards => Cards.new}
    end
  end

  def view_hand(player, caller)
    @hands.each do |hand|
      if hand[:player] == player
        if hand[:player] == caller or caller == self
          puts "%s: You can access all these cards: %s" % [caller.name, hand[:cards]]
        else
          # Do something to only display limited cards depending on this caller's view capabilities
          puts "%s: You can only access the cards I will let you see: %s" % [caller.name, hand[:cards]]
        end
      end
    end
  end

  def my_cards(player)
    @hands.each do |hand|
      puts "%s's cards: %s" % [player.name, hand[:cards]] if hand[:player] == player
    end
  end

end

g = Game.new([Player.new('Bob'), Player.new('Ben')])

puts "\nCalling each Player's cards as each Player:\n\n"
g.players.each do |gp|
  g.players.each do |p|
    g.view_hand(gp, p)
  end
end

puts "\nCalling each Player's cards as Game:\n\n"
g.players.each do |p|
  g.view_hand(p, g)
end

puts "\nEach Player calls for their own cards:\n\n"
g.players.each do |p|
  g.my_cards(p)
end

Выход:

    Added Bob to game.
    Added Ben to game.

    Calling each Player's cards as each Player:

    Bob: You can access all these cards: #<Cards:0x100121c58>
    Ben: You can only access the cards I will let you see: #<Cards:0x100121c58>
    Bob: You can only access the cards I will let you see: #<Cards:0x100121bb8>
    Ben: You can access all these cards: #<Cards:0x100121bb8>

    Calling each Player's cards as Game:

    Game Master: You can access all these cards: #<Cards:0x100121c58>
    Game Master: You can access all these cards: #<Cards:0x100121bb8>

    Each Player calls for their own cards:

    Bob's cards: #<Cards:0x100121c58>
    Ben's cards: #<Cards:0x100121bb8>
2 голосов
/ 04 марта 2010

С этим было весело играть. Я не уверен, что это лучший ответ, но он работает. Ключ заключается в том, чтобы передать вызывающий объект Player.cards (obj) и проверить, является ли он самим игроком или имеет тип Game, оба из которых имеют законный доступ.

class Player
  attr_accessor :name, :game
  attr_writer :cards

  def initialize(name)
    @name = name
    @game = nil
    @cards = nil
  end

  def cards(caller)
    puts "%s cards called by %s." % [self, caller]
    if caller.kind_of?(Game) or caller == self
      puts "Here's your cards %s." % @cards
    else
      puts "Nice try sucker!  Cheating is for losers."
    end
  end
end

class Cards
  def initialize
    @cards = [1, 2, 3]
  end
end

class Game
  attr_reader :players

  def initialize(players)
    @players = players.each do |p|
      puts "Added %s to game." % p.name
      p.game = self
      p.cards = Cards.new
    end
  end
end

g = Game.new([Player.new('Bob'), Player.new('Ben')])

puts "\nCalling each Player's cards as each Player:\n\n"
g.players.each do |gp|
  g.players.each do |p|
    p.cards(gp)
  end
end

puts "\nCalling each Player's cards as Game:\n\n"
g.players.each do |p|
  p.cards(g)
end

И вывод:

    Added Bob to game.
    Added Ben to game.

    Calling each Player's cards as each Player:

    #<Player:0x100122b30> cards called by #<Player:0x100122b30>.
    Here's your cards #<Cards:0x1001229c8>.
    #<Player:0x100122ae0> cards called by #<Player:0x100122b30>.
    Nice try sucker!  Cheating is for losers.
    #<Player:0x100122b30> cards called by #<Player:0x100122ae0>.
    Nice try sucker!  Cheating is for losers.
    #<Player:0x100122ae0> cards called by #<Player:0x100122ae0>.
    Here's your cards #<Cards:0x100122928>.

    Calling each Player's cards as Game:

    #<Player:0x100122b30> cards called by #<Game:0x100122ab8>.
    Here's your cards #<Cards:0x1001229c8>.
    #<Player:0x100122ae0> cards called by #<Game:0x100122ab8>.
    Here's your cards #<Cards:0x100122928>.
2 голосов
/ 04 марта 2010

Сохраняйте Game.player конфиденциальным, чтобы запретить игрокам доступ к другим игрокам через массив.

Например, когда self игрок, self.game.players[0].name глупо.

Возможно, вам нужен публичный Game.player_names метод, который просто возвращает массив имен игроков?

Кроме того, вы можете создать публичный Players.opponents метод.

Примеры * +1014 * Game.player_names class Game # ... def player_names self.players.collect { |p| p.name } end private # private game methods end Player.opponents class Player # ... def opponents(i=nil) return i.nil? ? self.game.player_names : self.game.player_names[i] end end

1 голос
/ 17 марта 2010

Спасибо за все ваши ответы.

В конце концов я решил, что могу дать авторизованному объекту ключ, который используется для предоставления ему доступа к основной части метода.

Игровой объект имеет @auth_object и устанавливает его для объекта игрока, для которого он предназначен для доступа к секретным методам, а секретный метод игрока проверяет, равен ли hand.auth_object self, иначе он ничего не делает. Тогда @auth_object возвращается в ноль. Существует атрибут attr_reader, но нет автора для @ auth_object.

Это работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...