Clojure 中的发牌
我正在尝试编写一个蜘蛛纸牌播放器作为学习 Clojure 的练习。我正在尝试弄清楚如何发牌。
我(在 stackoverflow 的帮助下)创建了来自两个标准牌组的 104 张牌的洗牌序列。每张牌都表示为一个
(defstruct card :rank :suit :face-up)
蜘蛛的画面将表示如下:
(defstruct tableau :stacks :complete)
其中:stacks是牌向量的向量,其中4个包含5张牌面朝下和1张牌面朝上,而6个包含4张牌面朝下和1 张牌面朝上,总共 54 张牌,并且 :complete 是完整的 A-K 组的(最初)空向量(例如,出于打印目的,表示为 King-Hearts)。未发牌的剩余牌组应保存在参考中。
(def deck (ref seq))
在游戏过程中,画面可能包含,例如:
(struct-map tableau
:stacks [[AH 2C KS ...]
[6D QH JS ...]
...
]
:complete [KC KS])
其中“AH”是一张包含 {:rank :ace :suit :hearts :face-up false} 的牌,等等。
如何编写一个函数来处理堆栈,然后将剩余部分保存在引用中?
I am trying to write a Spider Solitaire player as an exercise in learning Clojure. I am trying to figure out how to deal the cards.
I have created (with the help of stackoverflow), a shuffled sequence of 104 cards from two standard decks. Each card is represented as a
(defstruct card :rank :suit :face-up)
The tableau for Spider will be represented as follows:
(defstruct tableau :stacks :complete)
where :stacks is a vector of card vectors, 4 of which contain 5 cards face down and 1 card face up, and 6 of which contain 4 cards face down and 1 card face up, for a total of 54 cards, and :complete is an (initially) empty vector of completed sets of ace-king (represented as, for example, king-hearts, for printing purposes). The remainder of the undealt deck should be saved in a ref
(def deck (ref seq))
During the game, a tableau may contain, for example:
(struct-map tableau
:stacks [[AH 2C KS ...]
[6D QH JS ...]
...
]
:complete [KC KS])
where "AH" is a card containing {:rank :ace :suit :hearts :face-up false}, etc.
How can I write a function to deal the stacks and then save the remainder in the ref?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是我在研究了上面的答案后提出的解决方案。请注意,我仍在完善它,并欢迎提出改进建议,特别是使用更惯用的 Clojure。另请注意,这些函数是在多个单独的文件中定义的,并且不一定按所示顺序出现(如果有区别)。
Here is a solution that I came up with after studying the answer above. Note that I am still refining it and welcome suggestions for improvements, particularly the use of more idiomatic Clojure. Also note that these functions are defined in several separate files and do not necessarily appear in the order shown (if that makes a difference).
您可以编写一个函数来获取给定序列中每个
size
项的chunk
向量,并使用另一个函数从前面删除这些块:然后也许添加一个函数来执行这两项操作(以
split-at
和split-with
为模型):假设每张牌最初都是
{:face-up false}
,您可以使用下面的函数用于翻转堆栈中的最后一张牌:然后是一个函数,用于处理给定牌组中的初始堆栈/块:
返回值是一个 doubleton 向量,其第一个元素是牌组的剩余部分,第二个元素是初始堆栈的向量。
然后在事务中使用它来考虑 Ref:
更好的是,将游戏的整个状态保留在单个 Ref 或 Atom 中,并从
ref-set
切换到alter
/swap!
(本例中我将使用 Ref,省略dosync
并将alter
切换为swap! 使用原子代替):
免责声明:这些都没有受到丝毫的测试关注(尽管我认为它应该可以正常工作,以我可能错过的任何愚蠢的拼写错误为模)。不过,这是你的练习,所以我认为将测试/完善部分留给你就可以了。 :-)
You could write a function to take
chunks
vectors ofsize
items each from a given sequence and another one to drop those chunks from the front:Then maybe add a function to do both (modelled after
split-at
andsplit-with
):Assuming that each card is initially
{:face-up false}
, you can use the following function to turn the last card on a stack:Then a function to deal out the initial stacks / chunks from the the given deck:
The return value is a doubleton vector whose first element is the remainder of the deck and whose second element is a vector of the initial stacks.
Then use this in a transaction to take the Ref into account:
Better yet, keep the whole state of the game in a single Ref or Atom and switch from
ref-set
toalter
/swap!
(I'll use a Ref for this example, omit thedosync
and switchalter
toswap!
to use an atom instead):Disclaimer: None of this has received the slightest amount of testing attention (though I think it should work fine, modulo any silly typos I might have missed). It's your exercise, though, so I think leaving the testing / polishing part to you is fine. :-)