Метод программирования: Как создать простую карточную игру

поскольку я учу язык Ruby, я становлюсь ближе к фактическому программированию. Я думал о создании простой карточной игры. Моим вопросом не является ориентированный Ruby, но я действительно знаю, хотят изучить, как решить эту проблему с подлинным подходом ООП. В моей карточной игре я хочу иметь четыре плеера, с помощью стандартной деки с 52 картами, никакими шутниками/подстановочными знаками. В игре я не буду использовать туз в качестве двойной карты, это всегда - самая высокая карта.

Так, проблемы программирования интересно о, следующие:

  1. Как я могу сортировать/рандомизировать деку карт? Существует четыре типа, каждый имеющий 13 значений. В конечном счете могут быть только уникальные значения, так выбор случайных значений мог генерировать дубликаты.

  2. Как я могу реализовать простой AI? Как существуют тонны карточных игр, кто-то уже понял бы эту часть, таким образом, ссылки будут большими.

Я - истинный Ruby nuby, и моя цель здесь состоит в том, чтобы учиться решать проблемы, таким образом, псевдо код был бы большим, только чтобы понять, как решить проблему программно. Я приношу извинения за свою грамматику и пишущий стиль, если это неясно, поскольку это не мой родной язык.

Кроме того, указатели на сайты, где такие проблемы объяснены, были бы большим ресурсом!

Спасибо за Ваши комментарии, ответы и обратную связь!

9
задан Svante 15 April 2010 в 00:23
поделиться

6 ответов

Немного для начала

Вы можете очень легко гарантировать уникальность карточек, используя числа от 0 до 51.

Массив # Метод перемешивания основан на алгоритме перемешивания Кнута-Фишера-Йейтса. http://en.wikipedia.org/wiki/Fisher–Yates_shuffle

class Card
  RANKS = %w(2 3 4 5 6 7 8 9 10 J Q K A)
  SUITS = %w(Spade Heart Club Diamond)

  attr_accessor :rank, :suit

  def initialize(id)
    self.rank = RANKS[id % 13]
    self.suit = SUITS[id % 4]
  end
end

class Deck
  attr_accessor :cards
  def initialize
    # shuffle array and init each Card
    self.cards = (0..51).to_a.shuffle.collect { |id| Card.new(id) }
  end
end

# people with Ruby 1.9 (or 1.8.7 with backports) can safely ignore this duck punch
class Array
  # knuth-fisher-yates shuffle algorithm
  def shuffle!
    n = length
    for i in 0...n
      r = rand(n-i)+i
      self[r], self[i] = self[i], self[r]
    end
    self
  end
  def shuffle
    dup.shuffle!
  end
end

тест

d = Deck.new
d.cards.each do |card|
  puts "#{card.rank} #{card.suit}"
end

вывод

6 Spade
5 Heart
2 Heart
8 Heart
8 Diamond
7 Club
J Diamond
4 Club
K Spade
5 Diamond
J Heart
8 Spade
10 Club
4 Diamond
9 Heart
7 Diamond
3 Diamond
K Diamond
7 Spade
Q Diamond
9 Diamond
6 Heart
A Heart
9 Club
A Spade
5 Club
J Club
Q Spade
2 Club
2 Spade
Q Heart
A Diamond
10 Spade
10 Diamond
Q Club
3 Club
A Club
K Club
6 Club
10 Heart
2 Diamond
3 Spade
K Heart
5 Spade
9 Spade
7 Heart
4 Spade
J Spade
3 Heart
4 Heart
8 Club
6 Diamond
15
ответ дан 4 December 2019 в 08:15
поделиться

Ответ Мачека хорош в том, что касается создания колоды.

Вы также спрашивали о других сущностях.

Вы, вероятно, захотите четырех «Игроков». Каждый игрок может управляться человеком или машиной.

Чтобы реализовать человека-игрока, вы взаимодействуете с экраном / мышью / клавиатурой; для реализации игроков, управляемых машиной, у вас есть рука, и вы можете видеть некоторые центральные карты на столе (все игроки должны знать о центральном столе, на котором хранятся все карты, которые будут на столе).

Отсюда логика зависит от того, в какую игру вы играете.

Как только ваш «Игрок» (ИИ) получит ход (например, для вашего объекта игрока вызывается метод takeTurn ), он должен изучить свои карты и принять правильные решения - взять карты из складывает на стол или кладет карты из руки на стол. (На столе почти наверняка есть как минимум два стека, к которым игрок может получить доступ - «Draw» и «Discard».)

Когда игрок-человек вызывает свой метод takeTurn , он должен взаимодействовать с экраном - обновление руки игрока, позволяющее ему брать и сбрасывать.

Когда каждый игрок закончит свой ход, он должен вернуться. Он не может напрямую вызвать следующего игрока (иначе вы начнете наращивать стек), поэтому вам нужна какая-то форма управления ходом, которая может вызывать игроков по порядку.Этот централизованный контроль также не позволяет игрокам знать друг о друге, в этом им на самом деле не должно быть (одна из лучших тактик объектно-ориентированного проектирования состоит в том, что каждый объект должен знать как можно меньше о других объектах).

... Все еще думаю ... Я могу добавить еще ...

2
ответ дан 4 December 2019 в 08:15
поделиться

Не беспокойтесь о поиске пакета AI

Вы узнаете больше и получите большее удовлетворение, написав код «AI» себя.

Начните с простого, просто подумайте:

  • состояние игры - какие карты были сыграны или просмотрены, какие карты видны всем игрокам
  • стратегия - как компьютерный игрок реагирует на его текущая рука и ее знание игрового состояния

, как только вы это заработаете, вы сможете разработать более сложные стратегии:

  • вывод - какие карты у игрока-человека, вероятно, есть на основе его предыдущих действий
  • поиск по дереву игр - как максимизировать шансы на победу, учитывая то, что может произойти

, тогда, если вы хотите получить действительно изощренный, вы можете начать изучать моделирование оппонента

3
ответ дан 4 December 2019 в 08:15
поделиться

Я не уверен, какую карточную игру вы хотите создать, но наиболее распространенный способ создания такого рода ИИ - это создание дерева возможных вариантов. Я не Думаю, есть библиотека, чтобы сделать это как таковое, но Ruby может легко создавать деревья.

Цель состоит в том, чтобы иметь корневой узел, который является настоящим временем, а затем каждый дочерний узел является возможным действием. Тогда дочерний узел каждого возможного действия является следующее возможное действие. Оттуда вы можете построить дерево всех возможных исходов. Все, что остается, - это выбрать тот результат, который вам нравится.

Если у вас нет всей информации (например, вы не можете видеть карты оппонентов) вы моделируете это. Под моделированием я подразумеваю предположение. Среднее значение всех имитаций / предположений даст вам хорошее представление о том, какое дерево ches, вероятно, будут лучшими.

Если вы можете сделать все, что у вас хорошо получается (а это действительно хорошее упражнение), о котором написаны сотни статей об ИИ, Google станет вашим другом. Единственная проблема с подходом, который я описал, заключается в том, что он может быть очень медленным, но есть много умных методов для его ускорения, таких как таблицы транспонирования, альфа-бета-обрезка и т. Д., Которые я пока не рекомендую вам искать.

1
ответ дан 4 December 2019 в 08:15
поделиться

Вместо того, чтобы втиснуть все это в комментарий, я добавляю это как примечание для людей, которые могут найти его полезным. Собственный Ruby 1.9 Array # shuffle! и Array # shuffle на самом деле использует алгоритм перемешивания Knuth-Fisher-Yates .

ruby-1.9.1-p376 / array.c

/*
 *  call-seq:
 *     array.shuffle!        -> array
 *  
 *  Shuffles elements in _self_ in place.
 */

static VALUE
rb_ary_shuffle_bang(VALUE ary)
{
    long i = RARRAY_LEN(ary);

    rb_ary_modify(ary);
    while (i) {
    long j = rb_genrand_real()*i;
    VALUE tmp = RARRAY_PTR(ary)[--i];
    RARRAY_PTR(ary)[i] = RARRAY_PTR(ary)[j];
    RARRAY_PTR(ary)[j] = tmp;
    }
    return ary;
}


/*
 *  call-seq:
 *     array.shuffle -> an_array
 *  
 *  Returns a new array with elements of this array shuffled.
 *     
 *     a = [ 1, 2, 3 ]           #=> [1, 2, 3]
 *     a.shuffle                 #=> [2, 3, 1]
 */

static VALUE
rb_ary_shuffle(VALUE ary)
{
    ary = rb_ary_dup(ary);
    rb_ary_shuffle_bang(ary);
    return ary;
}
5
ответ дан 4 December 2019 в 08:15
поделиться

Что-то очень простое для начала:

class CardGame
  DECK = %w[A 2 3 4 5 6 7 8 9 T J Q K].product(%w[c d h s]).map(&:join)

  def initialize(decks=1)
    @decks = decks
  end

  def shuffle
    @playing_deck = (DECK*@decks).shuffle
  end

  def deal(players=1, cards=5)
    shuffle
    @dealt = Array.new(players) { Array.new }

    @dealt.map { |hand| cards.times { hand << @playing_deck.pop } }
  end

  def display
    @dealt.each_with_index { |cards, i| puts "Player #{i+1}: #{cards.join(' | ')}" }
    puts "Cards used: #{@dealt.flatten.size}"
    puts "Cards remaining: #{@playing_deck.size}"
  end

  private :shuffle   
end

game1 = CardGame.new   
game1.deal   
game1.display    
puts 
game1.deal(4)  
game1.display   
puts   
game2 = CardGame.new(2)   
game2.deal(6,10)   
game2.display
0
ответ дан 4 December 2019 в 08:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: