C#實(shí)現(xiàn)撲克游戲(21點(diǎn))的示例代碼
一、游戲介紹
1.1 游戲規(guī)則
21點(diǎn)又名黑杰克,該游戲由2到6個(gè)人玩,使用除大小王之外的52張牌,游戲者的目標(biāo)是使手中的牌的點(diǎn)數(shù)之和不超過(guò)21點(diǎn)且盡量大。
1.2 牌點(diǎn)計(jì)算
A至10牌,按其原點(diǎn)數(shù)計(jì)算;J、Q、K都算作10點(diǎn)。
1.3 判斷勝負(fù)
二十一點(diǎn)玩法規(guī)則和概率在二十一點(diǎn)游戲中,擁有最高點(diǎn)數(shù)的玩家獲勝,其點(diǎn)數(shù)必須等于或低于21點(diǎn);超過(guò)21點(diǎn)的玩家稱(chēng)為爆牌。擁有最高點(diǎn)數(shù)的玩家獲勝,其點(diǎn)數(shù)必須等于或低于21點(diǎn);超過(guò)21點(diǎn)之間判負(fù)。
二、游戲設(shè)計(jì)
2.1 游戲流程
發(fā)牌:
玩家和AI每人發(fā)兩張牌,由手牌點(diǎn)數(shù)和大的玩家優(yōu)先選擇是否在牌堆中取牌
取牌:
手牌點(diǎn)數(shù)和小于21,等待1中優(yōu)先選擇后再順時(shí)針輪到其他玩家選擇是否取牌
取牌后:
若牌點(diǎn)大于21則直接判負(fù)出局,場(chǎng)上只剩1人,直接游戲結(jié)束;否則重復(fù)2-3
若牌點(diǎn)小于等于21則輪到下家取牌,重復(fù)2-3
游戲結(jié)束
其他玩家取牌后都超過(guò)21點(diǎn),只剩1人,直接獲勝
所有玩家都選擇不取牌后,按規(guī)則比較所有玩家手牌點(diǎn)數(shù)和,牌點(diǎn)大的獲勝。
2.2 玩家類(lèi)
由玩家自己選擇是否繼續(xù)拿牌。(輸入Y繼續(xù)拿牌,N為不拿牌)
2.3 AI類(lèi)
簡(jiǎn)化AI邏輯,發(fā)牌后AI手牌和為4-8時(shí)繼續(xù)拿牌,一直到17點(diǎn)或17點(diǎn)以上不再拿牌;因?yàn)榇藭r(shí)再拿牌就有一半以上的概率超過(guò)21點(diǎn)。
三、參考代碼
using System;
namespace _21dian
{
using System;
using System.Collections.Generic;
namespace Game21Points
{
class Project
{
static void Main(string[] args)
{
Console.WriteLine("----- 游戲開(kāi)始 -----");
// 撲克牌
List<int> cards = new List<int>()
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52
};
// 創(chuàng)建對(duì)象
Poker poker = new Poker(cards);
Player player = new Player();
AIPlayer ai = new AIPlayer();
// --> 玩家入場(chǎng)
player.playerName = "Czhenya";
ai.playerName = "AI";
poker.AddPlayer(player);
poker.AddPlayer(ai);
// 事件關(guān)系綁定
poker.GameSratrHandler += player.GameStart;
poker.GameSratrHandler += ai.GameStart;
// 游戲開(kāi)始
poker.GameStart();
// 每人發(fā)兩張牌
poker.SendCard();
poker.SendCard();
// 詢(xún)問(wèn)取牌
poker.TaskCard();
Console.ReadKey();
}
}
abstract class AbsPlayer
{
public string playerName;
public bool IsContinueTakeCard = true;
public List<int> handCards = new List<int>();
public abstract void GameStart();
public virtual void SendCard(int card)
{
handCards.Add(card);
}
public abstract bool TakeCard();
public bool GameOver()
{
bool isGameOver;
if (HandCardsPoint > 21)
{
isGameOver = true;
}
else
{
isGameOver = !IsContinueTakeCard;
}
return isGameOver;
}
public int HandCardsPoint { get { return PokeTools.HandCardsSum(handCards); } }
}
class Player : AbsPlayer
{
public override void GameStart()
{
handCards.Clear();
Console.WriteLine("玩家整理了一下衣服,準(zhǔn)備開(kāi)局;");
}
public override void SendCard(int card)
{
handCards.Add(card);
Console.WriteLine("玩家發(fā)牌:" + PokeTools.PokerBrandByPoint(card));
}
public override bool TakeCard()
{
Console.WriteLine("當(dāng)前您的手牌點(diǎn)數(shù)和為:" + HandCardsPoint);
Console.WriteLine("是否繼續(xù)取牌(Y/N)?");
string readStr = Console.ReadLine();
// 輸入Y取牌,其他為不取牌
IsContinueTakeCard = readStr.Equals("Y");
return IsContinueTakeCard;
}
}
class AIPlayer : AbsPlayer
{
public override void GameStart()
{
handCards.Clear();
Console.WriteLine("AI:清理一下內(nèi)存,與之一戰(zhàn);");
}
public override void SendCard(int card)
{
base.SendCard(card);
Console.WriteLine("AI發(fā)牌:" + PokeTools.PokerBrandByPoint(card));
}
public override bool TakeCard()
{
// 手牌數(shù)點(diǎn)數(shù)小于17,就繼續(xù)取牌
return HandCardsPoint < 17;
}
}
class Poker
{
List<AbsPlayer> players = new List<AbsPlayer>();
public Action GameSratrHandler;
public Action<int> SendCardHandler;
public Func<int, bool> TaskCardHandler;
// 發(fā)牌用
List<int> sendCards;
public Poker(List<int> cards)
{
// 復(fù)制一份發(fā)牌用
sendCards = new List<int>(cards);
}
public void AddPlayer(AbsPlayer player)
{
players.Add(player);
}
public void GameStart()
{
for (int i = 0; i < players.Count; i++)
{
if (!players[i].GameOver())
{
players[i].GameStart();
}
}
}
/// <summary>
/// 發(fā)牌 -- 會(huì)剔除已經(jīng)發(fā)過(guò)的牌
/// </summary>
public void SendCard()
{
for (int i = 0; i < players.Count; i++)
{
players[i].SendCard(SendOneCard());
}
}
int SendOneCard()
{
// 隨機(jī)發(fā)一張牌
Random random = new Random();
int index = random.Next(0, sendCards.Count);
// 取到牌值
int cardPoint = sendCards[index];
// 從手牌中移除 --> 為避免發(fā)到相同的牌
sendCards.RemoveAt(index);
return cardPoint;
}
public void TaskCard()
{
for (int i = 0; i < players.Count; i++)
{
// 選擇取牌后再發(fā)一張牌
if (players[i].TakeCard())
{
players[i].SendCard(SendOneCard());
}
Console.WriteLine($"玩家:{players[i].playerName} 手牌:{PokeTools.ShowHandCard(players[i].handCards)}");
}
if (!GameOver())
{
TaskCard();
}
}
public bool GameOver()
{
int playerCount = 0;
for (int i = 0; i < players.Count; i++)
{
if (!players[i].GameOver())
{
playerCount++;
}
}
bool isGameOver = playerCount <= 1;
if (isGameOver)
{
Console.WriteLine("游戲結(jié)束:");
List<AbsPlayer> playerList = new List<AbsPlayer>();
int maxPoint = 0;
for (int i = 0; i < players.Count; i++)
{
if (players[i].HandCardsPoint > 21)
{
Console.WriteLine($"玩家:{players[i].playerName} 爆牌了" );
}
else
{
playerList.Add(players[i]);
if (maxPoint < players[i].HandCardsPoint)
{
maxPoint = players[i].HandCardsPoint;
}
}
}
if (playerList.Count == 0)
{
Console.WriteLine("平局");
}
else if (playerList.Count == 1)
{
Console.WriteLine($"玩家:{playerList[0].playerName} 贏了");
}
else
{
for (int i = 0; i < playerList.Count; i++)
{
if (maxPoint == playerList[i].HandCardsPoint)
{
Console.WriteLine($"玩家:{playerList[i].playerName} 贏了");
}
}
}
}
return isGameOver;
}
}
}
class PokeTools
{
/// <summary>
/// 根據(jù)牌點(diǎn)返回牌名 如:14 ->紅桃3
/// </summary>
/// <param name="card"></param>
/// <returns></returns>
public static string PokerBrandByPoint(int card)
{
if (card > 52 || card <= 0)
{
Console.WriteLine("不是撲克牌點(diǎn)");
return "不是撲克牌點(diǎn)";
}
string[] flowerColor = new string[4] { "黑桃", "紅桃", "梅花", "方片" };
string[] points = new string[13] { "K", "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q" };
int huaSe = (card - 1) / 13;
int point = card % 13;
// 返回花色 + 牌點(diǎn) 如:紅桃3
return flowerColor[huaSe] + points[point];
}
/// <summary>
/// 手牌求和
/// </summary>
/// <param name="handCards"></param>
/// <returns></returns>
public static int HandCardsSum(List<int> handCards)
{
// "K", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q"
int[] points = new int[13] { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10 };
int sumRes = 0;
for (int i = 0; i < handCards.Count; i++)
{
sumRes += points[handCards[i] % 13];
}
return sumRes;
}
// 顯示手牌
public static (string, string) ShowHandCard(List<int> handCards)
{
string resStr = "";
for (int i = 0; i < handCards.Count; i++)
{
resStr += PokeTools.PokerBrandByPoint(handCards[i]);
if (handCards.Count - 1 != i)
{
resStr += ",";
}
}
return (resStr, "牌點(diǎn)和:" + PokeTools.HandCardsSum(handCards));
}
}
}
測(cè)試結(jié)果:

到此這篇關(guān)于C#實(shí)現(xiàn)撲克游戲(21點(diǎn))的示例代碼的文章就介紹到這了,更多相關(guān)C#撲克游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#中基數(shù)排序算法的原理及實(shí)現(xiàn)
基數(shù)排序算法是一種非比較式的排序方法,通過(guò)分配和收集步驟對(duì)數(shù)字的每一位進(jìn)行排序,學(xué)習(xí)基數(shù)排序有助于提高排序效率,解決特定問(wèn)題,廣泛應(yīng)用于多個(gè)領(lǐng)域如數(shù)據(jù)分析和數(shù)據(jù)庫(kù)索引建立等2024-10-10
C#實(shí)現(xiàn)在前端網(wǎng)頁(yè)彈出警告對(duì)話框(alert)的方法
這篇文章主要介紹了C#實(shí)現(xiàn)在前端網(wǎng)頁(yè)彈出警告對(duì)話框(alert)的方法,涉及C#通過(guò)自定義函數(shù)調(diào)用window.alert方法彈出對(duì)話框的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04
C# 通過(guò) inline-asm 解決嵌入x86匯編
此篇文章通過(guò)C#語(yǔ)言解決嵌入x86匯編,主要通過(guò)INline-asm方法來(lái)實(shí)現(xiàn),下面我通過(guò)圖片和代碼的形式給大家分享下,需要的朋友可以參考下2015-07-07
利用MySqlBulkLoader實(shí)現(xiàn)批量插入數(shù)據(jù)的示例詳解
MySQLBulkLoader是MySQL?Connector/Net類(lèi)中的一個(gè)類(lèi),用于包裝MySQL語(yǔ)句。本文將利用MySqlBulkLoader實(shí)現(xiàn)批量插入數(shù)據(jù)功能,感興趣的可以了解一下2022-06-06
C#中使用Lambda表達(dá)式自定義比較器實(shí)現(xiàn)兩個(gè)列表合并實(shí)例
這篇文章主要介紹了C#中使用Lambda表達(dá)式自定義比較器實(shí)現(xiàn)兩個(gè)列表的合并實(shí)例,本文給出示例代碼和運(yùn)行效果,需要的朋友可以參考下2014-10-10
10分鐘學(xué)會(huì)Visual Studio將自己創(chuàng)建的類(lèi)庫(kù)打包到NuGet進(jìn)行引用(net,net core,C#)
這篇文章主要介紹了10分鐘學(xué)會(huì)Visual Studio將自己創(chuàng)建的類(lèi)庫(kù)打包到NuGet進(jìn)行引用(net,net core,C#),本文給大家介紹的非常詳細(xì)對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
Unity3D動(dòng)態(tài)對(duì)象優(yōu)化代碼分享
這篇文章主要介紹了Unity3D動(dòng)態(tài)對(duì)象優(yōu)化代碼分享的相關(guān)資料,需要的朋友可以參考下2015-03-03

