I am making an OO twenty one game. I have a Card class and a Deck class, the deck is made up of card objects. When a player shows their hand I call the to_s method on a card object which I represent in ascii characters. This all works fine except that the players hand prints out one card on top of the other. Wondering how I would go about printing the whole hand side by side. I have searched online and cannot find anything other than to use print instead of puts, but that does not resolve my issue. Thank you in advance for any advice you may have.
class Card
attr_reader :value
def initialize(suit, value)
@suit = suit
@value = value
end
def to_s
"""
+-----+
|#{@value} |
| |
| #{@suit} |
| |
| #{@value}|
+-----+
"""
end
end
Sample output:
Your Hand:
+-----+
|Q |
| |
| C |
| |
| Q|
+-----+
+-----+
|K |
| |
| S |
| |
| K|
+-----+
Your total is 20
Let me start by saying that there's no easy solution for what you're trying to do. Terminals are designed to print text row by row, not column by column. And once something is printed to the console, you generally can't go back and modify it. Given that, you have two options:
1) Use ncurses (or a similar library): ncurses is a library for creating "gui" applications in the terminal. The library treats the terminal as a grid of cells, letting the developer specify each character in each cell at any given moment. This gives the developer tons of power, but it also forces you to manually add "traditional" terminal functionality (ie receiving user input and printing rows of output).
2) Buffer your string and print it all at once: even though the terminal can only print strings of text row by row, there's nothing stopping you from taking a bunch of cards and rearranging their strings manually so they can be printed properly. It seemed like an interesting programming task, so I went ahead and gave it a shot:
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)]
This code takes an array of cards, gathers their string representations into arrays and then uses zip
to group them by row. So essentially instead of printing card 1, card 2, card 3, etc., it prints row 1 of all cards, row 2 of all cards, etc.
Hope this helps!