999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

基于QT的武漢麻將游戲起牌設計

2024-01-23 00:44:39徐子怡
現代信息科技 2023年23期

徐子怡 等

林富生? 宋志峰? 徐自立? 余聯慶

摘? 要:為實現程序自動打牌,必須首先正確顯示四家手牌。針對正確顯示手牌這一需求,設計了武漢麻將游戲,構造排序算法、皮子癩子獲取算法和起牌算法等。即在起始階段搖骰子以確定起牌的起始位置和莊家,然后有序顯示各家手牌。通過對武漢麻將起牌規則的機器學習,將口語化的規則用計算機語言準確描述,以實現正確起牌。為了驗證算法的有效性,使用QT框架構建了武漢麻將自動打牌軟件進行相應的實驗驗證,實驗結果表明:起牌算法可以正確起牌,并顯示四家手牌,具有一定的實用性。

關鍵詞:武漢麻將;QT框架;起牌算法

中圖分類號:TP311.1? 文獻標識碼:A? 文章編號:2096-4706(2023)23-0083-07

Design of Wuhan Mahjong Game Starting Card Based on QT

XU Ziyi1,2,3, LIN Fusheng1,2,3, SONG Zhifeng1,2,3, XU Zili1,2, YU Lianqing1

(1.School of Mechanical Engineering and Automation, Wuhan Textile University, Wuhan? 430200, China;

2.Hubei Provincial Engineering Research Center of 3D Textile, Wuhan? 430200, China;

3.Hubei Provincial Key Laboratory of Digital Textile Equipment, Wuhan? 430200, China)

Abstract: To achieve automatic card playing in the program, it is necessary to first display the four hands correctly. In view of the need to display the hand cards correctly, Wuhan Mahjong game is designed, and sorting algorithm, skin scab acquisition algorithm and starting card algorithm are constructed. At the beginning of the Mahjong game, it rolls the dice to determine the starting position and dealer of the cards, and then displays the cards of each player in an orderly manner. Through machine learning of the rules of starting card in Wuhan Mahjong, the spoken rules are accurately described in computer language to achieve correct starting of cards. In order to verify the effectiveness of the algorithm, a Wuhan Mahjong automatic card playing software is constructed using the QT framework for corresponding experimental verification. The experimental results show that the starting card algorithm can correctly play cards and display four hands, which has certain practicality.

Keywords: Wuhan Mahjong; QT framework; starting card algorithm

0? 引? 言

計算機博弈一直是驗證人工智能理論的試金石,也是人工智能最活躍的研究領域之一[1],麻將屬于非完全信息博弈,相對完全信息博弈更為困難。為了方便玩家快速進入游戲,供休閑娛樂[2],設計并開發了武漢麻將游戲軟件,該軟件可以滿足玩家隨時隨地進入游戲,還能使計算機學習到最佳的打牌算法實現自動打牌[3]。其中最主要的是在開始打牌之前需要對牌進行初始化,自動按規則發牌,正確顯示四家手牌,為打牌做好準備。通過對武漢麻將規則的學習以及計算機語言的描述,可以實現智能麻將。本文主要針對麻將初始化、發牌、顯示手牌進行研究。

1? 武漢麻將簡介

武漢麻將,又稱開口翻、紅中癩子杠,核心是二五八、癩子、七皮四賴、開口翻和口口翻。麻將牌:筒、條、萬、風,共136張牌。其中萬、條、筒各九種,風牌七種,沒有梅、蘭、竹、菊、春、夏、秋、冬。普通牌可以吃、碰和杠,但紅中不能吃、碰紅中,只能杠;癩子可代替任何牌張,但不能吃、碰,可以杠癩子。

武漢麻將順時針發牌,逆時針打牌。開局時4位玩家以東、南、西、北入座,每人起手摸13張牌,莊(東風位置)玩家起手多摸1張牌,共計14張,之后由莊家位玩家開始按逆時針出牌操作[1]。通過兩點數的和(add)確定起始拿牌方位,再通過較小的點子數(nums)確定留牌墩數(add為1、5、9時從東方起牌,留nums墩;add為2、6、10時從南方起牌,留nums墩;add為3、7、11時從西方起牌,留nums墩;add為12、8、4時從北方起牌,留nums墩)。

文中關于武漢麻將的名詞解釋:

癩子:武漢麻將“癩子”是在四個選手閑家抓完13張牌莊家抓完第14張牌后翻取的第一張牌加一就是“癩子”。

皮子:武漢麻將“皮子”是在四個選手閑家抓完13張牌莊家抓完第14張牌后翻取的第一張牌。

玩家:武漢麻將游戲由4名玩家組成。

牌庫:牌的總張數。武漢麻將分為條、筒、萬、風四門,共計136張。

牌墻:洗完牌開局使牌墻共136張牌,發完初始手牌后,牌墻剩下的牌為83張。

局面:某位玩家在某一個時刻可以觀察到的所有信息[1]。

一墩:2張牌。

2? 程序實現

2.1? QT介紹

本文中的麻將游戲是采用了一個跨平臺的圖形用戶界面應用程序框架QT,是在Windows開發環境下結合QT和C++技術開發的一款游戲[4]。QT具有跨平臺的優良性和面向對象,具有豐富的API,庫的特點,即使用QT開發的軟件,相同的代碼可以在任何支持的平臺上編譯與運行,而不需要修改(或修改極少)源代碼并且會自動依平臺的不同,表現平臺特有的圖形界面風格。QT的良好封裝機制使得QT的模塊化程度非常高,可重用性較好,極大地提高了開發者的工作效率[5]。在計算機網絡全面普及形勢下,互聯網應用屢見不鮮,而作為大眾化網絡娛樂方式,網絡游戲用戶不斷增多[6]。網絡麻將因此備受喜愛,根據用戶的產品需求,確定軟件的設計策略[7],利用C++語言進行軟件的開發與設計,可以使得應用軟件的編程代碼在不同的平臺下進行工作[8]。

2.2? 游戲的流程圖

軟件運行時步驟流程:運行程序首先需要洗牌將牌墻顯示,然后搖骰子顯示出點子數同時進行起牌(52張牌),使得牌墻對應部分的牌消失,顯示出莊家和四家手牌(每家13張牌),發莊家的第14張牌,再取皮子、癩子,最后顯示排序后的四家手牌(每家的皮子、癩子顯示在手牌首部,普通牌根據牌型聚集,根據數字由小到大排序)。流程如圖1所示。

2.3? 數據結構設計

系統的主要數據結構是一個結構體,這個結構體Card表示牌。結構體中的屬性包括QString類型的suit表示“萬、條、筒、風”,int類型的牌上的數point,int類型的四家num[9],如圖2所示。

2.4? 函數設計

首先確定上、下、左、右分別為西、東、南、北。

2.4.1? 洗牌算法

隨機交換兩張牌,使牌墻隨機無序顯示136張普通牌,洗牌發牌初始化將所有容器(比如手牌容器、手牌排序容器、手牌保存容器)清空,所有按鈕也設置為空,避免錯誤。將洗好的牌裝入一個全局Cards_One_Game容器中,Cards_One_Game是一個每局存儲所有牌的容器,大小為136。再將所有牌轉換為String類型用于顯示(這一算法見下)。

2.4.2? 表述牌Card

為了在界面顯示出牌,在整個程序里表述每張牌,將card轉換為String類型的字符串,每張牌根據其牌型,數可以唯一確定一個字符串。這里需要的資源是135張普通牌的圖片,135張癩子牌的圖片,135張皮子牌的圖片,一張紅中杠的圖片,分別放入四個文件夾中。需要用到QT資源系統將這四個文件夾加載,以方便牌的加載顯示與替換,防止圖標被修改或圖標文件丟了程序界面就不能正常顯示,使程序更為可靠。以萬字牌為例:萬字牌的suit屬性可以為“萬”“萬(皮)”“萬(癩)”,不同的字對應不同的資源文件,根據不同的suit從資源文件中不同的文件夾中加載對應的圖片資源,運用arg()函數實現根據point填充字符串。為了方便這里使用靜態加載方式,直接將資源數據存儲在可執行文件中以保證即使刪除了文件夾中的圖標也不會影響界面圖標的加載。

2.4.3? 確定起牌起始位置算法

隨機確定兩個1到6之間的數并顯示到界面固定區域實現搖骰子。兩數的和為add,兩數中較小的一個數賦值給nums,可以由add確定起牌起始處的方位,nums為留牌墩數,一起確定起牌起始位置(start_pc_btn)。

當add等于1或者5或者9時,從東家面前開始拿牌,起牌開始處n為0;當add等于2或者6或者10時,從南家面前開始拿牌,n為102;當add等于3或者7或者11時,從西家面前開始拿牌,n為68;當add等于4或者8或者12時,從北家面前開始拿牌,n為34;開局一人拿13張牌,一共52張,則52張牌在牌墻中消失,不顯示。倘若起牌開始處大于136,則起牌開始處更新為start_pc_btn%136。

2.4.4? 確定莊家

點擊顯示莊家按鈕,根據確定的莊家顯示東、南、西、北、相應的圖片[10]。

2.4.5? 起牌算法

起牌是一家拿兩墩(4張),再下一家拿,四家拿完16張牌為一輪,如此重復拿三輪,最后每家再拿一張即可拿夠52張牌。需要通過三個for循環嵌套實現,第一次為輪次,總共三輪,需要一個計數器k保證三輪。在每一輪中需判斷玩家的拿牌順序,第二次為四位玩家的循環,需要一個計數器z保證四家,從莊家開始拿牌,玩家根據東南西北順序拿牌,初始時計數器z為莊家,每一家拿完兩墩牌計數器加一,同時對計數器進行判斷:計數器小于等于4,如果計數器大于4則用z%4更新z。在每家拿四張牌中需要判斷每張牌的合法性,所以需要一個計數器i小于四(i從0開始)的循環確保每家拿四張牌,因為一共136張牌,不可能拿到第137張牌,所以每拿一張牌都要對這張牌的序號進行判斷,再將每家拿到的牌裝入相應容器內。起牌開始處start_pc_btn加前幾輪四家共拿牌數(輪數×16)加這一輪前幾家所拿牌數((計數器z-1)×4)加自己所拿的四張牌的計數器i(0到3)的和需要小于136(牌的序號從0開始),否則總和模136來更新序號y。

最后每一家按序拿一張牌,這里只需要一次玩家循環,對每張牌序號的判斷,然后存入容器,排序顯示,更新index(指向牌墻中剩余牌的第一張),52張牌發牌完成。

2.4.6? 發莊家最后一張牌

莊家拿第53張牌即index指向的那張牌,從容器Cards_One_Game中取出Cards_One_Game[index]保存到手牌保存容器,排序顯示,牌墻中對應位置設為空,index加一。

2.4.7? 取皮子癩子

莊家翻一張牌,這張牌以及其前面的一張牌叫皮子,這張牌后面的一張牌叫癩子;特別的當紅中被翻,西、北、紅中都為皮子;紅中不能是癩子,翻北風,則發財是癩子;由莊家翻到的牌確定皮子2(pizi2)得到皮子1(pizi1)、皮子0(pizi0)、癩子(laizi)。莊家翻的牌即是index(發完53張牌后)所指向的牌,得到pizi2,調用getPizi(pizi2),getLaizi(pizi2)函數得到皮子1、癩子。由于每張牌由數據結構card描述,并且萬、條、筒的point都是1到9,字牌的point是10到16,當皮子2是數牌時,癩子和其他的皮子也是數牌根據規則即可推出;當皮子2是風牌時,根據東、南、西、北、中、發、白的順序也可以推出皮子、癩子;當皮子2不為紅中時皮子0(pizi0)為空不顯示。

2.4.8? 排序算法

手牌完全顯示時或者每次摸牌時,需要將數牌、字牌按序(同一牌型相鄰,相同牌型根據point從小到大)顯示,并將皮子癩子顯示在手牌前面。在沒有確定皮子、癩子時,起52張牌也需要排序,把數牌、字牌按序顯示。所以排序算法中要分為兩種情況,一種是在未確定皮子、癩子,各家發了13張牌時的手牌排序顯示;一種是在確定了皮子、癩子,莊家已經發了第14張牌時的手牌排序顯示。

在未確定皮子、癩子時通過for循環對容器進行遍歷,統計萬、條、筒、風牌(通過牌的suit屬性)計數并裝入相應的容器中。

在確定皮子、癩子后通過for循環對容器進行遍歷統計不為皮子、癩子(通過牌的point,suit屬性)的萬、條、筒加入容器,計數;再統計皮子牌和癩子牌,加入容器,計數(與皮子字相同、數相同的牌就是皮子;與癩子字相同、數相同的牌就是癩子),注意52張手牌完全顯示時,手牌中的皮子癩子牌上沒顯示皮/癩的標記,所以suit屬性還是“萬、條、筒、東風……”,但在開始打牌后,suit屬性就可能是“萬(皮)/(癩)、條(皮)/(癩)、筒(皮)/(癩)、東風(皮)/(癩)……”或者“萬、條、筒、東風……”。所以為了程序的可擴展性,需要對suit屬性進行多重判斷,在滿足suit屬性相等的同時point屬性也要相等,然后加入容器,計數。

定義一個比較器compless(),重載運算符“<”,用牌的point屬性比較兩張牌的大小,std::sort是C++ STL中最重要的算法之一,std::sort封裝了快速排序算法,可以與for_each算法相提并論,當我們有排序需要時,可能最先想到的就是它。這個算法是一個接口模板,在內部實現可能會根據不同情況使用不同的算法。在使用形式上存在兩種方式,一種是使用小于運算符進行比較,一種使用傳入的函數對象(仿函數)進行比較。這里使用后一種。

在上面獲得的各個容器中從容器的開頭到結尾用仿函數進行比較,在皮子癩子容器中將suit屬性為“萬、條、筒、東風……”改為“萬(皮)/(癩)、條(皮)/(癩)、筒(皮)/(癩)、東風(皮)/(癩)……”再排序。

用排序好的牌更新容器,返回此容器。

2.5? 核心算法

起52張牌部分偽代碼:

算法1:起牌算法

輸入:136張牌

輸出:四家手牌

1)if 輪次k<3 then

2) if 玩家數z<=4 then

3)? if z>4 更新z;

4)? ? if 牌的序號合法then

5)? ? ?從全局牌容器中取出對應序號的牌加入玩家手牌容器中;

6)? ? else

7)? ? ?更新牌的序號;

8)? ? ?從全局牌容器中取出對應序號的牌加入玩家手牌容器中;

9)? ? end if

10)? end if

11) end if

12)end if

13)if 玩家數z<=4 then

14) 四家按順序拿一張牌,從全局牌容器中取出對應序號的牌加入玩家手牌容器中;

15)end if

排序算法的偽代碼:

算法2:排序算法

輸入:每家的手牌

輸出:排序后的手牌

1)定義萬、條、筒、風、皮子、癩子的計數器,容器,p=一張手牌

2) if 已確定皮子

3)? if 手牌的suit屬性=“萬”(以萬字牌為例)

4)? ?if 皮子的suit屬性!=“萬”

5)? ? ?將這張手牌p加入萬字牌容器,計數;

6)? ?end if

7) else if

8)? if 手牌p的point屬性!=皮子的point屬性and手牌p的point屬性!=癩子的point屬性

9)? ?將這張手牌p加入萬字牌容器,計數;

10) end if

11) if p的suit==“萬(皮)”or”萬”

12)? if p的suit==皮子的suit and p的point==皮子的point

13)? ?將這張手牌p加入皮子牌容器,計數

14)? end if

15) end if

16) if p的suit==“萬(癩)”or”萬”

18)? if p的suit==癩子的suit and p的point==癩子的point

19)? ?將這張手牌p加入癩子牌容器,計數

20)? end if

21) end if

22)end if

23)if 未確定皮子

24) 根據suit屬性將相應的牌加入對應容器,計數

25)end if

26)if 皮子or癩子的計數器!=0

27) 將皮子or癩子排序

28) if 皮子癩子未賦值

29)? 對皮子癩子進行賦值

30) end if

31)將其他牌排序

32)返回排序后的牌

3? 結果及分析

程序運行時界面布局:左上角為皮子癩子顯示區域,左側欄為功能按鈕區,右邊為成牌、手牌、牌墻、牌池顯示區,如圖3所示。

進入有游戲界面需要手動洗牌,起牌,確定莊家,取皮子癩子。點擊洗牌按鈕,牌墻隨機顯示136張牌,手牌為空,牌池為空,如圖4所示。

點擊搖骰子和起牌按鈕,點子部分出現兩個范圍為1到6的隨機數,根據這兩個數確定起始起牌位置,然后牌墻的52張牌消失。如圖5所示,兩個點子數是1、3,所以從北方拿牌,留一墩牌,圖中黑色框圈出的即為起的52牌。

點擊顯示莊家按鈕顯示莊家。

點擊顯示手牌按鈕,調用確定莊家函數,起牌函數,將牌墻中消失的52張牌按規則顯示在四家手牌位置,如圖6黑色框部分所示。

點擊發莊家最后一張牌按鈕將莊家的第14張牌發牌,排序顯示,并刪除牌墻中的后一張牌,牌墻更新,莊家手牌顯示更新,如圖7所示。

點擊取皮子,癩子按鈕,調用相關函數并顯示皮子癩子在相關區域。

根據排序算法將手牌中的皮子癩子顯示到手牌首部,其他牌按序顯示,得到排序后的手牌,如圖8所示。

4? 結? 論

通過對武漢麻將規則的學習以及相關算法的分析,確定出了麻將起牌過程中的關鍵點,借助C++語言,QT平臺顯示最終起牌效果。研究發現,起牌核心是搖骰子確定點子數,通過兩點數和與較小點子數確定起始拿牌具體位置;排序算法應用于摸牌和起牌函數中,在確定了皮子、癩子前后,牌面顯示有所差異,確定了皮子、癩子后,對比之下需要統計皮子、癩子的數目,并將皮子、癩子排在手牌前面。通過一系列的算法分析,以C++語言編程實現起牌效果的顯示,從而使游戲可以順利進行。

參考文獻:

[1] 李淑琴,李奕.一種多重優先經驗回放的麻將游戲數據利用方法 [J].重慶理工大學學報:自然科學,2022,36(12):162-169.

[2] 李霞麗,王昭琦,劉博等.麻將博弈AI構建方法綜述 [J/OL].智能系統學報:1-12(2023-07-31).http://kns.cnki.net/kcms/detail/23.1538.TP.20230731.1007.002.html.

[3] 程衛星,郝愛民.一種基于智能體的游戲消息公平處理方法 [J].計算機科學,2008(3):283-288.

[4] 陳龍,吳龍飛.基于Qt的數字圖像處理實驗演示系統 [J].實驗室研究與探索,2018,37(7):170-173+202.

[5] 劉坤,涂德浴,朱慶,等.基于Qt的鋼管壁厚在線檢測軟件設計 [J].機床與液壓,2023,51(7):93-99.

[6] 李樊.基于VR技術的三維射擊游戲開發研究 [J].自動化技術與應用,2021,40(1):163-166.

[7] 張少玉.基于信息化的軟件開發策略 [J].信息技術與信息化,2022(11):94-97.

[8] 湯曉軍.基于C++語言的跨平臺軟件開發設計 [J].信息技術與信息化,2022(3):36-39.

[9] 李淑琴,馮浩東.牌型預測與蒙特卡洛模擬結合的麻將博弈策略 [J].重慶理工大學學報:自然科學,2022,36(12):148-154.

[10] 黃勇,尚亞東,陳秀華,等.麻將桌上的一個概率問題 [J].數學的實踐與認識,2015,45(16):132-136.

作者簡介:徐子怡(2000—),女,漢族,湖北仙桃人,碩士研究生在讀,研究方向:人工智能;通訊作者:林富生(1965—),男,漢族,江蘇臺州人,教授,博士,研究方向:人工智能;宋志峰(1972—),男,漢族,湖北孝感人,副教授,碩士,研究方向:計算機集成制造系統;徐自立(1964—),男,漢族,湖北武漢人,教授,博士,研究方向:耐磨與抗磨材料;余聯慶(1972—),男,漢族,湖北咸寧人,教授,博士,研究方向:機器人機構學。

主站蜘蛛池模板: 日日拍夜夜操| 亚洲妓女综合网995久久| 国内精品九九久久久精品| 国产无遮挡裸体免费视频| 新SSS无码手机在线观看| 色哟哟色院91精品网站| 久久久久无码精品国产免费| 最新国产网站| 天天色综合4| 亚洲国产日韩欧美在线| 日韩精品无码免费专网站| 国产日本一区二区三区| 久久狠狠色噜噜狠狠狠狠97视色| 久久精品一品道久久精品| 亚洲男人天堂2018| 国产精品 欧美激情 在线播放| 天天色天天操综合网| 国产国产人成免费视频77777| 91精品国产91欠久久久久| 无码高清专区| 亚洲系列中文字幕一区二区| 国产主播喷水| 72种姿势欧美久久久大黄蕉| 免费黄色国产视频| www.91在线播放| 国产网站免费观看| 国产靠逼视频| 在线亚洲精品自拍| 亚洲AⅤ无码国产精品| 国产精品不卡永久免费| 亚洲精品国产首次亮相| 国产女人18水真多毛片18精品 | 午夜精品久久久久久久无码软件 | 亚洲国产欧美国产综合久久| аv天堂最新中文在线| 日本一区高清| 亚洲一级无毛片无码在线免费视频| 欧美日韩第三页| 99精品这里只有精品高清视频| 亚洲一区无码在线| 日本人妻丰满熟妇区| 日韩一级二级三级| 欧美色视频日本| 日韩欧美综合在线制服| 亚洲国产日韩在线成人蜜芽| 欧美日韩福利| 国内丰满少妇猛烈精品播| 国产精品无码久久久久久| 精品国产成人高清在线| 亚洲中字无码AV电影在线观看| 精品国产中文一级毛片在线看| 高清无码一本到东京热| 亚洲精品男人天堂| 国产精品网拍在线| 国产一级毛片yw| 综合久久五月天| 亚洲啪啪网| 亚洲精品在线影院| 狠狠做深爱婷婷综合一区| 青草免费在线观看| 久久夜色精品国产嚕嚕亚洲av| 99青青青精品视频在线| 久久99热66这里只有精品一| 国产一级毛片网站| 亚洲最大情网站在线观看 | 伊人久久福利中文字幕| www.av男人.com| 国产污视频在线观看| 欧美不卡在线视频| 欧美黄网在线| 久久五月视频| 亚洲国产成人在线| 欧美日一级片| 人妖无码第一页| 日韩国产无码一区| 亚洲乱伦视频| 91亚洲精选| 美女视频黄频a免费高清不卡| 国产欧美日韩在线在线不卡视频| 亚洲午夜综合网| 日本欧美午夜| 成人午夜视频在线|