第三章 如何解八層三角殺棋 如何解八層三角殺棋 如何解八層三角殺棋 如何解八層三角殺棋? ? ? ?
第三節 壓縮盤面狀態資料結構 壓縮盤面狀態資料結構 壓縮盤面狀態資料結構 壓縮盤面狀態資料結構
第三節 第三節
第三節 壓縮盤面狀態資料結構 壓縮盤面狀態資料結構 壓縮盤面狀態資料結構 壓縮盤面狀態資料結構
對三角殺棋切一刀將三角殺棋分割為兩個子盤面的策略在第五種到第七種
測試時就須動用到 8G Bytes 的記憶體,若不希望動用到系統的虛擬記憶體,則
必須改變策略,犧牲三角殺棋程式搜尋勝負時的速度,在程式中對盤面狀態的資
料結構進行壓縮。進而達到節省記憶體的目的,使八層三角殺棋在目前配有 8G
Bytes 的個人電腦下,能進行對三角殺棋切一刀將三角殺棋分割為兩個盤面的測
試。
對於三角殺棋的盤面狀態的資料結構,每一個狀態勝負其實僅需 1 bit 就可
以儲存,其實不需使用要到 1 byte 來儲存。但是以 C 語言來說最小的資料型態
為 char,而該資料型態佔用的空間為 1 byte。根據這個簡單的想法,我們即對
資料結構做編碼壓縮,使之可以用 1 byte 的空間儲存八個盤面狀態的資訊。
設定盤面狀態陣列資訊的方式,是用兩個匹配陣列達成,如圖 3-22。匹配陣
列之所以會設計成這個樣子,目的是為了要和原本的盤面狀態資料陣列做 and、
or 運算。因為我們知道在程式語言中,做硬體的 and、or 邏輯運算的速度是很快
的,而這樣的設計將可以使八層三角殺棋求勝負解的程式多付出的計算時間降
低。
圖 3-22 壓縮盤面資料的匹配陣列
我們要將匹配陣列設計成如圖 3-22 的原因,則是因為這樣的編碼方式是較
為簡單的,我們將兩個陣列的值皆轉換為二進位就可以了解為何會這樣設計匹配
陣列,二進位表示法的示意圖如圖 3-23。原始盤面狀態陣列中每個元素原本是用
char 來宣告,該陣列元素所佔大小是 1 byte,也就是 8 bit,可表示的範圍為-128
~ 127。為了盤面狀態的壓縮,我們將其宣告為 unsigned char,可表示的範圍為
0 ~ 255,這樣的改變使得在程式設計上比較方便。
圖 3-23 匹配陣列二進位表示法示意圖
若我們要將盤面狀態陣列的一個元素設為 1,也就是將該盤面狀態設為先手
勝,我們只要將該盤面狀態陣列元素與 Compare1 匹配陣列中對應的元素做 or 運
算。若我們要將盤面狀態陣列的一個元素設為 0,也就是將該盤面狀態設為先手
敗,我們只要將該盤面狀態陣列元素與 Compare0 匹配陣列中對應的元素做 and
運算。
我們將狀態盤面設為 1 之所以要用 or 運算,主要是因為這樣不會影響到其
他狀態的值,如圖 3-24。因為其他盤面狀態的值與 0 做 or 運算,其盤面狀態不
會改變,只有與 1 做 or 運算會改變。將狀態盤面設為 0 用 and 運算也是同樣的
道理。其它盤面資料與 1 做 and 運算,其結果將不會改變原本的值,盤面資料原
本不論是 0 或 1,對其與 1 做 and 運算後,都還是原本結果。只有與 0 做 and 運
算才會改變結果,如圖 3-25。
圖 3-24 與匹配陣列作 or 運算
圖 3-25 與匹配陣列作 and 運算
要尋找對應的 Compare0 匹配陣列元素或 Compare0 匹配陣列元素時,我們是
使用簡單的求餘數計算。舉例來說,若以八層三角殺棋以倒推法從最後一個盤面
往前倒推時,遇到的第一個盤面狀態為 236-2,也就是 68719476734,但因為現在
資料壓縮的關係其真正儲存的盤面狀態陣列的索引值必須先除以 8,以便取得真
正的盤面狀態陣列的索引值。而儲存在盤面狀態陣列裡的位置是由除以 8 之後的
餘數來決定,其餘數的值會介於 0~7 之間,我們就利用餘數的值來尋找對應的匹
配陣列,這麼一來就可以達到資料壓縮的目的。資料壓縮演算法的簡單示意圖如
圖 3-26。
圖 3-26 壓縮盤面狀態之資料處理示意圖