2023年全國(guó)碩士研究生考試考研英語一試題真題(含答案詳解+作文范文)_第1頁
已閱讀1頁,還剩22頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、<p><b>  目錄</b></p><p><b>  1緒論1</b></p><p>  1.1課程設(shè)計(jì)意義1</p><p>  1.2課設(shè)目的1</p><p>  1.3課設(shè)要求1</p><p>  2網(wǎng)絡(luò)五子棋介紹2</

2、p><p>  2.1網(wǎng)絡(luò)五子棋介紹2</p><p>  2.2游戲玩法2</p><p>  3系統(tǒng)整體設(shè)計(jì)3</p><p>  3.1整體設(shè)計(jì)3</p><p>  3.2系統(tǒng)流程圖4</p><p><b>  4原理分析5</b></p

3、><p>  4.1服務(wù)器和客戶端通信機(jī)制5</p><p>  4.2多線程機(jī)制7</p><p>  5服務(wù)器的設(shè)計(jì)與實(shí)現(xiàn)8</p><p>  5.1服務(wù)器監(jiān)聽8</p><p>  5.2傳遞信息9</p><p>  6客戶端設(shè)計(jì)與實(shí)現(xiàn)10</p>&

4、lt;p>  6.1客戶端界面設(shè)計(jì)11</p><p>  6.1.1GUI圖形界面設(shè)計(jì)12</p><p>  6.1.2注冊(cè)監(jiān)聽者13</p><p>  6.2連接服務(wù)器14</p><p>  6.3傳遞信息14</p><p>  6.4棋盤數(shù)據(jù)結(jié)構(gòu)15</p>&

5、lt;p>  6.5判斷輸贏算法16</p><p>  6.6背景音樂17</p><p><b>  7設(shè)計(jì)實(shí)現(xiàn)18</b></p><p><b>  8總結(jié)20</b></p><p><b>  謝辭21</b></p><

6、p><b>  參考文獻(xiàn)21</b></p><p><b>  緒論</b></p><p><b>  課程設(shè)計(jì)意義</b></p><p>  五子棋是起源于中國(guó)古代的傳統(tǒng)黑白棋種之一。五子棋不僅能增強(qiáng)思維能力,提高智力,而且富含哲理,有助于修身養(yǎng)性。</p><p&

7、gt;  經(jīng)過一個(gè)學(xué)期的學(xué)習(xí),使我對(duì)Java有了一定的了解。但要深入理解Java語言,單靠上課是不夠的。必須通過課程設(shè)計(jì),設(shè)計(jì)一個(gè)比較大的程序,才能更深一步地理解Java語言。在這次課程中,我選擇了網(wǎng)絡(luò)五子棋作為課題。編寫網(wǎng)絡(luò)五子棋游戲要利用到Socket網(wǎng)絡(luò)編程技術(shù)和多線程。通過這次課程設(shè)計(jì),熟悉Java的GUI圖形界面設(shè)計(jì),網(wǎng)絡(luò)Socket 編程和多線程編程。</p><p><b>  課設(shè)目的&

8、lt;/b></p><p>  通過課程設(shè)計(jì),使學(xué)生理論聯(lián)系實(shí)際,在程序設(shè)計(jì)實(shí)踐中進(jìn)一步了解JAVA程序設(shè)計(jì)方法掌握類和對(duì)象的基本編程方法,熟悉GUI圖形界面編程技術(shù),初步了解Socket編程方法。</p><p><b>  課設(shè)要求</b></p><p>  通過課程設(shè)計(jì)完成一個(gè)網(wǎng)絡(luò)五子棋游戲。由服務(wù)器和客戶端組成。在Intern

9、et中不同用戶使用客戶端通過服務(wù)器與其它玩家連接。進(jìn)行五子棋網(wǎng)絡(luò)對(duì)戰(zhàn)或聊天。</p><p>  程序中要實(shí)現(xiàn)GUI圖形界面的棋盤、黑子、白子功能,設(shè)計(jì)棋局存儲(chǔ)數(shù)據(jù)結(jié)構(gòu), 實(shí)現(xiàn)開始、重來、退出等基本功能, 實(shí)現(xiàn)輸贏自動(dòng)判別算法, 實(shí)現(xiàn)網(wǎng)絡(luò)對(duì)戰(zhàn)功能, 背景音樂播放功能等。</p><p><b>  網(wǎng)絡(luò)五子棋介紹</b></p><p><

10、;b>  網(wǎng)絡(luò)五子棋介紹</b></p><p>  五子棋是起源于中國(guó)古代的傳統(tǒng)黑白棋種之一。五子棋不僅能增強(qiáng)思維能力,提高智力,而且富含哲理,有助于修身養(yǎng)性。五子棋既有現(xiàn)代休閑的明顯特征“短、平、快”,又有古典哲學(xué)的高深學(xué)問“陰陽易理”;它既有簡(jiǎn)單易學(xué)的特性,為人民群眾所喜聞樂見,又有深?yuàn)W的技巧和高水平的國(guó)際性比賽;它的棋文化源遠(yuǎn)流長(zhǎng),具有東方的神秘和西方的直觀;既有“場(chǎng)”的概念,亦有“點(diǎn)”

11、的連接。它是中西文化的交流點(diǎn),是古今哲理的結(jié)晶。</p><p>  網(wǎng)絡(luò)五子棋是一般五子棋的網(wǎng)絡(luò)版,沒有加入人機(jī)對(duì)戰(zhàn)功能。本軟件使兩個(gè)不同計(jì)算機(jī)的使用者通過一定的網(wǎng)絡(luò)連接,達(dá)到兩人對(duì)戰(zhàn)的功能。首先運(yùn)行服務(wù)器監(jiān)聽客戶端連接請(qǐng)求。運(yùn)行客戶端與服務(wù)器相連,若連接成功,則進(jìn)入游戲。選擇房間,一個(gè)房間最多兩個(gè)人,人滿后,雙方可以開始游戲。</p><p><b>  游戲玩法</b

12、></p><p>  網(wǎng)絡(luò)五子棋規(guī)則:棋盤采用15條橫線×15條堅(jiān)線組成交叉的每個(gè)點(diǎn)都可以放棋。</p><p>  本游戲至少需要二個(gè)客戶端才能進(jìn)行游戲。客戶端與服務(wù)器連接成功后,進(jìn)入游戲大廳(房間號(hào)為0),選擇一個(gè)大于0的房間號(hào),如果該房間未滿,即小于兩個(gè)人,則可進(jìn)入。點(diǎn)“游戲開始”,處于等待狀態(tài)。如果對(duì)方也點(diǎn)擊了“游戲開始”。雙方就可以在網(wǎng)上進(jìn)行對(duì)戰(zhàn)了。在對(duì)戰(zhàn)的同時(shí)

13、還可以聊天,可以在同一房間內(nèi)私聊,也可以發(fā)送消息給所有在線的用戶。</p><p>  游戲分黑白兩方,每局由規(guī)定黑方先行。黑方玩家移動(dòng)鼠標(biāo)在棋盤中點(diǎn)擊行棋。當(dāng)黑方行棋完畢,轉(zhuǎn)由白方行棋。同色棋子在棋盤上形成橫、豎、斜形成 “五子相連”則獲勝。如果棄權(quán),則判為輸。</p><p><b>  系統(tǒng)整體設(shè)計(jì)</b></p><p><b&g

14、t;  整體設(shè)計(jì)</b></p><p>  網(wǎng)絡(luò)五子棋是采用網(wǎng)絡(luò)協(xié)議為TCP/IP的網(wǎng)上對(duì)弈游戲,運(yùn)用“客戶端-服務(wù)器“(c/s)網(wǎng)絡(luò)架構(gòu)模式。實(shí)現(xiàn)用戶通過Internt連接在任何地方與不同玩家進(jìn)行對(duì)戰(zhàn)。服務(wù)器可以創(chuàng)建任意多局游戲。</p><p>  通過使用多線程和網(wǎng)絡(luò)套接字SOCKET來實(shí)現(xiàn)游戲之間的通訊,它是基于點(diǎn)對(duì)點(diǎn)的通訊。開始讓服務(wù)器初始化建立服務(wù)器套接字SOCK

15、ET,基于某個(gè)端口PORT,服務(wù)器始終處于監(jiān)聽狀態(tài)。客戶端是動(dòng)作的發(fā)起者,何時(shí)發(fā)出申請(qǐng)由客戶端決定??蛻舳讼蚍?wù)器發(fā)出申請(qǐng),服務(wù)器給予響應(yīng)。打開客戶端套接字SOCKET,連接到服務(wù)器端的地址ADDRESS和端口PORT。連接建立后,創(chuàng)建一個(gè)SOCKET實(shí)例,并開始一個(gè)線程,監(jiān)聽該客戶端請(qǐng)求。服務(wù)器繼續(xù)監(jiān)聽其它用戶的連接。服務(wù)器通過數(shù)據(jù)輸入流從客戶端接收信息,并且通過數(shù)據(jù)輸出流把相應(yīng)的信息發(fā)送給客戶端??蛻舳税l(fā)送請(qǐng)求和響應(yīng)接收到的各種信息

16、。</p><p>  在服務(wù)器和客戶端之間傳遞的消息格式是采用“[消息類別]+內(nèi)容“組成的,服務(wù)器和客戶端在傳遞消息的過程,根據(jù)消息的類別來進(jìn)行相關(guān)的操作。比如要發(fā)送聊天信息,則在客戶端發(fā)送的過程中,自動(dòng)加上[MSG]在要發(fā)送的消息前面,服務(wù)器接收到客戶端發(fā)來的消息,用startsWith()的方法來讀取消息頭部,如果等于”[MSG]“,進(jìn)行一步判定是為群聊還是私聊,分別調(diào)用不同的方法向客戶端發(fā)送聊天內(nèi)容。&l

17、t;/p><p><b>  圖3-1</b></p><p><b>  系統(tǒng)流程圖</b></p><p>  服務(wù)器流程圖:圖1-2</p><p><b>  圖3-2</b></p><p>  客戶端流程圖:圖3-3</p><

18、;p><b>  圖3-3</b></p><p><b>  原理分析</b></p><p>  服務(wù)器和客戶端通信機(jī)制</p><p>  Socket是面向客戶/服務(wù)器模型設(shè)計(jì)的,網(wǎng)絡(luò)上的兩個(gè)程序通過一個(gè)雙向的通訊連接實(shí)現(xiàn)數(shù)據(jù)的交換,這個(gè)雙向鏈路的一端稱為一個(gè)Socket。 Socket通常用來實(shí)現(xiàn)客戶方和服

19、務(wù)方的連接。客戶程序可以向Socket寫請(qǐng)求,服務(wù)器將處理此請(qǐng)求,然后通過Socket將結(jié)果返回給用戶 。</p><p>  在java中使用套接字相當(dāng)簡(jiǎn)單,Java API為處理套接字的通信提供了一個(gè)類java.net.Socket。使得編寫網(wǎng)絡(luò)應(yīng)用程序相對(duì)容易。JAVA支持流套接字(stream socket)和數(shù)據(jù)報(bào)套接字(datagram socket)。流套接字使用TCP(Transmission C

20、ontrol Protocol,傳輸控制協(xié)議)進(jìn)行數(shù)據(jù)傳輸,而數(shù)據(jù)報(bào)套接字使用UDP(User Datagram Protocol,用戶數(shù)據(jù)報(bào)協(xié)議)。</p><p><b>  圖4-1</b></p><p>  在Java中Socket可以理解為客戶端或者服務(wù)器端的一個(gè)特殊的對(duì)象,這個(gè)對(duì)象有兩個(gè)關(guān)鍵的方法,一個(gè)是getInputStream方法,另一個(gè)是getO

21、utputStream方法。getInputStream方法可以得到一個(gè)輸入流,客戶端的Socket對(duì)象上的getInputStream方法得到的輸入流其實(shí)就是從服務(wù)器端發(fā)回的數(shù)據(jù)流。GetOutputStream方法得到一個(gè)輸出流,客戶端Socket對(duì)象上的getOutputStream方法返回的輸出流就是將要發(fā)送到服務(wù)器端的數(shù)據(jù)流,(其實(shí)是一個(gè)緩沖區(qū),暫時(shí)存儲(chǔ)將要發(fā)送過去的數(shù)據(jù))。</p><p>  客戶端

22、啟動(dòng)以后,與服務(wù)器連接,服務(wù)器會(huì)啟動(dòng)一個(gè)線程來與客戶進(jìn)行文字交流。</p><p>  要完成這個(gè)工作,需要完成三個(gè)部分的工作:</p><p>  Java中有一個(gè)專門用來建立Socket服務(wù)器的類,名叫ServerSocket,可以用服務(wù)器需要使用的端口號(hào)作為參數(shù)來創(chuàng)建服務(wù)器對(duì)象。</p><p>  ServerSocket server=new Server

23、Socket(8888);</p><p>  這條語句創(chuàng)建了一個(gè)服務(wù)器對(duì)象,這個(gè)服務(wù)器使用8888號(hào)端口。當(dāng)一個(gè)客戶端程序建立一個(gè)Socket連接,所連接的端口號(hào)為8888時(shí),服務(wù)器對(duì)象server便響應(yīng)這個(gè)連接,并且server.accept()方法會(huì)創(chuàng)建一個(gè)Socket對(duì)象。服務(wù)器端便可以利用這個(gè)Socket對(duì)象與客戶進(jìn)行通訊。Socket socket=server.accept();</p>

24、;<p>  進(jìn)而得到輸入流和輸出流,并進(jìn)行封裝。</p><p>  reader=newBufferedReader(newInputStreamReader (socket.getInputStream()));</p><p>  writer = new PrintWriter(socket.getOutputStream(), true);</p>

25、<p>  隨后,就可以使用reader.readLine()方法得到客戶端的輸入,也可以使用writer.println()方法向客戶端發(fā)送數(shù)據(jù)。從而可以根據(jù)程序的需要對(duì)客戶端的不同請(qǐng)求進(jìn)行回應(yīng)。</p><p>  在所有通訊結(jié)束以后應(yīng)該關(guān)閉這兩個(gè)數(shù)據(jù)流,關(guān)閉的順序是先關(guān)閉輸出流,再關(guān)閉輸入流,即使用 </p><p>  reader.close(); </p>

26、<p>  writer.close();</p><p>  相比服務(wù)器端,客戶端要簡(jiǎn)單一些,客戶端只需用服務(wù)器所在機(jī)器的ip以及服務(wù)器的端口作為參數(shù)創(chuàng)建一個(gè)Socket對(duì)象。得到這個(gè)對(duì)象后,就可以用"建立服務(wù)器"部分介紹的方法實(shí)現(xiàn)數(shù)據(jù)的輸入和輸出。</p><p>  socket=new Socket("127.0.0.1", 8

27、888);</p><p>  reader=newBufferedReader(new InputStreamReader(socket.getInputStream()));</p><p>  writer=new PrintWriter(socket.getOutputStream(), true);</p><p>  以上的程序代碼建立了一個(gè)socket

28、對(duì)象,這個(gè)對(duì)象連接到ip地址為127.0.0.1(本機(jī)IP地址,為了驗(yàn)證方便)的主機(jī)、端口為8888的服務(wù)器對(duì)象。并且建立了輸入流和輸出流,分別對(duì)應(yīng)服務(wù)器的輸出和客戶端的寫入。</p><p><b>  多線程機(jī)制</b></p><p>  多線程機(jī)制是指單個(gè)程序可以運(yùn)行多個(gè)不同的線程,執(zhí)行不同的任務(wù)。因?yàn)榫€程只能在單個(gè)進(jìn)程的作用域內(nèi)活動(dòng),所以創(chuàng)建線程比創(chuàng)建進(jìn)程要

29、廉價(jià)得多,同一類線程共享代碼和數(shù)據(jù)空間,每個(gè)線程有獨(dú)立的運(yùn)行桟和程序計(jì)數(shù)器(PC),線程切換的開銷小。因此多線程編程在現(xiàn)代軟件設(shè)計(jì)中在量采用。</p><p>  創(chuàng)建新線程必須編寫一個(gè)線程類,用Java編寫多線程代碼有兩種方式</p><p>  直接繼承Java的線程類Thread;</p><p>  實(shí)現(xiàn)Runnable接口</p><p

30、>  無論采用哪種方式均需要在程序中編寫Run()方法,線程在運(yùn)行時(shí)要完成的任務(wù)在該方法實(shí)現(xiàn)。Thread 類封裝了線程的行為。繼承Thread類須重寫run()方法實(shí)現(xiàn)各自的任務(wù)。程序中不要直接調(diào)用線程的run()方法,而是調(diào)用start()方法啟動(dòng)線程,讓其進(jìn)入可調(diào)度的狀態(tài),線程獲得調(diào)度時(shí)將自動(dòng)執(zhí)行run()方法。</p><p>  由于Java的單重繼承的限制,有些類必須繼承其它個(gè)類時(shí)又要實(shí)現(xiàn)線程的

31、特性。這時(shí)可通過實(shí)現(xiàn)Runnable接口的方式來滿足兩方面的要求。Runnable 接口只有一個(gè)方法 run(),它就是線程運(yùn)行時(shí)要執(zhí)行的方法,只要將具體代碼寫入其中即可。線程在調(diào)度時(shí)將自動(dòng)調(diào)用Runnable 接口對(duì)象的run方法。</p><p>  多線程是Java的一個(gè)特點(diǎn),多線程可以使程序反應(yīng)更快、交互性更強(qiáng),并能提高執(zhí)行效率。在網(wǎng)絡(luò)五子中如果服務(wù)器是單線程的,則只能與一個(gè)客戶端相連,就失去了網(wǎng)絡(luò)對(duì)戰(zhàn)的

32、意義了。所以應(yīng)該采用多線程方式。當(dāng)服務(wù)器與一個(gè)客戶端建立連接,就開啟一個(gè)線程與之相連,同時(shí)監(jiān)聽其它用戶的連接。</p><p><b>  服務(wù)器的設(shè)計(jì)與實(shí)現(xiàn)</b></p><p>  網(wǎng)絡(luò)五子棋游戲服務(wù)器端主要由以下幾部分組成:圖5-1</p><p><b>  圖5-1</b></p><p&g

33、t;  網(wǎng)絡(luò)五子棋游戲服務(wù)器端主要有三個(gè)類: Server類、five_ Thread類(線程類)和BManager類(消息廣播者)。服務(wù)器端主要通過建立流連接來連接客戶端。服務(wù)器建立與一個(gè)客戶端連接,就開始一個(gè)線程,并同時(shí)監(jiān)聽其它客戶端的連接。服務(wù)器接收一客戶端的信息,接收信息后按照此客戶端的要求將信息發(fā)送到相應(yīng)的客戶端,端起到了中介服務(wù)器的作用。為了更清楚地了解客戶端的登陸情況,將服務(wù)器設(shè)計(jì)成圖形界面。創(chuàng)建成一個(gè)可以顯示游戲信息的框

34、架。在框架中創(chuàng)建一個(gè)包含文本區(qū)的滾動(dòng)窗格,并在文本區(qū)顯示游戲信息。</p><p><b>  圖5-2</b></p><p><b>  服務(wù)器監(jiān)聽</b></p><p>  首先創(chuàng)建一個(gè)服務(wù)器對(duì)象,并把它附加到8888號(hào)端口上,服務(wù)通過這個(gè)端口來監(jiān)聽客戶端的連接請(qǐng)求。通過服務(wù)器對(duì)象的accept方法來創(chuàng)建一個(gè)Soc

35、ket對(duì)象并使其與客戶機(jī)連接,就開啟一個(gè)線程處理客戶之間數(shù)據(jù),同時(shí)繼續(xù)監(jiān)聽其它客戶端的連接請(qǐng)求。并將線程添加至BManager對(duì)象bMan中。</p><p>  ServerSocket server=new ServerSocket(8888);</p><p>  Socket socket=server.accept();</p><p>  five_Th

36、read thread=new five_Thread(socket);//建立一線程</p><p>  thread.start();//啟動(dòng)線程</p><p>  bMan.add(thread);//線程添加至BManager對(duì)象</p><p><b>  傳遞信息</b></p><p>  當(dāng)于客戶端建

37、立連接后,就建立輸入輸出流,由于消息的發(fā)送和接收。</p><p>  reader=newBufferedReader(newInputStreamReader (socket.getInputStream()));</p><p>  writer = new PrintWriter(socket.getOutputStream(), true);</p><p&g

38、t;  five_Thread對(duì)象不僅可以獲取套接字、輸入輸出流,而且它還提供了有關(guān)客戶機(jī)的消息。例如客戶機(jī)的姓名、房間號(hào)、游戲開始與否等。這是因?yàn)槲覀冃枰_定消息的來源及主要在某個(gè)房間傳播的消息。并且,消息廣播者也需要參照線程對(duì)象的房間號(hào),以便將消息發(fā)送至某個(gè)房間中。</p><p>  BManager類繼承了Vector類,它的元素為five_ Thread線程對(duì)象,這樣可以更容易用BManager 的對(duì)象

39、來管理線程對(duì)象,如添加、刪除、返回線程對(duì)象。BManager可以自由地參照five_Thread對(duì)象的房間號(hào)和玩家的名字,這樣能向指定的房間發(fā)送消息和用戶名字。需要比較Bmanager各元素的房間號(hào)和給定的房間號(hào),若兩者相同,則向此房間發(fā)送消息。</p><p>  服務(wù)器和客戶端之間的交流主要是相同的房間號(hào)之間的用戶進(jìn)行。如發(fā)送聊天消息,棋子信息,贏輸消息的傳送。</p><p>  s

40、endToAll(String msg)方法向所有用戶發(fā)送消息,主要是發(fā)送群聊消息。因?yàn)橄⒌陌l(fā)送主要在相同的房間號(hào)中時(shí)行,要發(fā)送群聊消息,即所有房間的用戶都能招收到。在輸入聊天信息前加‘a(chǎn)’。表示向所有人發(fā)送。</p><p>  SendToRoom(five_Thread thread, String msg)方法用于向指定的房間(roomnum)發(fā)送消息(msg)。房間內(nèi)的兩個(gè)用戶都能接收到消息。主要用于

41、發(fā)送發(fā)私聊信息。</p><p>  sendTothreadhers(five_Thread thread, String msg)方法用于向與消息發(fā)送者處于同一房間的用戶發(fā)送各種命令。比如發(fā)送在1號(hào)房間的一個(gè)用戶發(fā)來“[WIN]“,服務(wù)器向1號(hào)房間的另一個(gè)用戶發(fā)送[[LOSE]。實(shí)現(xiàn)原理:使用for循環(huán)檢查元素(線程)的房間號(hào)。用getRoomNumber()得到發(fā)送信息的線程的房間號(hào),當(dāng)房間號(hào)相等時(shí),則調(diào)用

42、sendTo(i, msg)方法向第i個(gè)房間發(fā)送消息。但并不向thread連接的客戶機(jī)發(fā)送消息。</p><p>  服務(wù)器在five_Thread類中重寫run()方法,由于處理在與客戶端連接過程中的數(shù)據(jù)傳輸,處理和控制。消息傳遞格式“[消息類別]+內(nèi)容“。</p><p>  “[ROOM]2“表示客戶端請(qǐng)求進(jìn)入第二號(hào)房間。服務(wù)器判斷2號(hào)房間是否為滿,如果不為滿,則向客戶端發(fā)送“[RO

43、OM]2”,表示可以進(jìn)入,并發(fā)送ROOM2中的其它用戶名字。如果人數(shù)已滿,則發(fā)送[FULL]。表示房間已滿,無法進(jìn)入。</p><p>  “[NAME]“表示進(jìn)入游戲大廳的用戶名字。</p><p>  “[START]“表示客戶端要求開始游戲,如果對(duì)方也要求游戲,則游戲開始。服務(wù)器發(fā)送[COLOR]WRITE和[COLOR]BLACK表示棋子顏色分別給兩個(gè)客戶端。</p>

44、<p>  “[DROPGAME]”表示放棄正在進(jìn)行中的游戲。服務(wù)器發(fā)送“[DROPGAME]“給相同房間中的另一用戶。</p><p><b>  客戶端設(shè)計(jì)與實(shí)現(xiàn)</b></p><p>  客戶端負(fù)責(zé)與用戶之間的交互。包括棋盤類OmokBoard類和Client類。OmokBoard類繼承了JPanel類,它主要用于棋盤的繪制和監(jiān)聽鼠標(biāo)事件,獲得棋子

45、坐標(biāo)和繪制棋子。它必須擁有輸出流,用以向?qū)κ謧鬟f棋手的下棋信息。主要的方法有:</p><p>  putOpponent ()在客戶端顯示對(duì)方棋子,保持雙方棋子的一致性。</p><p>  check()判斷一方向上同色棋子個(gè)數(shù)。</p><p>  drawStones()繪制棋子。</p><p>  drawBoard()調(diào)用不同的

46、方法,分析實(shí)現(xiàn)棋盤、棋子、提示信息的顯示。</p><p>  isRunning()標(biāo)記游戲運(yùn)行狀態(tài)。</p><p>  reset()清空棋盤,在游戲結(jié)果后運(yùn)行。</p><p>  Client類,繼承JFrame類和實(shí)現(xiàn)Runnable接口。主要由于界面初始化和注冊(cè)事件監(jiān)聽者。主要方法:</p><p>  Run()方法覆蓋Run

47、nable接口里的run ()方法,用以對(duì)游戲過程中的數(shù)據(jù)傳輸,處理,控制。</p><p>  actionPerformed(ActionEvent ae)實(shí)現(xiàn)點(diǎn)擊菜單、按鈕、文本框回車事件的具體代碼。</p><p>  Connect()與服務(wù)器連接。</p><p>  endgame()結(jié)束游戲。</p><p>  player

48、sInfo()顯示用戶位置信息,是在游戲大廳中,還是在房間里。</p><p>  goToWaitRoom()從房間里退出,進(jìn)入游戲大廳。</p><p>  網(wǎng)絡(luò)五子棋客戶端主要由以下幾部分組成:圖6-1</p><p><b>  圖6-1</b></p><p><b>  客戶端界面設(shè)計(jì) </b

49、></p><p><b>  圖6-2</b></p><p><b>  GUI圖形界面設(shè)計(jì)</b></p><p>  五子棋客戶端界面本軟件的的客戶端的界面如圖6-2所示,主要應(yīng)用SWING的組件來實(shí)現(xiàn)。界面由菜單、按鈕、文本框、各種對(duì)話框、棋盤和黑白棋子等組成。</p><p>  

50、客戶端中的按鈕、文本框、標(biāo)簽等GUI部件都是布置在面板JPanel上的,</p><p>  其中還包括將一塊面板入在另一塊面板中。這樣能實(shí)現(xiàn)比較復(fù)雜的布局。多個(gè)不同的GUI部件放在面板上時(shí),還要設(shè)置它們的布局方式。這里采用了網(wǎng)絡(luò)布局(GridLayout)和方位布局(BorderLayout)。最后將各個(gè)面板JPanel添加到窗體JFrame中。</p><p>  菜單包括游戲、音樂、

51、和幫助菜單項(xiàng)。首先創(chuàng)建一個(gè)菜單條(MenuBar) jmb,</p><p>  然后創(chuàng)建不同的菜單項(xiàng)(Menu)加入到菜單條中。</p><p>  JMenu sound = new JMenu("音樂"); </p><p>  jmb.add(sound);</p><p>  最后創(chuàng)建菜單子項(xiàng)(MenuItem)

52、加入菜單項(xiàng),比如給“音樂”菜單項(xiàng)添加“播放”菜單子項(xiàng):</p><p>  JMenuItem play = new JMenuItem("播放");</p><p>  Sound.add(play);</p><p>  棋盤的繪制。五子棋盤(OmokBoard類),五子棋盤繼承了JPanel,它內(nèi)嵌于框架窗口中棋盤的大小采用15*15個(gè)方格

53、。每個(gè)交叉點(diǎn)處可放置棋子。</p><p>  private void drawLine(){</p><p>  gbuff.setColor(Color.BLACK);</p><p>  for(int i=1; i<=size;i++) {</p><p>  gbuff.drawLine(cell, i*cell, cell

54、*size, i*cell);</p><p>  gbuff.drawLine(i*cell, cell, i*cell , cell*size);</p><p><b>  }</b></p><p><b>  }</b></p><p>  當(dāng)一個(gè)用戶放下一個(gè)棋子后,同一房間里的兩個(gè)用戶的

55、棋盤都要重畫,以顯示自己和對(duì)方下的棋子等信息。</p><p>  棋子的繪制。用白色繪制一個(gè)圓形的邊框,將填充黑色,這樣就畫好了一個(gè)黑色棋。位置要根據(jù)獲得的鼠標(biāo)點(diǎn)擊的坐標(biāo)和棋盤的大小來定。</p><p>  private void drawBlack(int x, int y)//繪制黑棋</p><p><b>  {</b></

56、p><p>  Graphics2D gbuff=(Graphics2D)this.gbuff;</p><p>  gbuff.setColor(Color.black);</p><p>  gbuff.fillOval(x*cell-cell/2, y*cell-cell/2, cell, cell);</p><p>  gbuff.se

57、tColor(Color.red);</p><p>  gbuff.drawOval(x*cell-cell/2, y*cell-cell/2, cell, cell);//邊框</p><p><b>  }</b></p><p><b>  注冊(cè)監(jiān)聽者</b></p><p>  圖形用戶界

58、面的每個(gè)可能產(chǎn)生事件的組件稱為事件源, 希望事件源上發(fā)生的事件被程序處理, 就要把事件源注冊(cè)給能夠處理該事件源上事件的監(jiān)聽者。 </p><p><b>  圖6-3 </b></p><p>  在這里按鈕,菜單,和發(fā)送消息的文本框都是事件源。要想按鈕或菜單發(fā)生事件時(shí),程序能處理,必須注冊(cè)監(jiān)聽者。按鈕動(dòng)作事件ActionEvent的監(jiān)聽者接口為ActionLis

59、tener,給按鈕注冊(cè)監(jiān)聽者的方法為addActionListener()。</p><p>  sendBox.addActionListener(this);//文本框按回車鍵</p><p>  enterButton.addActionListener(this);</p><p>  exitButton.addActionListener(this);&

60、lt;/p><p>  在actionPerformed(ActionEvent ae)中編寫上體的事件處理代碼。在發(fā)生事件時(shí)事件源將給其注冊(cè)的所有監(jiān)聽者對(duì)象的發(fā)送消息,實(shí)際上就是調(diào)用監(jiān)聽者對(duì)象的actionPerformed()方法,從而完成事件的處理。通過getSource()方法:用來獲取事件源對(duì)象。處理不同的事件。如處理單擊“音樂播放”菜單和“游戲開始”引起的事件的actionPerfrmed()方法。<

61、;/p><p>  public void actionPerformed(ActionEvent ae) //播放音樂</p><p>  { if(ae.getSource()==play){</p><p>  Object selection[] = {"fi.MID","five.mid"};</p>

62、<p>  Object set = JOptionPane.showInputDialog(null,</p><p>  "選擇音樂...","播放...", JOptionPane.QUESTION_MESSAGE,null,selection,selecton[0]);</p><p>  music

63、=new Sound(set.toString());</p><p>  music.play();</p><p><b>  }</b></p><p>  else if(ae.getSource()==startButton){</p><p>  try{ writer.println("[ST

64、ART]");//發(fā)送開始信息</p><p>  infoView.setText("等待對(duì)方?jīng)Q定.");</p><p>  startButton.setEnabled(false);</p><p>  }catch(Exception e){}</p><p><b>  }</b>

65、;</p><p>  進(jìn)行五子棋游戲的一個(gè)重要的內(nèi)容是獲取鼠標(biāo)點(diǎn)擊時(shí)在棋盤中的坐標(biāo),即落下棋子的位置。</p><p>  addMouseListener(new MouseAdapter(){</p><p>  public void mousePressed(MouseEvent me){</p><p>  if(!enable)

66、return;//是否輪到下棋</p><p>  int x=(int)Math.round(me.getX()/(double)cell);//得到鼠標(biāo)坐標(biāo) </p><p>  int y=(int)Math.round(me.getY()/(double)cell);</p><p>  //坐標(biāo)要求不超過棋盤大小,在坐標(biāo)上不存在棋子</p>

67、<p>  if(x==0 || y==0 || x==size+1 || y==size+1)return;</p><p>  if(map[x][y]==BLACK || map[x][y]==WHITE)return;</p><p>  writer.println("[STONE]"+x+" "+y);//向服務(wù)器發(fā)送棋子信息&

68、lt;/p><p>  } </p><p><b>  連接服務(wù)器</b></p><p>  客戶端連接服務(wù)器,首先用服務(wù)器所在機(jī)器的ip以及服務(wù)器的端口作為參數(shù)創(chuàng)建一個(gè)Socket對(duì)象。客戶端調(diào)用connect()方法進(jìn)行連接。</p><p>  Socket socket=new Socket(&

69、quot;127.0.0.1", 8888);</p><p>  這里以本機(jī)地址127.0.0.1為IP地址,是為了方便服務(wù)器和客戶端運(yùn)行在同一臺(tái)機(jī)器上做實(shí)驗(yàn)??蛻舳艘婚_始運(yùn)行,便連接IP127.0.0.1主機(jī)的8888號(hào)端口如果連接成功,則在TextArea對(duì)象msgViewk中顯示成功消息。否則顯示連接錯(cuò)誤的消息。</p><p><b>  傳遞信息</b

70、></p><p>  客戶端之間的信息傳遞,比如發(fā)送開始游戲,聊天都要通過先經(jīng)過服務(wù)器發(fā)送。服務(wù)器接收到客戶端發(fā)送的各種消息,識(shí)別不同消息的類別,采用不同的方法進(jìn)行處理。</p><p>  當(dāng)建立與服務(wù)器的連接后,客戶端通過數(shù)據(jù)輸出流發(fā)送相應(yīng)的請(qǐng)求給服務(wù)器,并且通過數(shù)據(jù)輸入流從服務(wù)器端接收信息。客戶端通過開啟一個(gè)線程,處理與服務(wù)器之間的數(shù)據(jù)。</p><p&g

71、t;  reader=new BufferedReader(new InputStreamReader(socket.getInputStream())); writer=new PrintWriter(socket.getOutputStream(), true);</p><p>  new Thread(this).start();//開始一個(gè)將調(diào)用這個(gè)runnable的run()方法的線程</p&g

72、t;<p>  Java運(yùn)行系統(tǒng)調(diào)用這個(gè)方法run()來執(zhí)行線程。在Client類中,繼承了JFrame類,由于Java的單繼承性,Client類就不能再繼承Thread,但可以實(shí)現(xiàn)runnable</p><p>  接口,通過覆蓋Runnable接口里的run ()方法,用以對(duì)游戲過程中的數(shù)據(jù)傳輸,處理,控制。</p><p>  客戶端與服務(wù)器之間傳遞的信息,都是由“[

73、消息種類]+內(nèi)容“組成的,服務(wù)器接收到來客戶端的消息,分析”[消息種類]“中的內(nèi)容,進(jìn)行相關(guān)的操作。下面對(duì)各種消息的種類作一個(gè)介紹。</p><p>  [NAME]當(dāng)用戶在客戶登陸時(shí),發(fā)送給服務(wù)器,用于顯示登陸用戶名字。</p><p>  [ROOM]當(dāng)用戶登陸上時(shí),[ROOM]號(hào)為0,記為“游戲大廳”,選擇房間的用戶在“游戲大廳“,房間號(hào)為大于0的整數(shù),一個(gè)房間最多容納2人,即對(duì)戰(zhàn)的

74、雙方。當(dāng)服務(wù)器端接收到查看[ROOM]房間號(hào)人數(shù)是否為滿。不為滿,則發(fā)送”[ROOM]+n”,給客戶端,表示可以進(jìn)入。否則發(fā)送“[FULL]”。</p><p>  [PLAYERS]在客戶端顯示相同房間用戶列表。</p><p>  [DISCONNECT]表示對(duì)方斷線。</p><p>  [COLOR]得到棋子顏色。[COLOR]BLACK表示黑棋。[WIN

75、]表示獲勝。</p><p>  [LOSE]表示失敗。</p><p>  [EXIT]表示對(duì)方離開房間。</p><p>  [ENTER]顯示相同房間中登陸的用戶。</p><p>  [STONE]表示對(duì)方下棋棋子的坐標(biāo)。</p><p>  [MSG]表示聊天的信息,只在相同的房間內(nèi)可見。如果要想讓所有的登陸

76、的用戶都能收到聊天信息,則消息種類為”[MSG]a”</p><p><b>  棋盤數(shù)據(jù)結(jié)構(gòu)</b></p><p>  棋盤設(shè)置成有15*15個(gè)方格。定義了一個(gè)二維數(shù)組Map[][]用于保存棋子在棋盤中的位置。在程序中用常數(shù)1表BLACK(黑棋),用-1表示W(wǎng)RITE(白棋),用0表示在此位置上無棋子。如在(3,3)位置上有一個(gè)黑棋。則Map[3][3]的值為1。

77、</p><p>  public static final int BLACK=1, WHITE=-1;//顏色標(biāo)識(shí)值</p><p>  private int[][] map;//Map是一個(gè)二元數(shù)組,用于保存棋子的位置</p><p><b>  判斷輸贏算法</b></p><p>  輸贏的判斷是網(wǎng)絡(luò)五子棋游

78、戲中一個(gè)很重要的部分。當(dāng)雙方每放下一個(gè)棋子的時(shí)候,程序都要進(jìn)行判斷是否已經(jīng)產(chǎn)生了輸贏。如果是,則停止游戲,并發(fā)送結(jié)果給服務(wù)器,服務(wù)器再發(fā)送結(jié)果給對(duì)方。橫,豎或者對(duì)角線方向上擁有五顆同樣的棋子時(shí),即為勝利。</p><p>  當(dāng)在棋盤中放入一個(gè)棋子時(shí),比如白色。程序要計(jì)算它左邊連在一起的白色棋子的個(gè)數(shù),然后計(jì)算右邊與它相連在一起的白色棋子的個(gè)數(shù)。再將兩數(shù)相加,如果為四,與自己加起來剛好為五。則白棋獲勝。用同樣的方

79、法在垂直和對(duì)角線方向進(jìn)行判斷同色棋子個(gè)數(shù)。如果獲勝,則客戶端發(fā)送[WIN]給服務(wù)器,否則由對(duì)方下棋,并重復(fù)進(jìn)行相同的運(yùn)算。</p><p>  count()方法用來查找并計(jì)算連在一起的棋子的個(gè)數(shù)。P為基準(zhǔn)坐標(biāo),dx、dy分別為表示橫向于豎向的變量。col代表棋子顏色。弱dx為-1,dy為0,則計(jì)算左邊連續(xù)棋子的個(gè)數(shù);若dx為1,dy為1,則計(jì)算左下到右上連續(xù)棋子的個(gè)數(shù)。dx與dy只取-1、0、1三個(gè)值之一。下面

80、是count()方法的代碼。</p><p>  private int count(Point p, int dx, int dy, int col)</p><p><b>  {</b></p><p><b>  int i=0;</b></p><p>  for(; map[p.x+(i

81、+1)*dx][p.y+(i+1)*dy]==col ;i++);</p><p><b>  return i;</b></p><p><b>  }</b></p><p>  用check()方法調(diào)用count()方法,分別在橫、豎和對(duì)角線方向上計(jì)算相連同色棋子的個(gè)數(shù)。</p><p>  

82、private boolean check(Point p, int col)</p><p><b>  {</b></p><p>  if(count(p, 1, 0, col)+count(p, -1, 0, col)==4)//橫向檢查</p><p>  return true;</p><p>  if(c

83、ount(p, 0, 1, col)+count(p, 0, -1, col)==4)//豎向檢查</p><p>  return true;</p><p>  if(count(p, -1, -1, col)+count(p, 1, 1, col)==4)//對(duì)角線方向檢查</p><p>  return true;</p><p>

84、  if(count(p, 1, -1, col)+count(p, -1, 1, col)==4)//對(duì)角線方向檢查</p><p>  return true;</p><p>  return false;</p><p><b>  }</b></p><p><b>  背景音樂</b>&

85、lt;/p><p><b>  圖6-4</b></p><p>  通過下拉框,選擇要播放的音樂,點(diǎn)擊確定開始播放。停止播放,在菜單欄中單擊停止播放。如圖6-4所示。</p><p>  播放背景音樂通過Sound類實(shí)現(xiàn)。首先要獲得播放文件的URL地址具體過程如下:</p><p>  urlLoader=(URLClas

86、sLoader)this.getClass().getClassLoader();</p><p>  url=urlLoader.findResource("audio/"+soundfile);//當(dāng)前目錄audio下</p><p>  再據(jù)url地址獲得一個(gè)用于播放的音頻的AudioClip對(duì)象</p><p>  AudioClip 

87、soundData=ap.newAudioClip(url);</p><p>  通過soundData的play()和stop()方法就可以實(shí)現(xiàn)音樂的播放和停止。</p><p><b>  設(shè)計(jì)實(shí)現(xiàn)</b></p><p><b>  首先運(yùn)行服務(wù)器</b></p><p><b>

88、  圖7-1</b></p><p>  運(yùn)行兩個(gè)客戶端,以便進(jìn)行對(duì)戰(zhàn)??蛻舳说倪B接的IP為127.0.0.1。兩個(gè)用戶分別命名為feng和tang。進(jìn)行游戲大廳后,輸入房間號(hào)1,進(jìn)入1號(hào)房間。點(diǎn)擊“開始游戲”進(jìn)行游戲。</p><p><b>  圖7-2</b></p><p><b>  圖7-3</b>

89、</p><p>  當(dāng)游戲一方贏時(shí),顯示提示信息。圖7-4所示。</p><p><b>  圖7-4</b></p><p>  同色棋子成“五子相連”為勝,下面黑棋勝。圖7-5所示</p><p><b>  圖7-5</b></p><p>  當(dāng)游戲進(jìn)行時(shí),一方棄權(quán)

90、,則按輸處理。另一方獲勝。如圖:圖7-6</p><p><b>  圖7-6</b></p><p><b>  總結(jié)</b></p><p>  Java作為一種分布式和可移植的計(jì)算機(jī)語言,在網(wǎng)絡(luò)軟件開發(fā)上有著特別的優(yōu)點(diǎn)。它開發(fā)方便、快捷,安全性高,對(duì)以往復(fù)雜的功能,尤其是網(wǎng)絡(luò)通信等方面,實(shí)現(xiàn)起來簡(jiǎn)潔明了,在網(wǎng)絡(luò)編程領(lǐng)

91、域有著巨大的發(fā)展?jié)摿Α_@次Java課程設(shè)計(jì)完成了一個(gè)網(wǎng)絡(luò)五子棋的設(shè)計(jì)和開發(fā)。包括服務(wù)器和客戶端。不同的用戶使用客戶端,利用服務(wù)器相連。實(shí)現(xiàn)了用戶在Internet上任何地方與別人進(jìn)行五子對(duì)戰(zhàn)。網(wǎng)絡(luò)五子棋的實(shí)現(xiàn)用到了網(wǎng)絡(luò)套接字和多線程的相關(guān)知識(shí)。服務(wù)器創(chuàng)建服務(wù)器Socket,并處于監(jiān)聽狀態(tài)??蛻舳讼蚍?wù)器發(fā)出申請(qǐng),服務(wù)器接受后,利用輸入輸出流進(jìn)行通信。并開始一個(gè)線程,處理與這個(gè)相連的客戶端在游戲過程的數(shù)據(jù)傳輸、控制等。進(jìn)行五子棋的一個(gè)主要

92、算法就是判斷輸贏。這里采用計(jì)算落下棋子的橫、豎及對(duì)角線方向的同色棋子的個(gè)數(shù)來實(shí)現(xiàn)。當(dāng)個(gè)數(shù)為5時(shí)為勝。服務(wù)器與客戶端在通信過程中,雙方如何知道發(fā)送信息的意義呢?這里發(fā)送的信息采用“[消息類別]+內(nèi)容“的格式。服務(wù)器和客戶端通過分析“消息類別”來采取不同的方法處理發(fā)送的數(shù)據(jù)。</p><p>  通過這次課程設(shè)計(jì),加深了我對(duì)Java網(wǎng)絡(luò)編程和多線程編程方面的了解。網(wǎng)絡(luò)五子棋基本實(shí)現(xiàn)了網(wǎng)絡(luò)對(duì)戰(zhàn)的功能,但只能通過網(wǎng)絡(luò),沒

93、有實(shí)現(xiàn)人機(jī)對(duì)戰(zhàn)的功能。也沒有添加“禁手”規(guī)則。這時(shí)是已后要改進(jìn)的地方。</p><p><b>  謝辭</b></p><p>  二周的課程設(shè)計(jì)很快就過去了,首先要感謝xx老師的細(xì)心的指導(dǎo)。對(duì)我能準(zhǔn)時(shí)完成任務(wù)有很大的幫助。王xx嚴(yán)謹(jǐn)?shù)闹笇?dǎo)態(tài)度與深厚的理論知識(shí)都讓我受益非淺,從他身上我學(xué)到了很多的東西,無論是理論還是實(shí)踐都使我的知識(shí)有很大的提高.借此我特提出感謝。還

94、要感謝同學(xué)在課程設(shè)計(jì)期間對(duì)我的幫助,最后要感謝互聯(lián)網(wǎng),有很多問題,通過搜索很快就得到解決的方法。</p><p><b>  參考文獻(xiàn)</b></p><p>  丁振凡 . Java語言實(shí)用教程[M]. 北京郵電大學(xué)出版社. 2006.9</p><p>  宛延闿 . 實(shí)用Java語言程序設(shè)計(jì)教程習(xí)題解答與上機(jī)實(shí)踐[M]. 機(jī)械工業(yè)出版社.

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫(kù)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論