2017-08-13 89 views
2

試圖找出如何爲國際象棋遊戲編程存儲一些有用的數據。Javascript:優化國際象棋遊戲的數據結構

我決定將由機載西洋棋棋子發出的光線存儲在Raycaster中;這個問題是關於這個結構的實現。

TL; DR(僅用於國際象棋遊戲玩家...)

首先,我已確定了三個各種射線:

  • Ray.NORMAL或Ray.FULL:它們是由發射所有的棋子,但不是棋子,在一個迭代的方式(車,象,後)否(騎士和國王)
  • Ray.CAPTURE:只能通過典當發出,左前方和/或右前方捕捉
  • Ray.OFFSET :向前移動時由兵發出,以及爲鑄造而成的國王/白嘴鴉

因此光線的定義如下:

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 
    } 
} 

光線也有兩個特殊化合物性質:

  • 遮蔽{射線:空,IDX:-1}
  • 交叉{ray:null,idx:-1}

它表示這個光線實例在哪裏可以由另一棋子被隱藏,並且其中另一個射線橫穿它,以檢測通過性和干擾(對於易位)

該問題:

如何存儲有效光線在RayCaster?

在優化諸如操作的方式:

    1. 添加新計算的射線,計算與先前存儲的人的相互作用,在MO,opmal成本?
  • 從一個給定的起始REF確定,所有目標磚/ REF?
  • 確定哪個容易射線靶向給定的參考,來計算在此瓦PRESSION平衡?

提出的解決方案/ ALTERNATIVES

  • 射線的單一陣列:最壞的情況下64層* 63層的元件,珍貴尋求的光線和計算相互作用
  • 地圖陣列:Map.set( startingRef,[list_of_emtted_rays_from_startingRef])
  • 數組映射:映射。集(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)?

+0

按方向和列/行/對角線存儲光線。 – Bergi

回答

0

終於因爲地圖是時間常數的訪問,我也考慮過雙地圖實現:

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 
} 

和AA簡單射線:

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 
} 

工作的其餘部分只是在射線類別確定如何兩條射線能相互作用(交叉或陰影)

感謝您的諮詢,最好的問候!