2019級C語言大作業 - 三國殺
https://www。zhihu。com/video/1198206990734852096
分享19級同學大一上學期用C語言實現的三國殺遊戲。分步驟程式碼、圖片音樂素材、可執行程式可以從百度網盤下載:
一、 設計思路
《三國殺》是中國傳媒大學動畫學院2004級遊戲專業學生設計,由北京遊卡桌遊文化發展有限公司出版發行的一款熱門的桌上游戲,並在2009年6月底由杭州邊鋒網路技術有限公司開發出網路遊戲。該遊戲融合了西方類似遊戲的特點,並結合中國三國時期背景,以身份、勢力或陣營等為線索,以卡牌為形式,合縱連橫,經過一輪一輪的謀略和動作獲得最終的勝利。三國殺集合歷史、文學、美術等元素於一身,在中國廣受歡迎。
由其本身特性可知,《三國殺》遊戲,完全可以由C語言完成,並且實現過程具有一定難度,再加上於我組組員都深深熱愛此項卡牌運動,於是,在我組一致商議決定下,確定在此次C語言專案設計,我組將藉由所學知識親手創造一款相似的軟體遊戲。
二、 功能描述
我組此次完成的《三國殺》遊戲支援實現真實三國殺的大部分設定,包括殺、閃、桃等的基本牌,萬箭齊發、南蠻入侵、無中生有等的錦囊牌以及諸葛連弩,青龍偃月刀等的裝備牌。玩家將以教程闖關形式面對並設法戰勝越發智慧的簡單AI,並在闖關途中解鎖新的卡牌,最終獲得遊戲的勝利。
《(簡易)三國殺》基本規則:
1、起始手牌
將遊戲牌洗混,隨機分給每個玩家4張,此為起始手牌。
手牌:拿在手裡的牌。
將剩餘遊戲牌放在桌子中央,作為牌堆(玩家在遊戲中棄置的牌放在一旁,組成棄牌堆)。
2、回合流程
進行遊戲時,由玩家開始,按逆時針方向以回合的方式進行。即:每名玩家有一個自己的回合,一名玩家回合結束後,右邊玩家的回合開始,依次輪流進行。
每個玩家的回合可以分為六個階段:
2。1 準備階段
通常可以跳過,有些武將可以使用此階段的技能。
2。2 判定階段
若面前橫置著延時類錦囊,必須依次對這些延時類錦囊進行判定。
若面前橫置有兩種或更多的延時類錦囊,從最後一個施加的錦囊開始判定(最早放置的最後判定)。
2。3 摸牌階段
從牌堆頂摸兩張牌。
在遊戲裡,若沒有特殊說明,“摸X張牌”指的就是從牌堆最上方摸牌。
當需要摸牌或將要對牌堆產生影響時,牌堆沒牌,則立即將棄牌堆洗混後形成新的摸牌堆。
2。4出牌階段
可以使用0到任意張牌,加強自己或攻擊他人,但必須遵守以下兩條規則:
2。4。1、每個出牌階段僅限使用一次【殺】。
2。4。2、任何一個玩家面前的判定區或裝備區裡不能放有兩張同名的牌。
2。4。3、每使用一張牌,即執行該牌之效果。如無特殊說明,遊戲牌在使用後均需棄置(放入棄牌堆)。
2。5、 棄牌階段
在出牌階段中,不想出或沒法出牌時,就進入棄牌階段,此時檢查手牌數是否超出當前的體力值(手牌上限等於當前的體力值),每超出一張,需要棄一張手牌。
2。6、 結束階段
通常可以跳過,有些武將可以使用此階段的技能。
3、補充說明
3。1、在遊戲裡,若無特殊說明,摸牌即是說從遊戲牌堆頂摸牌。
3。2、玩家在遊戲中使用、打出或棄置的遊戲牌放在一旁,組成棄牌堆。
3。3、當牌堆沒牌時,則立即將棄牌堆洗混後形成新的牌堆。
3。4、“體力上限”與“當前體力值”不一樣。
4、武將死亡
當一個武將的體力降到0或更低時,即進入瀕死狀態,除非自己或他人在此時用“桃”來挽救該武將,否則該武將出局。武將出局後,棄置該武將所有牌。
5、遊戲結束
5。1、AI死亡,玩家獲勝,進入下一關或獲得遊戲勝利
5。2、玩家死亡,玩家落敗
6、卡牌效果
6。1、殺
你的出牌階段,對除你外,你攻擊範圍內的一名角色使用,效果是對該角色造成1點傷害。
◆遊戲開始時你的攻擊範圍是1 。
◆每個出牌階段你只能使用一張【殺】。
6。2、閃
當你受到【殺】的攻擊時,你可以使用一張【閃】來抵消【殺】的效果。
◆閃通常情況下只能在回合外使用或打出。
6。3、桃
桃能在兩種情況下使用:
1、在你的出牌階段,你可以使用它來回復你的1點體力。
2、當有角色處於瀕死狀態時,你可以對該角色使用【桃】,防止該角色的死亡。
◆出牌階段,若你沒有損失體力,你不可以對自己使用【桃】。
6。4、過河拆橋
出牌階段,對除你以外的任意一名區域內有牌的角色使用。你選擇並棄置該角色區域裡的一張牌。
◆區域包括手牌、裝備區和判定區。
6。5、順手牽羊
出牌階段,對除你以外的與你距離1以內且區域內有牌的一名角色使用。你選擇並獲得該角色區域內的一張牌。
◆使用順手牽羊時,注意你裝備區裡的馬和目標角色裝備區裡的馬。
◆區域包括手牌、裝備區和判定區。
6。6、決鬥
出牌階段,對除你以外的任意一名角色使用。由目標角色先開始,你和其輪流打出一張【殺】。【決鬥】對首先不出【殺】的一方造成1點傷害,而另一方視為此傷害的來源。
◆使用【決鬥】有可能讓自己受傷
◆受到因【決鬥】導致的傷害時,來源為決鬥的獲勝方。
6。7、借刀殺人
出牌階段,對除你以外的裝備區裡有武器牌的一名角色使用。該角色需對其攻擊範圍內,由你指定的另一名角色使用一張【殺】,否則你獲得該角色裝備區裡的武器牌。
◆角色使用【殺】時,角色技能和武器技能可以照常發動。
6。8、萬箭齊發
出牌階段,對除你以外的所有角色使用。按行動順序結算,除非目標角色打出一張【閃】,否則該角色受到【萬箭齊發】對其造成的1點傷害。
◆你必須指定除你外的所有角色為目標,然後他們(從你的下家開始)依次選擇是否打出【閃】。
6。9、南蠻入侵
出牌階段,對除你以外的所有角色使用。按行動順序結算,除非目標角色打出一張【殺】,否則該角色受到〔南蠻入侵〕對其造成的1點傷害。
◆你必須指定除你外的所有角色為目標,然後他們依次(從你的下家開始)選擇是否打出【殺】。
6。10、無中生有
出牌階段,對你自己使用。摸兩張牌。
6。11、五穀豐登
出牌階段,對所有角色使用。你從牌堆亮出等同於現存角色數量的牌,然後按行動順序結算,目標角色選擇並獲得其中的一張。
◆這張牌會讓包括你在內的角色每人各從一定數量的牌裡挑選一張加入手牌。
6。12、桃園結義
出牌階段,對所有角色使用。按行動順序結算,目標角色回覆1點體力。
◆這張牌會讓包括你在內的角色各回復1點體力。即使所有人都滿血也可使用,只是沒有效果。
6。13、無懈可擊
在目標錦囊生效前,抵消其對一名角色產生的效果。
◆【無懈可擊】是一張可以在其他錦囊開始結算時使用的錦囊,它只能抵消目標錦囊對一名指定角色產生的效果。
◆【無懈可擊】本身也是錦囊,所以也可以被抵消。
三、 開發步驟實現方法
在本組組內,我主要負責各與卡牌效果的實現相關的演算法編譯,而要實現最終版所具有的功能,我在編碼過程中主要經歷了四大步:
1、 回合制基本框架
這是《三國殺》遊戲的最基本之處,也是第一個讓我組組員頭疼的地方。在先前製作的一系列遊戲中,主函式一般包括:
while
(
1
)
{
show
();
//顯示介面
updateWithoutInput
();
//無需使用者輸入的更新
updateWithInput
();
//需使用者輸入的更新
}
如何實現操作的轉換,即在玩家執行完摸牌、出牌、棄牌後控制AI進行操作,成了一大難題。最後,在我組組員的共同努力與創新下,藉由進一層次的迴圈控制完成了此項操作,最終完成的主函式如下
while
(
1
)
{
show
();
//顯示
huihe_player
();
//玩家回合
huihe_npc
();
//電腦回合
}
其中,在玩家回合huihe_player函式中置入了另一重迴圈,在執行完棄牌操作後退出迴圈,完成回合制設定。
2、 基本牌實現
比較其他部分來說,這一部分是相對輕鬆的,需要注意的只有對於任一角色,每一個回合所能出的【殺】次數是有限並受距離限制,因此需要另外定義相關變數。
int
player_sha_num
=
0
;
//玩家出殺次數
int
npc_sha_num
=
0
;;
//電腦出殺次數
int
npc_player
=
1
,
player_npc
=
1
;
//
距離
3、 錦囊牌實現
這一部分的難點是對於任一錦囊牌,【無懈可擊】可以被打出以使其失效(包括【無懈可擊】本身),這就要求對於玩家每一次使用錦囊,AI判斷手牌中是否包含【無懈可擊】、是否應該打出,為簡化程式碼,遂將這一步驟以函式形式封裝
int
npc_wuxie
(
int
success
)
//判斷手牌是否包含【無懈可擊】
{
for
(
i
=
0
;
i
<
npc_shoupai_num
;
i
++
)
{
if
(
npc
[
i
]
==
11
)
{
npc
[
i
]
=
0
;
success
=
0
;
break
;
}
}
//打出【無懈可擊】,使相應錦囊的success變數轉化為0
return
success
;
}
4、 裝備牌實現
這一部分的難點是裝備牌一方面佔有額外的儲存位置,一方面又與另外幾種牌種都有互動,這就要求我們定義新的變數儲存各角色裝備情況並根據裝備情況對該角色使用牌的規則進行調整。例如,當某一角色裝備【諸葛連弩】時,其每回合使用殺的限制將解除。又如,當某一角色裝備【青龍偃月刀】時,其所使用的【殺】被【閃】抵消時可以繼續出殺
void
player_1
()
{
int
input
;
int
success_1
=
1
;
if
(
player_sha_num
==
1
&&
player_weapon
!=
21
)
{
printf
(
“您本回合已使用過殺,無法繼續出殺”
);
Sleep
(
20
);
}
//一般情況對出【殺】次數有限制,裝備【諸葛連弩】時解除
else
{
if
(
player_npc
<=
1
)
{
player
[
player_out
]
=
0
;
player_shoupai_num
——
;
if
(
npc_armor
==
27
)
printf
(
“殺無效”
);
//判斷對方是否裝備【明光鎧】
else
{
success_1
=
npc_2
(
success_1
);
if
(
success_1
==
1
)
{
npc_life
——
;
show
();
printf
(
“npc收到一點傷害”
);
npc_bingsi
();
gameover
();
}
else
if
(
player_weapon
==
22
)
{
player_zhengli
();
show
();
printf
(
“是否發動青龍偃月刀繼續出殺”
);
scanf
(
“%d”, &input);
input
——
;
if
(
player
[
input
]
==
1
)
player_1
();
}
//當【殺】被【閃】抵消時,判定是否裝備【青龍偃月刀】,若是,可繼續出【殺】
}
player_sha_num
++
;
}
else
printf
(
”距離不足“
);
}
}