Javascript:优化国际象棋游戏的数据结构
试图找出如何为国际象棋游戏编程存储一些有用的数据 我决定将船上棋子发出的光线存储在一个光线投射器中;这个问题是关于这个结构的实施 TL;DR(仅限国际象棋玩家…) 首先,我确定了三种射线:Javascript:优化国际象棋游戏的数据结构,javascript,dictionary,chess,Javascript,Dictionary,Chess,试图找出如何为国际象棋游戏编程存储一些有用的数据 我决定将船上棋子发出的光线存储在一个光线投射器中;这个问题是关于这个结构的实施 TL;DR(仅限国际象棋玩家…) 首先,我确定了三种射线: 雷.NORMAL或雷.FULL:它们由所有棋子发射,但不是棋子,以迭代的方式(车、主教、女王)或非(骑士和国王)发射 射线捕获:仅由棋子发射,左前方和/或右前方捕获 射线偏移:向前移动时由兵发射,用于投掷的国王/车发射 因此,光线的定义如下: class Ray { constructor (own
- 雷.NORMAL或雷.FULL:它们由所有棋子发射,但不是棋子,以迭代的方式(车、主教、女王)或非(骑士和国王)发射
- 射线捕获:仅由棋子发射,左前方和/或右前方捕获
- 射线偏移:向前移动时由兵发射,用于投掷的国王/车发射
class Ray {
constructor (owner, kind) {
this.owner = owner // chessman which emits ray
this.kind = kind
this.ref = null
this.sequence = []
}
// is computed afetr construction
expand (ref, sequence) {
this.ref = ref // starting ref (origin of the ray)
this.sequence = sequence // array of refs
}
// is called when ray is inserted into raycaster
interact (otherRay) {
// to be implemented
}
}
射线还具有两种特殊的化合物特性:
- 阴影{ray:null,idx:-1}
- 交叉{ray:null,idx:-1}
- 添加一个新计算的光线,计算与先前存储的光线的交互,以最低的成本
- 从给定的起始参考确定所有目标瓷砖/参考
- 轻松确定哪些光线指向给定的参考,以计算此瓷砖上的压力平衡
- 单个光线阵列:最坏情况下64*63个元素,查找光线和计算交互的成本很高
- 数组的映射:Map.set(startingRef,[list\u of\u emtted\u rays\u from\u startingRef])
- 数组映射:Map.set(endingRef[list\u of_targetinghg\u rays\u to_endingRef])
class RayCaster {
constructor() {
this.startings = new Map()
this.endings = new Map()
}
cast(board) { ...iterate through board and casts individual rays }
add(ray) { ... }
getRefsAttackedBy(ref) { ... }
getRefsAttacking(ref) { ... }
}
那么您对这个数据结构(RayCaster)有什么感觉呢?最后,由于地图是时间常数访问,我考虑了双地图实现:
constructor() {
this.startings = new Map()
this.endings = new Map()
this.counters = { rays: 0, interactions: 0 }
}
每个地图由电路板参考设置键,从“a1”到“h8”
添加光线是严格向前的:
raysFrom(board) {
let counter = 0;
board.traverse((ref, chessman) => {
let rays = chessman.cast(ref)
for(let ray of rays) {
this.add(ray)
}
counter += rays.length
})
return counter
}
和一条简单的光线:
add (ray) {
let skey = ray.ref
let sRays = this.startings.get(sKey)
if(sRays.indexOf(ray) === -1) {
sRays.push(ray)
}
ray.traverse((seqIdx, seqRef) => {
let seqKey = seqRef.key
let eRays = this.endings.get(seqKey)
if (eRays.indexOf(ray) === -1) {
eRays.push(ray)
}
})
}
计算光线交互(交叉和着色)更复杂:
computeInteractions() {
let counter = 0
// consider all starting rays
for (let {sRef, sRays} of this.startings) {
for (let sRay of sRays) {
sRay.traverse((seqIdx, seqRef) => {
// consider all possible intersections
// into the endings map
let eRays = this.endings.get(seqRef.ref)
for(let eRay of eRays) {
// ensure that rays are different
if (sRay !== eRay) {
sRay.interact(eRay)
eRay.interact(sRay)
}
}
})
}
}
return counter
}
剩下的工作只是在ray类中确定两条光线如何相互作用(交叉或着色)
谢谢你的建议,最好的问候 按方向和列/行/对角线存储光线。
computeInteractions() {
let counter = 0
// consider all starting rays
for (let {sRef, sRays} of this.startings) {
for (let sRay of sRays) {
sRay.traverse((seqIdx, seqRef) => {
// consider all possible intersections
// into the endings map
let eRays = this.endings.get(seqRef.ref)
for(let eRay of eRays) {
// ensure that rays are different
if (sRay !== eRay) {
sRay.interact(eRay)
eRay.interact(sRay)
}
}
})
}
}
return counter
}