系統開發-01初始化

更新 發佈閱讀 19 分鐘


raw-image


我們將之前寫過的發牌程式碼與撲克牌圖片,並新增Player類別,套到上一篇的程式框架內

Default.aspx如下

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<style>
/*撲克牌圖片顯示在網頁上的尺寸大小*/
img {
width:100px;
height:145px;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<table border="1" style="border-collapse:collapse">
<tr>
<td>牌堆</td>
<td>
<asp:Label ID="lab_deck" runat="server" Text=""></asp:Label>
</td>
</tr>
<tr>
<td>莊家</td>
<td>
<asp:Label ID="lab_dealer" runat="server" Text=""></asp:Label>
</td>
</tr>
<tr>
<td>玩家</td>
<td>
<asp:Label ID="lab_player" runat="server" Text=""></asp:Label>
</td>
</tr>
<tr>
<td colspan="2">
<asp:Label ID="lab_msg" runat="server" Text=""></asp:Label>
</td>
</tr>
<tr>
<td colspan="2">
<asp:Button ID="btn_hit" runat="server" Text="要牌(Hit)" OnClick="btn_hit_Click" />
<asp:Button ID="btn_stand" runat="server" Text="停牌(Stand)" OnClick="btn_stand_Click" />
<asp:Button ID="btn_newgame" runat="server" Text="新牌局" OnClick="btn_newgame_Click" />
</td>
</tr>
</table>
</div>
</form>
</body>
</html>

Default.aspx.cs如下

public partial class _Default : System.Web.UI.Page
{
Deck deck; //排堆
Player dealer; //莊家
Player player; //玩家

protected void Page_Load(object sender, EventArgs e)
{
ResetGame();

UpdateUI();
}

protected void ResetGame() { //初始化遊戲參數與動作(初始發牌)
deck = new Deck();
dealer = new Player();
player = new Player();

//初始發牌
DrawForPlayer();
DrawForDealer();
DrawForPlayer();
DrawForDealer();

//清空label內容
lab_deck.Text = "";
lab_dealer.Text = "";
lab_player.Text = "";
}

protected void UpdateUI()
{
lab_deck.Text = deck.ShowCards();

//顯示玩家手牌
for (int i = 0; i < player.cards.Count; i++)
{
lab_player.Text += $"<img src='./images/{player.cards[i].Rank}-{player.cards[i].Suit}.png'>";
}

//顯示莊家手牌
for (int i = 0; i < dealer.cards.Count; i++)
{
lab_dealer.Text += $"<img src='./images/{dealer.cards[i].Rank}-{dealer.cards[i].Suit}.png'>";
}
}

//發牌給莊家
protected void DrawForDealer() {
Card c = deck.DrawCard();
dealer.AddCard(c); //加到手牌
}

//發牌給玩家
protected void DrawForPlayer() {
Card c = deck.DrawCard();
player.AddCard(c); //加到手牌
}

//按鈕OnClick後觸發
//玩家要牌,呼叫DrawForPlayer()
protected void btn_hit_Click(object sender, EventArgs e)
{
DrawForPlayer();
}

//玩家停牌,換莊家要牌DrawForDealer(),直到計分比較輸贏
protected void btn_stand_Click(object sender, EventArgs e)
{
DrawForDealer();
}

//新牌局(下一回合),呼叫NextRound()
protected void btn_newgame_Click(object sender, EventArgs e)
{
ResetGame();
}

protected void NextRound() { } //下一回合,呼叫ResetGame()
}

public class Player
{
public List<Card> cards { get; private set; }

public Player()
{
cards = new List<Card>();
Init();
}

public void Init()
{
cards.Clear();
}

public void AddCard(Card card)
{
cards.Add(card);
}
}

public class Deck
{
private Card[] cards; //牌堆(只能透過DrawCard取得,所以設定private)
private int dealIndex = 0; //發牌順序
string[] suitNames = { "黑桃", "紅心", "方塊", "梅花" };

public Deck() { //建立類別
cards = new Card[52];
string[] suits = { "S", "H", "D", "C" };

int index = 0;

for (int i = 0; i < suits.Length; i++) //四種花色
{
for (int j = 1; j <= 13; j++) //一種花色13張牌1-13
{
cards[index] = new Card(suits[i], suitNames[i], j); //初始化
index++;
}
}

Init();
}

public void Init()
{
BubbleSort(cards); //復原順序
Shuffle(cards); //重新洗牌
dealIndex = 0; //回復預設值
}

//發牌
public Card DrawCard()
{
Card card = null;

if (dealIndex < cards.Length)
{
card = cards[dealIndex];
}
//超出一副牌的52張數量

dealIndex += 1;
return card; // 回傳抽到的牌
}

void Shuffle(Card[] cards) { //洗牌(生成時,自動洗牌,所以不需要設定public)
Random rand = new Random();

for (int i = 0; i < cards.Length; i++)
{
int j = rand.Next(cards.Length); //// 產生一個隨機索引 0-51

//例如:
// i=0, j=12,表示第一張牌 (cards[0] 黑桃1) 與第13張牌 (cards[12]黑桃13) 互換
// 互換後的結果為,第一張牌 (cards[0] 黑桃13,第13張牌 (cards[12]黑桃1)
// 一直換52次(每一個位置的牌都換一次)
Swap(cards, i, j);
}
}

//將撲克牌順序由小到大排序
void BubbleSort(Card[] cards)
{
for (int i = 0; i < cards.Length; i++)
{
for (int j = 0; j < cards.Length - 1; j++) //反過來就是由大到小排序
{
if (cards[j].Seq > cards[j + 1].Seq)
{
Swap(cards, j, j + 1);
}
}
}
}

//陣列中兩個元素交換,通過暫存變數的方式來實現交換
void Swap(Card[] cards, int i, int j)
{
Card tmp = cards[i]; //將 cards[i] 的值暫存到 temp
cards[i] = cards[j]; //將 cards[j] 的值賦給 cards[i]
cards[j] = tmp; //將剛才暫存的 tmp 值賦給 cards[j]
}

public string ShowCards()
{
string str = string.Empty;

for (int i = 0; i < cards.Length; i++)
{
if (i % 13 == 0) //13張牌排成一行
{
str += $"<br>{cards[i].ToString()}"; //換行
}
else
{
str += $",{cards[i].ToString()}"; //自訂顯示方式
}
}

return str;
}
}

public class Card
{
public string Suit { get; set; } // 花色
public string SuitName { get; set; } // 花色名稱,為了顯示排堆時方便辨識
public int Rank { get; set; } // 點數
public int Seq { get; set; } // 順序

public Card(string suit, string SuitName, int rank) {
this.Suit = suit;
this.SuitName = SuitName;
this.Rank = rank;
} //建立類別

// 顯示卡片的文字表示
public override string ToString()
{
return $"{Rank} of {SuitName}";
}
}

完成後,當網頁載入後就會洗好牌,並請發給莊家和玩家各兩張牌

畫面如下

raw-image

但在按下要牌(Hit)時,會發生整個牌堆和手牌的資料都不一樣了,這是因為ASP.Net按下按鈕後,會重新載入網頁,所以Page_Load()都會重新執行一次,牌堆和手牌當然會不一樣,下一篇將使用Session儲存資料來解決這個問題。


Page_Load()請參考ASP.Net生命週期(Life Cycle)相關網頁


留言
avatar-img
Phyxsius
0會員
19內容數
FIRE
你可能也想看
Thumbnail
賽勒布倫尼科夫以流亡處境回望蘇聯電影導演帕拉贊諾夫的舞台作品,以十段寓言式殘篇,重新拼貼記憶、暴力與美學,並將審查、政治犯、戰爭陰影與「形式即政治」的劇場傳統推到台前。本文聚焦於《傳奇:帕拉贊諾夫的十段殘篇》的舞台美術、音樂與多重扮演策略,嘗試解析極權底下不可言說之事,將如何成為可被觀看的公共發聲。
Thumbnail
賽勒布倫尼科夫以流亡處境回望蘇聯電影導演帕拉贊諾夫的舞台作品,以十段寓言式殘篇,重新拼貼記憶、暴力與美學,並將審查、政治犯、戰爭陰影與「形式即政治」的劇場傳統推到台前。本文聚焦於《傳奇:帕拉贊諾夫的十段殘篇》的舞台美術、音樂與多重扮演策略,嘗試解析極權底下不可言說之事,將如何成為可被觀看的公共發聲。
Thumbnail
柏林劇團在 2026 北藝嚴選,再次帶來由布萊希特改編的經典劇目《三便士歌劇》(The Threepenny Opera),導演巴里・柯斯基以舞台結構與舞台調度,重新向「疏離」進行提問。本文將從觀眾慾望作為戲劇內核,藉由沉浸與疏離的辯證,解析此作如何再次照見觀眾自身的位置。
Thumbnail
柏林劇團在 2026 北藝嚴選,再次帶來由布萊希特改編的經典劇目《三便士歌劇》(The Threepenny Opera),導演巴里・柯斯基以舞台結構與舞台調度,重新向「疏離」進行提問。本文將從觀眾慾望作為戲劇內核,藉由沉浸與疏離的辯證,解析此作如何再次照見觀眾自身的位置。
Thumbnail
本文深入解析臺灣劇團「晃晃跨幅町」對易卜生經典劇作《海妲.蓋柏樂》的詮釋,從劇本歷史、聲響與舞臺設計,到演員的主體創作方法,探討此版本如何讓經典劇作在當代劇場語境下煥發新生,滿足現代觀眾的觀看慾望。
Thumbnail
本文深入解析臺灣劇團「晃晃跨幅町」對易卜生經典劇作《海妲.蓋柏樂》的詮釋,從劇本歷史、聲響與舞臺設計,到演員的主體創作方法,探討此版本如何讓經典劇作在當代劇場語境下煥發新生,滿足現代觀眾的觀看慾望。
Thumbnail
《轉轉生》為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,融合舞蹈、音樂、時尚和視覺藝術,透過身體、服裝與群舞結構,回應殖民歷史、城市經驗與祖靈記憶的交錯。本文將從服裝設計、身體語彙與「輪迴」的「誕生—死亡—重生」結構出發,分析《轉轉生》如何以當代目光,形塑去殖民視角的奈及利亞歷史。
Thumbnail
《轉轉生》為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,融合舞蹈、音樂、時尚和視覺藝術,透過身體、服裝與群舞結構,回應殖民歷史、城市經驗與祖靈記憶的交錯。本文將從服裝設計、身體語彙與「輪迴」的「誕生—死亡—重生」結構出發,分析《轉轉生》如何以當代目光,形塑去殖民視角的奈及利亞歷史。
Thumbnail
※ 先建立基本的express後端服務: 1.建立新資料夾:WebSocket mkdir websocket 2.進入資料夾:WebSocket cd ​websocket 3. 安裝 Experss 到專案中 npm init -y //初始化專案,建立 package.json 檔
Thumbnail
※ 先建立基本的express後端服務: 1.建立新資料夾:WebSocket mkdir websocket 2.進入資料夾:WebSocket cd ​websocket 3. 安裝 Experss 到專案中 npm init -y //初始化專案,建立 package.json 檔
Thumbnail
這篇文章提供一個逐步指南,教導讀者如何使用VB.Net和ASP.NET Web Forms建立一個簡單的Web應用程式。從安裝開發環境到撰寫程式碼、執行與測試,步驟清晰易懂,適合初學者學習。
Thumbnail
這篇文章提供一個逐步指南,教導讀者如何使用VB.Net和ASP.NET Web Forms建立一個簡單的Web應用程式。從安裝開發環境到撰寫程式碼、執行與測試,步驟清晰易懂,適合初學者學習。
Thumbnail
在這篇文章中,我們將介紹工作與以前念書時期在開發流程上的差異,並深入瞭解CI/CD、Travis CI以及加解密的應用。 CI/CD是自動化的軟體開發實踐,而加解密則是保護機密資料安全的重要技術。
Thumbnail
在這篇文章中,我們將介紹工作與以前念書時期在開發流程上的差異,並深入瞭解CI/CD、Travis CI以及加解密的應用。 CI/CD是自動化的軟體開發實踐,而加解密則是保護機密資料安全的重要技術。
Thumbnail
軟體系統的發展歷程大多相似,首重解決基本需求、提供操作介面,進而提升安全性、擴充功能、優化操作。
Thumbnail
軟體系統的發展歷程大多相似,首重解決基本需求、提供操作介面,進而提升安全性、擴充功能、優化操作。
Thumbnail
這個系列是專門寫給 0 程式設計經驗的初學者的 C++ 教學, 無需架設環境,直接開始無痛入手 C++ ~
Thumbnail
這個系列是專門寫給 0 程式設計經驗的初學者的 C++ 教學, 無需架設環境,直接開始無痛入手 C++ ~
Thumbnail
前年第一次藉公司機會,參加了DevOpsDay的活動。雖然devOps一詞各自表述,大多狀況還是偏向維運會遇到的技術為主,做為平時開發、跟使用者訪談需求的工作內容來說,參加聚會如果沒有一定的知識,對講者所提到的狀況比較難有共鳴...
Thumbnail
前年第一次藉公司機會,參加了DevOpsDay的活動。雖然devOps一詞各自表述,大多狀況還是偏向維運會遇到的技術為主,做為平時開發、跟使用者訪談需求的工作內容來說,參加聚會如果沒有一定的知識,對講者所提到的狀況比較難有共鳴...
Thumbnail
第一份正職工作 在iot公司擔任後端工程師,一上工就使用先前沒用過的php/laravel,也馬上負責公司產品的架構規劃,先前資料庫只有簡單記載使用者跟使用者的一些設定,很多地方有資料不一致的問題,產品內容還有很多實體的關係沒有被定義進資料庫都是這次改版我要做的事情。 改版納入公司、機器
Thumbnail
第一份正職工作 在iot公司擔任後端工程師,一上工就使用先前沒用過的php/laravel,也馬上負責公司產品的架構規劃,先前資料庫只有簡單記載使用者跟使用者的一些設定,很多地方有資料不一致的問題,產品內容還有很多實體的關係沒有被定義進資料庫都是這次改版我要做的事情。 改版納入公司、機器
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News