
執行檔在此
Frm_ShowHand.cs(表單)
/********************** Frm_ShowHand.cs **********************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace HW5
{
public partial class Frm_ShowHand : Form
{
CardDeck Deck = new CardDeck();
StudCard[] Players = new StudCard[2];
ScoreTable Table = new ScoreTable();
TextBox[,] txt_player_cardArray;
/*********** 建構子 ***********/
public Frm_ShowHand()
{
InitializeComponent();
CreateStudCard();
CreateTxtArray();
}
/*********** 控制項函數 ***********/
private void btn_DealOnePlayer_Click(object sender, EventArgs e) // 按鈕 發一副牌
{
Deck.ShufflePartial(5); // 洗5張牌
Deck.Deal(Players[0], 0, 5); // 發牌給玩家0,從第0張起,共5張牌
OnePlayerShowCards(); // 顯示牌面
OnePlayerShowType(); // 顯示牌形
Players[0].Reset(); // 玩家0捨棄手牌
// Test1();
}
private void btn_DealTwoPlayers_Click(object sender, EventArgs e) // 按鈕 發兩副牌
{
Deck.ShufflePartial(10); // 洗10張牌
Deck.Deal(Players[0], 0, 5); // 發牌給玩家0,從第0張起,共5張牌
Deck.Deal(Players[1], 0, 5); // 發牌給玩家1,從第0張起,共5張牌
TwoPlayersShowCards(); // 顯示兩玩家的牌面
TwoPlayersShowType(); // 顯示兩玩家的牌型
ShowWhoWin(); // 顯示贏家
Players[0].Reset(); // 玩家0捨棄手牌
Players[1].Reset(); // 玩家1捨棄手牌
}
private void btn_DealManyTimes_Click(object sender, EventArgs e) // 按鈕 發多副牌
{
Table.Reset(); // 記分板先清空資料
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); // 引用stopwatch物件
sw.Reset(); // 碼表歸零
sw.Start(); // 碼表開始計時
BuildSamples(50000000); // 建立樣本
sw.Stop(); // 碼錶停止
CleanAllTxt(); // 清空顯示欄位
ShowCostTime(sw.Elapsed.TotalMilliseconds); // 印出所花費的總豪秒數
ShowProbability(); // 顯示機率表
}
/*********** 其他函數 ***********/
private void CreateStudCard() // 產生手牌物件
{
for (int i = 0; i < Players.Length; i++)
{
Players[i] = new StudCard();
}
}
private void CreateTxtArray() // 產生txtbox陣列參考
{
txt_player_cardArray = new TextBox[,] {{ txt_player1_card1, txt_player1_card2, txt_player1_card3, txt_player1_card4, txt_player1_card5 },
{ txt_player2_card1, txt_player2_card2, txt_player2_card3, txt_player2_card4, txt_player2_card5 }};
}
private void BuildSamples(int NumberOfSamples) // 建立統計樣本
{
switch (GetAlgorithmsSelectIndex())
{
case -1:
case 0: // 方法0: 二分法,由低至高
for (int i = 0; i < NumberOfSamples; i++) // 50000000次測試
{
Deck.ShufflePartial(5); // 洗5張牌
Deck.Deal(Players[0], 0, 5); // 發牌給玩家0,從第0張起,共5張牌
Table.TypeCount[Players[0].CardType]++; // 記分板紀錄牌形出現次數
Players[0].Reset(); // 玩家0捨棄手牌
}
break;
case 1: // 方法1: 二分法,由高至低
for (int i = 0; i < NumberOfSamples; i++) // 50000000次測試
{
Deck.ShufflePartial(5); // 洗5張牌
Deck.Deal(Players[0], 0, 5); // 發牌給玩家0,從第0張起,共5張牌
Table.TypeCount[Players[0].CardType_By_CheckTypeHighToLow]++; // 記分板紀錄牌形出現次數
Players[0].Reset(); // 玩家0捨棄手牌
}
break;
case 2: // 方法2: 同步判斷法 (不含牌分)
for (int i = 0; i < NumberOfSamples; i++) // 50000000次測試
{
Deck.ShufflePartial(5); // 洗5張牌
Deck.Deal(Players[0], 0, 5); // 發牌給玩家0,從第0張起,共5張牌
Table.TypeCount[Players[0].CardType_By_CheckTypeAllInOne]++; // 記分板紀錄牌形出現次數
Players[0].Reset(); // 玩家0捨棄手牌
}
break;
case 3: // 方法3: 同步判斷法 (含牌分)
for (int i = 0; i < NumberOfSamples; i++) // 50000000次測試
{
Deck.ShufflePartial(5); // 洗5張牌
Deck.Deal(Players[0], 0, 5); // 發牌給玩家0,從第0張起,共5張牌
Table.TypeCount[Players[0].CardType_By_CheckTypeAndGradeAllInOne]++;// 記分板紀錄牌形出現次數
Players[0].Reset(); // 玩家0捨棄手牌
}
break;
case 4: // 方法4: 直接判斷法
for (int i = 0; i < NumberOfSamples; i++) // 50000000次測試
{
Deck.ShufflePartial(5); // 洗5張牌
Deck.Deal(Players[0], 0, 5); // 發牌給玩家0,從第0張起,共5張牌
Table.TypeCount[Players[0].CardType_By_CheckTypeStraightly]++; // 記分板紀錄牌形出現次數
Players[0].ResetTypeAndGrade(); // 玩家0捨棄手牌
}
break;
default:
break;
}
}
/*********** 與介面輸入及輸出相關函數 ***********/
static private string[] TypeString = { "", "Zilch", "One Pair", "Two Pairs", "Three of a Kind", "Straight", "Flush", "Fullhouse", "Four of a Kind", "Straight Flush" };
private void OnePlayerShowCards() // 顯示發一副牌的牌面
{
string s = "";
CleanAllTxt();
for (int i = 0; i < txt_player_cardArray.GetLength(1); i++)
{
s = Players[0].cards[i].RankToStr() + Players[0].cards[i].SuitToStr();
if ((Players[0].cards[i].Suit == 2) || (Players[0].cards[i].Suit == 3))
{
txt_player_cardArray[0, i].ForeColor = Color.Red;
}
else
{
txt_player_cardArray[0, i].ForeColor = Color.Black;
}
txt_player_cardArray[0, i].Text = s;
}
}
private void OnePlayerShowType() // 顯示發一副牌的牌型
{
lbl_Display.Text = TypeString[Players[0].CardType_By_CheckTypeAndGradeAllInOne] + " " + Convert.ToString(Players[0].CardGrade);
// lbl_Display.Text = TypeString[Players[0].CardType_By_CheckType2];
}
private void TwoPlayersShowCards() // 顯示發兩副牌的牌面
{
string s = "";
CleanAllTxt();
for (int i = 0; i < txt_player_cardArray.GetLength(0); i++)
{
for (int j = 0; j < txt_player_cardArray.GetLength(1); j++)
{
s = Players[i].cards[j].RankToStr() + Players[i].cards[j].SuitToStr();
if ((Players[i].cards[j].Suit == 2) || (Players[i].cards[j].Suit == 3))
{
txt_player_cardArray[i,j].ForeColor = Color.Red;
}
else
{
txt_player_cardArray[i,j].ForeColor = Color.Black;
}
txt_player_cardArray[i,j].Text = s;
}
}
}
private void TwoPlayersShowType() // 顯示發兩副牌的牌型
{
lbl_player1display.Text = TypeString[Players[0].CardType_By_CheckTypeAndGradeAllInOne] + " " + Convert.ToString(Players[0].CardGrade);
lbl_player2display.Text = TypeString[Players[1].CardType_By_CheckTypeAndGradeAllInOne] + " " + Convert.ToString(Players[1].CardGrade);
}
private void ShowWhoWin() // 顯示誰贏了
{
if (Players[0].CardType > Players[1].CardType)
{
lbl_Display.Text = "Player1 Won!";
}
else if (Players[0].CardType < Players[1].CardType)
{
lbl_Display.Text = "Player2 Won!";
}
else
{
if (Players[0].CardGrade > Players[1].CardGrade)
{
lbl_Display.Text = "Player1 Won!";
}
else
{
lbl_Display.Text = "Player2 Won!";
}
}
}
private void CleanAllTxt() // 清除所有顯示欄位
{
string s = "";
for (int i = 0; i < txt_player_cardArray.GetLength(0); i++)
{
for (int j = 0; j < txt_player_cardArray.GetLength(1); j++)
{
txt_player_cardArray[i, j].Text = s;
}
}
txt_Display.Text = s;
lbl_Display.Text = s;
lbl_player1display.Text = s;
lbl_player2display.Text = s;
}
private void ShowProbability() // 顯示統計機率
{
double[] prob = Table.Probability();
string s = "";
for (int i = 1; i <= 9; i++)
{
s += TypeString[i] + ": ";
s += Convert.ToString(prob[i]);
s += Environment.NewLine;
}
txt_Display.Text = s;
}
private void ShowCostTime(double CostTime) // 顯示花費時間
{
CostTime /= 1000;
lbl_Display.Text = "時間: " + CostTime.ToString() + " (s)";
}
private int GetAlgorithmsSelectIndex() // 取得演算法的選擇
{
return cmo_AlgorithmsSelect.SelectedIndex;
}
/*********** 測試 ***********/
private void Test1() // 確認是否能出現指定牌形
{
// 測試牌形
while (true)
{
Deck.ShufflePartial(5);
Deck.Deal(Players[0], 0, 5);
if (Players[0].CardType == 7)
break;
else
Players[0].Reset();
}
OnePlayerShowCards();
OnePlayerShowType();
Players[0].Reset();
}
}
}
/********************** StudCard.cs **********************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HW5
{
class StudCard
{
public PokerCard[] cards = new PokerCard[5];
private int[] RankTable = new int[15];
private int cardtype = 0;
private int cardgrade = 0;
public int CardType // 牌形
{
get
{
if (cardtype == 0)
{
SetupRankTable();
CheckType();
}
return cardtype;
}
}
public int CardType_By_CheckTypeHighToLow // 牌形(以二分法,由同花開始)
{
get
{
if (cardtype == 0)
{
SetupRankTable();
CheckTypeHighToLow();
}
return cardtype;
}
}
public int CardType_By_CheckTypeAllInOne // 牌形(以同步判斷法)
{
get
{
if (cardtype == 0)
{
SetupRankTable();
CheckTypeAllInOne();
}
return cardtype;
}
}
public int CardType_By_CheckTypeAndGradeAllInOne // 牌形(以含牌分同步判斷法)
{
get
{
if (cardtype == 0)
{
SetupRankTable();
CheckTypeAndGradeAllInOne();
}
return cardtype;
}
}
public int CardType_By_CheckTypeStraightly // 牌形(以直接判斷法)
{
get
{
if (cardtype == 0)
{
CheckTypeStraightly();
}
return cardtype;
}
}
public int CardGrade // 牌分
{
get
{
if (cardtype == 0)
{
CheckTypeAndGradeAllInOne();
}
else if (cardgrade == 0)
{
CheckGrade();
}
return cardgrade;
}
}
public void Reset() // 丟棄手牌
{
/* 迴圈比較慢
for (int i = 0; i < cards.Length; i++)
{
RankTable[cards[i].Rank] = 0;
// cards[i] = null; // No need in here!
}
*/
RankTable[cards[0].Rank] = 0;
RankTable[cards[1].Rank] = 0;
RankTable[cards[2].Rank] = 0;
RankTable[cards[3].Rank] = 0;
RankTable[cards[4].Rank] = 0;
cardtype = 0;
cardgrade = 0;
}
public void ResetTypeAndGrade() // 初始化牌型與分數
{
cardtype = 0;
cardgrade = 0;
}
private void SetupRankTable() // 紀錄點數出現次數
{
/*
for (int i = 0; i < cards.Length; i++)
{
RankTable[cards[i].Rank]++;
}*/
RankTable[cards[0].Rank]++;
RankTable[cards[1].Rank]++;
RankTable[cards[2].Rank]++;
RankTable[cards[3].Rank]++;
RankTable[cards[4].Rank]++;
RankTable[14] = RankTable[1];
}
private bool isOnePair() // 一對
{
for (int i = 1; i <= 13; i++)
{
if (RankTable[i] > 1)
{
return true;
}
}
return false;
}
private bool isTwoPairs() // 二對
{
for (int i = 1; i <= 12; i++)
{
if (RankTable[i] > 1)
{
if (RankTable[i] > 3)
{
return true;
}
for (int j = i + 1; j <= 13; j++)
{
if (RankTable[j] > 1)
{
return true;
}
}
return false;
}
}
return false;
}
private bool isThreeOfAKind() // 三條
{
for (int i = 1; i <= 13; i++)
{
if (RankTable[i] > 2)
{
return true;
}
}
return false;
}
private bool isStraight() // 順子
{
for (int j = 1; j <= 5; j++)
{
if (RankTable[j] != 1)
{
break;
}
if (j == 5)
{
return true;
}
}
for (int i = 2; i <= 10; i++)
{
if (RankTable[i] == 1)
{
for (int j = i + 1; j <= i + 4; j++)
{
if (RankTable[j] != 1)
{
return false;
}
}
return true;
}
}
return false;
}
private bool isFlush() // 同花
{
int Flush = cards[0].Suit;
for (int i = 1; i < 5; i++)
{
if (cards[i].Suit != Flush)
{
return false;
}
}
return true;
}
private bool isFullhouse() // 葫蘆
{
bool ThreeOfAKind = false;
bool OnePair = false;
int i = 1;
for (i = 1; i <= 13; i++)
{
if (RankTable[i] == 2)
{
OnePair = true;
break;
}
if (RankTable[i] == 3)
{
ThreeOfAKind = true;
break;
}
}
if (OnePair)
{
for (int j = i + 1; j <= 13; j++)
{
if (RankTable[j] == 3)
{
return true;
}
}
}
if (ThreeOfAKind)
{
for (int j = i + 1; j <= 13; j++)
{
if (RankTable[j] == 2)
{
return true;
}
}
}
return false;
}
private bool isFourOfAKind() // 鐵支
{
for (int i = 1; i <= 13; i++)
{
if (RankTable[i] > 3)
{
return true;
}
}
return false;
}
private void CheckType() // 判斷牌型
{
if (isOnePair())
{
if (isTwoPairs())
{
if (isFullhouse())
{
cardtype = 7; // Fullhouse
}
else
{
if (isFourOfAKind())
{
cardtype = 8; // Four Of A Kind
}
else
{
cardtype = 3; // Two Pairs
}
}
}
else
{
if (isThreeOfAKind())
{
cardtype = 4; // Three Of A Kind
}
else
{
cardtype = 2; // One Pair
}
}
}
else
{
if (isStraight())
{
if (isFlush())
{
cardtype = 9; // Straight Flush
}
else
{
cardtype = 5; // Straight
}
}
else
{
if (isFlush())
{
cardtype = 6; // Flush
}
else
{
cardtype = 1; // Zilch
}
}
}
}
private void CheckGrade() // 判斷牌分
{
int RankGrade = 0;
int SuitGrade = 0;
switch (CardType)
{
case 1: // 無對
case 6: // 同花
for (int i = 14; i >= 1; i--)
{
if (RankTable[i] == 1)
{
RankGrade = i;
break;
}
}
break;
case 2: // 一對
case 3: // 二對
for (int i = 14; i >= 1; i--)
{
if (RankTable[i] == 2)
{
RankGrade = i;
break;
}
}
break;
case 4: // 三條
case 7: // 葫蘆
for (int i = 14; i >= 1; i--)
{
if (RankTable[i] == 3)
{
RankGrade = i;
break;
}
}
break;
case 8: // 鐵支
for (int i = 14; i >= 1; i--)
{
if (RankTable[i] == 4)
{
RankGrade = i;
break;
}
}
break;
case 5: // 順子
case 9: // 同花順
if ((RankTable[1]==1)&&(RankTable[2]==1))
{
RankGrade = 5;
}
else
{
for (int i = 14; i >= 1; i--)
{
if (RankTable[i] == 1)
{
RankGrade = i;
break;
}
}
}
break;
default:
RankGrade = 0;
break;
}
RankGrade = (RankGrade - 1) % 13 + 1;
for (int i = 0; i < cards.Length; i++)
{
if ((cards[i].Rank == RankGrade) && ((5 - cards[i].Suit) > SuitGrade))
{
SuitGrade = 5 - cards[i].Suit;
}
}
if (RankGrade == 1)
{
RankGrade += 13;
}
cardgrade = RankGrade * 4 + SuitGrade;
}
private void CheckTypeAllInOne() // 判斷牌型 (同步判斷)
{
for (int i = 14; i >= 1; i--)
{
if (RankTable[i] > 0)
{
switch (RankTable[i])
{
case 1: // 至少是無對
cardtype = 1;
for (int j = i - 1; i >= 1; j--)
{
if (RankTable[j] > 0)
{
switch (RankTable[j])
{
case 1: // 至少是無對
for (int k = j - 1; k >= 1; k--)
{
if (RankTable[k] > 0)
{
switch (RankTable[k])
{
case 1: // 至少是無對
for (int l = k - 1; l >= 1; l--)
{
if (RankTable[l] > 0)
{
switch (RankTable[l])
{
case 1: // 至少是無對
bool isFlushHere = true; // 判斷是否為同花,初始設定為是
int Flush = cards[0].Suit;
for (int m = 1; m < 5; m++)
{
if (cards[m].Suit != Flush)
{
isFlushHere = false; // 不是
}
}
if ((i - 3 == l && RankTable[i - 4] == 1) || // 一般順子
(i - 9== j)) // A2345順子
{
if (isFlushHere) // 同花順
{
cardtype = 9;
}
else // 順子
{
cardtype = 5;
}
}
else if (isFlushHere) // 同花
{
cardtype = 6;
}
goto LeaveThisLoop;
case 2: // 一對
cardtype = 2;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 2: // 一對
cardtype = 2;
goto LeaveThisLoop;
case 3: // 三條
cardtype = 4;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 2: // 至少是一對
cardtype = 2;
for (int k = j - 1; k >= 1; k--)
{
if (RankTable[k] > 0)
{
switch (RankTable[k])
{
case 1: // 一對
goto LeaveThisLoop;
case 2: // 兩對
cardtype = 3;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 3: // 三條
cardtype = 4;
goto LeaveThisLoop;
case 4: // 鐵支
cardtype = 8;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 2: // 至少是一對
cardtype = 2;
for (int j = i - 1; i >= 1; j--)
{
if (RankTable[j] > 0)
{
switch (RankTable[j])
{
case 1: // 至少是一對
for (int k = j - 1; k >= 1; k--)
{
if (RankTable[k] > 0)
{
switch (RankTable[k])
{
case 1: // 一對
goto LeaveThisLoop;
case 2: // 兩對
cardtype = 3;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 2: // 兩對
cardtype = 3;
goto LeaveThisLoop;
case 3: // 葫蘆
cardtype = 7;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 3: // 至少是三條
cardtype = 4;
for (int j = i - 1; i >= 1; j--)
{
if (RankTable[j] > 0)
{
switch (RankTable[j])
{
case 1: // 三條
goto LeaveThisLoop;
case 2: // 葫蘆
cardtype = 7;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 4: // 鐵支
cardtype = 8;
goto LeaveThisLoop;
}
}
}
LeaveThisLoop:
cardgrade = 0;
}
private void CheckTypeAndGradeAllInOne() // 判斷牌型與牌分 (同步判斷)
{
int RankGrade = 0;
int SuitGrade = 0;
for (int i = 14; i >= 1; i--)
{
if (RankTable[i] > 0)
{
switch (RankTable[i])
{
case 1: // 至少是無對
cardtype = 1;
RankGrade = i;
for (int j = i - 1; i >= 1; j--)
{
if (RankTable[j] > 0)
{
switch (RankTable[j])
{
case 1: // 至少是無對
for (int k = j - 1; k >= 1; k--)
{
if (RankTable[k] > 0)
{
switch (RankTable[k])
{
case 1: // 至少是無對
for (int l = k - 1; l >= 1; l--)
{
if (RankTable[l] > 0)
{
switch (RankTable[l])
{
case 1: // 至少是無對
bool isFlushHere = true; // 判斷是否為同花,初始設定為是
int Flush = cards[0].Suit;
for (int m = 1; m < 5; m++)
{
if (cards[m].Suit != Flush)
{
isFlushHere = false; // 不是
break;
}
}
if ((i - 3 == l && RankTable[i - 4] == 1) || // 一般順子
(i - 9 == j)) // A2345順子
{
if (i - 9 == j) // A2345順子, 最大為5
{
RankGrade = 5;
}
else // 一般順子
{
RankGrade = i;
}
if (isFlushHere) // 同花順
{
cardtype = 9;
}
else // 順子
{
cardtype = 5;
}
}
else if (isFlushHere) // 同花
{
cardtype = 6;
RankGrade = i;
}
goto LeaveThisLoop;
case 2: // 一對
cardtype = 2;
RankGrade = l;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 2: // 一對
cardtype = 2;
RankGrade = k;
goto LeaveThisLoop;
case 3: // 三條
cardtype = 4;
RankGrade = k;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 2: // 至少是一對
cardtype = 2;
RankGrade = j;
for (int k = j - 1; k >= 1; k--)
{
if (RankTable[k] > 0)
{
switch (RankTable[k])
{
case 1: // 一對
goto LeaveThisLoop;
case 2: // 兩對
cardtype = 3;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 3: // 三條
cardtype = 4;
RankGrade = j;
goto LeaveThisLoop;
case 4: // 鐵支
cardtype = 8;
RankGrade = j;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 2: // 至少是一對
cardtype = 2;
RankGrade = i;
for (int j = i - 1; i >= 1; j--)
{
if (RankTable[j] > 0)
{
switch (RankTable[j])
{
case 1: // 至少是一對
for (int k = j - 1; k >= 1; k--)
{
if (RankTable[k] > 0)
{
switch (RankTable[k])
{
case 1: // 一對
goto LeaveThisLoop;
case 2: // 兩對
cardtype = 3;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 2: // 兩對
cardtype = 3;
goto LeaveThisLoop;
case 3: // 葫蘆
cardtype = 7;
RankGrade = j;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 3: // 至少是三條
cardtype = 4;
RankGrade = i;
for (int j = i - 1; i >= 1; j--)
{
if (RankTable[j] > 0)
{
switch (RankTable[j])
{
case 1: // 三條
goto LeaveThisLoop;
case 2: // 葫蘆
cardtype = 7;
goto LeaveThisLoop;
}
}
}
goto LeaveThisLoop;
case 4: // 鐵支
cardtype = 8;
RankGrade = i;
goto LeaveThisLoop;
}
}
}
LeaveThisLoop:
RankGrade = (RankGrade - 1) % 13 + 1;
for (int i = 0; i < cards.Length; i++)
{
if ((cards[i].Rank == RankGrade) && ((5 - cards[i].Suit) > SuitGrade))
{
SuitGrade = 5 - cards[i].Suit;
}
}
if (RankGrade == 1)
{
RankGrade += 13;
}
cardgrade = RankGrade * 4 + SuitGrade;
}
private void CheckTypeHighToLow() // 判斷牌型 (二分法,由同花開始)
{
if (isFlush() && isStraight())
{
cardtype = 9;
}
else if (isFourOfAKind())
{
cardtype = 8;
}
else if (isFullhouse())
{
cardtype = 7;
}
else if (isFlush())
{
cardtype = 6;
}
else if (isStraight())
{
cardtype = 5;
}
else if (isThreeOfAKind())
{
cardtype = 4;
}
else if (isTwoPairs())
{
cardtype = 3;
}
else if (isOnePair())
{
cardtype = 2;
}
else
{
cardtype = 1;
}
}
private static int[] PairTable = { 0, 2, 3, 4, 7, 0, 8 }; // 對數與牌型轉換表
private void CheckTypeStraightly() // 判斷牌型 (直接判斷)
{
int PairCount = 0;
for (int i = 0; i < 4; i++)
{
for (int j = i + 1; j < 5; j++)
{
if (cards[i].Rank == cards[j].Rank)
{
PairCount++;
}
}
}
if (PairCount > 0)
{
cardtype = PairTable[PairCount];
}
else
{
bool isFlushHere = true; // 判斷是否為同花,初始設定為是
int Flush = cards[0].Suit;
for (int m = 1; m < 5; m++)
{
if (cards[m].Suit != Flush)
{
isFlushHere = false; // 不是
break;
}
}
int X = cards[0].Rank + cards[1].Rank + cards[2].Rank + cards[3].Rank + cards[4].Rank;
int Y = cards[0].Rank * cards[0].Rank + cards[1].Rank * cards[1].Rank + cards[2].Rank * cards[2].Rank + cards[3].Rank * cards[3].Rank + cards[4].Rank * cards[4].Rank;
if ((5 * Y - X * X == 50) || (X == 47 && Y == 535))
{
if (isFlushHere)
{
cardtype = 9;
}
else
{
cardtype = 5;
}
}
else
{
if (isFlushHere)
{
cardtype = 6;
}
else
{
cardtype = 1;
}
}
}
}
}
}
/********************** CardDeck.cs **********************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HW5
{
class CardDeck
{
private int CardNum = 52;
private int TopIndex = 0;
private PokerCard[] Cards;
private Random rand = new Random();
public CardDeck()
{
Cards = new PokerCard[CardNum];
CreateDeck();
ResetDeck();
}
public void CreateDeck() // 產生卡片
{
for (int i = 0; i < CardNum; i++)
{
Cards[i] = new PokerCard();
}
}
public void ResetDeck() // 復歸初始排列
{
for (int i = 0; i < CardNum; i++)
{
Cards[i].Suit = i / 13 + 1;
Cards[i].Rank = i % 13 + 1;
}
TopIndex = 0;
}
public void Shuffle() // 洗牌
{
int RandNum = 0;
PokerCard TempCard;
for (int i = 0; i < CardNum; i++)
{
RandNum = rand.Next(CardNum);
TempCard = Cards[RandNum];
Cards[RandNum] = Cards[i];
Cards[i] = TempCard;
}
TopIndex = 0;
}
public void ShufflePartial(int Num) // 部分洗牌
{
int RandNum = 0;
PokerCard TempCard;
for (int i = 0; i < Num; i++)
{
RandNum = rand.Next(CardNum);
TempCard = Cards[RandNum];
Cards[RandNum] = Cards[i];
Cards[i] = TempCard;
}
TopIndex = 0;
}
public void Deal(StudCard player, int StartIndex, int NumberOfCards) // 發牌
{
for (int i = StartIndex; i < StartIndex + NumberOfCards; i++)
{
player.cards[i] = Cards[TopIndex];
TopIndex++;
}
}
}
}
/********************** ScoreTable.cs **********************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HW5
{
class ScoreTable
{
public int[] TypeCount = new int[10];
public double[] Probability() // 計算機率
{
int sum = 0;
double[] Prob = new double[10];
for (int i = 0; i < TypeCount.Length; i++)
{
sum += TypeCount[i];
}
for (int i = 0; i < TypeCount.Length; i++)
{
Prob[i] = (double)TypeCount[i] / (double)sum;
}
return Prob;
}
public void Reset() // 清空資料
{
for (int i = 0; i < TypeCount.Length; i++)
{
TypeCount[i] = 0;
}
}
}
}
/********************** PokerCard.cs **********************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HW5
{
class PokerCard
{
public int Suit = 0; //花色
public int Rank = 0; //點數
private static string[] RankTable = {"", "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };
private static string[] SuitTable = {"", "♠", "♥", "♦", "♣"};
public string RankToStr() //將點數轉為字串
{
return RankTable[Rank];
}
public string SuitToStr() //將花色轉為字串
{
return SuitTable[Suit];
}
}
}
PokerCard類別裡的欄位Suit跟Rank應該用private比較好 第九組
回覆刪除這裡不能設private,不然Suit跟Rank根本不能更改,除非用屬性的存取運算子,
刪除但測試結果是會略為降低效能,而且為了符合進度而沒有使用。
[第六組]
回覆刪除一般的梭哈就只用牌型、點數、花色來比較大小,所以當初看到你們把牌轉換成分數的做法覺得怪怪的.
演算法:直接判斷法,我覺得蠻酷的! 不過裡面的X和Y都要平方,其中Y還得分別對五張牌點數做平方後才相加. 這種處理其實花的時間會比判斷兩張牌之間的差是否為1來的久. 不過這個方法的好處就在不用排序,或許在處理張數很多的情況下,這個方法反而會比"排序後再檢查兩張之間的差是否為1"還快.
梭哈在比大小時,除了判斷牌型外,剩下的其實就是找到5張手牌中的「關鍵牌」,所以可以理解的是在同牌型的情況下其實就是在比這張「關鍵牌」的大小,而牌分其實就是這張「關鍵牌」的分數,因此會與點數與花色相關。一副牌52張攤開來看,可以從小排到大而且不會有一樣大小的牌,因此我們可以給予不同牌不同的分數,從而進行大小的判定,這是牌分概念的來源。
回覆刪除如果有詳細看這個程式的話,其實可以發現這些亂七八糟的演算法就是一直在迴避排序的演算法,主要原因當然還是排序很花時間。直接判斷法中的順子判斷規則是有其數學理論為基礎的,這條5Y-X^2=50是由變異數的概念推導而來,想當然爾會有比較多的數值運算,而具有較少的邏輯判斷。這方法基本上應該會比判斷差1來得慢,但畢竟不需經過排序,實際的效率可能還是要實做看看才能得知。