二、 游戏规则的算法实现
二十一点游戏是玩家要取得比庄家更大的点数总和,但点数超过二十一点即为爆牌,并输掉注码。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用枚举型数据。这些,我们可以在编程中逐步地添加完善。
随着编程实践的深入,我们的经验也会随之丰富起来。如何写一系列的类去支持各式游戏(包括升级、斗地主等需要用大小王牌的游戏)?如何记录玩家得分?如何支持网络?如何处理网络游戏中玩家离开?如此等等。经一个月、两个月,一年、两年的实践后,你将成为行家里手。
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器