纸牌游戏洗牌发牌排序算法设计
本文提供纸牌游戏设计制作的基础部分,即洗牌,发牌,牌张排序排列显示的算法。
以及游戏开始时间使用时间的显示。我是用简单的C语言编译器MySpringC在安卓手机上编写的。此是游戏的框架,供游戏设计者参考。
下面是纸牌游戏设计的通用部分:
shuffle_cards ( ){ // 洗牌设计 }
transcards ( ){ //传入牌序号num转为牌点和牌花色,画出牌张 }
cardback ( ){ //发牌时隐藏牌面显示牌背图案 }
showtimes ( ){ //计算和显示使用时间 }
print_t ( ){ //打印标题提示等文字
//** 参数:位置 sx , sy,字串 t$,文字尺寸 tsize }
//以下是样例的源码:
//************************************
//* 纸牌游戏《 □□□□ 》 Version 1.1.0
//* 制作:张纯叔 ( micelu@126.com )
//************************************
Canvas cs ; //画布
string sBarDes[10];
int nBarId[10];
float src[4]; //ClearDraw (cls) clear screen
string s,ss,ss1,ss2,ss3 ; //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 p1,p2,c1,c2,px1,py1,px2,py2 ; //找配对
int pnum[54]; //洗牌后的牌序列(2付牌)
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 round ;
int score0,score1,total0,total1 ; //show score
int mode ; //设置卡牌花色
int wnum ; //切换玩家 2-4
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 ; //排序
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 ();
round=0 ; //start round
score0=0 ; score1=0 ;
total0=0 ; total1=0 ;
//isdo=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♠ , 27= 2♣ , 13--25 ❤
transcards ();
px=300; py=90;
num=13 ;
transcards ();
px=390; py=90; //❤
num=25 ;
transcards ();
px=480; py=120;
num=24 ;
transcards ();
px=570; py=120;
num=23 ;
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粗体
ss="Copyright v.1.1.0 micelu@126.com ";
cs.SetTextSize (22);
cs.SetColor (255,250,20,250);
cs.DrawText (ss,50,360);
cs.Update ();
isdo=0 ;
}//drawcover ()
mycanvasProc (int context,int obj,int id,int event,float x,float y){
if (isdo==0) return ;
//纸牌区域点击切换玩家
if (x>150&&x<570&&y>810&&y<950&&wnum==1){
sn=(int)((x-158)/80) ; //纸牌排列坐标
num=spn[sn] ;
p1=num ;
c1=(num-num/13*13) ;
px1=sn*80+158 ; //调整画牌left,top
py1=815 ;
} //南家
}//mycanvasProc ()
score (){
//显示局数,得分
cs.SetColor(255,0,120,0);
cs.DrawRect (0,35,155,250); // clear print
cs.DrawRect (0,730,155,930); // clear print
t$=ts ; //show start time
sx=15; sy=25; tsize=24;
print_t ();
t$="第 "+intToString (round)+" 局" ;
sx=15; sy=70; tsize=32;
print_t1 ();
t$="总分:"+intToString (total0) ; //北家
sx=15; sy=115; tsize=26;
print_t ();
t$="得分:"+intToString (score0) ;
sx=15; sy=160; tsize=26;
print_t ();
t$="总分:"+intToString (total1) ; //南家
sx=15; sy=845; tsize=26;
print_t ();
t$="得分:"+intToString (score1) ;
sx=15; sy=890; tsize=26;
print_t ();
cs.Update () ;
showtimes () ; //finished & show times
t$=ts1 ;
sx=200; sy=490; tsize=40;
print_t ();
t$=ts2 ;
sx=200; sy=530; tsize=40;
print_t ();
//print 最后得分
t$="总分:"+intToString (total0) ;
sx=15; sy=115; tsize=26;
print_t ();
t$="得分:"+intToString (score0) ;
sx=15; sy=160; tsize=26;
print_t ();
t$="总分:"+intToString (total1) ;
sx=15; sy=845; tsize=26;
print_t ();
t$="得分:"+intToString (score1) ;
sx=15; sy=890; tsize=26;
print_t ();
isdo=0 ;
}//score ()
//纸牌序列:
//cardP num 0 to 12 黑桃 A234..JQK
//cardP num 13 to 25 红心 A234..JQK
//cardP num 26 to 38 梅花 A234..JQK
//cardP num 39 to 51 方块 A234..JQK
//52 大王 53 小王
// VB6,VS2007 编程:设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 ();
//**** 洗牌 **********************
//**** 无大小王 52,有王54,二付牌108
//如用2付牌可参考本站博文《小猫钓鱼》
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] ; //num 已洗牌序
// transcards (); //用于洗牌查验测试,游戏时注释掉
}
}//shuffle_cards ()
start (){ //开始游戏,每人发13张牌
cs.SetColor (255,0,120,0); //backcolor
cs.DrawRect (0,0,720,1030);
t$="纸牌游戏 >> 开局" ;
sx=250; sy=500; tsize=30;
print_t ();
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++){ //SENW排序
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 ; //set position
py=830; //南家
transcards ();
num=epn[k];
px=640 ; //set position
py=k*40+200; //东家
transcards ();
num=npn[k];
px=k*45+55 ; //set position
py=50; //北家
transcards ();
num=wpn[k];
px=5 ; //set position
py=k*40+200; //西家
transcards ();
}
round=round+1 ;
score0=0 ; score1=0 ;
isdo=1 ;
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;
ss2=hhts+" : "+mmts+" : "+ssts;
ts="开始 > "+ss2; //show start time
cs.SetColor (255,0,220,0); //框线
cs.SetTextSize(20);
cs.DrawText (ts,10,25) ;
cs.Update ();
// change_id () ; //玩家
}//start ()
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,250,160,0); //框线
cs.SetColor (255,0,80,0); //框线
cs.DrawRect (px+10,py-10,px+68,py+115);
cs.DrawRect (px,py-1,px+79,py+104);
cs.DrawCircle (px+10,py,9);
cs.DrawCircle (px+10,py+105,9);
cs.DrawCircle (px+69,py+105,9);
cs.DrawCircle (px+69,py,9);
cs.SetColor (255,250,250,250); //牌面白色
cs.DrawRect (px+13,py-8,px+65,py+113);
cs.DrawRect (px+2,py,px+76,py+103);
cs.DrawCircle (px+12,py+2,10);
cs.DrawCircle (px+12,py+103,10);
cs.DrawCircle (px+66,py+103,10);
cs.DrawCircle (px+66,py+2,10);
//******* 画出牌面
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.SetColor (255,250,160,0); //框线
cs.DrawRect (px+10,py-10,px+68,py+115);
cs.DrawRect (px,py-1,px+79,py+104);
cs.DrawCircle (px+10,py,9);
cs.DrawCircle (px+10,py+105,9);
cs.DrawCircle (px+69,py+105,9);
cs.DrawCircle (px+69,py,9);
cs.SetColor (255,0,180,200); //牌背色
cs.DrawRect (px+13,py-8,px+65,py+113);
cs.DrawRect (px+2,py,px+76,py+103);
cs.DrawCircle (px+12,py+2,10);
cs.DrawCircle (px+12,py+103,10);
cs.DrawCircle (px+66,py+103,10);
cs.DrawCircle (px+66,py+2,10);
cs.SetTextSize(50);
cs.DrawText (cas3,px+8,py+70); //show 背花
cs.Update ();
}//cardback ()
showtimes (){ //计算使用时间
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; //输出
}//showtimes ()
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,0,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 () ; //洗牌
}
if(nBtn==101){ // 开始摸鱼
setDisplay (1);
shuffle_cards () ; //洗牌
start () ; //开始
}
if(nBtn==102){ //换牌
setDisplay (1);
// deal () ;
}
if(nBtn==103){//
setDisplay (1);
}
if(nBtn==104){//退出程序
clearOutput();
cs.ClearDraw (0,src);
setDisplay (0);
exit (0);
}
if(nBtn==105){//@About
setDisplay (1);
drawcover ();
}
}//myToolBar ()
//**** End ****