Javascript:优化国际象棋游戏的数据结构

Javascript:优化国际象棋游戏的数据结构,javascript,dictionary,chess,Javascript,Dictionary,Chess,试图找出如何为国际象棋游戏编程存储一些有用的数据 我决定将船上棋子发出的光线存储在一个光线投射器中;这个问题是关于这个结构的实施 TL;DR(仅限国际象棋玩家…) 首先,我确定了三种射线: 雷.NORMAL或雷.FULL:它们由所有棋子发射,但不是棋子,以迭代的方式(车、主教、女王)或非(骑士和国王)发射 射线捕获:仅由棋子发射,左前方和/或右前方捕获 射线偏移:向前移动时由兵发射,用于投掷的国王/车发射 因此,光线的定义如下: class Ray { constructor (own

试图找出如何为国际象棋游戏编程存储一些有用的数据

我决定将船上棋子发出的光线存储在一个光线投射器中;这个问题是关于这个结构的实施

TL;DR(仅限国际象棋玩家…)

首先,我确定了三种射线:

  • 雷.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])
也许是个不错的候选人:

维护2个阵列图,一个用于发射,一个用于瞄准

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
}