随着我学习 Ruby 语言,我越来越接近实际编程。我正在考虑创建一个简单的纸牌游戏。我的问题不是面向 Ruby 的,但我确实知道想学习如何用真正的 OOP 方法解决这个问题。
所以,我想知道的编程问题如下:
最终只能有唯一的值,所以选择随机值可能会产生重复。
我怎样才能实现一个简单的 AI?由于有大量的纸牌游戏,有人已经想通了这部分,所以参考将是巨大的。
我是一个真正的 Ruby nuby,我的目标是学习解决问题,所以伪代码将是伟大的,只是为了了解如何以编程方式解决问题。
此外,指向解释这些挑战的网站的指针将是一个很好的资源!
感谢您的评论,答案和反馈!
让你开始的东西
您可以使用从 0 到 51 的数字轻松确保唯一的卡。
Array#shuffle
方法基于 Knuth-Fisher-Yates 洗牌算法。http://en..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
Ruby 1.9 的原生Array#shuffle!
和Array#shuffle
实际上使用了Knuth-Fisher-Yates shuffle algorithm。
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;
}
不要费心寻找一个 AI 包
通过自己编码“AI”,您将了解更多并获得更大的满足感。
开始简单,只是考虑:
游戏状态-已经玩过或看过什么牌,所有玩家都可以看到什么牌
策略-计算机玩家如何根据其当前手牌和对游戏状态的了解做出反应
一旦你有了这个工作,你可以得到开发更复杂的策略:
inference-人类玩家根据她之前的动作可能持有什么牌
game tree search-考虑到可能发生的情况,如何最大化获胜的机会
然后,如果您想使真正复杂,则可以开始查看opponent modeling
Macek 的答案就设置甲板而言是好的。
您还询问了其他实体。
你可能想要四个“玩家”。每个玩家可能是人或机器控制的。
要实现一个人的球员,你的界面与屏幕 / 鼠标 / 键盘;实现机器控制的球员,你有一只手,你可以看到一些中央卡在桌子上(所有的球员需要知道的中央表,持有任何卡,将在桌子上)。
从那里的逻辑是基于你在玩什么游戏。
一旦你的“玩家”(AI)得到轮到(例如,一个takeTurn
方法被调用你的玩家对象),它应该检查它的卡,并做出正确的决定-从桌上的堆叠卡或将卡从它的手放在桌子上。
当一个人类玩家调用他的takeTurn
方法时,它应该与屏幕接口-更新玩家的手,允许他绘制和丢弃。
当每个玩家完成他的回合时,它应该返回。它不能直接调用下一个玩家(否则你会开始建立一个堆栈),所以你需要某种形式的回合控制,可以按顺序调用玩家。这种集中控制还可以防止玩家相互了解,他们不应该真正需要(最好的 OO 设计策略之一是每个对象应该尽可能少地了解其他对象)。
...还在想...我可能会添加更多...
本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处
评论列表(41条)