第一篇:五子棋游戲總體設計與實現
4.系統總體設計與實現
4.1 總體設計分析
總體設計是軟件開發過程中的另一個重要階段,在這一階段中將根據需求分析中提出的邏輯模型,科學合理地進行物理模型的設計。這個階段的主要目標是將反映用戶信息需求的邏輯方案轉換成物理方案,并為下一階段提供必要的技術資料。
4.1.1 總體設計原則
(1)整體性:軟件是作為統一整體而存在的。因此,在總體設計中要從整個軟件的角度進行考慮。
(2)靈活性:為保持軟件長久的生命力,要求該手機游戲軟件具有很強的環境適應性。為此,游戲軟件應具有較好的開放性和結構的可變性。
(3)可靠性:可靠性是指軟件抵御外界干擾的能力及受外界干擾時的恢復能力。
(4)經濟性:經濟性是指在滿足游戲軟件需求的前提下,盡可能地減小游戲軟件的開銷。
4.1.2 軟件模塊總體設計
軟件中各模塊之間的關系通常利用層次圖來表示。它是一種一系列多層次的用樹形結構的矩形框描繪數據的層次結構框圖。一個單獨的矩形框作為樹形結構的頂層,各個數據的子集由下面的各層矩形框代表,最底層的各個矩形框代表組成這個數據的實際數據元素(不能再分割的元素),它代表完整的數據結構。這模式非常適合于需求分析階段的需要,層次方框圖對數據結構描繪隨著結構精細化也越來越詳細。反復細化沿著圖中每條路徑,從對頂層信息的分類開始,直到確定了數據結構的全部細節為止。
開始游戲重新游戲游戲選項悔棋認輸五子棋游戲背景音樂退出游戲先后手設置游戲設置棋盤底紋設置棋盤大小設置游戲幫助幫助關于 圖4-1 游戲功能結構
本研究中將游戲軟件分為三大模塊,如圖4-1所示,包括:游戲選項、游戲設置和幫助。按照在調研中搜集的資料對每個模塊的功能進行編排制作。依據上述功能的分析,本研究中,將游戲軟件在三大模塊的基礎上又對每一大模塊又分為幾個子模塊:
游戲選項包括六個模塊:開始游戲、重新游戲、悔棋、認輸、背景音樂和退出游戲。
游戲設置包括三個模塊:先后手設置、棋盤底紋顏色設置和棋盤大小設置。
幫助包括兩個模塊:游戲幫助和關于。
4.2 游戲設計
4.2.1 游戲前的準備
本游戲在開發之前需要做一些前期準備工作,尤其是對于精通五子棋游戲的Java 游戲開發者來說。通常情況下,一款運用起來比較熟練地 J2ME 開發工具
是必不可少的。本游戲使用的是J2ME的簡化開發工具 Sun Java(TM)Wireless Toolkit 2.5.2 for CLDC,他需先將Java虛擬機安裝調試好之后才能使用。WTK 2.5.2 不帶有文本編輯功能,所以需要另尋搭配使用。本游戲采用 Ultra Edit 進行編輯。本游戲需要幾張后綴名為.png格式的卡通圖,除了一張用作五子棋游戲的 Logo 外,其余的都將在游戲中使用。4.2.2 游戲界面和事件驅動設計
游戲的界面設計采取傳統游戲界面風格,如圖4-2所示。游戲設計中采用傳統界面游戲風格,首先啟動游戲,然后進入游戲開始界面,界面中放置“設置”、“開局”、“幫助”、“關于”四個選項供玩家選擇。其中“設置”選項主要是對游戲的相關功能進行設置,如游戲難度設置。另外還有“悔棋”、“重玩”等項目的設置。除此之外還包括查看游戲幫助、游戲介紹等。
圖4-2 游戲界面設計
所謂事件驅動,簡單地說就是你點什么按鈕(即產生什么事件),電腦執行什么操作(即調用什么函數)。當然事件不僅限于用戶的操作。我們知道,事件是事件驅動的核心自然是。從事件角度說,一個事件收集器、一個事件發送器和一個事
件處理器組成了事件驅動程序的基本結構。事件收集器專門負責收集包括來自硬件的(如時鐘事件等)、來自用戶的(如鍵盤、鼠標事件等)及來自軟件的(如應用程序本身、操作系統等)的所有事件。將收集器收集到的事件分發到目標對象中則由事件發送器負責完成。具體的事件響應工作則由事件處理器完成,它需要運用虛函數機制(函數名取為類似于 Handle Msg 的一個名字),它往往要到實現階段才完全確定。事件處理器對于框架的使用者來說是他們唯一能夠看到的。棋類游戲通常具備兩個重要特性,首先是對戰雙方輪流落子,其次是落子間隔通常是不確定的,尤其是對戰后期,可能每一步棋都要經過深思熟慮,無論是人還是計算機,都無法對時間間隔有事先的預期。基于以上兩個特性,本游戲摒棄了大多數游戲采用的線程或定時器驅動游戲的方法,而采用了事件驅動的方法,即玩家的鍵盤或觸摸筆觸發游戲的下一個動作。事件驅動大大減少了不必要的工作量,只有玩家發出消息時,計算機才啟動運算,而在玩家思考期間,計算機不做任何運算和重繪操作。4.2.3 游戲的類設計
五子棋游戲屬于二維棋類游戲,因此可以定義一個 Chesses 類來表示棋子,用一個 Chess 類型的二維數組來包含棋盤上的所有棋子,對于該棋子玩家的區分使用Chesses 的 boolean 型的變量 is Player1 來區分。可以考慮直接生成數組的每一個對象而不是在數組建立后,而是把每一個棋子對象(Chesses)放在游戲的進行中生成,這主要是考慮到移動設備的資源有限,盡可能減少系統資源占用。這樣在游戲進行時,可以避免還沒有下的棋子在一開始就占用了系統內存,玩家每下一步棋,在數組相應位置生成該棋子的對象。
對于游戲中的每一類的設計,首先就是一個 MIDlet 類,Gobang 類繼承自MIDlet 類,通過方法 start App,pause App,destroy App 來通知游戲的開始,暫停和銷毀結束,用于連接設備的應用程序管理器(Application Manager)。
本游戲共由7個類組成,它們各自的功能如下:
(1)Gobang MIDlet類
負責程序的啟動和屏幕之間的切換;
(2)Gobang Canvas 類
玩家的對戰平臺,他繼承于 Canvas 類;(3)Setting 類
用于創建游戲的各項設置參數表單;
(4)Gobang Logic 類
游戲的邏輯類,負責勝負判斷和計算機落子;
(5)Dot 類
棋子類,包含了棋子的位置信息;(6)Help 類
游戲的幫助類,包含五子棋的一些常識信息和五子棋教學內容;(7)About類
游戲的關于類,包含游戲的版本、版權等信息。各個類之間的關系如圖4-3所示:
圖4-3游戲類設計
4.2.4 游戲的流程設計
對于棋盤界面的更新,游戲進行繪制棋子時是按照棋子的二維數組來完成的,玩家下棋后,設置is Player1 值,程序修改數組相應位置,然后重新繪制(repaint)。為了使游戲的操作盡可能的簡便,本文設計上不在游戲進入時設計菜
單,玩家可以直接開始對戰,而是在開始游戲的過程中設置重新開始和退出的按鈕。即一鍵開始,運行即玩,重來或退出都使用一鍵操作。游戲流程的設計依據主要是游戲的界面設計和游戲的類的設計。游戲啟動時,Gobang MIDlet 對象先顯示游戲的主屏幕,在屏幕下方一側是出軟鍵(軟鍵指描述抽象客戶端設備如何顯示),另一側是用軟件構成的菜單,菜單元素主要有“開局”、“游戲設置”、“游戲幫助”、“關于”選項。當玩家選擇“游戲設置”軟鍵時,則顯示游戲參數設置表單;當玩家選擇“開局”軟鍵時,則顯示游戲對戰主界面;當玩家選擇“游戲幫助”軟鍵時,則顯示游戲幫助表單;當玩家選擇“關于”軟鍵時,則顯示游戲關于表單。玩家進入游戲參數設置表單,當玩家按下“確定”軟鍵時,則確認當前游戲參數,返回游戲主屏幕;當玩家按下“取消”軟鍵時,則放棄此次對游戲的修改,直接返回游戲主屏幕。玩家進入游戲對戰畫布,對戰中畫布有兩個軟鍵,當玩家按下“返回主菜單”軟鍵時,則退出游戲到達游戲主菜單;當玩家按下“悔棋”軟鍵時,則進行悔棋操作;當游戲結束時,“悔棋”軟鍵被換成了“重玩”軟鍵。玩家進入游戲介紹表單,當玩家按下“確定”軟鍵時,返回游戲主屏幕。4.2.5 游戲算法的設計
1、五子棋的獲勝組合
有哪些獲勝組合是在一場五子棋的游戲中計算機必須要知道的,因此,獲勝組合的總數必須要求得。在本文中我們假定當前的棋盤為15*15:
(1)每一列的獲勝組合是11,共15列,計算水平方向的獲勝組合數,所以水平方向的獲勝組合數為:11*15=165。
(2)每一行的獲勝組合是11,共15列,則可計算垂直方向的獲勝組合總數,垂直方向的獲勝組合數為:11*15=165。
(3)同理,可計算正對角線方向的獲勝組合總數,正對角線上的獲勝組合總數為11+(10+9+8+7+6+5+4+3+2+1)*2=121。
(4)計算反對角線上的獲勝組合總數。計算反對角線方向的獲勝組合總數可計算為11+(10+9+8+7+6+5+4+3+2+1)*2=121。這樣可計算得所有的獲勝組合數為:165+165+121+121=572。
2、設計獲勝棋型
通過上面的計算,一個15*15的屋子棋盤在此已經計算出了會有572中獲勝方式,因此,我們就可以利用數組建立一些常規棋型,棋型的主要作用是:
(1)判斷是否有任何一方獲勝;
(2)根據當前格局判斷最可能的落子方式。
然而在現實中,高手留給我們的經驗就是把握前奏,如“沖四”、“活三”,除了“連五”以外,這些也是同向勝利的捷徑。
3、攻擊與防守
獲勝棋型的算法是中性的,不區分計算機和玩家,這就涉及到攻擊和防守何者優先的問題。而許多高手都認為五子棋的根本是“防守”,“攻擊”是靈魂。進攻是取勝的手段,是防守的延續和發展。許多經驗和研究表明,一個棋手只要掌握了全面的、基本的防守原理和技巧,就能和比自己棋力高一個等級的進攻型選手對抗,起碼能立于不敗之地。對手進過越偏激,則防守的效果越好。沒有進攻的防守就像只開花不結果,沒有實際意義,頑強的防守是反攻的前奏,沒有進攻的延續,防守也失去了價值。而這缺一不可。根據以上原理,計算機在接受最佳的攻擊位置之前,還要計算當前玩家的最佳攻擊位置。如果玩家存在最佳攻擊位置,那么計算機就將下一步的棋子擺在玩家的最佳攻擊位置上以阻止玩家的進攻,否則計算機便將棋子下在自己的最佳攻擊位置上進行攻擊。
4、用到的典型算法(1)坐標變換算法
游戲的實質其實是對所下棋子的位置進行操作和判斷,因此將己方、對方以及棋盤上空點的位置坐標存儲在相應的List中。我對所下棋子的坐標進行了處理,因為我所采用的棋盤為15*15,所以棋子橫坐標為0到14的整數,縱坐標也為0到14的整數。因此,每次在棋盤上下子之后,計算機在存儲該點的坐標時,便要對坐標進行加工。假設左上角點為firstPoint,它的實際坐標為(x1,y1),而我是將它作為(0,0)存儲的,其它的坐標,其它點都是以該點為標準進行變換的,假設棋盤上每個格子的寬度為w,某實際點為(x2,y2),變換后的坐標為(x,y),x=(x2-x1)/w,y=(y2-y1)/w。
(2)勝負判斷算法
勝負判斷的規則很簡單,就是判斷游戲雙方的棋子在同一條水平線、同一條豎線或是同一條斜線上誰先出現5個連續的棋子,誰先達到這樣的目標,誰就獲得勝利。在本設計中,是在每次下完一個子后進行判斷,看己方是否達到了勝利的標準,若勝利游戲便結束;否則,游戲繼續。
(3)人工智能算法
人工智能算法的主體思想分為以下三個步驟:
第一步:根據雙方的當前的形勢循環地假設性的分別給自己和對方下一子(在某個范圍內下子),并判斷此棋子能帶來的形勢上的變化,如能不能沖4,能不能形成我方或敵方雙3等。
第二步:根據上一步結果,組合每一步棋子所帶來的所有結果(如某一步棋子可能形成我方1個活3,1個沖4(我叫它半活4)等),包括敵方和我方的。
第三步:根據用戶給的規則對上一步結果進行排序,并選子(有進攻形、防守形規則)。
5、典型類的具體設計(1)應用程序類
Gobang 類用于連接設備的應用程序管理器(Application Manager),Gobang類繼承自 MIDlet 類,通過 Gobang 類的方法 start App,pause App,destroy App 來通知游戲的開始,暫停和銷毀結束。源代碼如下:
package com.occo.j2me.game.gobang;import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;public class Gobang extends MIDlet
//定義游戲界面的 Canvas 類 Gobang Canvas 的對象 Gobang public { Gobang Canvas gobang;Gobang(){
super();
gobang=new Gobang Canvas(this);//生成 Gobang Canvas 類的對象 gobang
} protected void start App(){
Display.get Display(this).set Current(gobang);
} protected void pause App(){
} protected void destroy App(boolean arg0){
}} //在屏幕上繪出游戲見面 gobang(2)游戲界面類
Gobang Canvas 類繼承自 Canvas,游戲的核心類是 Gobang Canvas 類,此類將完成游戲的繪圖、互動、控制、邏輯、等所有功能,此類的框架代碼如下:
Package com.occo.j2me.game.gobang;import javax.microedition.lcdui.Displayable;import javax.microedition.lcdui.Command;import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command Listener;public Gobang Canvas(Gobang gobang){
this.gobang=gobang;
}
protected void paint(Graphics g){
}
import javax.microedition.lcdui.Graphics;public class Gobang Canvas extends Canvas implements Command Listener{protected Gobang gobang;
public Gobang Canvas(){
}
}(3)棋子類
整個棋盤是一個 Chesses 類型的二維數組,棋盤上的每一個棋子都對應著一個Chesses 的對象,此類定義了一個棋子,源代碼如下:
package com.occo.j2me.game.gobang;public Chesses(){
}
public class Chesses {boolean is Player1;
public Chesses(boolean is Player1){
this.is Player1=is Player1;
}}
4.3 游戲實現
4.3.1 主類的實現
YpkWuZiQiActivity類是五子棋游戲的主類,同時也是五子棋游戲的入口,它繼承自Activity類。進入程序后,首先調用init()方法,init()方法通過調用setContentView(R.layout.welcomeview)顯示登錄該游戲的第一個界面。welcomeview.xml是一個布局文件,里面存儲了界面信息。該界面中有四個Button,分別為welButton1、welButton12、welButton3、welButton4,點擊每個Button都會觸發一個事件,其中點擊welButton1和welButton2還會給它的成員變量FIGHTINGMODE賦值,因為在人人對戰和人機對戰是寫在同一個ChessBoard類中的,所以需要通過FIGHTINGMODE的值來區分是人人對戰還是人機對戰。
點擊welButton1時,FIGHTINGMODE=1,然后會調用initTwo()方法,該方法通過調用setContentView(R.layout.chess)方法,來顯示對戰的界面。chess.xml文件存儲了對戰界面的信息。在chess.xml文件中調用了ChessBoard類,該類中主要定義了棋盤的信息,下文會對該類做具體的介紹的。在對戰界面中也有四個Button,分別是b1、b2、b3、b4。
首先來介紹一下b2,該Button的功能是返回主頁,調用init()方法就可以實現。b3的功能是重新開始,這個也只需要調用initTwo()方法。b3的功能是退出,調用了系統方法:System.exit(1)。下面重點介紹一下b1,該Button的功能是悔棋。該Button設定的點擊事件詳細內容如下:
b1.setOnClickListener(new OnClickListener(){ public void onClick(View v){ ChessBoard chess =(ChessBoard)findViewById(R.id.chess);Point temp = null;if(chess.whoRun == 1){
if(chess.firstPlayer.getMyPoints().size()>=1 &&chess.secondPlayer!=null){ temp=chess.secondPlayer.getMyPoints().get(chess.secondPlayer.getMyPoints().size()-1);
chess.secondPlayer.getMyPoints().remove(temp);chess.freePoints.add(temp);temp=chess.firstPlayer.getMyPoints().get(chess.firstPlayer.getMyPoints().size()-1);chess.firstPlayer.getMyPoints().remove(temp);chess.freePoints.add(temp);chess.freshCanvas();
}
} if(chess.whoRun == 2){ if(chess.firstPlayer.getMyPoints().size()>=1 && chess.secondPlayer!=null){ temp=chess.firstPlayer.getMyPoints().get(chess.firstPlayer.getMyPoints().size()-1);chess.firstPlayer.getMyPoints().remove(temp);chess.freePoints.add(temp);temp=chess.secondPlayer.getMyPoints().get(chess.secondPlayer.getMyPoints().size()-1);chess.secondPlayer.getMyPoints().remove(temp);chess.freePoints.add(temp);chess.freshCanvas();
} })首先獲取ChessBoard對象,該對象繼承自View,詳細的定義了棋盤信息,主要負責顯示棋盤的內容。接下來判斷一下觸發悔棋事件的是哪一個玩家,再判斷是否符合悔棋的條件,這個條件很簡單,就是棋盤上至少要有兩個棋子。之后便進行悔棋操作,分別將兩個玩家最后下的棋子取出,程序實現就是將兩個ArrayList的最后一個元素remove出來,再分別放到記錄棋盤中沒有棋子的點的}
}
集合中,最后更新一下畫布,主要是調用ChessBoard的invalidate()方法。通過以上步驟之后,呈現在我們面前的便是悔完棋的畫面了。
點擊welButton2時,FIGHTINGMODE=2,之后的步驟便會點擊welButton1是相同的了,不同的是,由于對戰模式的改變,從人人對戰變成了人機對戰。
點擊welButton
3時,通
過
initThree()
方
法
調
用setContentView(R.layout.netchess)方法實現網絡對戰。詳細的對戰實現細節將會在下文一一介紹。在這個界面中只保留了兩個Button:b2和b4。這兩個Button所實現的功能和上面的b2和b4是相同的。
最后,welButton4比較簡單。它所實現的功能為退出應用程序,調用System.exit(1)方法。4.3.2 游戲設置類的實現
游戲設置表單用來對游戲參數進行設置,包括棋盤大小、先手選擇、智能級別。表單中使用了 Gauge 和 Choice Group 兩種高級用戶界面組件。
1、棋盤尺寸選擇
標準的五子棋棋盤為 15*15,但為了滿足不同玩家的需求,這里提供了大小為10*10 到 20*20 的棋盤,用戶可以通過 Gauge 組件改變。棋盤的最小值為 10,而Gauge 組件的最小值為 0,所以當前的 Gauge 值需要角上 10 才是當前棋盤大小。創建 Gauge 組件的代碼如下:
form = new Form(“ 游戲設置”);// 創建參數設置表單并添加標簽 gauge Size = new Gauge(“棋盤規格: ” + board Size + “ X ” + board Size, true, 10, board Size-10);//棋盤規格
form.append(gauge Size);
圖4-4 棋盤尺寸的設計
在Gauge交互模式下可以為Gauge對象所在的表單對象綁定一個Item State Listener 事件監聽器,并在監聽器上捕捉 Gauge 對象的事件,當 Gauge 的值發生變化時就會觸發事件。這里將根據 Gauge 的當前值改變標簽,顯示當前的棋盤大小。其代碼如下:
public void item State Changed(Item item){
if(item == gauge Size)//當 Gauge 組件發生變化時
{
int bs = gauge Size.get Value()+ 10;//獲取當前的 Gauge 值并計算棋盤大小(加10)
gauge Size.set Label(“棋盤規格: ” + bs + “ X ” + bs);//改變 Gauge 組件的標簽
}
}
2、難度選擇
游戲的難易程度根據計算機的智能級別來控制,創建及添加選項的方法和復選框一樣,所不同的是在創建 Choice Group 對象時,類型設置為 1(單選)。對于單選框,set Selected Index 只能用來指定某個選項被選中,因此,布爾值 selected 的值必然為 true,否則便沒有意義。
游戲共有 3 個難度級別,分別是:拜師學藝、棋行天下、誰與爭鋒(此游戲中并未作出區分),初始情況下為拜師學藝,該選項的索引值為 0。創建難度選擇單選框的代碼如下:
level = 1;//默認情況下的難度級別
choicelevel = new Choice Group(“電腦智能級別:”, 1);//創建難度級別選項組 choicelevel.append(“拜師學藝”, null);//難度 1 choicelevel.append(“棋行天下”, null);//難度 2 choicelevel.append(“誰與爭鋒”, null);//難度 3
choicelevel.set Selected Index(level-1 , true);//設置默認情況為難度 1,索引值為0
form.append(choicelevel);//將選項組添加到主表單中
游戲設置選項表單還有兩個 Command 對象,分別用于玩家卻熱和取消,所以表單需要監聽軟鍵事件和組件事件:
public class Setting implements Command Listener, Item State Listener
3、棋手選擇
選擇先手和難度等級用 Choice Group 組件來實現。Choice Group 組件用來構造選擇框,其構造函數如下:
Choice Group(String label, int choice Type)選擇先手的選項框為選擇組件,屬性為復選框,標簽名為空。創建好選擇組件后,逐條添加選項元素。添加選項的方法如下:
int append(String string Part, Image image Part)該方法追加一個選項元素到選擇組中,追加的選項為選擇組中的最后一個元素,選擇組的大小加 1。
對于多選類型的 Choice Group,還可以設置個別選項的選擇狀態。設置初始選擇狀態的方法如下:
void set Selected Index(int element Num, Boolean selected)這里創建一個只有一個選項元素的多選框用于玩家設置是否計算機先行,在默認情況下為true,創建完成多選框后將其添加到主表單中,代碼如下:
Computer First = true;//在默認情況下為計算機先行 choice First = new Choice Group(null, 2);//創建復選框 choice First.append(“電腦先手”, null);//添加選項元素
choice First.set Selected Index(0, Computer First);//設置多選框的默認狀態 form.append(choice First);//將多選框添加到主表單中 4.3.3 棋子類的實現
1、棋子的行列位置
此五子棋游戲是一個二維棋類游戲,所以定了了一個 Dot 類來表示棋子。由于移動設備的局限性,所以程序不在下每一步棋時生成一個對象,而是在游戲進行時,玩家或者計算機沒下一步棋,在數組相應位置生成該棋子的對象,而將已經下過的棋子保存到數組中隨時檢索,這樣可以避免過多棋子對象占用系統內存。Dot 類的 UML 圖如圖 4-5 所示:
圖4-5棋子行列設計
Dot 類主要有兩個變量 row 和 col,分別表示行和列:
public int row;//行
public int col;//列
2、檢查越位
棋子的位置并非是任意的,玩家和計算機每走一步棋之前都要線檢查該位置的合法性,即棋子是否在棋盤上,否則判為無效落子。檢查是否越界的代碼如下:
public boolean is In Board(int board Size)//判斷棋子是否越界(超出棋盤){ return row >= 0 && row < board Size && col >= 0 && col < board Size;}
3、修改棋子位置
在創建好 Dot 對象后,Dot 類提供了兩種方法更改棋子位置,包括設置行列位置和從已有棋子中復制參數。
public void set Row Col(int r, int c)//設置棋子位置
{
row = r;col = c;
}
public void copy From(Dot d)//復制已有的棋子
{
row = d.row;
col = d.col;
} 4.3.4 對戰邏輯類的實現
1、建立數據結構
本程序以數組保存當前盤面的情況,每個位置可能有三種狀態:空、玩家的落子、計算機的落子,分別用 0、1、2 來表示。代碼如下:
public static int PLAYER_NONE = 0;//該位置為空
public static int PLAYER_COMPUTER = 1;//該位置有電腦的落子
public static int PLAYER_HUMAN = 2;//該位置有玩家的落子
棋盤在初始情況下為空,即棋子上沒有任何棋子,在Gobang Logic類的構造函數中對棋盤進行初始化:
table = new int[board Size][board Size];//創建棋盤數組 for(int r = 0;r < board Size;r++){
for(int c = 0;c < board Size;c++)
table[r][c] = 0;//初始化盤面為空 }
除了記錄棋盤上每個位置的落子狀態外,程序還將對每種狀態的位置個數進行統計,以對算法進行簡化。對三種狀態的統計存儲在整型數組中,該數組為全局變量。
private int player Counter[];
在 Gobang Logic 類的構造函數中對三種狀態的計數進行初始化,即棋盤上都是空、計算機的落子或玩家的落子狀態的個數為 0,在數據結構上,把空也當做某一特殊玩家。
初始化代碼如下:
player Counter = new int[3];//落子狀態計數器
player Counter[0] = board Size * board Size;//整個棋盤都是空的狀態 player Counter[1] = 0;//電腦落子0 player Counter[2] = 0;//玩家落子0
2、落子和悔棋
這里使用了一個 Dot 類棋子對象來記錄最后一步棋的位置,當玩家下了一步棋后需要將上一步重新繪制,以消除旗子上的引導框。另外,還是用了堆棧來存儲最近的幾步落子,以便玩家悔棋。
private Dot last Dot;//棋子對象,存儲最后一步落子 private Stack steps;//棋子對象的堆棧
最后一步棋子和棋子堆棧在 Gobang Logic 類的構造函數中進行初始化;
last Dot = new Dot(board Size);//創建棋子對象用來存儲最后一步棋,初始化
位置為棋盤中央steps = new Stack();//堆棧對象,用來存儲最近的幾部棋在棋盤上落子的代碼如下:
private void go At(int row, int col, int player)//電腦或人在 row、col 位置上走
{
int last Row = last Dot.row;//記錄上一步的行坐標
int last Col = last Dot.col;//記錄上一步的列坐標
table[row][col] = player;//當前位置填充玩家代碼
last Dot.set Row Col(row, col);//將這一部設置為“最后一步”
game Canvas.repaint At(last Row, last Col);//重新繪制上一步(將引導框去掉)
game Canvas.repaint At(row, col);//繪制當前這步
switch(player)//統計雙方落子數量
{
case 1:
player Counter[1]++;//電腦的步數
break;
case 2:
player Counter[2]++;//玩家的步數
break;
}
player Counter[0]--;//空白的個數
if(steps.size()> 10)//堆棧數量超過上限(10)
steps.remove Element At(0);//清除棧底
steps.push(new Dot(row, col));//將當前這步棋子壓入堆棧
}
Stack(堆棧類)從 Vector 集成而來,它使用 push()方法進入堆棧,需要時使用 pop()方法從堆棧的頂部將其取出。悔棋動作由玩家做出,從數據結構來看,是同時后退兩步(將最后兩步棋位置的落子狀態設置為空)。
Stack 類的 peek()方法將獲取棧頂對象,但不移。悔棋代碼如下: :
public boolean undo()//悔棋
{
if(steps.size()>= 3)
{
Dot d = new Dot();//創建棋子對象
d.copy From((Dot)steps.pop());//從堆棧彈出的棋子中復制行列位置坐標
table[d.row][d.col] = 0;//將該位置設置為空
game Canvas.repaint At(d.row, d.col);//在棋盤上重新繪制該位置
d.copy From((Dot)steps.pop());//從堆棧彈出的棋子中復制行列位置坐標
table[d.row][d.col] = 0;//將該位置設置為空
game Canvas.repaint At(d.row, d.col);//在棋盤上重新繪制該位置
d.copy From((Dot)steps.peek());//獲取棧頂對象,作為最后一步棋存儲 last Dot.copy From(d);
game Canvas.repaint At(d.row, d.col);//重新繪制最后一步(添加引導框)return true;//悔棋成功
}
else
{
return false;
//悔棋失敗
}
} 4.4 本章小結
本章主要內容是游戲的實現,包括主類的實現,如構造函數、事件處理等,游戲幫助和介紹表單類的實現,游戲設置類的實現,如棋盤、選手、難度等,旗子類的實現,如棋子行列位置、檢查越界等,對戰邏輯類的實現,如落子和悔棋、邏輯運算等的實現。
第二篇:QT基于linux的五子棋游戲設計與實現
課題名稱:基于linux的五子棋游戲設計與實現
專業:計算機科學與技術(計算機工程方向)
開發工具及語言:,ubuntu12.04,QT
運行環境:linux下的QT
論文字數:1w左右
是否需要PPT:是
是否需要安裝說明:是
所在城市:武漢市
所在學校:華中農業大學楚天學院
功能需求分析
系統的基本功能需求分析如下:
(1)游戲進入界面的菜單選擇,有自我對戰、人機對戰、網絡對戰和退出 游戲四個選項;
(2)進入游戲之后,顯示一個十三行十三列的五子棋的棋盤。棋盤旁邊顯 示一個菜單,菜單選項有棋局重現、繼續上步、上級菜單和退出游戲,在界面上可以在棋盤落子操作和菜單操作之間進行切換,用鍵盤的按鍵來控制,棋局重現功能是在某方勝利之后才能手動操作一步步查看并回顧雙方下棋的過程;繼續上步可以切換回棋盤操作;上級菜單功能可以使五子棋游戲退出當前的游戲模塊(自我對戰、人機對戰、網絡對戰其中的一種),回到游戲開始界面時候的菜單,進行重新選擇;退出游戲是退出整個游戲界面;
(3)棋盤上顯示光標,可以對光標進行移動操作,也可以在棋盤和菜單來 回切換的時候重繪和擦除;
(4)在上面棋盤將光標移動到上面對應的位置,可以落子,棋盤上將在光 標顯示處出現相應的棋子,并且棋子在橫縱交點處;
(5)自我對戰的過程中有悔棋的功能;
(6)游戲的過程中會有提示信息,如該哪一方落子,棋盤旁邊顯示相應按 鍵對應的操作列表;
(7)可以自動判斷勝負,勝利一方形成一列的五個或5個以上的棋子閃 爍數次,顯示是黑方或者白方已經勝利的字樣,并且停止落子的功能;
(8)能夠實現三種游戲模式,自我對戰、人機對戰和網絡對戰。
非功能需求分析
非功能需求如下:
(1)在程序運行的過程中程序不能崩潰,更不能使系統出現問題,造成 災難性的后果;
(2)希望在此項目的基礎上不做改動或做很少的改動就能在其他的系統 或設備上運行;
(3)界面清晰容易看懂,方便玩家操作;
(4)游戲運行速度不能太慢,要反應及時,以免影響玩家的興趣。
(5)程序代碼必須每行都有詳細注釋。以上是要登記的內容。這個是例子。自己修改相關信息。一定要寫的詳細,開發以文檔為依據。注意請把文件名換成自己的作品名,以防技術開發錯誤
注意事項:
第三篇:區域游戲五子棋
10:10-10:40 區域游戲
一、活動目標:
1、新增區域中幼兒能迅速接受理解新游戲。
2、大膽選擇自己喜歡的游戲材料和游戲內容,自主愉快地游戲。
3、能與同伴合作游戲,積極交流自己的想法。
二、活動準備:
1、經驗準備:知道各區域的游戲玩法。
2、物質準備:(1)各區游戲材料如:穿編游戲、飛行棋、小畫板等。
(2)新增游戲區域材料如:五子棋
3、區域內容:
(1)公共區域:大舞臺、美發屋等。(2)班級區域:
(3)美食區(關東煮):肉串、涮爐等。
美食區(面包店):面包、披薩等。
美食區(咖啡店):咖啡機、桌椅等。
動手區(制作區):剪刀、雙面膠等。
動手區(編織區):編制籃等。
益智區(好玩的磁鐵):磁鐵、迷宮板等。
益智區(解鎖):鎖、鑰匙等。
閱讀區:書籍,桌椅等。
三、活動過程:
(一)介紹玩法,激發興趣。
教師:今天我們的益智區有了新的棋類游戲——五子 棋。
五子棋是中國民間的一種棋類小游戲,十分地簡單,誰先橫排、豎排、斜排列出5個棋子就算獲勝。
(在電腦上下載五子棋的小游戲進行演示,并講解。)
(二)提出要求,注意安全。
師:
游戲前老師有幾點要求提醒大家。
1、動手區里做粘貼畫時要注意不要把豆子撒在地上,更不能放進鼻子耳朵里。
2、建構區的小朋友在堆擺易拉罐的時候請輕拿輕放。
3、益智區里初學五子棋的小朋友遇到問題主動找老師。
4、要和其他小朋友文明交往、合作,學會謙讓。
5、垃圾放在垃圾桶,不可以隨地亂丟。
小朋友們坐坐好,坐的好的小朋友先插卡進區。
(三)自主進區,觀察記錄
1、了解幼兒入區的情況,是否全部入區,情緒如何。
2、關注各區域活動情況,教師適當加入。
3、仔細觀察并記錄,給予有困難的幼兒幫助。
4、提醒幼兒遵守游戲規則,學會謙讓合作。
(四)重點指導手工區——五子棋
(五)結束活動,觀察記錄。整理和收拾
督促幼兒收拾整理,做到輕、快、齊,教師協助收拾整理。
(六)游戲評價
(1)講解與展示
幼兒自己介紹自己的作品,感受成功后的快樂。
(2)交流與發現
讓幼兒交流今天的活動,活動中開心的事情和遇到的問題。
(3)小結
表揚與批評,出示活動中拍攝的照片進行點評,提出新要求。
第四篇:Java五子棋實現報告
一、實驗目的
(1)使用Java編寫五子棋程序
(2)掌握編寫過程的一些類和類成員的使用,并且了解五子棋制作過程的一些步驟和了解一些算法。
二、實驗環境
在電子樓2樓,裝有My Eclipse 的計算機上進行
三、實驗內容
編寫一個五子棋程序。程序主要實現以下功能:
1.實現五子棋界面,要求人性化界面簡潔美觀; 2.實現黑白色輪流下棋功能,能提示下棋方; 3.實現連成五子自動判斷功能; 4.實現時間設置功能,認輸功能;
核心代碼如下:
1.我的第一步是設計界面。在這個過程的要使用到以下的步驟:
1.使用MyEclipse 創建一個Project關于這個工程,加入兩個類,分別是ChessFrame和Chess,而ChessFrame是這個工程中最重要的一個部分。創建過程中要繼承JFrame類,并且要繼承Runnable 和 MouseListener 這兩個接口,分別是用來監聽鼠標的移動和時間的變化。2.在給這個JFrame設置大小和顏色等一些東西。這里最主要的是使用了兩個函數,是以前沒見過的:
1.這個是用來設置默認的窗口關閉事件的
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);2.這兩個是用來獲得屏幕的大小的
Toolkit.getDefaultToolkit().getScreenSize().height;Toolkit.getDefaultToolkit().getScreenSize().width;
3.把本地的背景圖片加到這個窗口中,作為這個窗口的背景圖:
使用的到的類有BufferedImage和 ImageIO這兩個類,這兩個類是專門用來處理這種功能的。主要的代碼如下:
BufferedImage bg = null;bg = ImageIO.read(new File(“e:/background.jpg”));g.drawImage(bg,0,0,this);這樣這個圖片就加到了這個窗口的背景去了。
這里有一個改進就是雙緩沖技術,可以防止閃屏。這個技術就是在界面和內存都有一幅圖,我們的改動不是直接畫界面,而是內存中先畫好然后把內存中直接顯示出來,那樣就沒有了一前一后的,那就沒有了閃屏的事情發生了。
4.就是畫棋盤和寫一些游戲信息:
這步比較簡單,也沒什么可以說的,用到的一些畫線的函數,和寫String的一些函數。
以上做完以后就可以出現以下的界面:
1.我的第二步就是增加對mouse的點擊和移動的處理,這樣以后就可以用來下棋。在這個過程的要使用到以下的步驟: 1.增加對mouse的監視,然后重寫它的一些函數:
1.我們在ChessFrame的構造函數中加入了addMouseListener()函數,然后重寫關于這個的四個函數,我們這這里不重寫所有的函數,就改寫一個MousePress函數就可以了。改寫的代碼如下:
public void mousePress(MouseEvent arg0){
this.x = arg0.getX();this.y = arg0.getY();if(this.canplay)
} this.repaint();現在要處理的就是加上棋子了,我在這個做了一下小改動可以更加準確的定位下棋的位置:
if(x >= 10 && x <= 374 && y >= 72 && y <= 450){
int sx1 =(this.x72)/ 20;int yx1 =(this.x72)% 20;if(yx1 >= 10){ } if(yy2 >= 10){ } sy2++;sx1++;就是這個,我們通過監控鼠標的就可以得到點擊的X,Y坐標,我在這里通過對它求余,假如余數大于10(就是一個格子的一半)那就給+1,不然不變。后面的畫棋子是很簡單的一個過程,使用的是現成的函數(drawoval)
2.這部要做的就是記錄棋子和五子連的判斷:
1.我們通過一個數組int給保存棋子,如果是0就是沒子,1表示是黑子,2表示白子。在每次重繪的時候遍歷這個數組顯示,這樣就可以保存棋子了。2.判斷五子連起來然后獲勝的算法: 這個算法是鑒戒例子上的:
private boolean isline(int x, int y, int xchange, int ychange, int color){
int tempx = xchange;int tempy = ychange;int count = 1;while(x + xchange >= 0 && y + ychange >= 0
&& color == chess1[x + xchange][y + ychange]){ count++;if(xchange!= 0){ } if(ychange!= 0){ if(ychange < 0){ xchange++;
}
}
}
} ychange--;ychange++;} else { xchange = tempx;ychange = tempy;while(xychange >= 0
} if(count >= 5){
} return true;return false;} else { && color == chess1[xychange]){ count++;if(xchange!= 0){ } if(ychange!= 0){
} if(ychange < 0){
} ychange--;ychange++;} else { xchange++;中心思想就是要判斷就要判斷8個方向,其中有的只是相反的方向,我們使用關于X,Y的相對的變化來判斷,并且使用count來計數,如果到了5個就可以判斷勝利啦。
1.我的第三步就是時間的變化和一些鍵的設置
1.關于時間的變化主要是在于線程的使用,這里我們這個JFrame它繼承了Runnable 這個接口,不過我們要重寫Run函數,這個run函數的代碼如下: public void run(){
if(this.second > 0){
while(true){
this.repaint();if(this.isblack){
this.ss1--;
if(this.ss1 == 0){
JOptionPane
.showMessageDialog(this, “黑方超時~~~~?¤游戲結束”);
this.message1=“0:0:0”;
{
“白方超時~~~~?¤?¤游戲結束”);this.message2=“0:0:0”;this.canplay = false;
{
{ }
this.ss2--;
if(this.ss2 == 0){
this.message1 = this.ss
1/ 3600 + “ : ”
+(this.ss1 / 60this.ss1 / 60 *
this.ss1=-1;
this.canplay = false;
}else if(this.ss1>0)3600 * 60)60this.ss2 / 3600 + “ : ”
+(this.ss2this.ss2 / 3600 * 60 * 60);
this.repaint();}else { }
try {
}
Thread.sleep(1000);e.printStackTrace();} catch(InterruptedException e){ 這個函數是用來事時間的變化,所以每操作以后就讓線程sleep(1000)就可以了,那樣就是一秒鐘。這樣就可以倒計時了。2.現在我們要點擊一個按鈕要它有響應。
這里我們其實就沒用到什么button,那為什么會有反應呢,因為我們通過鼠標的點擊范圍來確定要響應什么函數,這就是這里面的秘密.在public void mouseClicked(MouseEvent arg0)函數里有下面這些if的判斷
if(x1 >= 404 && x1 <= 473 && y1 >= 74 && y1 <= 103)if(x1 >= 404 && x1 <= 473 && y1 >= 127 && y1 <= 155)if(x1 >= 404 && x1 <= 473 && y1 >= 179 && y1 <= 208)if(x1 >= 404 && x1 <= 473 && y1 >= 286 && y1 <= 316)if(x1 >= 404 && x1 <= 473 && y1 >= 338 && y1 <= 367)if(x1 >= 404 && x1 <= 473 && y1 >= 390 && y1 <= 419)這就是為了確定鼠標的范圍,然后相對調用函數。
其他還有就是一些Debug處理,在程序已經處理了,結果的還是蠻可以處理的,不過只能是人人對戰。
四、實驗心得與小結
這次試驗總的來說沒有想像中那么難,還有視屏的幫助,感覺起還是很容易動手的,不過由于自己沒上心,沒有做比較大的改動,最主要的人機的對戰沒做出來是滿遺憾的,不過通過這個試驗,讓我學習了不少的知識,比如雙緩沖,mouselistener 等許多許多的知識,還有關于五子棋算法的設計也是一部分。不管怎么說還是有學到知識的,沒什么改動,但對現有的知識的掌握還是很可以的。
五、指導教師評議
成績評定:
指導教師簽名:
第五篇:五子棋游戲軟件工程課程設計
軟件工程設計
專 業:班 級:姓 名:學 號:指導老師:
I
目錄
第一章 需求分析.......................................................1 1.1 總體分析..........................................................1 1.2 初始化............................................................1 1.3 主循環控制模塊....................................................1 1.4 玩家下子..........................................................1 1.5 盤面分析填寫棋型表................................................2 1.6 對方下子..........................................................2 1.7 勝負判斷..........................................................2 第二章 功能描述.......................................................3 2.1 功能模塊圖........................................................3 2.2 功能說明..........................................................3 第三章 系統設計.......................................................4 3.1 流程圖............................................................4 3.2 流程圖說明........................................................5 第四章 運行結果.......................................................6 第五章 總結...........................................................7 附錄一 源代碼.........................................................8
II
軟件工程設計
五子棋游戲
第一章 需求分析
1.1 總體分析
軟件需求分析是軟件開發周期的第一個階段,也是關系到軟件開發成敗的關鍵一步。對于任何一個軟件而言,需求分析工作都是至關重要的一步。只有通過軟件需求分析,才能把軟件的功能和性能由總體的概念性描述轉化為具體的規格說明,進而建立軟件開發的基礎。實踐表明,需求分析工作進行得好壞,在很大程度上決定了軟件開發的成敗。
軟件需求分析的任務是:讓用戶和開發者共同明確將要開發的是一個什么樣的軟件。具體而言,就是通過對問題及其環境的理解、分析和綜合,建立邏輯模型,完成新軟件的邏輯方案設計。
基于本游戲,首先得為整個棋盤建立一張表格用以記錄棋子信息,我們使用一個15*15的二維數組Table[15][15](15*15是五子棋棋盤的大小),數組的每一個元素對應棋盤上的一個交叉點,用‘0’表示空位、‘1’代表己方的子、‘2’代表對方的子;這張表也是今后分析的基礎。在此之后還要為兩個玩家雙方各建立一張棋型表Computer[15][15][4]和Player[15][15][4],用來存放棋型數據。
1.2 初始化
首先,建立盤面數組Table[15][15]、對戰雙方的棋型表Computer[15][15][4]和Player[15][15][4]并將它們清零以備使用;然后初始化顯示器、鍵盤、鼠等輸入輸出設備并在屏幕上畫出棋盤(棋盤可以不顯示)。
1.3 主循環控制模塊
控制下棋順序,當輪到某方下子時,負責將程序轉到相應的模塊中去,主要擔當一個調度者的角色。
1.4 玩家下子
當輪到玩家下時,您通過鍵盤或鼠標在棋盤上落子,程序會根據該點的位置,在Table[15][15]數組的相應地方記錄‘2’,以表明該子是玩家下的。
軟件工程設計
1.5 盤面分析填寫棋型表
您在下五子棋時,一定會先根據棋盤上的情況,找出當前最重要的一些點位,如“活三”、“沖四”等;然后再在其中選擇落子點。先來分析己方的棋型,我們從棋盤左上角出發,向右逐行搜索,當遇到一個空白點時,以它為中心向左挨個查找,如果遇到己方的子則記錄然后繼續,如果遇到對方的子、空白點或邊界就停止查找。左邊完成后再向右進行同樣的操作;最后把左右兩邊的記錄合并起來,得到的數據就是該點橫向上的棋型,然后把棋型的編號填入到Computer[x][y][n]中就行了(x、y代表坐標,n=0、1、2、3分別代表橫、豎、左斜、右斜四個方向)。而其他三個方向的棋型也可用同樣的方法得到,當搜索完整張棋盤后,己方棋型表也就填寫完畢了。然后再用同樣的方法填寫對方棋型表。
注意:所有棋型的編號都要事先 定義好,越重要的號數越大!
1.6 對方下子
有了上面填寫的兩張棋型表,就是遍歷棋型表Computer[15][15][4]和Player[15][15][4]找出其中數值最大的一點,在該點下子即可。但這種算法的弱點非常明顯,只顧眼前利益,不能顧全大局,這就和許多五子棋初學者一樣犯了“目光短淺”的毛病。如果在這兒下子將會形成對手不得不防守的棋型(例如:‘沖四’、‘活三’);那么下一步對手就會照您的思路下子來防守您,如此一來便完成了第一步的預測。這時再調用模塊4對預測后的棋進行盤面分析,如果出現了‘四三’、‘雙三’或‘雙四’等制勝點,那么己方就可以獲勝了(當然對黑棋而言‘雙三’、‘雙四’是禁手,另當別論);否則照同樣的方法向下分析,就可預測出第二步、第三步??
等一等,要是盤面上沒有對手必須防的棋型,哪該怎么辦呢?進攻不成的話就得考慮防守了,將自己和對手調換一下位置,然后用上面的方法來預測對手的棋,這樣既可以防住對手巧妙的攻擊,又能待機發動反擊,何樂而不為呢!
1.7 勝負判斷
務須多言,某方形成五子連即獲勝;若黑棋走出‘雙三’、‘雙四’或長連即以禁手判負。
軟件工程設計
第二章 功能描述
2.1 功能模塊圖
五子棋游戲判斷棋盤是否已滿判斷是否出錯并提示判斷那方獲勝交替循環雙方下棋 圖2.1 功能模塊圖
2.2 功能說明
該五子棋程序基本上實現了五子棋的游戲功能,有雙方下棋的界面及最終判定結果的界面。同時該游戲采用二維坐標實現,明了易懂,方便玩家在游戲過程中的基本操作,使游戲更加簡便。在細節方面,該系統提供實時存儲功能,隨時記錄為完成的游戲,使用戶可以很好的處理意外中斷的情況。該游戲基本實現了游戲的一些要求和特征。在游戲的源程序及文檔方面,我們也嚴格遵守軟件工程思想,立足實驗要求,確定任務,需求分析,設計和編碼,每個步驟力求清晰易懂。原代碼注釋詳盡,各功能模塊功能分明,可移植性強。當然該系統也有很多不足的地方,第一次進行獨立的課程設計,也有很多細節方面是考慮到的,這款游戲也是在不斷的調試和修改中產生和完善的。希望老師能夠指出不足,幫助我不斷提高。
軟件工程設計
第三章 系統設計
3.1 流程圖
開始棋盤已滿是輸出平局否“0”方選位置判斷該位置是否有棋有另找位置無“0”方落子否判斷“0”方是否獲勝是輸出“0”方獲勝否棋盤已滿是輸出平局結束否“x”方選位置判斷該位置是否有棋有另找位置無“x”方落子判斷“x”方是否獲勝是輸出“x”方獲勝 圖3.1 流程圖
軟件工程設計
3.2 流程圖說明
本程序定義了各種操作函數、各種狀態判定宏,思想明確,思路清晰。各個判斷選擇了不同路徑,因此繼續進行或輸出結果。程序中,“循環”的利用非常直接和清晰,雙方交替下棋,因此循環往復。最終決出勝負或最終平局。分析時,也考慮了許多種情況,針對各個情況均作出了相對措施和解決方案。
程序采用循環進行雙方交替下棋,并進行了很多判斷。首先判斷棋盤是否已滿,若棋盤已滿,則輸出平局,結束游戲;若棋盤未滿,則繼續進行。然后判斷“0”方是否勝出,若“0”方獲勝,則輸出“0”方獲勝,結束游戲;若“0”方沒有獲勝,則繼續進行。再判斷“x”方是否獲勝,若“x”方獲勝,則輸出“x”方獲勝,結束游戲;若“x”方沒有獲勝,則繼續進行。回到“首先”的判斷。如此循環??
軟件工程設計
第四章 運行結果
圖4.1 運行結果初始圖
圖4.2 游戲過程圖
圖4.3
軟件工程設計
圖4.4
圖4.5
軟件工程設計
圖4.6
圖4.7
軟件工程設計
圖4.8 游戲進行圖
圖4.9 “0”方獲勝圖
軟件工程設計
附錄一 源代碼
#include
using namespace std;
int Hsheng(char a[][15]);
//判斷o子是否獲勝的函數
int Bsheng(char a[][15]);
//判斷x子是否獲勝的函數
int he(char a[][15]);
//判斷是否平局(也就是棋盤下滿了)的函數
void qipan(char a[15][15])
//執行輸出棋盤命令 {
cout<<“本游戲采用二維數組實現,棋盤為15X15的二維直角坐標系,均從1到15,祝二位游戲愉快.”;for(int i=0;i<15;i++)
//打印棋盤
{