百行 HTML5 程式碼實現四種雙人對弈遊戲

發表於2012-06-30

來源:於丙超@developerworks

簡介: 本文是一個非常具有挑戰性的程式設計,因為 100 行程式碼,約莫 10000 個字元左右,將實現圍棋、五子棋、四子棋和翻轉棋四種雙人對弈遊戲。請注意,這四個對弈遊戲不是初級程式設計者的習作,而是有著棋盤、立體棋子、事件、走棋規則判斷、輸贏判斷的完整對弈遊戲,並且可以離線儲存到 iPad、Android 平板中,試想一下,把這種遊戲下載到平板中,就可以在火車,旅遊景區,等沒有訊號的地方進行對弈,是不是擴充套件了平板電腦的功能,是不是一種很愜意的事情。而且,關鍵是,這個程式沒有圖片,不需要去應用商店付費下載,僅僅是用 HTML5 技術寫的 100 行程式碼而已,絕對是目前最迷您精悍的雙人對弈遊戲原始碼。(編者注:由於網頁程式碼的寬度有限制,所以作者的原始碼經過了一些換行處理,特此說明。)

目標

要做一個完整的雙人對弈遊戲,至少要做如下事情,第一步:繪製棋盤。不同的棋類遊戲棋盤不同,這一點需要進行動態處理;第二步:繪製棋子。需要說明的是,圍棋,五子棋等這些棋子都是圓的啊,請不要為了圖片苦惱,在 HTML5 時代,我們用程式碼就可以實現立體圓形棋子;第三步:判斷落子事件。當然是要定位手指的點選位置,這四種棋中,有的是落在框裡面的,有的卻是落在縱橫交錯的棋盤十字線上,需要動態處理;第四步:判斷落子規則。下棋都有規則,不要因為程式碼少,就將規則打折扣,否則程式不成熟,會變成小朋友的玩具了;第五步:判斷輸贏。最後,我們要判斷輸贏。也就是要數子,這個事情必須由程式來完成,因為下棋總得需要一個裁判嘛;第六步:就是平板電腦時代,我們得實現離線應用。這個太重要了,否則,要是在臺式電腦上,接根網線玩的遊戲,已經遍地都是了,您寫得再牛,有什麼用?就是要移動,在沒有訊號的地方,才有市場,現在平板,智慧手機這麼多,在沒有網路訊號的地方,掏出移動裝置來下棋,才是一件很牛的事情。

繪製棋盤

前面說了圍棋、五子棋、四子棋和翻轉棋的棋盤並不相同,圍棋是縱橫 18 個格,其他三種棋則是 8 個格。所以繪製棋盤是需要有引數。這是個小問題,大問題是,選擇什麼方法來繪製棋盤?

HTML5 框架下,有至少 3 種方法:第一種,用 Canvas 畫線;第二種,用 DIV,CSS3 裡面增加了行列屬性;第三種,用 table 標籤。

用哪一種速度最快,程式碼少呢?答案是:第三種。多少有點失望啊,HTML5 不是萬能的。詳細程式碼如下:

上面程式碼中,最重要的是標黑體的第 6 行程式碼,這裡面有兩個訣竅,第一個就是 table 的定義,第二個就是使用了 Array 陣列。為什麼要使用陣列,而不是定義一個字串呢?答案是優化,就是 Array 陣列的 push 方法的速度要遠遠快於 String 字串的加 + 運算。共計 16 行程式碼,一個棋盤就畫好了,當然這其中不僅僅是畫線,還有棋子處理,事件定義等方法的呼叫,後面將陸續談到。

繪製棋子

繪製完棋盤,我們來繪製棋子。我們挑選的這四種棋,雖然棋盤不同,但是棋子都是相同的,都是黑白棋子。這在以前,做線上對弈,除了 Flash 能實現美觀效果外,其他的必須先請美工做幾副小圖片,HTML5 時代,美工的人力和溝通成本就節省了。

我們至少有兩種方法繪製棋子,第一種是:canvas 類,第二種就是 css 的圓角屬性。用哪種速度又快程式碼又少呢?答案是第二種,圓角。程式碼如下:

上面程式碼中,我們看到,我們將每一個棋子定義了一個 DIV,使用了 CSS3 的 shadow,gradient 屬性,並且可以根據棋盤的大小自動計算棋子的大小,另外,如果使用者不喜歡黑白顏色,甚至可以定義成紅黃顏色,女生和小朋友估計會喜歡。這 5 行程式碼是畫一個棋子的方法,做一個簡單的迴圈,就可以畫出多個棋子,方法如下。

處理事件

繪製完棋盤和棋子,我們來分析一下使用者的動作。使用者的動作無非就是兩種,一種是點選棋盤 table,另外一種就是點選棋子 DIV。難點在點選 table 這裡,我們要獲知使用者點選 table 的位置。

傳統思路可能是這樣,使用 event 方法,獲得 x,y 的座標,然後與 table 的左上角做減法,然後再跟單元格 cell 做除法。聽起來都麻煩。

如果您仔細閱讀了前面的程式碼,就應該發現,其實在畫棋盤是,我們向 array 陣列中 push 了一個 evt 方法,很明顯,這個 evt 方法要返回一個字串變數的,那麼他的內容是什麼呢?答案揭曉:

原理是一個 DIV。對了,這個新增事件的方法非常特殊,實際上是在每個棋盤的交叉的地方畫了一個 DIV,然後給 DIV 新增事件。

需要說明的是,DIV 一定要先定義,即 document.write 輸出出來,然後才能執行 onclick 的定義,否則會返回 DIV 未定義的錯誤。寥寥 10 行程式碼,把事件問題搞定了。

落子規則

前面說了,使用者點選事件有兩種,點選棋盤 table 事件我們採用額外增加 DIV 的方法巧妙解決了,第二種點選棋子的方法又該如何呢?

先要說明的是,點選棋子其實是一種錯誤的事件,點選棋盤可以落子,點選棋子是什麼意思?黑白棋點選棋子是無意義的,我們必須要進行判斷,不能在有子的地方落子,這是規則之一。所以必須要定義一個方法,判斷是不是點選的地方是不是有棋子。程式碼如下:

想不到吧,其實只要一行程式碼就可以就可以做是否有子的判斷,怎麼判斷的,訣竅就在於判斷 DIV 的顏色,棋子要麼黑,返回 0,要麼白,返回 1,但是空白地方是沒有顏色的,返回 null。這裡要特別注意返回值,後面判斷輸贏的時候還要用,所以不能簡單通過 true 或者 false 的的返回值來判斷是否有子,而是要判斷出有什麼顏色的子。

對於五子棋和圍棋,這一條規則夠用了,但是對於翻轉棋和四子棋,還有第二條規則:不能在四周空白的地方落子,就是說必須是相連的。也就是說,不僅僅要判斷點選的地方是不是有棋子,還要判斷其四周是不是有棋子,這個,不是可以有,而是,必須有。需要做一個小迴圈啊,程式碼如下:

迴圈中,反覆呼叫 isMan 方法判斷是否有棋子,所以如果 isMan 寫得不夠簡練,快速,不知道要耗費多少時間啊。數一數,總共 19 行程式碼就處理了落子規則。

到這裡,我們繪製了棋盤,棋子,獲得了點選時間,判斷了落子規則,才用了 40 行左右的程式碼,其實程式基本上可用了,但是我們不能滿足啊,還得讓他更加智慧一些,我們還需要一個裁判斷輸贏。

判斷輸贏

要判斷輸贏,我們必須要知道下棋的規則:

五子棋是各個方向的五子相連算贏,四子棋是各個方向四個子相連算贏,翻轉棋數棋子的個數,圍棋則要麻煩些,不僅僅數棋子個數,還要數圍住的區域。

邏輯上好像很複雜啊,似乎也是計算最多的地方,有點人工智慧的意思。沒錯,如果前面的基礎打得不好,這裡的確要耗費很多程式碼,但是因為我們前面定義了 DIV 用顏色判斷是否存在棋子的 iaMan 方法,這裡再使用一個小技巧,就可以輕鬆搞定這個輸贏判斷。先看看五子棋和四子棋的輸贏判斷程式碼,然後對照程式碼來分析。

共計 9 行程式碼就搞定,看懂沒?首先定義了一個 Javascript 多維陣列 rs=[[],[],[],[]],這種定義多維陣列的方法,挑出來重點說明一下,因為搜尋引擎上都是搜不到的,我講課時差不多遇到的學生也都不清楚,他們大多采用 new Array,然後加迴圈的蝸牛方法。

第二步:從落子的地方開始迴圈,注意,不是迴圈整個棋盤,為的就是節省時間啊。迴圈設計縱橫交叉四個方向,有棋子的地方,就向這個四維陣列 push 棋子的顏色。

第三步:把陣列 join 起來就 ok 啦,如果有 4 個或 5 個 1 相連,自然就是白棋勝,否則就是黑棋勝。

寫道這裡,就有點意思啦,注意我們處理的資料的方法,我稱之為“塊資料”的處理方法,就是充分利用 array 陣列,儲存一塊一塊的資料,無論寫入,讀取,還是統計分析,都是針對這一塊資料進行,這樣既可以提高內聚度,便於提煉出可以重用的方法,就可以大大的加快執行速度。

處理相連都不在話下,數子就更簡單了,使用塊資料處理方法,3 行搞定。

棋子初始化

環環相扣地寫到這裡,還有最後一個關於棋子的問題需要處理。那就是,下五子棋是從空白棋盤開始,其他三種棋卻一開始都是有子的。其實給一個空白棋盤也行,但是其他三種棋因為一般的前幾步走法都是固定的,我們為了提高智慧化程度,不得不在浪費四行程式碼,畢竟,我們的目標是一個市場化的產品,而不是一個初學者不考慮使用者體驗的程式。

其實就是呼叫了一下 moreMan 方法,注意也是塊資料引用,傳輸了一個陣列,用下劃線分割橫向和縱向座標。

做成離線應用

本文開頭就說過,臺式電腦的雙人或多人對弈程式早已多如牛毛爛大街了,只有移動應用才能有市場,我們的目標就是奔著這個來的,所以最後必須做成離線應用。

如何實現 HTML5 的離線應用,搜尋引擎很快能找到結果,其實只要三個關鍵步驟。

第一步;在 Web 伺服器的配置檔案中宣告一下。Tomcat 和 Apache 的宣告方式不相同,需要注意;

第二步:定義 manifest 檔案,檔案格式需要注意;

第三步:在 HTML 的檔案中呼叫一下 manifest 檔案。

根據這三個步驟,讀者可以自行搜尋細節,這裡就不贅述了,我只講搜尋引擎搜不到的。

另外需要說明的是,iPad 和 Android 平板上瀏覽器實現全屏的方法也不一樣,針對 iPad 使用者,我們還必須定義一行能夠實現全屏的程式碼。

9. 效果圖、線上演示、開放原始碼

本文的線上演示網址是:http://www.chofo.com/chess.htm,效果圖如下圖所示:

圖 1. 效果圖


百行 HTML5 程式碼實現四種雙人對弈遊戲

圖中加了一個選擇棋型別和設定背景功能,如要獲得全部原始碼,只要使用瀏覽器的檢視原始碼功能即可,限於篇幅,這裡就不貼了。

總結

作為一個程式設計師,最高的境界不是寫得程式碼越多越好,而是用最少的程式碼實現最多的計算,解決最多的問題。回想當年,蓋茨在編寫 Basic 時,為了節省幾個字元需要絞盡腦汁通宵達旦,以至於遺留了千年蟲世紀難題,反觀今日,在雲端計算時代,隨著硬碟和記憶體的容量越來越大,CPU 的運算越來越快,很多大型專案的程式設計師似乎失去了精簡程式碼的習慣。但是移動計算的硬體,目前還沒有那麼高的配置,本文通過 HTML5 對弈遊戲,使用“塊資料”計算方法,實現了用最少程式碼實現最多計算的目標,特別適用移動計算,與大家共勉。

 

相關文章