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

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

我决定将由机载西洋棋棋子发出的光线存储在雷克斯特(Raycaster)中; 这个问题是关于这个结构的实现。

TL; DR(仅限国际象棋游戏玩家...)

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

  • Ray.NORMAL或Ray.FULL:它们是由所有棋子排出而不是棋子,以反复的方式(白嘴鸦,主教,女王)或不是(骑士和国王)
  • Ray.CAPTURE:仅由典当,左前方和/或右前方拍摄发出
  • Ray.OFFSET:当前进时由兵发出,而国王/车队则为castling
  • 因此,光线是这样定义的:

    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}
  • 它表示这个光线实例可能被另一个棋子遮挡,并且另一条光线穿过它,检测通过性和干涉(对于castling)

    问题:

    如何在RayCaster中有效存储光线?

    以一种优化操作的方式,例如:

  • 添加一个新计算的光线,以最近的成本计算与之前存储的光线的相互作用?
  • 从一个给定的起始参考来确定所有有针对性的瓦片/参考?
  • 轻松确定哪些射线瞄准给定的参考,来计算这块瓷砖上的压力平衡?
  • 建议的解决方案/替代方案

  • 单光线阵列:最坏情况下的64 * 63元素,对于寻找光线和计算交互成本很高
  • 数组映射:Map.set(startingRef,[list_of_emtted_rays_from_startingRef])
  • 数组映射:Map.set(endingRef,[list_of_targetinhg_rays_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”

    casts(board) {
      this.counters = {
        rays: this.raysFrom(board),
        interactions: this.computeInteractions()
      }
    }
    

    添加光线很直接:

    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
    }
    

    其余的工作是在射线课程中确定两条射线如何相互作用(交叉或阴影)

    感谢您的建议,最好的问候!

    链接地址: http://www.djcxy.com/p/84633.html

    上一篇: Javascript : optimize data structure for chess game

    下一篇: stuck on minimax algorithm