跳到主要內容

發表文章

java實作多人連線麻將

斷斷續續用java寫了一個多人連線麻將。目前有一個Server,一個連線測試用Client,及一個單機測試用Client,全都是用java實作的Console程式。當進行中的牌局有人離開,則AI會接手打牌,直到所有人離開或打完一圈。 目前考慮使用WebSocket作一個Client。等有空再看看,已經作了點相關 研究 。

HTML5 Kill Sudoku

花了二晚將前次發表的 KillSudoku 移植成Web版,這次利用HTML5的繪圖功能取代掉原來簡單的文字模式顯示,改良成更好的圖形顯示。 這個版本實作了簡單的編輯功能,可以很容易的輸入或創造謎題(滑鼠左鍵輸入再點一下取消輸入)。不過目前還沒有實作檢查輸入的題目是否有唯一解,所以如果嘗試去解沒有唯一解的題目時可能有會不可預期的結果。 這次增加了一個新的Pattern:XYZ Wings,不過現在懶的介紹了~ 目前只在Chrome及Safari上試過。 ( 試試看 )

Kill Sudoku

前陣子斷斷續續的玩了一陣子 數獨 (sudoku),才終於把安裝在我的 野火機 裡的 OpenSudoku 的全部謎題解到只剩下一題VeryHard等級的謎題留作紀念。 在解這些題目的過程中一直有個想法,就是想要也自己寫個可以解數獨的小程式。數獨解答機在網路上很多,大多是使用 回溯法 為基礎的演算法製作的,也就是基於試誤法或窮舉法的方式,和我們一般在解題時使用的方法不同。我想要寫的是一個可以像人類一樣,使用各種技巧來解數獨謎題的程式,解題過程的每一個步驟都要清楚條列出來,這樣這個程式也可以用來作學習用途。 這個想法一直到最近才動手,目前還只是初步階段,寫了一支文字模式的小程式,可以從文字檔案裡讀出一個數獨謎題,將解題過程一個一個步驟都顯示出來,如下圖所示。將來可以寫成圖形化的APP或者是Web的型式,以更豐富的圖式方式來呈現。( HTML5 KillSudoku ) 這個程式是基於使用候選數法來製作的,所以從上圖可以看到個一個還未解出答案的格子裡都會列出全部的可能的數字,這些數字就叫作候選數。 ~~~ 一道數獨謎題是由9(row)x9(column)=81個格子(cell)組成,每一個cell裡可以填入1~9中的一個數字。這9x9個格子裡面,又可以再分成較小的9(box)個3x3的格子。 如上的一個9x9宮格圖所示,左側數字1~9為每一列(row)的編號,上方小寫英文字母a~i為每一行(column)的編號,b1~b9為每一個小九宮(box)的編號。 以上定義了幾個基本名詞:cell, row, column, box,再加上前面所提到過的候選數(candidate),就是我們全部需要知道的幾個定義。至於數獨的規則部份,這裡就不再複述。 ~~~ 這個程式的基本原理很單純,只是把我們平常在解數獨題時所用到的手法程式化而已。例如要找唯一數存不存在,就一行一行一列一列的去找看看某數是不是在這一行或這一列裡面是唯一的,如果是的話那就把這個數填入。目前版本的程式還很陽春,只實作了7種pattern,下面一一介紹。使用這7種找pattern的方法最多可以解出初級到中級左右的題目。 在開始找pattern前,需要把輸入資料作一些轉換成內部資料的處理。謎題的輸入是81個數字,由左至右,由上而下,一列一列的由上往下輸入。每一個數字範...

當機除錯法

小朋友:... 老王:... 小朋友:... 老王:兄弟怎麼了? 小朋友:老大,最近我在作的XXX在YYY的時候一直會ZZZ,不知道怎麼搞的, 我已經看Code看了幾天了, 一直找不到問題。 老王:為什麼不動手去找Bug呢?看Code太花時間了,也太難看出問題來。 小朋友:我也想,但實在是沒辨法啊... T_T 老王:不行Trace? 小朋友:不行... T_T 老王:不行丟訊息? 小朋友:不行... T_T 老王:Draw Something也不行? 小朋友:T_T 老王:丟Port也不行? 小朋友:嗚嗚嗚... T_T 老王:讓它叫一叫也不行? 小朋友 :嗚嗚嗚... T_T 老王:.... 小朋友:老大,還有什麼招式可以教教我嗎? 老王:好吧,這個時候就只好用我最後的絕招了!這是從我最尊敬的林老師那裡所繼承得到的絕招。據我所知,這個絕招原本只有三個人懂,一個是林老師,一個是我,另一個已經不在了,現在我傳授給你。 小朋友:(肅然起敬) 老王:聽好了! 我最尊敬的 林老師告訴過我說:你要當!就讓它當! 小朋友:...?? 老王:好了,以上就是禁斷的絕技當機除錯法的要訣。現在跟著我再複頌一遍。 老王 and 小朋友: 你要當!就讓它當! 老王:這是在任何方法都無效的情況之下,最後的Debug手段了,它的另一個別名叫作人工Debugger。這是因為我們要用人工的方法,一步一步的讓我們的程式在我們自己指定的地點造成當機,用這個手段來檢驗追踪程式執行的流程。這是個萬不得已的笨方法,很慢很花時間,但也只能用這個辨法了。 小朋友:我大概有點懂了。 老王:想辨法去找到可疑的問題點,再配合當機法慢慢夾擠,找到問題所在。總之,這個辨法的應用也還要再根據遭遇到的問題,配合應用。 我最尊敬的 林老師曾經告戒過我說:找Bug, 無論如何就是要不擇手段。你懂了嗎? 小朋友:嗯嗯,Yes Sir!我再去試試看。 (三個星期後....) 小朋友:老大!老大!哈哈哈,這下子終於讓我找到問題了!!! 老王:嗯,很好。怎麼找到的啊? 小朋友:我把電腦重灌,再重灌一次VC就可以Trace了。 ^_^ 老王:......

C++ INI 類別的設計

使用INI格式,底下有幾個優點。 格式簡單易懂 、容易使用 編輯器隨處可得,編輯維護相對容易 實作一個INI Parser不難 在程式裡,無論是作為程式設定儲存格式,或是作為小型的資料庫格式,使用INI資料格式對於以上需求,綽綽有餘。Good Game Editor的 資料格式 就是現成的實例。 ; INI的格式內容非常結構化,一個INI是由Section組成,每一個Section裡面可以包含Item,每一個Item是由一對Key和Value組成。 一個Section由字元'['及']'所構成,括號所包圍起來的字串為Section的名稱。如[Player]。 Item由Key及Value成對以字元'='隔開組成。如Name=Waync Cheng。 所有在字元';'後面到行尾的文字都視為註解而被忽略。 底下是一個簡單的範例。 [Player] Name=Waync Cheng Windows提供了 GetPrivateProfileString 系列的API可以讀寫INI的資料內容,使用Windows API寫入INI檔案的方式如下。 char StrName[] = "Waync Cheng" WritePrivateProfileString("Player","Name",StrName,"c:\\test.ini"); 從INI檔案讀出的方法如下。 char StrName[MAX_LEN]; GetPrivateProfileString("Player","Name","DefaultName", StrName, MAX_LEN, "c:\\test.ini"); ; Windows API使用起來稍微不方便,同時也不具跨平台,底下使用C++語言設計一個新的INI讀寫類別,主要的設計考量是更方便的讀寫INI。 C++語言提供了operator  overloading 的機制,正好可以被我們利用來作為一個介面,讓我們可以更直覺的讀寫INI的內容。 ...

Good Game Player for PSP

使用DevkitPSP編譯最新的程式 修了幾個小問題 先只port一種圖形格式 現在可以顯示png貼圖 下面是用我爛爛的野火機很克難的錄下來的一小段影片 品質不好請多見諒.. 沒錯 背景那個鬼鬼祟祟的人就是我

TextBox如何顯示行號

用C#來開發工具有很高的生產力,不過有些功能還是需要自己實作或是要找其它資源作整合。例如TextBox元件就沒有像許多文字編輯器都有的顯示文件行號的功能,這個功能需要自己想辨法。要作到顯示行號,有幾種方法,而下面要介紹的是一個較簡單的實現方法。 基本概念是這樣: 在TextBox左邊加一個Panel元件,在Panel上根據目前TextBox的位置顯示行號在其上 每當TextBox內容變更(OnTextChanged)或垂直捲軸發生滾動(OnVScroll)時重畫Panel 想法很簡單,實作也同樣不難。 在Form放上一個Panel元件,屬性設置如下: (Name) = panel1 BorderStyle = None Dock = Left 接著放上一個RichTextBox元件,,屬性設置如下: (Name) = textBox1 BorderStyle = None Dock = Fill WordWrap = False 完成後如下圖所示。 接下來是加上事件的處理。 在TextBox上加上TextChanged和VScroll二個事件處理函式。 private void textBox1_TextChanged(object sender, EventArgs e) {   panel1.Invalidate(); } private void textBox1_VScroll(object sender, EventArgs e) {   panel1.Invalidate(); } 當文字內容變更或發生捲動時,重畫在Panel上的行號,反應目前的狀態。 接下來加上Panel的Paint事件處理,在這裡面把行號顯示出來。這部份的處理主要分幾個部份。 計算可見範圍的行號,這樣作是避免作多虛功,只畫需要畫的部份 建立一個Off Screen Graphics,先畫在這個緩衝區上,然後再一次貼上畫面,這樣作是為了避免畫面更新如果不夠快的話會造成閃爍 底下是部份程式碼。 private void panel1_Paint(object sender, PaintEventArgs e) {   // ...