跳到主要內容

good的資料格式

自從使用Ini之後我就不再碰XML了,在任何情況下,只要情況允許我都會儘可能的使用Ini作為資料格式或設定檔案。雖然Ini不像XML那樣天生就能表達結構化的資料,但也不是完全不行,至少應用在good上就沒什麼問題。

good專案資料格式使用Ini,再透過smallworld2的Ini模組就能很簡單的操作讀寫。

+ + +

專案檔頭

每個good專案檔裡,至少會有個名稱叫作good的Section,這相當於檔案的Header。這個Section包含了整個專案的內容資訊,是個總表。底下是個典型的範例。
[good]
version=0.3
name=mmc
window=176 208
texs=1
maps=2 3
sprites=4 5 6 7 8 9 10 11 12 13 14 15
levels=18
如上。格式版本是0.3;專案名稱是mmc;視窗的大小或解析度是176X208;有一個ID為1的貼圖資源;有二個ID分別是2和3的地圖資源;有12個精靈資源;以及一個ID為18的關卡資源。

多麼簡單一目了然,這就是我喜歡使用Ini的原因。

Script資源

接著有個叫scripts的Section,這個Section的內容是Script資源列表,和其它類型的資源比較起來是比較特別的,因為它不是在Section good裡面的一個項目,而是獨立出來一個Section。底下是個範例。
[scripts]
16=./mmc.lua
在scripts Section裡,每一個項目表示一個Script資源,項目的Key值表示為這個Script資源的ID,而項目的Value值表示為Script資源的檔案路徑。在good裡面的所有牽涉到檔案路徑的欄位,內容一律都是相對於專案檔本身的相對路徑。

貼圖資源

在專案檔頭裡列出的貼圖資源,每一個項目都對應到一個貼圖資源Section,底下是個簡單的範例。
[tex5]
name=tileset
fileName=./weeder.bmp
hasKeyColor=1
keyColor=253 0 255
貼圖資源Section的名稱固定以tex開始,後面的數字表示這個資源的ID。其它不同類型的資源也是以同樣的規則定義,所以你大概可以猜到Section map2就是ID為2的地圖資源。

上面的例子可以清楚的看到,這個貼圖的ID為5;名稱叫作tileset;圖形資源檔案路徑名稱為./weeder.bmp;使用KeyColor,顏色值為RGB(253,0,255)。

在目前的設定,good裡除了Script外所有的資源都有一個可有可無的name欄位。以上面的例子來說,假如tex5不指定名稱的話,那整個name項目都可以拿掉,沒必要再多寫個name=或name=""放在那裡表示空內容。

hasKeyColor和keyColor欄位也是同樣可有可無,一但hasKeyColor內容不是0(一般使用1)就表示要用使keyColor欄位的顏色,否則hasKeyColor和keyColor二個欄位都可以省略。

地圖資源

地圖資源的資料格式是所有資源裡最複雜的。底下是個簡單的例子。
[map26]
width=6
height=6
texture=5
tileWidth=32
tileHeight=32
cxTile=8
cyTile=8
data=k2VgYJBEw1JALA/ElmhYgQhxayLVy2CxVxqIAQ==
vgrid=1 128 128 128
hgrid=1 128 128 128
先看width和height欄位,這二個欄位定義的是這張地圖的大小是由多少個Tile組成;而每一個Tile的大小由tileWidth和tileHeight定義,單位是Pixel。

而Tileset是由texture欄位所指定,數字5表示這張地圖使用tex5作為Tileset,再去參考tex5就能得到相關資訊。cxTile和cyTile是一個輔助訊息欄位,它們記錄的值是這張地圖新建時,根據相關設定對Tileset作切割所得到的Tile個數。

而vgrid和hgrid分別是垂直及水平輔助線的設定,每一條輔助線有4的數字設定值,第一個數字是格線的Tile間隔數,後面三個數字是輔助線的顏色RGB值。

data欄位看起來是個亂它八糟的字串,這是編碼過的地圖資料。每張地圖是width乘height個Tile所組成,假如地圖比較大的話那要把所有資料都列出來會得到一個很大的字串,所以需要對它作壓縮,使用zip壓縮過後的資料還要經過base64作編碼才能以文字格式儲存下來。

精靈資源

精靈資源因為和地圖資源都是Tile Base的資源,所以格式和地圖資源的格式有點類似。底下是個簡單的範例。
[sprite32]
name=head_right
texture=5
tileWidth=32
tileHeight=32
cxTile=8
cyTile=8
data=8 60 9 60
loop=1
這裡只說明和地圖資源不同的地方,其它都和地圖資源相同。loop欄位簡單的指定這個精靈資源的用來作動畫播放時是否會自動的作循環播放,0表示只播一次,1表示作無限循環。

data欄位定義和地圖資源有所不同。精靈是由一個個的Frame所組成,每一個Frame有二個資料,Tile(指向Tileset)值及播放時間(Frame)。data欄位是由2的倍數的個數組成,每二個數字表示一個Frame,第一個數字表示Tile值,第二個數字表示的為播放時間。

關卡資源

關卡資源是的格式有點類似專案檔頭,因為關卡內含了物件。底下是個例子。
[level18]
width=176
height=208
script=Level
hasClearColor=1
clearColor=0 0 0
objects=19 20 21 22 23
width和height是關卡的大小,單位是Pixel。script欄位指定一個定義在Script資源裡的類別物件,這樣在執行時間就能透過它來控制這個關卡物件。

hasClearColor和clearColor類似貼圖的hasKeyColor和keyColor欄位,是用來指定一個作為清除畫面背景的顏色,同樣也是可有可無。

objects表示這個關卡總放擺放了5個物件在上面,ID分別是19到23。每一個物件類似像其它資源一樣,又關聯到一個物件資源Section。底下提供幾個範例。
[object31]
texture=1

[object30]
map=26
x=224
y=144

[object21]
sprite=4
x=144
y=32
script=BaseBlock

[object44]
dim=0 0 48 48
bgColor=255 0 0
以上分別表示了四種不同類型的物件,可以分別對應到在關卡編輯器裡可以擺放的四種物件類別。

object31是個貼圖物件,所以它有個texture欄位用來指明它是參考到tex1的貼圖資源。和底下的二個範例作比較,它少了x和y欄位,因為它的位置就在(0,0),而剛好是預設值,所以也省略不寫了。

object30是個地圖物件,參考的地圖資源是由map欄位所指定,這個地圖物件的位置是擺放在座標(224,144)的位置。

object21是個精靈物件,參考的精靈資源是由sprite欄位所指定。script的功能和關卡資源的script欄位功用一模一樣,在關卡裡面(包含本身)所有東西都可以指定一個Script物件。

object44是個純色塊物件,由bgColor指定色塊顏色RGB值,而dim的後二個數字用來指定色塊的大小。

+ + +

以上是good的資源檔格式的定義,非常簡單。也因為簡單再加上是文字格式,所以可以很容易也很方便的用文字編輯器開啟作編輯。不過為了避免發生錯誤,除非真的知道自己在改什麼,否則最好還是透過編輯器來編輯資料。

留言

這個網誌中的熱門文章

猜數字遊戲 (電腦猜人)

前幾天午睡時突然被告知要參加公司內部的程式設計比賽,題目是用C寫一支文字模式的4位數字猜數字遊戲,由使用者來猜電腦的數字。在上星期時其實就已經有公佈了,但我沒有注意到所以是臨時加入,還好這是個簡單的題目,不用花多少時間就可以寫出來。 規則: - 這是一對一比賽,雙方各選擇一4位數字,不讓對方知道。 - 4位數字由數字0至9組成,每位數不得重複。 - 雙方輪流猜對方的數字,直到一方猜中為止。 - A方猜B方的數字後,B方根據A方的猜測回答幾A幾B。 - 一個A表示猜中一個數字且位置正確,一個B表示猜中一個數字但位置不正確。 - 當一方猜中4A0B時即表示猜中對方全部4個數字且位置正確,贏得比賽。 - 例:B的謎底是4208,底下箭頭左測是A的猜測,箭頭右測是B的回答。    1234 ==> 1A1B    5678 ==> 1A0B    2406 ==> 1A2B    ...    4208 ==> 4A0B ; 寫個程式讓玩家來猜電腦的數字不難,不過我從來沒有寫過讓電腦來猜玩家數字的版本,所以花了點時間想想怎麼寫。 研究後歸納出二個點。 1, 使用窮舉法將所有可能數字組合列出。 2, 每次猜測後根據結果排除不可能是答案的組合,重複這個動作直到猜中答案為止。 第1點只是實作問題,第2點概念也很簡單,但要過濾不是答案的組合根據的是什麼?乍看之下沒什麼頭緒,不過想通之後就非常簡單了。 它的基本原理如下:假如謎底是4561,如果猜1524則會得到1A2B。從相反的角度來看,如果謎底是1524,則猜4561時也會得到1A2B的回答。 利用這個方法,每一次猜測一個數字X後,再以這個數字當作答案,來和所有剩下來的候選答案作比對,如果得到的結果(幾A幾B)和數字X是一樣的話,就把這個數字保留下來繼續作為候選答案,否則就過把這個數字過濾掉。下一把,繼續從候選答案裡選一個出來猜,重複上面的動作,直到猜中為止。 ; C++ STL的algorithm裡有個叫作next_permutation的函數,可以用來生成排列。 #include <iostream> #include <algorithm> using namespace std; int main () {   int myints[] = {1,2,3};  ...

KillSudoku 4顆星精彩數獨詳解 - 鍊技巧

這題數獨(sudoku)題目估計為4+顆星,有點難度。解題需要應用多種技巧,過程非常精彩有趣,是個好題。 底下使用 KillSudoku 作詳細圖解。 1,使用基本排除法則,可以簡單填入6個數字。到此為止,開始使用 候選數法 來解題。如下所示,為填入6個數字後的狀態圖。 2,如下圖,使用進階排除法,在第9列和第4行可以先排除幾個候選數。 3,如圖,在第2行有一個 Naked Subset (3,4),可以對3,4候選數作排除。附帶提一下,反過來看在同一行裡面也可以說有另一個Hidden Subset(2,5,8)存在。Naked Subset和Hidden Subset常是一體二面同時存在,只不過對我們來說,Naked Subset是相對比較容易看的出來。 排除第2行的3,4後,又可以對第2列以外的3作排除,如下圖。 4,接著,在第5行又發現了一個 Naked Subset (3,7,8)。 對第5行三個Subset以外的候選數3,7,8作排除後,又接著產生可以對第5行以外的3作排除。 5,這一題解到此為止,開始進入高潮。大部份能解到3顆星題目的人,猜想應該就此卡住。以下開始需要應用更高級的鍊技巧,才能夠繼續進行。 應用X-Chains鍊技巧,可以找到一條由4條強連結組成的鍊,可以排除候選數2。這裡的鍊指的是由2條以上的強連結組成,而所謂的強連結是指在同一行、或同一列或同一個Box裡,由唯二的候選數構成的連結。如上圖中的第9行中,只有二個2,這二個2構成一條強連結。為什麼說這是一條強連結?因為在這條連結的AB二個端點中,肯定會有一個2存在,要麼是A點要麼是B點。鍊技巧就是將多條強連結串連起來作候選數排除的技巧,而X-Chains是高級的鍊技巧裡面的基本技巧。 接上圖,這樣一來就又可以應用基本排除方法,填入3個數字,如下圖所示。 6,接下來就是本題最精彩的部份,以下需要連續找到3條鍊,才能繼續往下解。 7,找出3條鍊後,剩下來的部份就沒什麼特別的了,只需要應用基本法就能把所有剩餘數字填完。

KillSudoku 4顆星精彩數獨 (三) - XY-Chains

這是數獨解題技巧裡面的高級技巧,比X-Chains還再高一點點。會這個技巧的話,就可以解4或5顆星的題目了。 這個用來測試的題目,用 KillSudoku 來解可以解出,中間使用了2次Naked Subset,1次 W-Wings ,1次 X-Chains ,2次 XY-Chains 。所以算起來,這一題應該是有5顆星的題目。 附帶一提,目前找鍊的演算法並沒有去找一條最短的鍊,所以可以看到用 KillSudoku 解的時候,第36的步驟找到一條超長的鍊,這條鍊足足由13條連線構成,要是沒練過的話,絕對頭昏眼花,找不出這樣的鍊來的。 實際上在這個步驟裡,是可以找到另一條更短的鍊。不過目前以先能work,之後有空會再改進演算法的部份。