陶宇陽 蔣玉茹 劉林峰 王巖
(北京信息科技大學(xué)計(jì)算機(jī)學(xué)院 北京市 100101)
隨著互聯(lián)網(wǎng)在的快速發(fā)展,學(xué)生們擁有了許多可以獲取知識的渠道,但是如何短期提升學(xué)生獲取知識的成就感使學(xué)生進(jìn)一步提升學(xué)習(xí)的動力仍是一大重要問題,同時在一局快節(jié)奏的對戰(zhàn)游戲中,利用自己已有的知識和問題分析能力贏得比賽正是一種能快速獲得成就感的方式。
目前,已存在許多成熟的大型網(wǎng)絡(luò)學(xué)習(xí)平臺及互動答題游戲形式,這些平臺普遍擁有很多的學(xué)習(xí)資源而游戲也擁有較為成熟的游戲方案,但是學(xué)習(xí)平臺很容易陷入“學(xué)不動,不想學(xué)”的困境,單純的游戲又與學(xué)習(xí)不相關(guān)。鑒于此,立足于當(dāng)前廣大學(xué)生的學(xué)習(xí)模式單一的情況,根據(jù)學(xué)生的學(xué)習(xí)需要,結(jié)合網(wǎng)絡(luò)對戰(zhàn)游戲能夠快速獲得成就感的特點(diǎn),本文設(shè)計(jì)并開發(fā)了一款可以在線匹配多人組隊(duì)答題(專業(yè)知識)的網(wǎng)絡(luò)對戰(zhàn)游戲,致力于提供在線匹配、多人組隊(duì)、同步答題、積分多者獲勝等輕量化、個性化的游戲平臺解決方案。
本項(xiàng)目所設(shè)計(jì)與開發(fā)的系統(tǒng)與北京信息科技大學(xué)計(jì)算機(jī)學(xué)院的程序設(shè)計(jì)基礎(chǔ)(C 語言)過程化考核平臺緊密融合,已經(jīng)部署在校園內(nèi)網(wǎng)環(huán)境中。系統(tǒng)既以學(xué)生為主體,寓學(xué)于樂,為學(xué)生提供更加輕松的學(xué)習(xí)環(huán)境,又在潛移默化中提高學(xué)生的程序設(shè)計(jì)及C 語言應(yīng)用水平,同時,系統(tǒng)亦可幫助教師了解學(xué)生的學(xué)習(xí)情況,及時調(diào)整教學(xué)策略,最終使學(xué)生、教師和學(xué)校都可以獲益。
本系統(tǒng)包括基于Spring Boot 框架搭建的服務(wù)端和Android 客戶端。系統(tǒng)模塊結(jié)構(gòu)圖如圖1所示。
采用北京信息科技大學(xué)計(jì)算機(jī)學(xué)院的程序設(shè)計(jì)基礎(chǔ)(C 語言)過程化考核平臺的習(xí)題庫中的習(xí)題為出題內(nèi)容。習(xí)題庫中有困難、中等、容易三種評級的題目,由于困難評級的題目往往涉及長代碼閱讀或復(fù)雜計(jì)算,通常不能在短時間內(nèi)解答,因此不適合在本對戰(zhàn)系統(tǒng)中使用,系統(tǒng)僅采用簡單和中等兩種評級的題目。不同評級的題目有不同的答題時間,中等難度的題目答題時間為30 秒,容易難度的題目答題時間為10 秒。系統(tǒng)針對每一組成功匹配的用戶,從題庫中隨機(jī)抽取若干題目作為該組用戶的對戰(zhàn)題目。
對戰(zhàn)系統(tǒng)采用基于對戰(zhàn)積分的平衡匹配算法在匹配池中找到合適的一組用戶分成兩個隊(duì)伍組成對局。匹配算法盡可能保證對局雙方的平均水平接近,同時,隊(duì)內(nèi)的各個成員水平接近。避免出現(xiàn)雙方的知識水平差距過大,使得對局失去了緊張刺激的感覺,從而影響了用戶的游戲體驗(yàn)。
對局中,服務(wù)端通過統(tǒng)一消息指令的收發(fā),保證每道題目的內(nèi)容和選項(xiàng)盡可能同時出現(xiàn)在各個用戶的手機(jī)屏幕上,每個客戶端反應(yīng)在界面上的題目答題時限(倒計(jì)時)也盡可能保持一致。

圖1:選擇題對戰(zhàn)系統(tǒng)系統(tǒng)模塊結(jié)構(gòu)圖

圖2:匹配算法的存儲結(jié)構(gòu)簡略圖
每道題目都有相同的初始分?jǐn)?shù),題目分?jǐn)?shù)會隨著作答時間的流逝而減少。每名成員對每一道題僅有一次選擇答案的機(jī)會,無論答案是否正確。若某一個成員選擇了正確的答案,那么其所屬的隊(duì)伍就會加分。分值是該成員選擇答案時的題目分?jǐn)?shù)。最后,隊(duì)伍得分高的一方獲勝。
對戰(zhàn)雙方想獲取勝利就要在盡可能短的時間內(nèi)選出正確答案,這樣的對戰(zhàn)規(guī)則保證了游戲有一定的競技性,用戶在答題過程中,可以發(fā)現(xiàn)在課堂上沒有及時掌握的知識。不同于課堂上嚴(yán)肅的氣氛,相對緊張又不乏趣味的對戰(zhàn)過程可以加深用戶對平時容易忘記的細(xì)節(jié)知識點(diǎn)的記憶。同時,選擇題的答題方式簡單明確,不會像填空、解答題一樣產(chǎn)生語義上的誤差,適合在手機(jī)上操作,符合本系統(tǒng)在輕松使用時學(xué)習(xí)知識的設(shè)計(jì)初衷。
服務(wù)端分為對戰(zhàn)核心模塊和題目數(shù)據(jù)供給模塊。其中,對戰(zhàn)核心模塊提供網(wǎng)絡(luò)通信服務(wù)、匹配服務(wù)和對局服務(wù);題目數(shù)據(jù)供給模塊提供客戶端訪問數(shù)據(jù)庫的HTTP 接口,按需求獲取題目信息。
對戰(zhàn)核心模塊下屬的各個服務(wù)獨(dú)立運(yùn)行于不同的線程中,通過消息隊(duì)列進(jìn)行線程間的通訊。

圖3:自動機(jī)的圖結(jié)構(gòu)數(shù)據(jù)
(1)網(wǎng)絡(luò)通信服務(wù)負(fù)責(zé)與各客戶端建立連接,監(jiān)聽并接收消息,發(fā)送消息,封裝消息為JavaBean。
(2)匹配服務(wù)運(yùn)行設(shè)計(jì)好的平衡匹配算法,接受客戶端的匹配請求,當(dāng)匹配系統(tǒng)得出一組匹配結(jié)果時,將結(jié)果發(fā)送給對局服務(wù),創(chuàng)建對局。
(3)對局服務(wù)負(fù)責(zé)本系統(tǒng)的核心功能,調(diào)度對局的進(jìn)行階段。每一個對局獨(dú)立運(yùn)行于對局服務(wù)的子線程中,對局服務(wù)在創(chuàng)建新的對局時,隨機(jī)生成一個對局ID,并通過鍵值對保存其對象。當(dāng)接收客戶端消息時,通過鍵值對,發(fā)送給指定的線程。
每一個服務(wù)的運(yùn)行模式均為:服務(wù)在各自的線程中運(yùn)行時,會阻塞在從各自的消息隊(duì)列中獲取消息的步驟,阻塞時不會消耗CPU資源,當(dāng)服務(wù)從消息隊(duì)列中獲取到一條消息時,會根據(jù)消息內(nèi)容進(jìn)行業(yè)務(wù)邏輯上的處理,處理完畢以后再一次阻塞在獲取消息的步驟。
客戶端收到服務(wù)端的指令后,調(diào)用服務(wù)端題目數(shù)據(jù)供給模塊的相關(guān)接口,獲取JSON 形式的題目信息,封裝并顯示。
本系統(tǒng)數(shù)據(jù)庫存儲三個實(shí)體信息:科目信息、題目信息和題目選項(xiàng)信息。其他信息,比如用戶信息及用戶身份驗(yàn)證,則通過北京信息科技大學(xué)計(jì)算機(jī)學(xué)院的程序設(shè)計(jì)基礎(chǔ)(C 語言)過程化考核平臺提供的相關(guān)接口實(shí)現(xiàn)管理及操作,無需單獨(dú)建立數(shù)據(jù)庫。
網(wǎng)絡(luò)通信服務(wù)基于NIO 技術(shù),與各客戶端建立TCP 長連接,負(fù)責(zé)消息的發(fā)送、接收與封裝。消息分為兩類,分別為服務(wù)端向客戶端發(fā)送的ClientMessage,和客戶端向服務(wù)端發(fā)送的ServerMessage。這兩種消息均封裝為JavaBean,在類中規(guī)定消息結(jié)構(gòu)。當(dāng)其它服務(wù)需要向客戶端發(fā)送消息時,通過向網(wǎng)絡(luò)通信服務(wù)的消息隊(duì)列發(fā)送消息,網(wǎng)絡(luò)通信服務(wù)將隊(duì)列中的JavaBean 消息對象出隊(duì),并讀取其中的數(shù)據(jù),寫入字節(jié)緩沖區(qū)ByteBuffer,調(diào)用SocketChannel 類的write()方法,完成消息的發(fā)送;同時,網(wǎng)絡(luò)通信服務(wù)的下屬子服務(wù)MessageReceiver,獨(dú)立運(yùn)行于一個線程中,負(fù)責(zé)通過NIO 的多路復(fù)用選擇器Selector,阻塞式監(jiān)聽各客戶端的連接。若收到消息,則調(diào)用SocketChannel 的read()方法,讀取來自客戶端的消息數(shù)據(jù),并將其封裝為JavaBean 對象,然后后消息隊(duì)列發(fā)送給其它服務(wù)。
MessageReceiver的監(jiān)聽及接收消息的邏輯,用偽代碼表示如下:
1.選擇器監(jiān)聽到READ 事件;
2.將觸發(fā)READ 事件的SocketChannel 添加到集合中;
3.獲取集合的迭代器;
4.while(迭代器有剩余內(nèi)容) {
5.獲取觸發(fā)READ 事件的SocketChannel;
6.SocketChannel.read();
7.封裝消息為JavaBean;
8.發(fā)送JavaBean 給指定的服務(wù);
9.將當(dāng)前SocketChannel 從集合中刪除;
10.}
設(shè)計(jì)平衡匹配算法,以滿足下述目標(biāo):
(1)多個用戶進(jìn)行游戲時,需要盡可能保持用戶間水平相近來給用戶更好的游戲體驗(yàn);
(2)需要權(quán)衡用戶等待時間與用戶間的水平差距孰先孰后的問題。
為此,首先設(shè)計(jì)匹配隊(duì)列的數(shù)據(jù)結(jié)構(gòu):
(1)將發(fā)出匹配請求的用戶抽象為一個類,具有分?jǐn)?shù)和等待時間兩個屬性;
(2)利用集合存儲同一個分段的用戶
(3)從0 分起,每10 分為一個分段;
(4)利用有序數(shù)組存儲多個集合。
形成有序數(shù)組存儲多個集合、集合存儲多個用戶的數(shù)據(jù)結(jié)構(gòu)。
當(dāng)有新的用戶加入匹配隊(duì)列時,根據(jù)用戶的分?jǐn)?shù)將其放置到數(shù)組特定下標(biāo)的集合中,服務(wù)端中的實(shí)現(xiàn)是將用戶置入數(shù)組下標(biāo)為用戶分?jǐn)?shù)除以10 的集合中去,即用戶分?jǐn)?shù)為2733 則置入第273 個集合中去。
每秒以集合為單位遍歷一次數(shù)組,當(dāng)數(shù)組中某一集合滿足游戲開始所需要的人數(shù),則將這些用戶移出匹配隊(duì)列,組建成為一次游戲?qū)帧7駝t將獲取此集合中等待時間最長的用戶,根據(jù)此用戶的等待時間向兩側(cè)一定距離內(nèi)的集合獲取在匹配中的用戶。服務(wù)端中的實(shí)現(xiàn)是向兩側(cè)距離小于用戶等待時間的平方的集合中獲取用戶,即假如用戶在匹配隊(duì)列中等待了5 秒,分?jǐn)?shù)為2307 分,那么在第230 個集合中用戶,如果用戶數(shù)量不足以開始游戲,那么就會在239、238……205,231、232……255,這些集合中獲取用戶,直到達(dá)到游戲開始的要求。
這樣可以發(fā)現(xiàn),只要整個匹配隊(duì)列中的用戶數(shù)量滿足游戲開始的要求,那么在一分鐘以內(nèi)一定會成功組建游戲,如果匹配隊(duì)列中用戶較多,那么成功組建的對局中所有用戶的分?jǐn)?shù)的方差會盡可能小。
匹配算法的存儲結(jié)構(gòu)簡略圖如圖2所示。
狀態(tài)自動機(jī)是控制客戶端界面與后臺交互邏輯的核心。其設(shè)計(jì)思想包括:
(1)以有向圖結(jié)構(gòu)表示并存儲自動機(jī)的執(zhí)行邏輯,圖節(jié)點(diǎn)表示狀態(tài),結(jié)點(diǎn)間的連線表示事件。
(2)用戶對客戶端的互動行為(主要體現(xiàn)為點(diǎn)擊手機(jī)屏幕或點(diǎn)擊返回按鈕等),以及接收來自服務(wù)器的消息,均可觸發(fā)某種事件。
(3)每一個狀態(tài)均可由指定的某些事件,轉(zhuǎn)換成另一種狀態(tài)。
(4)在自動機(jī)中維護(hù)一個變量currentStatus,表示自動機(jī)的當(dāng)前狀態(tài)。
(5)自動機(jī)通過剛剛被觸發(fā)的事件,從有向圖中查找下一個狀態(tài),并更新為當(dāng)前狀態(tài)。
(6)自動機(jī)獨(dú)立運(yùn)行在一個線程中,通過Message 向界面線程發(fā)送指令以控制界面的變化。
(7)界面線程以及其他線程通過向自動機(jī)的事件隊(duì)列發(fā)送剛剛被觸發(fā)的事件。
(8)自動機(jī)的任務(wù)就是根據(jù)被觸發(fā)的事件,轉(zhuǎn)換當(dāng)前狀態(tài),并調(diào)用新狀態(tài)的某個方法,執(zhí)行一系列邏輯。
(9)自動機(jī)存儲并調(diào)用的所有狀態(tài)對象的類型,均為狀態(tài)的抽象父類。
(10)不同的狀態(tài)通過繼承同一個抽象父類,在同一個抽象方法中寫入不同的具體實(shí)現(xiàn),供自動機(jī)線程調(diào)用。
自動機(jī)的圖結(jié)構(gòu)數(shù)據(jù)由圖3 表示。
本文設(shè)計(jì)與開發(fā)了一個選擇題對戰(zhàn)系統(tǒng),基于SpringBoot 設(shè)計(jì)并實(shí)現(xiàn)了系統(tǒng)的服務(wù)端,基于Android 技術(shù)設(shè)計(jì)并實(shí)現(xiàn)了系統(tǒng)的客戶端。在客戶端利用自動機(jī)機(jī)制設(shè)計(jì)人機(jī)交互邏輯;在服務(wù)器端利用NIO 技術(shù)設(shè)計(jì)高效網(wǎng)絡(luò)通訊架構(gòu)。所實(shí)現(xiàn)系統(tǒng)本系統(tǒng)以實(shí)現(xiàn)勞逸結(jié)合為目的,將專業(yè)知識的學(xué)習(xí)與游戲競技的優(yōu)點(diǎn)融為一體,著重激發(fā)學(xué)生的學(xué)習(xí)興趣,減輕反饋不足所學(xué)習(xí)易產(chǎn)生的倦怠心理。本系統(tǒng)已經(jīng)實(shí)際部署于學(xué)校的過程考核平臺之中,心里,對游戲各個環(huán)節(jié)進(jìn)行設(shè)計(jì),提供既有娛樂性質(zhì)也可學(xué)習(xí)專業(yè)知識的對戰(zhàn)游戲。本系統(tǒng)具有較強(qiáng)的實(shí)用性,可以為用戶提供了完整的游戲較好的學(xué)習(xí)體驗(yàn)。