Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions comments/card.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Card

attr_reader :name, :count

def initialize(name, count)
@name = name
@count = count
end

end
192 changes: 192 additions & 0 deletions comments/controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
require_relative 'deck'
require_relative 'dealer'
require_relative 'user'

# game_deck = Deck.new
# user = User.new('vasya', game_deck)
# p user.user_cards
# p user.money
# p user.points

puts "
─────────────────────────────
─────────────▐█▌─────────────
─────────────▐░▌─────────────
─────────────▐░▌─────────────
─────────────▐░▌─────────────
──────────▄▄▀░░░▀▄▄──────────
────────▄▀░░░░░░░░░▀▄────────
──────▄▀░░░░░░░░░░░░░▀▄──────
─────▐░░░░░░░░░░░░░░░░░▌─────
────▐░░░░░░░░░░░░░░░░░░░▌────
───▐░░░░░░░░░░░░░░░░░░░░░▌───
───▐░░░░░░░░░░░░░░░░░░░░░▌───
───▐░░░░░░░░░░░░░░░░░░░░░▌───
───▐▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▌───
──▄███████████████████████▄──
─████▀────▀███████▀────▀███▄─
─███▀───────█████────────███─
─███───███───███───███───███─
─███───▀▀▀───███───▀▀▀───███─
─▀███▄─────▄█████▄─────▄███▀─
──▀███████████████████████▀──
───▐░░░░░░░░░░░░░░░░░░░░░▌───
───▐░░░░░░░░░░░░░░░░░░░░░▌───
───▐░▄▀▀█▀▀█▀▀█▀▀█▀▀█▀▀▄░▌───
───▐░█▄▄█▄▄█▄▄█▄▄█▄▄█▄▄█░▌───
───▐░█──█──█──█──█──█──█░▌───
───▐░█▀▀█▀▀█▀▀█▀▀█▀▀█▀▀█░▌───
───▐░▀▄▄█▄▄█▄▄█▄▄█▄▄█▄▄▀░▌───
───▐░░░░░░░░░░░░░░░░░░░░░▌───
───▐░░░░░░░░░░░░░░░░░░░░░▌───
────▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀────"
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙂


def init_game(username)
@deck = Deck.new
@player = User.new(username, @deck)
@dealer = Dealer.new('Bender', @deck)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не стоит хранить колоду внутри объекта игрока. Колода - это внешняя по отношению к игроку сущность.

end

def restart_game
@deck.create
@player.new_game
@dealer.new_game
rescue => e
puts e.message
puts "New game?
1) - yes
2) - no"
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

puts <<~TEXT
  New game?
  1) - yes
  2) - no
TEXT

loop do
user_input = gets.chomp.to_i
case user_input
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Либо case, либо весь обработчик исключения лучше вынести в отдельный метод.

when 1
@player.money = 100
restart_game
break
when 2
abort("Go home, baby")
else
puts "enter right num (1 or 2)"
end
end
end

def print_status
puts "Check your cards:"
@player.print_cards
puts "Check your points:"
puts @player.points
puts "Dealer cards: #{"* " * @dealer.user_cards.size}"
end

def user_check
if @player.check_available
@player.check
puts "Player checks..."
if @dealer.play?
@dealer.get_card
puts "Dealer got one card..."
else
puts "Dealer checks..."
end
else
puts "You lost your check"
end
end

def user_get_card
@player.get_card
print_status
rescue => e
puts e.message
end

def draw
puts "DRAW"
@player.add_money(10)
@dealer.add_money(10)
end

def user_wins
puts "#{@player.name} wins with #{@player.points} points against #{@dealer.name}'s #{@dealer.points} points"
@player.add_money
end

def dealer_wins
puts "#{@dealer.name} wins with #{@dealer.points} points against #{@player.name}'s #{@player.points} points"
@dealer.add_money
end

def user_open_cards
# if @dealer.points > 21 && @player.points > 21
# draw
# elsif @player.points > 21 || @dealer.points > 21
# if @player.points > 21
# dealer_wins
# else
# user_wins
# end
# elsif @player.points > @dealer.points
# user_wins
# elsif @player.points == @dealer.points
# draw
# elsif @dealer.points > @player.points
# dealer_wins
# end
puts "Dealer cards: "
@dealer.print_cards

if @dealer.points > 21 && @player.points > 21 || @dealer.points == @player.points
draw
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если у обоих очков больше 21-го, значит оба проиграли.

elsif @player.points <= 21 && @dealer.points > 21 || @player.points <= 21 && @dealer.points <= 21 && @player.points > @dealer.points
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Чтобы игрок выиграл, достаточно чтобы количество его очков было больше чем у дилера и меньше чем 21.

user_wins
elsif @player.points > 21 && @dealer.points <= 21 || @player.points <= 21 && @dealer.points <= 21 && @dealer.points > @player.points
dealer_wins
end
end

puts "Welcome to Bender's Black Jack room.
Rules:
1) At first you need to put your name
2) Then game will be started. Enjoy!
3) If you want go to your mom, put 'exit'

Put your name:"
user_input = gets.chomp
abort("Go home, baby") if user_input == 'exit'
puts "You have 100$"
init_game(user_input)

loop do
print_status
puts "\nChoose an action:
1) Check
2) Take card
3) Open cards"

user_input = gets.chomp.to_i
case user_input
when 1
user_check
when 2
user_get_card
when 3
user_open_cards
puts "your money: #{@player.money}"
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Похожая логика была внутри метода restart_game, это ещё одно подтверждение что нужен отдельный метод.

puts "\nOne more time?
1) - yes
2) - no"
loop do
user_input = gets.chomp.to_i
case user_input
when 1
restart_game
break
when 2
abort("Go home, baby")
else
puts "enter right num (1 or 2)"
end
end
end
end
11 changes: 11 additions & 0 deletions comments/dealer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require_relative 'gamer'

class Dealer < Gamer
def play?
if self.points > 18
false
else
true
end
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нет необходимости явно возвращать ture или false, достаточно написать так:

def play?
  self.points > 18
end

end
end
28 changes: 28 additions & 0 deletions comments/deck.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require_relative 'card'

class Deck

attr_reader :main_deck
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я бы назвал это свойство просто cards.


CARDS = {'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '9': 9, '10': 10,
'K+': 10, 'K<3': 10, 'K^': 10, 'K<>': 10,
'Q+': 10, 'Q<3': 10, 'Q^': 10, 'Q<>': 10,
'V+': 10, 'V<3': 10, 'V^': 10, 'V<>': 10,
'A': 11}

def initialize
create
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В данном случае можно было не определять дополнительный метод для создания колоды.

end

def create
@main_deck = []
CARDS.each {|title, count| @main_deck << Card.new(title, count)}
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно было использовать массив с номиналом карт, вместо хэша. Вообще, у нас 3 ситуации:

  • Если карта от 2-х до 10-ти, сумма считается по её номиналу, то есть фактически это title.to_i
  • Если карта является картинкой - это 10 очков
  • Если туз - это случай, требующий отдельной обработки

Исходя из этого, достаточно определить метод в классе Card который будет возвращать правильное количество очков и случай с тузом потом обрабатывать отдельно. Обязанность знать сколько очков приносит отдельная карта вполне подходит для объектов класса Card.

end

def get_card(n = 1)
raise "You should create a main deck before adding card" if @main_deck.empty?
a = @main_deck.sample(n)
@main_deck.delete(a)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно использовать метод pop, который принимает в качестве аргумента количество объектов которые последовательно нужно извлечь с конца массива.

a
end
end
60 changes: 60 additions & 0 deletions comments/gamer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
class Gamer
attr_accessor :name, :points, :money, :deck, :check_available, :user_cards
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Поскольку мы уже в контексте класса игрока, я бы назвал переменную с картами просто cards, вместо user_cards.


def initialize(name, deck)
@name = name
@money = 100
@deck = deck
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Колода - это нечто внешнее. Можно сделать отдельный класс hand который будет принадлежать игроку, это да. Но хранить объект колоды внутри объекта игрока не стоит. Даже с учётом что и дилеру, и пользователю при создании будет передан один и тот же объект колоды.

new_game
end

def new_game
make_bet
@check_available = true
@user_cards = []
get_card(2)
calculate_points
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Очки считаются в методе get_card, нет смысла считать их ещё раз здесь.

end

def make_bet
if @money - 10 >= 0
@money -= 10
else
raise 'no more money'
end
end

def add_money(cash = 20)
@money += cash
end

def print_cards
@user_cards.each {|card| puts "Name: #{card.name} Points: #{card.count}"}
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если переопределить метод to_s у карты, здесь можно будет написать:

@user_cards.each { |card| puts card }

end

def get_card(n=1)
if @user_cards.size < 3
@user_cards.concat(deck.get_card(n))
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@user_cards.push(*deck.get_card(n)).

calculate_points
else
raise 'max cards count reached'
end
end

def calculate_points
@points = @user_cards[0].count
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Поскольку мы храним количество очков в @points, в коде нам постоянно нужно будет держать в голове: вызывали мы calculate_points или нет? Это может привести к дополнительным ошибкам, поэтому я бы не хранил количество очков, сделав это значение вычисляемым. То есть если нужно получить количество очков, вызываем метод calculate_points.

#значение очков туза == 11
@user_cards[1..@user_cards.size-1].each do |card|
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@user_cards[1..-1].

if card.count == 11 && @points + card.count > 21
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лучше ориентироваться на name у карты.

@points +=1
else
@points += card.count
end
end
end

#пропустить
def check
@check_available = false
end
end
4 changes: 4 additions & 0 deletions comments/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require_relative 'gamer'

class User < Gamer
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

На мой взгляд, класс User является более общим поэтому я бы сделал его базовым и потом наследовал от него классами Gamer и Dealer.

end