我正在用红宝石制作纸牌游戏。
我有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
是合适的,并且玩家需要访问彼此的某些信息,因此我认为我不希望这样做{ {1}}要么......
基本上,我希望这些能够奏效。
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
如何处理更复杂的权限? 感谢。
答案 0 :(得分:3)
这比我的其他答案更实用,并使用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>
答案 1 :(得分:2)
保持Game.player
私密,禁止玩家通过阵列访问其他玩家。
self
是玩家时,self.game.players[0].name
有点傻。
也许你想要一个公共Game.player_names
方法,只返回一系列玩家名称?
最重要的是,您可以制作公开Players.opponents
方法。
class Game
# ...
def player_names
self.players.collect { |p| p.name }
end
private
# private game methods
end
class Player
# ...
def opponents(i=nil)
return i.nil? ? self.game.player_names : self.game.player_names[i]
end
end
答案 2 :(得分:2)
这很有趣。我不确定这是否是最好的答案,但它确实有效。关键是将调用对象传递给Player.cards(obj),并检查它是Player本身,还是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>.
答案 3 :(得分:1)
感谢您的所有回复。
最后,我想我可以给授权对象一个用于允许它访问方法内容的键。
游戏对象有@auth_object并将其设置为它打算访问其秘密方法的玩家对象,玩家秘密方法检查hand.auth_object是否为self
,否则它什么都不做。然后@auth_object被设置为nil。 @auth_object有一个attr_reader但没有编写器。
有效。