如何在终端中并排绘制卡片对象与堆叠在一起

How to draw card objects side by side vs stacked on top of each other in terminal

我正在制作一款面向对象的二十一游戏。我有一张卡片 class 和一张卡片组 class,卡片组由卡片对象组成。当玩家展示他们的手时,我在我用 ascii 字符表示的卡片对象上调用 to_s 方法。这一切都很好,除了玩家的手打印出一张卡片在另一张卡片上。想知道我将如何并排打印整只手。我在网上搜索过,除了使用 print 而不是 put 之外找不到任何东西,但这并不能解决我的问题。预先感谢您的任何建议。

    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

首先让我说,对于您要尝试做的事情,没有简单的解决方案。终端设计为逐行打印文本,而不是逐列打印。一旦某些内容打印到控制台,您通常无法返回并修改它。鉴于此,您有两个选择:

1) 使用 ncurses(或类似的库):ncurses 是一个用于在终端中创建 "gui" 应用程序的库。该库将终端视为单元格网格,让开发人员可以在任何给定时刻指定每个单元格中的每个字符。这为开发人员提供了大量的权力,但它也迫使您手动添加 "traditional" 终端功能(即接收用户输入和打印输出行)。

2) Buffer your string and print it all once:即使终端只能逐行打印文本字符串,也没有什么能阻止你拿一堆卡片并手动重新排列它们的字符串,以便它们可以正确打印。这似乎是一个有趣的编程任务,所以我继续尝试了一下:

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 行等。

希望对您有所帮助!