Про хеши и ассоциативные массивы, в ruby и php


#1

@kvokka , если там, где ты сейчас, не так жарко, как там, где сейчас я… то, уверен, тебе, как всегда, будет что мне ответить. У нас же душняк такой, что у народа соответственно крышняк съезжает, причем самым странным порой образом съезжает… for example, это я вчера вечером щелкнул на Невском. Комментарии излишни, суди сам, как здесь душно.

Ну а вопрос такой. Набросал тут игрушку на рубях… по сути это простой покер на костях, по ссылке. И вот в чем вопрос; верхняя строчка показанного далее хелпера окончательно формирует @die как массив пяти выпавших значений костей, который далее и считаем. Потом объявляю хеш, который обрабатываю и наполняю чем-то, напоминающим оператор инкремента (по крайней мере, в php именно так называется ++), это помогает мне в дальнейшем считать комбинации выпавших костей (показываю код фрагментарно, ибо еще в работе):

module PokerHelper
def one
 @die = @die.reject {|c| c.blank?}.map(&:to_i) 
 @numVals = Hash.new(0) 
 for @theval in 1..6 
 for @dienum in 0..4 
 if @die[@dienum] == @theval 
 @numVals[@theval] +=1 
 end 
end 
end

Почему хеш? - потому что, если бы я объявил здесь массив - сразу же получил бы NoMethodError блаблабла for nil:NilClass (пробовал), и придется это разруливать посредством #dig или какого-то безопасного оператора. А с хешем все легче, проще и короче, пашет именно так, как показал. Без никаких проблем. Дальше я могу работать уже как с хешем, так и с массивом на его основе, считая разные комбинации (их немного):

@numVals1 = Array.new(@numVals.values) 
 @two_pairs = @numVals1.find_all { |x| @numVals1.count(x) > 1 } 
 if @two_pairs.include?(2) 
 @cash = @cash.to_i + 3  
 flash[:success] = 'Two pairs! You bet 2. Payoff is 3.'
 elsif [1,2,3,4,5].index{ |x| [email protected]?(x) }.nil? 
 @cash = @cash.to_i + 7 
 flash[:success] = 'You have a street! You bet 2. Payoff is 7.'
 # etc

Вопрос. В пыхе ассоциативный массив и хеш - это практически одно и то же. А вот здесь, получается, нет. Насколько я понимаю, дело не столько в руби, сколько в рельсах? Объясни тупому пыхеру; логику построить мне несложно, но, чую, врубаюсь я несколько поверхностно.


(Kvokka) #2

зачем столько переменных? инстансных причем.
первуя функция меняется на (die.select(&:any?).map(&:to_i) + Array(4) { rand 1..6)).first(4)
и нафиг хеш тут не нужен. и зачем тут to_i не ясно, ну да хрен с ним

далее- рельсы тут не при чем, дело только в руби. почитай руби под микроскопом книжку, там рассказано как работает хеш и встанет все на свои места. вкратце ассоциативный массив это несколько более простая структура данных.

и тебе привет


#3

блин, было предчувствие, что так ответишь. :smiley:
спс, почитаю и поэкспериментирую.


(Magic2k) #4

отправлять за этим в Ruby under the microscope как-то жестко )))


#5

Да вообще жесткач.
Критиковать все мастера, а как че спросишь - на понтах шлют в библиютеку, хорошо еще если не оскорбишь при этом чуйства верующих в истинный coding standards, а то вообще жопа будет. “Неподдерживемые паттерны”, ну и все, звездец.

:stuck_out_tongue_winking_eye:

Ладно, я чего спросить хотел.
Полемика стимулирует развитие, разумеется… ну и вот, набросал на сей раз что-то похожее на классический карточный покер, в основу положил класс(ы):

class Card
  attr_accessor :suit
  attr_accessor :value
 
  def initialize (suit, value)
    self.suit = suit
    self.value = value
  end
 
  def inspect
    "Card(suit:#{suit}, value:#{value})"
  end
end
class CardComparable < Card
  include Comparable
 
  def <=>(other)
    suit <=> other.suit && value <=> other.value
  end
 
  def eql?(other)
    self.class == other.class && self == other
  end
 
  def hash
    suit.hash + value.hash
  end
end

, соответственно, далее получаем рандомные значения карт и работаем с ними. Аппликуха пашет без модели, данные перекидываем из hidden_fields в парамсы, колода, таким образом, уникальна на каждый цикл игры (два броска):

@card = []
while @card.length < 5 do
    d = CardComparable.new(rand(1..4), rand(1..13))
if params[:array_card].present?
  @card << d unless params[:array_card].include? ("#{d.suit},#{d.value}")
else
  @card << d
end
@card = @card.uniq
end

@total = []
@card.each_with_index do |line, index |
  if params[:keepit].present? && params[:keepit][index.to_s].present?
  @total << params[: keepit][index.to_s]
else
  @total << "#{line.suit},#{line.value}"
end
end

Это были вводные, теперь сам вопрос… tell me please, куда, в логике MVC рельсов, оптимально засунуть проверки комбинаций, как думаете? - имеется в виду вот что-то наподобие:

# 1. begin 'royal street flash' check
if (numSuit.find_all { |x| numSuit.count(x) == 1 }).include?(5) && total_value.sort == [1,10,11,12,13]
@cash = @cash.to_i + 10 
flash[:success] = 'Royal Street Flash! You bet 2. Payoff is 10.'
# end 'royal street flash' check

# 2. begin 'street flash' check
elsif (numSuit.find_all { |x| numSuit.count(x) == 1 }).include?(5) && total_value.sort.each_cons(2).all? { |x,y| y == x + 1 } == true
@cash = @cash.to_i + 6
flash[:success] = 'Street Flash! You bet 2. Payoff is 6.'
# end 'street flash' check
# etc

Повторяю, модели нет. В контроллер? - хм… зафигачил пока что в хелпер, для разнообразия. Коль скоро @cash - инстансная переменная.

Что скажут наимудрейшие?


#6

ок, сделал совсем тощий контроллер и еще один класс, куда и запихнул логику… контроллер вызывает статические методы проверок из класса, формируя на их основе флаш-мессаджи. На этой основе слепил покер-бота, крайне несложного… бот руководствуется на данный момент нехитрой стратегией, оставляя после первой раздачи карты, составляющие законченную комбинацию, остальные карты меняет, предпочитая накрайняк сбросить все, рисковать не пробует совершенно. Затем следуют подсчет и сравнение комбинаций (бот знает 10 классических комбинаций техасского холдема), при необходимости для определения выигравшего учитываются все возможные high card и kicker , в самых редких редком случае идет split pot. Даже и не знаю, вроде ничего лишнего себе не позволил и на рекламу азартных игр данный пост не тянет? - а то вон Яндекс как раз наскреб себе “дело” за рекламу букмекера. :slight_smile:

Короче, вот чего получилось. Если есть здесь любители покера… аффтор был бы весьма признателен за любые замечания, т. к. сам абсолютно не умеет играть в карты (это правда) и никому не рекомендует участие ни в каких азартных играх.