纸牌游戏红心大战设计 ( C语言 )
红心大战是Windows的经典游戏,中国式的红心是拱猪游戏,加入了方块J羊和梅花10 变压器(即俗称加倍)。加大了游戏难度和趣味性。
试制此游戏是准备编制网络版拱猪或红心大战的基础框架,若设计拱猪游戏还要加方块J (J49) 和♣梅花10 (c35) 。
此版本是手机界面的测试版,如单机版就要加入另三家的AI智能出牌设置。
另外桥牌游戏的设置也很相似,游戏开始时多一个叫牌环节,以及桥牌的计分方法。此游戏的通用部分能适用桥牌的设置。
注意:程序界面纸牌显示全是明牌,这是为AI智能出牌算法设计和测试。设计阶段查看和检测算法。游戏程序完成时,主玩家是明牌,其他3家均显示牌背。
游戏规则变更:
Windows的红心大战是玩家单独和PC对抗的,我倾向于中国式拱猪方式,按分组对抗,组合的二人的配合,这样更具有游戏的趣味性和博弈的竞争性。
本文提供了纸牌游戏设计的框架和基础部分,即洗牌,发牌,牌张排序排列显示的基本算法,以及游戏开始时间使用时间的显示。我是用简单的C语言编译器MySpringC在安卓手机上编写的。此是游戏的框架,供游戏设计者参考。
下面是纸牌游戏设计的通用部分:
shuffle_cards ( ){ // 洗牌设计 }
transcards ( ){ //传入牌序号num转为牌点和牌花色,画出牌张 }
cardback ( ){ //发牌时隐藏牌面显示牌背图案 }
start ( ) { //发牌,按SHCD黑桃红心梅花方块 4 花色排序 }
showtim ( ){ //计算和显示使用时间 }
print_t ( ){ //打印标题提示等文字
//** 参数:位置 sx , sy,字串 t$,文字尺寸 tsize }
新开局首攻梅花2 :
//以下是源码:
//***********************************************
//* 纸牌游戏《红心大战》 Version 1.1.0
//* 制作:张纯叔 ( micelu@126.com )
//***********************************************
Canvas cs ; //画布
string sBarDes[10];
int nBarId[10];
float src[4]; //ClearDraw (cls) clear screen
string ss1,ss2,ss3,ss4,ss5,ss6 ; //print , test
string s1,s2,s3,s4,s5,s6,s7,s8,s9 ; //print text
int sx,sy,dx,dy,px,py; //draw
int i,j,n,t,k; //t = times
int num; //select card number
int pn ; //发牌序号数
int pnum[54]; //洗牌后的牌序列(2付牌108)
int cardnum,cardstyle; //牌点牌花色
string cas1,cas2,cas4; //牌点牌花色图案
string cas3,cas5 ; //牌背花色
double Rn; //random number
string t$; //提示文字
int tsize; //textsize
int isdo ; //控制操作: 1 可操作 , 0 不可操作
int context; //canvasProc
int obj;
int id;
int event; //canvasProc
int tim[3]; //get Time & show finished time
int thh,tmm,tss;
int oldhh,oldmm,oldss;
int newhh,newmm,newss;
int mms; //show using time
string hhts,mmts,ssts;
string ts,ts1,ts2;
int sdfn,edfn,ndfn,wdfn ; //得分牌张数
int sdf,edf,ndf,wdf ; //4家计分
int sc0,sc1,sc2,sc3 ; //4家计分累计
int score0,score1; //SN , EW组合*计分
int total0,total1 ; //show score 总分
int wnum ; //切换玩家
int doit ;
int nn,wn,sn,en ; //北西南东牌序号
int spn[13]; //user south 牌序列
int epn[13]; //user east 牌序列
int npn[13]; //user north 牌序列
int wpn[13]; //user west 牌序列
int temp ; //排序
int dhh ; //全红心标记
//wnum , doit 出牌顺序
//fpn=100=新开局首攻c27=club 2
int fpn ; // c27 每圈首攻家 S=0 E=1 N=2 W=3
int fgstyle ; // 每圈主攻花色 S=0 H=1 C=2 D=3
//**EW东西 2家牌型张数分析,南北自家组不分析
//EW东西家AI计算 出牌,SN南北家手控出牌
int SS, SH, SC, SD ;
int ES, EH, EC, ED ;
int NS, NH, NC, ND ;
int WS, WH, WC, WD ;
//♠Q , J49=🔶J , c35=♣10 , c27= 2♣ , 13--25 ❤
int Q11, J49, c35 ;
int uRnd ; // 1 -- 4 各家出牌
int tRnd ; // tRnd=13 一付牌打完,计算分数
// 满4家 uRnd=4 比大小定下圈领攻家
int isplay ; //出牌计数
int c[4] ; //比大小
int ch[4] ; //比大小时有❤
int dd ; //控制出牌
main(){
setDisplay(1);
cs.SetBackground(0,120,0);
cs.Active();
cs.SetProc (context, mycanvasProc);
sBarDes[0]="重新开局";
nBarId[0]=100;
sBarDes[1]="发 牌 ";
nBarId[1]=101;
sBarDes[2]="出 牌 ";
nBarId[2]=102;
sBarDes[3]=" ";
nBarId[3]=103;
sBarDes[4]="退出程序";
nBarId[4]=104;
sBarDes[5]="📱" ;
nBarId[5]=105;
setToolBarHeight(6);
setButtonTextSize(13);
setToolBarBackgroundColor(255,0,120,0);
setButtonColor(255,0,0,240);
setButtonTextColor(255,255,255,0);
setToolBar(100,myToolBarProc,sBarDes,nBarId,6);
setTitle("纸牌游戏-红心大战 ");
//**********
cas3="🦁"; //预设牌背图案
cas4="🐒"; //预设牌面图案
cas5="🦁"; //预设图案
drawcover ();
uRnd=0 ; tRnd=0 ; //start round
score0=0 ; score1=0 ;
total0=0 ; total1=0 ;
while (){}
}//main ()
drawcover (){ // 画启动界面封面版本号
cs.SetColor (255,0,130,0); //back color
cs.DrawRect (0,0,720,1030);
cs.SetColor (255,0,250,0);
cs.DrawRect (50,320,650,326);
cs.SetColor (255,250,0,0);
cs.DrawRect (52,322,648,324);
px=390; py=265;
num=11 ; //11= Q♠
transcards ();
px=300; py=90;
num=13 ; //A
transcards ();
px=390; py=90; //❤K
num=25 ;
transcards ();
px=480; py=120;
num=24 ; // Q
transcards ();
px=570; py=120;
num=23 ; // J
transcards ();
t$="❤" ;
sx=140; sy=220; tsize=60;
print_t ();
t$=cas5 ; //狮子图案
sx=475; sy=350; tsize=120;
print_t ();
t$="纸牌游戏" ;
sx=60; sy=160; tsize=60;
print_t ();
t$="红心大战" ;
sx=60; sy=260; tsize=80;
print_t ();
t$="欢迎加入纸牌游戏团" ;
sx=135; sy=440; tsize=50;
print_t1 ();
cs.SetTextStyle (0); //0正常,1粗体
ss4="Copyright v.1.1.0 micelu@126.com ";
cs.SetTextSize (22);
cs.SetColor (255,250,20,250);
cs.DrawText (ss4,50,360);
cs.Update ();
isdo=0 ;
}//drawcover ()
mycanvasProc (int context,int obj,int id,int event,float x,float y){
if (isdo==0) return ;
isplay=0 ; //待出牌
wnum=doit ;
dd=4 ;
//纸牌区域点击选牌弹出
//isplay 选牌出牌控制
if (x>55&&x<670&&y>50&&y<150&&wnum==2){
nn=(int)((x-55)/45) ; //北家选取牌序号
if (nn>12) nn=12 ; //防出界
if (nn<0) nn=0 ;
cs.SetColor (255,0,140,0);
cs.DrawRect (55,5,675,155);
for (k=0;k<nn;k++){
if (npn[k]> -1) {
num=npn[k] ;
px=k*45+55 ; py=20 ; //调整画牌left,top
transcards () ; } }
num=npn[nn] ;
px=nn*45+55 ; py=40 ; //调整画牌left,top
transcards () ;
dd=2 ; isplay=1 ;
for (k=nn+1;k<13;k++){
if (npn[k]> -1) {
num=npn[k] ;
px=k*45+55 ; py=20 ; //调整画牌left,top
transcards () ; } }
} //北家
if (x>55&&x<670&&y>800&&y<950&&wnum==0){
sn=(int)((x-55)/45) ; //南家选取牌序号
if (sn>12) sn=12 ;
if (sn<0) sn=0 ;
cs.SetColor (255,0,140,0);
cs.DrawRect (55,840,675,990);
for (k=0;k<sn;k++){
if (spn[k]> -1) {
num=spn[k] ;
px=k*45+55 ; py=870 ; //调整画牌left,top
transcards () ; } }
num=spn[sn] ;
px=sn*45+55 ; py=850 ; //调整画牌left,top
transcards () ;
dd=0 ; isplay=1 ;
for (k=sn+1;k<13;k++){
if (spn[k]> -1) {
num=spn[k] ;
px=k*45+55 ; py=870 ; //调整画牌left,top
transcards () ; } }
} //南家
if (x>600&&x<720&&y>190&&y<800&&wnum==1){
en=(int)((y-200)/40) ; //东家选取牌序号
if (en>12) en=12 ;
if (en<0) en=0 ;
cs.SetColor (255,0,140,0);
cs.DrawRect (615,190,720,800);
for (k=0;k<en;k++){
if (epn[k]> -1) {
num=epn[k] ;
px=640 ; py=k*40+200 ; //调整画牌left,top
transcards () ; } }
num=epn[en] ;
px=620 ; py=en*40+200 ; //调整画牌left,top
transcards () ;
dd=1 ; isplay=1 ;
for (k=en+1;k<13;k++){
if (epn[k]> -1) {
num=epn[k] ;
px=640 ; py=k*40+200 ; //调整画牌left,top
transcards () ; } }
} //东家
if (x>5&&x<120&&y>190&&y<800&&wnum==3){
wn=(int)((y-200)/40) ; //西家选取牌序号
if (wn>12) wn=12 ;
if (wn<0) wn=0 ;
cs.SetColor (255,0,140,0);
cs.DrawRect (5,190,105,800);
for (k=0;k<wn;k++){
if (wpn[k]> -1) {
num=wpn[k] ;
px=5 ; py=k*40+200 ; //调整画牌left,top
transcards () ; } }
num=wpn[wn] ;
px=25 ; py=wn*40+200 ; //调整画牌left,top
transcards () ;
dd=3 ; isplay=1 ;
for (k=wn+1;k<13;k++){
if (wpn[k]> -1) {
num=wpn[k] ;
px=5 ; py=k*40+200 ; //调整画牌left,top
transcards () ; } }
} //西家
//**** 4家出牌 ***** play ()
}//mycanvasProc ()
play (){
//**** 4家出牌 ***********
//南家出牌
if (dd>3) return ;
if (wnum==0&&dd==0){
num=spn[sn] ; //南家选取牌序号
c[0]=spn[sn] ; //南家
if (uRnd==0) fgstyle=num/13 ; //主攻花色
px=323 ; py=587 ; //调整画牌left,top
transcards () ;
cs.SetColor (255,0,140,0);
cs.DrawRect (50,840,675,990);
spn[sn]= -1 ;
for (k=0;k<13;k++){
if (spn[k]> -1) {
num=spn[k] ;
px=k*45+55 ; py=870 ; //调整画牌left,top
transcards () ; } }
doit=1 ; isplay=1 ;
change_id () ; //下一家出牌
}
//北家出牌
if (wnum==2&&dd==2){
num=npn[nn] ; //北家选取牌序号
c[2]=npn[nn] ; //北家
if (uRnd==0) fgstyle=num/13 ; //主攻花色
px=323 ; py=292 ; //调整画牌left,top
transcards () ;
cs.SetColor (255,0,140,0);
cs.DrawRect (55,5,675,155);
npn[nn]= -1 ;
for (k=0;k<13;k++){
if (npn[k]> -1) {
num=npn[k] ;
px=k*45+55 ; py=20 ; //调整画牌left,top
transcards () ; } }
doit=3 ; isplay=1 ;
change_id () ; //下一家出牌
}
//东家出牌
if (wnum==1&&dd==1){
num=epn[en] ; //东家选取牌序号
c[1]=epn[en] ; //东家
if (uRnd==0) fgstyle=num/13 ; //主攻花色
px=448 ; py=442 ; //调整画牌left,top
transcards () ;
cs.SetColor (255,0,140,0);
cs.DrawRect (615,190,720,800);
epn[en]= -1 ; //消牌
for (k=0;k<13;k++){
if (epn[k]> -1) {
num=epn[k] ;
px=640 ; py=k*40+200 ; //调整画牌left,top
transcards () ; } }
doit=2 ; isplay=1 ;
change_id () ; //下一家出牌
}
//西家出牌
if (wnum==3&&dd==3){
num=wpn[wn] ; //西家选取牌序号
c[3]=wpn[wn] ; //西家
if (uRnd==0) fgstyle=num/13 ; //主攻花色
px=198 ; py=442 ; //调整画牌left,top
transcards () ;
cs.SetColor (255,0,140,0);
cs.DrawRect (5,190,105,800);
wpn[wn]= -1 ;
for (k=0;k<13;k++){
if (wpn[k]> -1) {
num=wpn[k] ;
px=5 ; py=k*40+200 ; //调整画牌left,top
transcards () ; } }
doit=0 ; isplay=1 ;
change_id () ; //下一家出牌
}
}//play () 出牌
change_id (){ //切换玩家 id SENW
if (isplay==0) return ;
cs.SetColor (255,0,180,0); //clear
cs.DrawCircle (360,490,85);
cs.SetColor (255,0,240,0);
cs.DrawCircle (360,560,11);
cs.DrawCircle (290,490,11);
cs.DrawCircle (360,420,11);
cs.DrawCircle (430,490,11);
//*************
cs.SetFillMode (0);//0不填色,1填色
cs.SetColor (255,0,240,0);
cs.DrawRect (320,575,400,700); // S
cs.DrawRect (445,430,525,555); // E
cs.DrawRect (320,280,400,405); // N
cs.DrawRect (195,430,275,555); // W
cs.SetFillMode (1);//0不填色,1填色
if ( isplay==1 ) {
if (doit==0) {
cs.SetColor (255,250,0,0);
cs.DrawCircle (360,560,11);
t$="南家出牌" ;
sx=305; sy=500; tsize=28;
print_t1();
t$="出牌" ;
sx=332; sy=645; tsize=28;
print_t1();
}
if (doit==1) {
cs.SetColor (255,250,0,0);
cs.DrawCircle (430,490,11);
t$="东家出牌" ;
sx=305; sy=500; tsize=28;
print_t1 ();
t$="出牌" ;
sx=457; sy=500; tsize=28;
print_t1();
}
if (doit==2) {
cs.SetColor (255,250,0,0);
cs.DrawCircle (360,420,11);
t$="北家出牌" ;
sx=305; sy=500; tsize=28;
print_t1 ();
t$="出牌" ;
sx=332; sy=355; tsize=28;
print_t1();
}
if (doit==3) {
cs.SetColor (255,250,0,0);
cs.DrawCircle (290,490,11);
t$="西家出牌" ;
sx=305; sy=500; tsize=28;
print_t1 ();
t$="出牌" ;
sx=207; sy=500; tsize=28;
print_t1();
} } //isplay=1
// 每圈牌出完比大小
if (isplay==1){ uRnd=uRnd+1 ; }
if (uRnd==4) { // 每圈牌出完比大小
compare () ; }
if (tRnd==13) { //整付牌结束计算分数
score () ; //show score
}
Analyse () ; //各家牌型分析
isplay=0 ;
}//change_id ()
// 若拱猪则加 🔶J =J49, ♣10=c35
// if (c[i]==49||c[i]==35) ch[i]=c[i] ;
compare (){
//出牌满4张比大小,得分牌显示,
//定下圈牌起攻, 消去已出的牌
for (i=0;i<4;i++){ ch[i]=0 ; }
for (i=0;i<4;i++){ //已出4张牌面 c[i]
if (c[i]==11) { ch[i]=c[i] ; Q11=6 ; } //got Q11
if (c[i]>12&&c[i]<26) ch[i]=c[i] ; //heart
// 若拱猪则加 🔶J =J49, ♣10=c35
// if (c[i]==49||c[i]==35) ch[i]=c[i] ;
}
if (fgstyle==0) {
for (i=0;i<4;i++){ //不是此花色弃去
if (c[i]>12&&c[i]<26) ch[i]= c[i] ; //❤
if (c[i]>12) c[i]= -1 ;
if (c[i]==0) c[i]=13 ; } //A
wnum=0 ;
if (c[3]>c[2]&&c[3]>c[1]&&c[3]>c[0]) wnum=3 ;
if (c[2]>c[3]&&c[2]>c[1]&&c[2]>c[0]) wnum=2 ;
if (c[1]>c[3]&&c[1]>c[2]&&c[1]>c[0]) wnum=1 ;
} //spade 比大小
if (fgstyle==1) {
for (i=0;i<4;i++){ //是A则加13,不是此花色弃去
if (c[i]>12&&c[i]<26) ch[i]= c[i] ; //❤
if (c[i]<13||c[i]>25) c[i]= 0 ;
if (c[i]==13) c[i]=26 ; } //A
wnum=0 ;
if (c[3]>c[2]&&c[3]>c[1]&&c[3]>c[0]) wnum=3 ;
if (c[2]>c[3]&&c[2]>c[1]&&c[2]>c[0]) wnum=2 ;
if (c[1]>c[3]&&c[1]>c[2]&&c[1]>c[0]) wnum=1 ;
} //heart
if (fgstyle==2) {
for (i=0;i<4;i++){ //是A则加13,不是此花色弃去
if (c[i]>12&&c[i]<26) ch[i]= c[i] ; //❤
if (c[i]<26||c[i]>38) c[i]= 0 ;
if (c[i]==26) c[i]=39 ; } //A
wnum=0 ;
if (c[3]>c[2]&&c[3]>c[1]&&c[3]>c[0]) wnum=3 ;
if (c[2]>c[3]&&c[2]>c[1]&&c[2]>c[0]) wnum=2 ;
if (c[1]>c[3]&&c[1]>c[2]&&c[1]>c[0]) wnum=1 ;
} //club
if (fgstyle==3) {
for (i=0;i<4;i++){ //是A则加13,不是此花色弃去
if (c[i]>12&&c[i]<26) ch[i]= c[i] ; //❤
if (c[i]<39) c[i]= 0 ;
if (c[i]==39) c[i]=52 ; } //A
wnum=0 ;
if (c[3]>c[2]&&c[3]>c[1]&&c[3]>c[0]) wnum=3 ;
if (c[2]>c[3]&&c[2]>c[1]&&c[2]>c[0]) wnum=2 ;
if (c[1]>c[3]&&c[1]>c[2]&&c[1]>c[0]) wnum=1 ;
} //diamand
if (Q11==6) Q11= wnum ; //got Q11 得猪家
//如有猪Q11或红心❤得分牌
for (i=0;i<4;i++){ //heart num=13--25 & Q11
if (ch[i]>0) {
if (wnum==0){
num=ch[i] ; sdfn=sdfn+1; n=sdfn ;
px=n*25+150 ; py=720 ; //S , left,top
transcards () ; }
if (wnum==1){
num=ch[i] ; edfn=edfn+1; n=edfn ;
px=535; py=n*20+265 ; //E , left,top
transcards () ; }
if (wnum==2){
num=ch[i] ; ndfn=ndfn+1; n=ndfn ;
px=n*25+150 ; py=165 ; //N , left,top
transcards () ; }
if (wnum==3){
num=ch[i] ; wdfn=wdfn+1; n=wdfn ;
px=110 ; py=n*20+265 ; //W , left,top
transcards () ; }
} } //heart & Q11
// 调试:已出4家牌,比大小
cs.SetColor (255,0,100,0); //调试: 出牌比大小
//cs.DrawRect (105,770,270,800);
cs.SetTextStyle (0); //0正常,1粗体
cs.SetTextSize (22);
cs.SetColor (255,0,250,0);
s1=intToString (c[0])+" " ;
s2=intToString (c[1])+" " ;
s3=intToString (c[2])+" " ;
s4=intToString (c[3]);
s5=s1+s2+s3+s4 ;
// cs.DrawText (s5,110,790) ;
s6=intToString (wnum) ;
//cs.DrawText (s6,250,790) ;
// cs.Update () ;
cs.SetColor (255,0,140,0); //消除已出牌
cs.DrawRect (320,575,400,700); // S
cs.DrawRect (445,430,525,555); // E
cs.DrawRect (320,280,400,405); // N
cs.DrawRect (195,430,275,555); // W
for (i=0;i<4;i++){ c[i]= -1 ; } //init
cs.SetColor (255,0,100,0); //clear t$
cs.DrawRect (5,160,175,185);
cs.DrawRect (540,810,720,835);
//计算本圈得分牌点分数 (按组合)
// int sdf,edf,ndf,wdf ;
score0=0 ;
score1=0 ;
sdf=sdfn ; edf=edfn ;
ndf=ndfn ; wdf=wdfn ;
if (Q11==0&&sdfn>0) sdf=sdfn+12 ;
if (Q11==1&&edfn>0) edf=edfn+12 ;
if (Q11==2&&ndfn>0) ndf=ndfn+12 ;
if (Q11==3&&wdfn>0) wdf=wdfn+12 ;
score0=sdf+ndf ;
score1=edf+wdf ;
t$="南北:"+intToString (score0)+" "+ss1;
sx=550; sy=830; tsize=24;
print_t ();
t$="东西 :"+intToString (score1)+" "+ss2 ;
sx=10; sy=180; tsize=24;
print_t ();
//下圈发牌 >>
uRnd= -1 ;
tRnd=tRnd+1 ;
doit=wnum ;
change_id ();
}//compare ()
score (){ //每13圈牌出完计算累计得分
cs.SetColor (255,0,100,0); //clear t$
cs.DrawRect (5,160,175,185);
cs.DrawRect (540,810,720,835);
if (sdf==13&&Q11 !=0) sdf= -13 ; //全红
if (ndf==13&&Q11 !=2) ndf= -13 ;
if (edf==13&&Q11 !=1) edf= -13 ;
if (wdf==13&&Q11 !=3) wdf= -13 ;
if (sdf==26) sdf= -26 ; //全得:全红心加Q11
if (ndf==26) ndf= -26 ;
if (edf==26) sdf= -26 ;
if (wdf==26) wdf= -26 ;
//计算和显示累计得分
sc0=sc0+sdf ; sc2=sc2+ndf ;
sc1=sc1+edf ; sc3=sc3+wdf ;
total0=(sc0+sc2)/2 ;
total1=(sc1+sc3)/2 ;
ss1=intToString (total0) ;
ss2=intToString (total1) ;
t$="南北:"+intToString (score0)+" "+ss1;
sx=550; sy=830; tsize=24;
print_t ();
t$="东西 :"+intToString (score1)+" "+ss2 ;
sx=10; sy=180; tsize=24;
print_t ();
//局胜负判别:得分先满或超100分,判负。二方组合
//得分超过100分,分数相同则判平局。
if (total1>99) { t$="南北组胜 !! " ; }
if (total0>99) { t$="东西组胜 !! " ; }
sx=200; sy=400; tsize=64;
print_t1 ();
}//score ()
Analyse() {
//WNE 3家牌型分析,用于AI出牌
int pa ;
ES=0 ; EH=0 ; EC=0 ; ED=0 ;
WS=0 ; WH=0 ; WC=0 ; WD=0 ;
cs.SetColor (255,0,100,0); //clear text
cs.DrawRect (5,990,720,1050);
cs.SetTextStyle (0); //0正常,1粗体
cs.SetTextSize (22);
for (k=0;k<13;k++){ //分析东家牌花色
if (epn[k]> -1) {
pa=epn[k] ;
if (pa<13) ES=ES+1 ;
if (pa>12&&pa<26) EH=EH+1 ;
if (pa>25&&pa<39) EC=EC+1 ;
if (pa>38) ED=ED+1 ; }
}
cs.SetColor (255,0,250,0);
s1=intToString (ES) ;
s2=intToString (EH) ;
s3=intToString (EC) ;
s4=intToString (ED) ;
s5="Eest : "+s1+" , "+s2+" , "+s3+" , "+s4 ;
cs.DrawText (s5,180,1010); //调试
for (k=0;k<13;k++){ //分析西家牌花色
if (wpn[k]> -1) {
pa=wpn[k] ;
if (pa<13) WS=WS+1 ;
if (pa>12&&pa<26) WH=WH+1 ;
if (pa>25&&pa<39) WC=WC+1 ;
if (pa>38) WD=WD+1 ; }
}
cs.SetColor (255,0,250,0);
s1=intToString (WS) ;
s2=intToString (WH) ;
s3=intToString (WC) ;
s4=intToString (WD) ;
s5="West : "+s1+" , "+s2+" , "+s3+" , "+s4 ;
cs.DrawText (s5,10,1010); //调试
ss3="U = "+intToString (uRnd) ;
ss4="T = "+intToString (tRnd) ;
ss5=ss3+" "+ss4 ;
cs.DrawText (ss5,350,1010);
if (fgstyle==0) s8="主攻:♠" ;
if (fgstyle==1) s8="主攻:❤" ;
if (fgstyle==2) s8="主攻:♣" ;
if (fgstyle==3) s8="主攻:🔶" ;
cs.DrawText (s8,600,1010); //调试
cs.Update ();
}//Analyse ()
//纸牌序列:
//cardP num 0 to 12 黑桃 A234..JQK
//cardP num 13 to 25 红心 A234..JQK7
//cardP num 26 to 38 梅花 A234..JQK
//cardP num 39 to 51 方块 A234..JQK
//52 大王 53 小王
// VB6,VS 编程:设picturebox:
// cardP(54)图片数组
// 图片高宽为单张纸牌图大小
// 预制扑克牌序列图片底图,程序启动时按序将
// 每单张图片BitBlt..SRCCOPY到图片数组,
// cardP (i)就是整付牌的图片,洗牌发牌都要用到。
// 本程序简化用 num 序号表示54张牌
//********************
shuffle_cards (){ //洗牌设计
cs.SetColor (255,0,120,0); //backcolor
cs.DrawRect (0,0,720,1030);
cs.Update ();
for (i=0;i<54;i++){ pnum[i]= -1 ; }
pn=0;
t$="纸牌游戏: 洗牌,验牌 " ;
sx=20; sy=60; tsize=28;
print_t ();
//*** * 洗牌 **********************
for (i=0;i<52;i++){ //洗牌, 54 ->108二付牌
ResetPiece: //已生成牌有相同则重新生成
Rn=random()*52 ; //随机洗牌
num=(int )(Rn);
pnum[i]=num ;
for (k=0;k<i; k++){
if (num==pnum[k]) goto ResetPiece ; }
}
for (k=0;k<52;k++){ //显示牌背面图案
px=(k-k/13*13)*50+18;
py=k/13*150+100;
//cardback (); //洗牌后可显示牌背或不显示
num=pnum[k] ;
// transcards (); //用于洗牌查验测试,游戏时注释掉
}
}//shuffle_cards ()
start (){ //开始游戏,每人发13张牌
cs.SetColor (255,0,120,0); //backcolor
cs.DrawRect (0,0,720,1030);
t$="开始 >>>" ;
sx=300; sy=500; tsize=38;
print_t ();
cs.SetColor (255,0,100,0); //screen area
cs.DrawRect (4,3,720,990);
cs.Update () ;
pn= -1 ; //已洗牌,发牌SENW各发13张牌
for (k=0;k<13;k++){ //牌序 pn= 0 to 51
pn=pn+1 ; sn=k ; //南
spn[sn]=pnum[pn];
pn=pn+1 ; en=k ; //东
epn[en]=pnum[pn];
pn=pn+1 ; nn=k ; //北
npn[nn]=pnum[pn];
pn=pn+1 ; wn=k ; //西
wpn[wn]=pnum[pn];
} //发牌定4家牌序号
//**** SENW 四家已发牌排序 ****
for (i=0;i<13;i++){ //SWNE排序
for (j=0;j<i;j++){
if (spn[j]>spn[i]) { //south南
temp=spn[i] ;
spn[i]=spn[j];
spn[j]=temp ; }
if (epn[j]>epn[i]) { //east东
temp=epn[i] ;
epn[i]=epn[j];
epn[j]=temp ; }
if (npn[j]>npn[i]) { //north北
temp=npn[i] ;
npn[i]=npn[j];
npn[j]=temp ; }
if (wpn[j]>wpn[i]) { //west西
temp=wpn[i] ;
wpn[i]=wpn[j];
wpn[j]=temp ; }
} } //SENW排序
for (k=0;k<13;k++){ //SENW排序后显示牌
num=spn[k];
px=k*45+55 ; py=870; //南家
transcards ();
num=epn[k];
px=640 ; py=k*40+200; //东家
cardback () ; // transcards ();
num=npn[k];
px=k*45+55 ; py=20; //北家
transcards ();
num=wpn[k];
px=5 ; py=k*40+200; //西家
cardback () ; // transcards ();
} //显示牌张
//round=round+1 ;
uRnd=0 ; tRnd=0 ;
score0=0 ; score1=0 ;
sdfn=0; edfn=0; ndfn=0; wdfn=0 ;
isdo=1 ;
dhh= -1 ; //init 全红心标记
getTime (tim); //取得系统时间
oldhh=tim[0];
oldmm=tim[1];
oldss=tim[2];
hhts=intToString (tim[0]);
mmts=intToString (tim[1]);
ssts=intToString (tim[2]);
if (oldhh<10)hhts="0"+hhts;
if (oldmm<10)mmts="0"+mmts;
if (oldss<10)ssts="0"+ssts;
ss6=hhts+" : "+mmts+" : "+ssts;
ts="开始 > "+ss6; //show start time
t$=ts ; sx=10 ; sy=830 ; tsize=20 ;
print_t () ;
//新开局fpn=100, 首攻club2,
//后以上局猪家wnum为主攻
doit=Q11 ;
Q11=-1 ;
uRnd=-1 ;
isplay=1 ;
change_id () ; //定玩家出牌序
total0=0 ; total1=0 ; //总分
//分析各家有pn27,新开局则定♧2那家出牌
if (fpn==100){
scan_c27 () ; } //首攻club 2
}//start ()
scan_c27 (){ //新开局首攻club2
for (k=0;k<13;k++){ //查找num27梅花♧2
if (spn[k]==27) {
num=spn[k] ; //南家出牌
px=323 ; py=587 ;
transcards ();
cs.SetColor (255,0,120,0);
cs.DrawRect (55,840,720,990);
spn[k]= -1 ;
for (k=0;k<13;k++){
if (spn[k]> -1) {
num=spn[k] ;
px=k*45+55 ; py=870; //南家
transcards () ; } }
doit=1 ; //wnum=0 ;
goto playc27 ; }
if (epn[k]==27) {
num=epn[k];
px=448 ; py=442; //东家
transcards ();
epn[k]= -1 ;
for (k=0;k<13;k++){
if (epn[k]> -1) {
num=epn[k] ;
px=640 ; py=k*40+200; //东家
transcards () ; } }
doit=2 ; //wnum=1 ;
goto playc27 ; }
if (npn[k]==27) {
num=npn[k] ; //北家出牌
px=323 ; py=292 ;
transcards ();
cs.SetColor (255,0,120,0);
cs.DrawRect (55,10,680,165);
npn[k]= -1 ;
for (k=0;k<13;k++){
if (npn[k]> -1) {
num=npn[k] ;
px=k*45+55 ; py=20; //北家
transcards () ; } }
doit=3 ; //wnum=2 ;
goto playc27 ; }
if (wpn[k]==27) {
num=wpn[k];
px=198 ; py=442; //西家
transcards ();
wpn[k]= -1 ;
for (k=0;k<13;k++){
if (wpn[k]> -1) {
num=wpn[k] ;
px=5 ; py=k*40+200; //西家
transcards () ; } }
doit=0 ; //wnum=3 ;
goto playc27 ; }
} //scan c27
return ;
//***********
playc27 : //首攻club 2
//跳出转下家
uRnd=0 ; tRnd=0 ;
ss1="0" ; ss2="0" ;
sc0=0 ; sc2=0 ;
sc1=0 ; sc3=0 ;
fgstyle=2 ; //♣
isplay=1 ;
change_id () ;
}//scan_c27 ()
transcards (){ //num 转换 cardnum, cardstyle
//牌序号转为牌点和牌花色,传入px,py 画出牌张
//此为游戏通用设置,启动界面画牌
if (num==-1) return ;
if (num>53) num=num-54 ; //二付牌
//**** draw cards 圆角 ****
cs.SetTextStyle (0); //0正常,1粗体
cs.SetColor (255,0,180,0); //框线
cs.DrawRect (px+5,py-8,px+70,py+110);
cs.DrawRect (px,py-3,px+75,py+105);
cs.DrawCircle (px+5,py-3,5);
cs.DrawCircle (px+5,py+105,5);
cs.DrawCircle (px+70,py+105,5);
cs.DrawCircle (px+70,py-3,5);
cs.SetColor (255,250,250,250); //牌面白色
cs.DrawRect (px+6,py-7,px+69,py+109);
cs.DrawRect (px+1,py-2,px+74,py+104);
cs.DrawCircle (px+6,py-2,5);
cs.DrawCircle (px+6,py+104,5);
cs.DrawCircle (px+69,py+104,5);
cs.DrawCircle (px+69,py-2,5);
//******* 画出牌面
cardnum=(num-num/13*13)+1;
cardstyle=num/13;
cas1=intToString(cardnum);
if(cardnum==1) cas1="A";
if(cardnum==11) cas1="J";
if(cardnum==12) cas1="Q";
if(cardnum==13) cas1="K";
if (cardstyle==0) cas2="♠";
if (cardstyle==1) cas2="❤";
if (cardstyle==2) cas2="♣";
if (cardstyle==3) cas2="🔶";
if(cardstyle==0||cardstyle==2) {
cs.SetColor (255,0,0,0); }
if(cardstyle==1||cardstyle==3) {
cs.SetColor (255,250,0,0); }
cs.SetTextSize (30);
n=0;
if (cardnum==10) n=8;
cs.DrawText (cas1,px+14-n,py+20);
cs.DrawText (cas2,px+5,py+50);
cs.SetTextSize (26);
cs.SetTextSize (42); //牌面图
cs.DrawText (cas4,px+14,py+95);
cs.Update ();
}//transcards ()
cardback (){ //draw cards back picture
//发牌时隐藏牌面显示牌背图案
if (num==-1) return ;
//**** draw cards 圆角 ****
cs.SetTextStyle (0); //0正常,1粗体
cs.SetColor (255,0,180,0); //框线
cs.DrawRect (px+5,py-8,px+70,py+110);
cs.DrawRect (px,py-3,px+75,py+105);
cs.DrawCircle (px+5,py-3,5);
cs.DrawCircle (px+5,py+105,5);
cs.DrawCircle (px+70,py+105,5);
cs.DrawCircle (px+70,py-3,5);
cs.SetColor (255,0,150,150); //牌背色
cs.DrawRect (px+6,py-7,px+69,py+109);
cs.DrawRect (px+1,py-2,px+74,py+104);
cs.DrawCircle (px+6,py-2,5);
cs.DrawCircle (px+6,py+104,5);
cs.DrawCircle (px+69,py+104,5);
cs.DrawCircle (px+69,py-2,5);
cs.SetTextSize(50);
cs.DrawText (cas3,px+8,py+70); //show 背花
cs.Update ();
}//cardback ()
showtime (){ //计算使用时间
getTime (tim);
newhh=tim[0];
newmm=tim[1];
newss=tim[2];
hhts=intToString (tim[0]);
mmts=intToString (tim[1]);
ssts=intToString (tim[2]);
if (newhh<10)hhts="0"+hhts; //格式00:00:00
if (newmm<10)mmts="0"+mmts;
if (newss<10)ssts="0"+ssts;
mms=((newhh-oldhh)*3600)+
((newmm-oldmm)*60)+((newss-oldss));
if (mms<0) mms=mms+864000;
thh=mms/3600;
tmm=(mms-thh*2600)/60;
tss=mms-thh*3600-tmm*60;
ss1=intToString (tmm)+" 分 "+intToString (tss)+" 秒";
ss2=hhts+" : "+mmts+" : "+ssts;
ts1= "完成 > "+ss2; //输出
ts2= "用时 > "+ss1; //输出
}//showtime ()
print_t (){ //打印标题提示等文字
//** 参数 sx,sy, ss0=$, tsize=text size
cs.SetFillMode (1);//0不填色,1填色
cs.SetTextStyle (0); //0正常,1粗体
cs.SetTextSize (tsize);
cs.SetColor (255,0,200,60);
cs.DrawText (t$,sx+2,sy+3);
cs.SetColor (255,250,120,0);
cs.DrawText (t$,sx,sy);
cs.SetFillMode (0);//0不填色,1填色
cs.SetColor (255,250,250,0);
cs.DrawText (t$,sx,sy);
cs.SetFillMode (1);//0不填色,1填色
cs.Update ();
}//print _t ()
print_t1 (){ //打印标题提示等文字
//** 参数 sx,sy, ss0=$, tsize=text size
cs.SetFillMode (1);//0不填色,1填色
cs.SetTextStyle (1); //0正常,1粗体
cs.SetTextSize (tsize);
cs.SetColor (255,0,20,100);
cs.DrawText (t$,sx+3,sy+4);
cs.SetColor (255,250,250,0);
cs.DrawText (t$,sx,sy);
cs.SetFillMode (0);//0不填色,1填色
cs.SetColor (255,250,0,0);
cs.DrawText (t$,sx,sy);
cs.SetFillMode (1);//0不填色,1填色
cs.Update ();
}//print _t1 ()
myToolBarProc(int nBtn,int nContext){
if(nBtn==100){ // 重新开局
setDisplay (1);
shuffle_cards () ; //洗牌
fpn=100 ; //首攻club 2
start () ; //发牌
}
if(nBtn==101){ // 每局发牌
setDisplay (1);
shuffle_cards () ; //洗牌
fpn=0 ;
start () ; //发牌
}
if(nBtn==102){ //切换玩家
setDisplay (1);
play () ; //change_id () ;
}
if(nBtn==103){//
setDisplay (1);
//test (); //测试
}
if(nBtn==104){//退出程序
clearOutput();
cs.ClearDraw (0,src);
setDisplay (0);
exit (0);
}
if(nBtn==105){//@About
setDisplay (1);
drawcover ();
}
}//myToolBar ()
// 纸牌游戏《红心大战》V.1.1.0 设计
// 2023年 1 月 10日完成于上海
//**** End ****