Четвърта задача

Предадени решения

Краен срок:
11.11.2015 17:30
Точки:
6

Срокът за предаване на решения е отминал

Игри с карти

В тази задача ще искаме от вас да имплементирате колоди за три игри с карти + специфични функционалности за всяка игра.

Игрите са: Война, Белот и Сантасе (66).

Уточнения

  • Колода == Тесте
  • Ще използваме бои и suits като синоними
  • Стандартна колода - колода с 52 карти, четири бои (suits) и 13 ранга (ranks):

    Spades:   2 3 4 5 6 7 8 9 10 Jack Queen King Ace
    Hearts:   2 3 4 5 6 7 8 9 10 Jack Queen King Ace
    Diamonds: 2 3 4 5 6 7 8 9 10 Jack Queen King Ace
    Clubs:    2 3 4 5 6 7 8 9 10 Jack Queen King Ace
    
  • Считаме, че картите от колодата са с гърбове към нас:

    • Най-горната карта приемаме за първа карта от колодата
    • Най-долната карта приемаме за последна карта от колодата

Карти, бои и рангове

Всяка карта се характеризира със suit и rank:

  • Suits: :spades, :hearts, :diamonds и :clubs
  • Ranks: 2, 3, 4, 5, 6, 7, 8, 9, 10, :jack, :queen, :king, :ace

Имайки предвид горното, ще представим основните компоненти на една колода със следните класове:

  • Клас Card със следните възможности:
    • Конструктор, приемащ rank и suit
    • Метод #rank - връща rank-а на картата
    • Метод #suit - връща suit-а на картата
    • Метод #to_s - връща името на картата като низ. Име на карта се дефинира като: <Rank> of <Suit>. Примери: Ace of Spades, 2 of Clubs, 10 of Hearts, Jack of Diamonds Обърнете внимание на главните/малките букви! Важно е!

    Две карти трябва да могат да се сравняват с ==. Тоест Card.new(:queen, :spades) == Card.new(:queen, :spades) # => true

Общи изисквания за всяка колода

  • Конструкторът приема опционален аргумент - масив от карти. Първата карта в масива се счита за първа в колодата (най-горна). Ако не бъде подаден този аргумент - считаме, че колодата трябва да съдържа всички възможни за играта карти.
  • Имплементира Enumerable
  • Методи:
    • #size - връща текущия брой на картите в колодата
    • #draw_top_card - премахва най-горната карта от колодата и я връща като резултат
    • #draw_bottom_card - премахва най-долната карта от колодата и я връща като резултат
    • #top_card - връща горната карта без да я премахва от колодата
    • #bottom_card - връща долната карта без да я премахва от колодата
    • #shuffle - разбърква картите в колодата
    • #sort - сортира колодата. Първо по suit (в следния ред: Spades, Hearts, Diamonds, Clubs) и после по rank (в намаляващ ред). Тоест, ако имаме стандартна колода с 52 карти, то най-горната карта ще бъде Ace of Spades, а най-долната - 2 of Clubs
    • #to_s - връща имената на всички карти от колодата, всяко на нов ред, като започва от най-горната карта и запазва реда им. Пример (при сортирана колода):

      Ace of Spades    <- Най-горната карта
      ...
      Queen of Hearts
      ...
      2 of Diamonds
      ...
      Ace of Clubs
      King of Clubs
      ...
      3 of Clubs
      2 of Clubs       <- Най-долната карта
      
    • #deal - връща обект, представляващ картите в ръката на играч

      • #deal раздава карти от колодата като взима от най-горната към най-долната
      • Върнатият обект отговаря на метода #size, както и на други методи, специфични за всяка игра. #size връща броя на картите в ръката. Този брой е специфичен за всяка колода.

Всеки метод, модифициращ колодата, трябва да променя обекта, върху който се изпълнява. Например, #shuffle не трябва да връща нова колода, а да промени текущата. За подобни методи няма да се интересуваме от върнатата стойност.

Колода за Война

  • Име на клас: WarDeck
  • Рангове в нарастващ ред - 2 3 4 5 6 7 8 9 10 Jack Queen King Ace
  • Общ брой карти - 52
  • Брой карти в ръка - 26 (тук #deal ще върне ръка с първите 26 карти от колодата)
  • Обектът, представляващ картите в ръката на играч, има следните методи:
    • #play_card - премахва и връща произволна (може да не е случайна) карта от ръката. Няма значение точно коя.
    • #allow_face_up? - връща true, ако броят на картите в ръката е по-малък или равен на 3 и false в противен случай

Колода за Белот

  • Име на клас: BeloteDeck
  • Рангове в нарастващ ред - 7 8 9 Jack Queen King 10 Ace
  • Общ брой карти - 32
  • Брой карти в ръка - 8 (тук #deal ще върне ръка с първите 8 карти от колодата)
  • Обектът, представляващ картите в ръката на играч, има следните методи:
    • #highest_of_suit(suit) - връща най-силната карта от подадената боя
    • #belote? - дали ръката съдържа двойка King и Queen от една боя
    • #tierce? - дали ръката съдържа поредица от три карти с последователни рангове от една и съща боя
    • #quarte? - дали ръката съдържа поредица от четири карти с последователни рангове от една и съща боя
    • #quint? - дали ръката съдържа поредица от пет карти с последователни рангове от една и съща боя
    • #carre_of_jacks? - дали ръката съдържа четири валета
    • #carre_of_nines? - дали ръката съдържа четири деветки
    • #carre_of_aces? - дали ръката съдържа четири аса

Колода за Сантасе

  • Име на клас: SixtySixDeck
  • Рангове в нарастващ ред - 9 Jack Queen King 10 Ace
  • Общ брой карти - 24
  • Брой карти в ръка - 6 (тук #deal ще върне ръка с първите 6 карти от колодата)
  • Обектът, представляващ картите в ръката на играч, има следните методи:
    • #twenty?(trump_suit) - дали ръката съдържа King и Queen от една боя, но не са козове
    • #forty?(trump_suit) - дали ръката съдържа King и Queen от една боя и са козове Забележка: trump_suit указва името на боята, която е коз. Отново като символ.

Важни неща

Пуснете си примерните тестове! Така ще сте по-спокойни, че не сте забравили да напишете някой метод.

Много е важно да не се спирате на първото решение, което напишете. Напишете нещо, след което се опитайте да го подобрите. Полезно е за всяко парче код да си задавате следните въпроси:

  • Има ли начин да се опрости?
  • Дублира ли се логиката на друго място? Ако да - къде би било по-логично да се намира тя?
  • Класът, в който се намира, трябва ли да се интересува от тези неща? Ако не - къде би било логично да се премести?

Ограничения

Тази задача има следните ограничения:

  • Най-много 80 символа на ред
  • Най-много 8 реда на метод
  • Най-много 2 нива на влагане
  • Най-много 4 аргумента на метод

Ако искате да проверите дали задачата ви спазва ограниченията, следвайте инструкциите в описанието на хранилището за домашните.

Няма да приемаме решения, които не спазват ограниченията. Изпълнявайте rubocop редовно, докато пишете кода. Ако смятате, че rubocop греши по някакъв начин, пишете ни на fmi@ruby.bg, заедно с прикачен код или линк към такъв като private gist. Ако пуснете кода си публично (например във форумите), ще смятаме това за преписване.