我应该如何在clojure中代表国际象棋棋盘?

时间:2012-04-27 08:23:28

标签: java clojure chess

在Clojure(/ Java)中表示国际象棋比特的一些可行方法是什么?

http://pages.cs.wisc.edu/~psilord/blog/data/chess-pages/rep.html

我需要能够访问各个位并执行按位操作。

我想过使用java.lang.Long,但由于标牌,这会导致1x10 ^ 63的问题。我也不确定如何访问特定索引处的位?

我也看了BitSet,但理想情况下我需要一个固定的长度。

2 个答案:

答案 0 :(得分:7)

没有理由你不能长时间使用。正如你所指出的那样,问题在于java(并因此是clojure的)长签名,只允许63位为正数

默认情况下,Java允许算术溢出而不会出错。默认情况下,Clojure不允许算术溢出而不会出现错误(请参阅*unchecked-math*标志)。它增加了对算术运算和强制转换的额外检查,因此,例如,(byte 128)将导致异常。从clojure v1.3.0开始,有类似(unchecked-byte)的函数,它等同于java函数....

(unchecked-byte 128)
;=> -128 ; 2s-complement of 10000000
(unchecked-byte 2r10000001)
;=> -127 ; 2s-complement of 10000001

可提供大量unchecked-*次操作(see clojuredocs)。

如果您使用笔直长和unchecked-*操作,那么您可以使用bit-*操作来旋转/检查位。

最后将棋盘存储在原子中是有意义的,然后用(swap! chessboard fn args)

更新它

(2013年2月15日更新,稍微更惯用的交换!来电)

e.g。

(inc Long/MAX_VALUE) ; java.lang.ArithmeticException

(unchecked-inc Long/MAX_VALUE) ; wraps.
-9223372036854775808

(def chessboard (atom 0))
@chessboard
;=> 0
(bit-test @chessboard 1)
;=> false
(swap! chessboard bit-flip 1)
;=> 2
(bit-test @chessboard 1)
;=> true
@chessboard
;=> 2
(reset! chessboard 0)
;=> 0
(swap! chessboard bit-flip 63)
;=> -9223372036854775808 
(bit-test @chessboard 63)
;=> true 

答案 1 :(得分:1)

=> (def chessboard (byte-array 8))
#'user/chessboard

=> (vec chessboard)
[0 0 0 0 0 0 0 0]

=> (for [row (range 8)] (aset-byte chessboard row (rand-int 8)))
(3 0 6 6 2 3 6 7)

=> (bigint chessboard)
216179404987106823N

=> (defn bigint-to-array
 [bi]
 (.toByteArray (biginteger bi)))

=> (vec (bigint-to-array 216179404987106823N))
[3 0 6 6 2 3 6 7]

Clojure以这种方式支持您需要的大多数功能。像所有的clojure数字一样,clojure.lang.BigInt支持二进制操作(bit-etc.等)。在字节数组上,您可以使用java.util.Arrays中的所有方法(搜索,填充,排序)。

请注意bigint fn强制执行clojure.lang.BigInt,并且biginteger fn强制执行java.math.BigInteger。如果你想使用java.math.BigInteger的方法,你需要通过biginteger来强制你的bigint或字节数组。