Clojure—从一个向量中删除项目,表示从一副牌中处理。

时间:2022-11-18 22:47:48

I have a vector of vectors that I'm using to represent a deck of cards:

我有一个向量,我用它来表示一副牌:

[["A" "D"] ["K" "H"] ["K" "C"] ["K" "S"] ["K" "D"] ["Q" "H"] ["Q" "C"] ["Q" "S"]
 ["Q" "D"] ["J" "H"] ["J" "C"] ["J" "S"] ["J" "D"] ["T" "H"] ["T" "C"] ["T" "S"]
 ["T" "D"] ["9" "H"] ["9" "C"] ["9" "S"] ["9" "D"] ["8" "H"] ["8" "C"] ["8" "S"]
 ["8" "D"] ["7" "H"] ["7" "C"] ["7" "S"] ["7" "D"] ["6" "H"] ["6" "C"] ["6" "S"]
 ["6" "D"] ["5" "H"] ["5" "C"] ["5" "S"] ["5" "D"] ["4" "H"] ["4" "C"] ["4" "S"]
 ["4" "D"] ["3" "H"] ["3" "C"] ["3" "S"] ["3" "D"] ["2" "H"] ["2" "C"] ["2" "S"]
 ["2" "D"]]

At some point, I would like to "deal" some cards and have those cards removed from the deck.

在某一时刻,我想要“处理”一些牌,并将牌从牌堆中移除。

It's also fine if you'd like to tell me to use a seq and actually my original was a seq of vectors, so it doesn't matter either way to me.

如果你想告诉我用一个seq,实际上我的原件是一个矢量的seq,所以这对我来说无所谓。

I do know that I would probably like to create an atom of "remaining-deck" and delete the items from this seq or vector.

我知道我可能会创建一个“保留牌”的原子,并从这个seq或vector中删除这些项。

I'm planning to open-source this, and this is the pertinent part of the code:

我打算开源这个,这是代码的相关部分:

(def suits ["H" "C" "S" "D"])
(def ranks ["A" "K" "Q" "J" "T" "9" "8" "7" "6" "5" "4" "3" "2"])

(def deck (for [x ranks
                y suits]
            [x y]))


;; alternative deck that creates vector:

(def deck2 (vec (for [x ranks
                y suits]
            [x y])))

;;Another way to do it: While it's fine if I have a sequence of string pairs, I'd rather use vectors of vectors because I think destructuring will work better plus I think it'll be consistent across the program. 

(def deck3 (for [x ranks
                y suits]
            (str x y)))


(def hand [(rand-nth deck) (rand-nth deck)])

(def full-hand (concat board hand))

It looks like I could concatenate subvecs via using some .indexOf functions and tossing it into an atom, but I can't help but think that this is hacky and a Lisp should be able to do better than this. I seriously can't find any good information on this anywhere. I am aware of remove and filter, but those don't appear to be doing anything but throwing errors.

看起来,我可以通过使用一些. indexof函数将子向量连接到一个atom中,但我不得不认为这是hacky,而Lisp应该能够做得更好。我真的无法在任何地方找到任何好的信息。我知道删除和过滤,但是那些看起来不是做任何事情,而是抛出错误。


EDIT: Why the downvote? I'm simply trying to update the deck after dealing the cards.

编辑:为什么downvote吗?我只是想在处理完牌后更新甲板。

Thus if I was representing a smaller deck:

因此,如果我代表一个较小的甲板:

[["A" "D"] ["K" "H"] ["K" "C"] ["K" "S"] ["K" "D"] ["Q" "H"] ["Q" "C"] ["Q" "S"]]

Then after an update from (ex: player is deal ["Q" "S"] ["Q" "C"], the remaining deck should look like:

然后在更新后(ex: player是deal ["Q"] " [Q" "C"],剩下的甲板应该是:

[["A" "D"] ["K" "H"] ["K" "C"] ["K" "S"] ["K" "D"] ["Q" "H"]]

So that there are no shared hands or duplicate cards during the rest of the deal.

因此,在剩下的交易中,没有共享的手或重复的卡片。

2 个解决方案

#1


1  

I am not sure if I understood your question properly, but whatever I have gathered I would represent the deck as a set wrapped in a atom and on each hand play update the atom.

我不确定我是否正确地理解了你的问题,但无论我收集了什么,我都将把甲板作为一个包裹在一个原子里的集合,并且每一个手的游戏都更新了原子。

(def suits ["H" "C" "S" "D"])
(def ranks ["A" "K" "Q" "J" "T" "9" "8" "7" "6" "5" "4" "3" "2"])

(def deck (atom  (->> (for [x ranks
                            y suits]
                        [x y])
                      (into #{}))))

(defn hand []
  (-> (rand-int (count @deck))
      (drop @deck)
      (first)))

(defn play-hand []
  (swap! deck clojure.set/difference #{(hand)}))

(play-hand)

#2


1  

I know this had an answer accepted already, but are you convinced you want to introduce state here? I would consider passing through deck as a parameter to hand and the like. What happens when you want to deal your hands in parallel?

我知道这个答案已经被接受了,但是你确信你想在这里引入状态吗?我将考虑通过deck作为一个参数来传递。当你想要同时处理你的手的时候会发生什么?

#1


1  

I am not sure if I understood your question properly, but whatever I have gathered I would represent the deck as a set wrapped in a atom and on each hand play update the atom.

我不确定我是否正确地理解了你的问题,但无论我收集了什么,我都将把甲板作为一个包裹在一个原子里的集合,并且每一个手的游戏都更新了原子。

(def suits ["H" "C" "S" "D"])
(def ranks ["A" "K" "Q" "J" "T" "9" "8" "7" "6" "5" "4" "3" "2"])

(def deck (atom  (->> (for [x ranks
                            y suits]
                        [x y])
                      (into #{}))))

(defn hand []
  (-> (rand-int (count @deck))
      (drop @deck)
      (first)))

(defn play-hand []
  (swap! deck clojure.set/difference #{(hand)}))

(play-hand)

#2


1  

I know this had an answer accepted already, but are you convinced you want to introduce state here? I would consider passing through deck as a parameter to hand and the like. What happens when you want to deal your hands in parallel?

我知道这个答案已经被接受了,但是你确信你想在这里引入状态吗?我将考虑通过deck作为一个参数来传递。当你想要同时处理你的手的时候会发生什么?