C#實現(xiàn)撲克游戲(21點)的示例代碼
一、游戲介紹
1.1 游戲規(guī)則
21點又名黑杰克,該游戲由2到6個人玩,使用除大小王之外的52張牌,游戲者的目標是使手中的牌的點數(shù)之和不超過21點且盡量大。
1.2 牌點計算
A至10牌,按其原點數(shù)計算;J、Q、K都算作10點。
1.3 判斷勝負
二十一點玩法規(guī)則和概率在二十一點游戲中,擁有最高點數(shù)的玩家獲勝,其點數(shù)必須等于或低于21點;超過21點的玩家稱為爆牌。擁有最高點數(shù)的玩家獲勝,其點數(shù)必須等于或低于21點;超過21點之間判負。
二、游戲設計
2.1 游戲流程
發(fā)牌:
玩家和AI每人發(fā)兩張牌,由手牌點數(shù)和大的玩家優(yōu)先選擇是否在牌堆中取牌
取牌:
手牌點數(shù)和小于21,等待1中優(yōu)先選擇后再順時針輪到其他玩家選擇是否取牌
取牌后:
若牌點大于21則直接判負出局,場上只剩1人,直接游戲結束;否則重復2-3
若牌點小于等于21則輪到下家取牌,重復2-3
游戲結束
其他玩家取牌后都超過21點,只剩1人,直接獲勝
所有玩家都選擇不取牌后,按規(guī)則比較所有玩家手牌點數(shù)和,牌點大的獲勝。
2.2 玩家類
由玩家自己選擇是否繼續(xù)拿牌。(輸入Y繼續(xù)拿牌,N為不拿牌)
2.3 AI類
簡化AI邏輯,發(fā)牌后AI手牌和為4-8時繼續(xù)拿牌,一直到17點或17點以上不再拿牌;因為此時再拿牌就有一半以上的概率超過21點。
三、參考代碼
using System;
namespace _21dian
{
using System;
using System.Collections.Generic;
namespace Game21Points
{
class Project
{
static void Main(string[] args)
{
Console.WriteLine("----- 游戲開始 -----");
// 撲克牌
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)建對象
Poker poker = new Poker(cards);
Player player = new Player();
AIPlayer ai = new AIPlayer();
// --> 玩家入場
player.playerName = "Czhenya";
ai.playerName = "AI";
poker.AddPlayer(player);
poker.AddPlayer(ai);
// 事件關系綁定
poker.GameSratrHandler += player.GameStart;
poker.GameSratrHandler += ai.GameStart;
// 游戲開始
poker.GameStart();
// 每人發(fā)兩張牌
poker.SendCard();
poker.SendCard();
// 詢問取牌
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("玩家整理了一下衣服,準備開局;");
}
public override void SendCard(int card)
{
handCards.Add(card);
Console.WriteLine("玩家發(fā)牌:" + PokeTools.PokerBrandByPoint(card));
}
public override bool TakeCard()
{
Console.WriteLine("當前您的手牌點數(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:清理一下內存,與之一戰(zhàn);");
}
public override void SendCard(int card)
{
base.SendCard(card);
Console.WriteLine("AI發(fā)牌:" + PokeTools.PokerBrandByPoint(card));
}
public override bool TakeCard()
{
// 手牌數(shù)點數(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ā)牌用
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ā)牌 -- 會剔除已經發(fā)過的牌
/// </summary>
public void SendCard()
{
for (int i = 0; i < players.Count; i++)
{
players[i].SendCard(SendOneCard());
}
}
int SendOneCard()
{
// 隨機發(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("游戲結束:");
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>
/// 根據牌點返回牌名 如:14 ->紅桃3
/// </summary>
/// <param name="card"></param>
/// <returns></returns>
public static string PokerBrandByPoint(int card)
{
if (card > 52 || card <= 0)
{
Console.WriteLine("不是撲克牌點");
return "不是撲克牌點";
}
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;
// 返回花色 + 牌點 如:紅桃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, "牌點和:" + PokeTools.HandCardsSum(handCards));
}
}
}
測試結果:

到此這篇關于C#實現(xiàn)撲克游戲(21點)的示例代碼的文章就介紹到這了,更多相關C#撲克游戲內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C#實現(xiàn)在前端網頁彈出警告對話框(alert)的方法
這篇文章主要介紹了C#實現(xiàn)在前端網頁彈出警告對話框(alert)的方法,涉及C#通過自定義函數(shù)調用window.alert方法彈出對話框的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-04-04
利用MySqlBulkLoader實現(xiàn)批量插入數(shù)據的示例詳解
MySQLBulkLoader是MySQL?Connector/Net類中的一個類,用于包裝MySQL語句。本文將利用MySqlBulkLoader實現(xiàn)批量插入數(shù)據功能,感興趣的可以了解一下2022-06-06
C#中使用Lambda表達式自定義比較器實現(xiàn)兩個列表合并實例
這篇文章主要介紹了C#中使用Lambda表達式自定義比較器實現(xiàn)兩個列表的合并實例,本文給出示例代碼和運行效果,需要的朋友可以參考下2014-10-10
10分鐘學會Visual Studio將自己創(chuàng)建的類庫打包到NuGet進行引用(net,net core,C#)
這篇文章主要介紹了10分鐘學會Visual Studio將自己創(chuàng)建的類庫打包到NuGet進行引用(net,net core,C#),本文給大家介紹的非常詳細對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-09-09

