متغيرات مثيل روبي الخاص ، مع استثناءات
-
24-09-2019 - |
سؤال
أنا أصنع لعبة بطاقة في روبي.
لدي فئة اللعبة ، التي لديها مجموعة من كائنات اللاعب.
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
شكرا لجميع ردودك.
في النهاية ، اعتقدت أنه يمكنني إعطاء الكائن المعتمد مفتاحًا يستخدم للسماح له بالوصول إلى لحم الطريقة.
يحتوي كائن اللعبة على Auth_Object ويقوم بتعيينه على كائن اللاعب الذي يعتزم الوصول إلى الأساليب السرية لـ ، ويتحقق الطريقة السرية للاعب إذا كان Hand.Auth_Object self
, ، وإلا فإنه لا يفعل شيئًا. ثم يتم تعيين Auth_Object إلى NIL. هناك attr_reader ولكن لا يوجد كاتب لـ Auth_Object.
انه يعمل انها تعمل.
نصائح أخرى
هذا أكثر عملية من إجابتي الأخرى ، ويستخدم كائن اللعبة كمندوب لجميع المعلومات في اللعبة نفسها (اللاعبين ، والبطاقات ، وما إلى ذلك). لاحظ أنه لا يزال يتعين عليك الوثوق بالمتصل لتمرير نفسه ، ولكن على محمل الجد أين ترسم الخط؟
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>
يحفظ Game.player
خاص لعدم السماح للاعبين من الوصول إلى لاعبين آخرين من خلال الصفيف.
على سبيل المثال ، متى self
هو لاعب ، self.game.players[0].name
هو نوع من سخيفة.
ربما تريد الجمهور Game.player_names
الطريقة التي تُرجع مجموعة من أسماء اللاعبين؟
علاوة على ذلك ، يمكنك أن تصنع الجمهور Players.opponents
طريقة.
أمثلة
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
كان هذا ممتعا للعب مع. لست متأكدًا مما إذا كانت هذه هي أفضل إجابة ممكنة ، لكنها تعمل. المفتاح هو تمرير كائن الاتصال إلى Player.cards (OBJ) ، والتحقق مما إذا كان إما اللاعب نفسه ، أو من نوع اللعبة ، وكلاهما لديه وصول قانوني.
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>.