Как рисовать объекты карты рядом друг с другом, а не складывать друг на друга в терминале

Я делаю ОО двадцать одну игру. У меня есть класс Card и класс Deck, колода состоит из карточных объектов. Когда игрок показывает свою руку, я вызываю метод to_s для объекта карты, который я представляю в символах ascii. Все это прекрасно работает, за исключением того, что игроки распечатывают одну карту поверх другой. Интересно, как я буду печатать всю руку рядом. Я искал в Интернете и не могу найти ничего, кроме как использовать print вместо puts, но это не решает мою проблему. Заранее благодарим вас за любой совет, который у вас может быть.

    class Card
  attr_reader :value
  def initialize(suit, value)
    @suit = suit
    @value = value
  end

  def to_s
    """
    +-----+
    |#{@value}    |
    |     |
    |  #{@suit}  |
    |     |
    |    #{@value}|
    +-----+
    """
  end
end

Пример вывода:

Your Hand:

    +-----+
    |Q    |
    |     |
    |  C  |
    |     |
    |    Q|
    +-----+

    +-----+
    |K    |
    |     |
    |  S  |
    |     |
    |    K|
    +-----+
    Your total is 20

person borgy88    schedule 08.08.2017    source источник


Ответы (1)


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

1) Используйте ncurses (или аналогичную библиотеку): ncurses — это библиотека для создания графических приложений в терминале. Библиотека рассматривает терминал как сетку ячеек, позволяя разработчику указывать каждый символ в каждой ячейке в любой момент времени. Это дает разработчику массу возможностей, но также вынуждает вас вручную добавлять «традиционные» функции терминала (т. е. получать пользовательский ввод и печатать строки вывода).

2) Буферизируйте свою строку и распечатайте ее всю сразу: хотя терминал может печатать строки текста только построчно, ничто не мешает вам взять кучу карточек и переставить их строки вручную, чтобы они можно нормально распечатать. Это казалось интересной задачей программирования, поэтому я решил попробовать:

def display_hand cards
  strings = cards.map { |c| c.to_s.each_line.to_a }
  first, *rest = *strings
  side_by_side = first.zip *rest
  side_by_side.each do |row|
    row.each { |s| print s.chomp }
    print "\n"
  end
end

display_hand [Card.new("A", 1), Card.new("B", 2), Card.new("C", 3)]

Этот код берет массив карточек, собирает их строковые представления в массивы, а затем использует zip для группировки их по строкам. Таким образом, вместо того, чтобы печатать карту 1, карту 2, карту 3 и т. д., он печатает строку 1 всех карт, строку 2 всех карт и т. д.

Надеюсь это поможет!

person eiko    schedule 08.08.2017
comment
Спасибо, это было отличное решение. Я смог поиграть с ним и заставить его работать в разных областях моей игры. Цените помощь! - person borgy88; 08.08.2017