ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 3825|回复: 0

[VBA程序开发] 〖转贴〗用Visual Basic.NET编写扑克牌游戏

[复制链接]

TA的精华主题

TA的得分主题

发表于 2005-3-8 15:51 | 显示全部楼层 |阅读模式
  扑克游戏林林总总,同一种游戏各地玩法亦不尽相同。编程爱好者多喜欢编写一些本地玩法的扑克游戏。那么,编写自己的扑克游戏该从何处入手呢?   扑克游戏编程关键有两点:一是扑克牌面的绘制;二是扑克游戏规则的算法实现。初学扑克游戏编程的爱好者可从一些简单的游戏、借用一些现有资源开始。本文拟借用Windows自带的Cards.dll和简单的21点游戏为例,介绍扑克游戏编程的初步方法。   一、 扑克牌面绘制   Cards.dll支持Windows自带的游戏,如Solitaire(纸牌游戏)。如果我们知道如何使用Cards.dll中的API函数,那么,我们就能像Windows自带的游戏一样绘制扑克牌面。我们需要使用其中三个基本函数:cdtInit, cdtDrawExt,和 cdtTerm。并且需要两个变量:width和height用于初始化函数cdtInit进行初始化。下面给出这些接口函数的声明及参数说明。 Private width As Integer = 0 Private height As Integer = 0 Declare Function cdtInit Lib "cards.dll" (ByRef width As Integer, _ ByRef height As Integer) As Boolean   参数说明:width,height返回牌默认宽和高,单位为pixels。 Declare Function cdtDrawExt Lib "cards.dll" (ByVal hdc As IntPtr, _ ByVal x As Integer, ByVal y As Integer, ByVal dx As Integer, _ ByVal dy As Integer, ByVal card As Integer, _ ByVal mode As Integer, ByVal color As Long) As Boolean   参数说明:hdc(handle to a device context)句柄;   x,y指定牌左上角坐标位;   dx,dy指定牌宽和高;   card需要绘制的牌,0-51[A(草花、方块、红桃、黑桃),2,…,K];53-65牌背面;   mode 指定绘制方式,牌面向上为0,牌面向下为1;   color 指定背景色。   Declare Sub cdtTerm Lib "cards.dll" ()   无参数。   我们需要在游戏开始时调用cdtInit对cards.dll进行初始化,这样我们才能使用cards.dll中的cdtDrawEx等函数;每绘制一张牌,我们都要调一次cdtDrawExt函数;当我们结束游戏时,调用一次cdtTerm以结束cards.dll的使用。   二、 游戏规则的算法实现   二十一点游戏是玩家要取得比庄家更大的点数总和,但点数超过二十一点即为爆牌,并输掉注码。J、Q、K算10点,A可算1点或11点,其余按牌面值计点数。“BlackJack”是由一张A和J、Q、K或10所组成。开始时每人发两张牌,一张明,一张暗,凡点数不足二十一点,可选择博牌。如果首两张牌是对子可选择分牌。   为简化起见,程序中只有两个玩家Dealer和Player,都发明牌,无下注过程,不记录输赢,不支持分牌和加倍等。二十一点游戏中,一张牌只要有四个属性说明:Face牌面大小、Suit牌面花色,Count点数,FaceUp牌面是否向上。因此,这里我们不用Card 类而用Card结构。 Structure card Public face As Integer Public suit As Integer Public count As Integer Public faceup As Boolean End Structure   游戏开始时,我们首先要取一副牌,然后将牌洗好,指定从第几张牌开始发起。洗牌时为取得真正的随机数,用My.Computer.Clock.TickCount作产生随机数的种子。

Dim Deck() As card Deck = New card(51) {} Dim TopCard As Integer Private Sub GetDeck()  Dim i, j As Integer  For i = 0 To 3   For j = 0 To 12    Deck(j + 13 * i).face = j    Deck(j + 13 * i).suit = i    If j < 10 Then     Deck(j + 13 * i).count = j + 1    Else     Deck(j + 13 * i).count = 10    End If    Deck(j + 13 * i).faceup = False   Next  Next End Sub Private Sub Shuffle()  Dim i, j, k As Integer  Dim tc As card  For k = 1 To 500   i = CType(My.Computer.Clock.TickCount * Rnd(), Integer) Mod 52   j = CType(Int(Rnd() * 52), Integer)   tc = Deck(i)   Deck(i) = Deck(j)   Deck(j) = tc  Next  topcard = 0 End Sub

  游戏界面中,我们设置三个命令按钮,两个标签。Button1为“发牌”、Button2为“要牌”、Button3为“停牌”。Label1记录庄家点数,Label2记录玩家点数。游戏过程中,如果一副牌发完,立即重洗一副牌,并弹出消息对话框告知。以下列出三个按钮单击事件代码。其中庄家游戏过程中,为简化起见,未曾使用游戏技巧。 Dim playerCount As Integer = 0 Dim playerAce As Integer = 0 Dim dealerCount As Integer = 0 Dim dealerAce As Integer = 0 Dim ipcard, idcard As Integer Private Sub delay(ByVal dt As Integer)  Dim t As Integer  t = My.Computer.Clock.TickCount  Do   If My.Computer.Clock.TickCount >= t + dt Then Exit Do  Loop End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click  Button1.Visible = False  Label1.Text=””  Label2.Text=””  Label1.Refresh()  Label2.Refresh()  MyBase.CreateGraphics.Clear(Color.DarkGreen)  dealerAce = 0  playerAce = 0  dealerCount = 0  playerCount = 0  cdtDrawExt(MyBase.CreateGraphics.GetHdc, 200, 200, 75, 100, (Deck(TopCard).face * 4 + Deck(TopCard).suit), 0, 0)  playerCount += Deck(TopCard).count  If Deck(TopCard).face = 0 Then playerCount += 10 : playerAce += 1  TopCard += 1  If TopCard >= 52 Then Shuffle() : MsgBox("NEW DECK!")  Label2.Text = playerCount.ToString  Label2.Refresh()  delay(1000)  cdtDrawExt(MyBase.CreateGraphics.GetHdc, 200, 10, 75, 100, (Deck(TopCard).face * 4 + Deck(TopCard).suit), 0, 0)  dealerCount += Deck(TopCard).count  If Deck(TopCard).face = 0 Then dealerCount += 10 : dealerAce += 1  TopCard += 1  If TopCard >= 52 Then Shuffle() : MsgBox("NEW DECK!")  Label1.Text = dealerCount.ToString  Label1.Refresh()  delay(1000)  cdtDrawExt(MyBase.CreateGraphics.GetHdc, 220, 200, 75, 100, (Deck(TopCard).face * 4 + Deck(TopCard).suit), 0, 0)  playerCount += Deck(TopCard).count  If Deck(TopCard).face = 0 And playerAce = 0 Then playerCount += 10 : playerAce += 1  TopCard += 1  If TopCard >= 52 Then Shuffle() : MsgBox("NEW DECK!")  Label2.Text = playerCount.ToString  Label2.Refresh()  delay(1000)  cdtDrawExt(MyBase.CreateGraphics.GetHdc, 220, 10, 75, 100, (Deck(TopCard).face * 4 + Deck(TopCard).suit), 0, 0)  dealerCount += Deck(TopCard).count  If Deck(TopCard).face = 0 And dealerAce = 0 Then dealerCount += 10 : dealerAce += 1  TopCard += 1  If TopCard >= 52 Then Shuffle() : MsgBox("NEW DECK!")  Label1.Text = dealerCount.ToString  Label1.Refresh()  delay(1000)  ipcard = 2  idcard = 2  Button2.Visible = True  Button3.Visible = True End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click  cdtDrawExt(MyBase.CreateGraphics.GetHdc, 200 + 20 * ipcard, 200, 75, 100, (Deck(TopCard).face * 4 + Deck(TopCard).suit), 0, 0)  playerCount += Deck(TopCard).count  If Deck(TopCard).face = 0 Then playerCount += 10 : playerAce += 1  TopCard += 1  If TopCard >= 52 Then Shuffle() : MsgBox("NEW DECK!")  ipcard += 1  Label2.Text = playerCount.ToString  Label2.Refresh()  If playerCount > 21 Then   If playerAce >= 1 Then    playerCount -= 10    playerAce -= 1    Label2.Text = playerCount.ToString    Label2.Refresh()   Else    MsgBox("Player loss!")    Button1.Visible = True    Button2.Visible = False    Button3.Visible = False   End If  End If End Sub Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click  Button2.Visible = False  Button3.Visible = False  dealerPlay() End Sub Private Sub dealerPlay()  Do   If dealerCount < 17 Then    cdtDrawExt(MyBase.CreateGraphics.GetHdc, 200 + 20 * idcard, 10, 75, 100, (Deck(TopCard).face * 4 + Deck(TopCard).suit), 0, 0)    dealerCount += Deck(TopCard).count   If dealerCount > 21 And dealerAce = 1 Then dealerCount -= 10 : dealerAce -= 1   If Deck(TopCard).face = 0 And dealerCount <= 11 Then dealerCount += 10   TopCard += 1   If TopCard >= 52 Then Shuffle() : MsgBox("NEW DECK!")   idcard += 1  Else   Exit Do  End If Loop Label1.Text = dealerCount.ToString Label1.Refresh() If dealerCount <= 21 Then  If playerCount > dealerCount Then   MsgBox("Player win!")  Else   MsgBox("Dealer win!")  End If Else  MsgBox("Player win!") End If Button1.Visible = True Button2.Visible = False Button3.Visible = False End Sub

  运行结果如下图所示:

  三、 实践与提高   上述编程中,我们用了结构描述Card,对Card的Face取值(A,2,…,K)和Suit取值(Club,Diamond,Heart,Spade)用了数值0-12和0-3表示。游戏规则也作了简化,只有两个玩家,也未对玩家属性(如:财富、下注、所持牌、持牌点数等)进行描述。实践表明,较好的方法是用Card、player类,Face和Suit用枚举型数据。这些,我们可以在编程中逐步地添加完善。   随着编程实践的深入,我们的经验也会随之丰富起来。如何写一系列的类去支持各式游戏(包括升级、斗地主等需要用大小王牌的游戏)?如何记录玩家得分?如何支持网络?如何处理网络游戏中玩家离开?如此等等。经一个月、两个月,一年、两年的实践后,你将成为行家里手。

〖转贴〗用Visual Basic.NET编写扑克牌游戏

〖转贴〗用Visual Basic.NET编写扑克牌游戏
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-24 03:58 , Processed in 0.029026 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表