近来和女朋友去打电玩发现了一个很好玩的游戏。规划是用电脑发给你的牌放在屏幕的空白处尽量使它们的和为21每个空白处可入5张牌。由于近来在学习游戏制作,感到这个游戏容易实现。回家后用有VC作了起。用程序来作扑克游戏的难点在于如何确定扑克的面值和花色。在本程序中我是把每个扑克的图像按顺序排列并加以编号,扑克的花色同样也加以编号。并用一个公式计算编号大于13的扑克图像的面值公式如下:扑克图像的编号-13*扑克花色的编号就可以得出该扑克图像编号的扑克的面值。例如扑克图像编号为15,花色的编号为1用公式15-13*1得出该扑克图像编号的扑克的面值是红桃2。
现将实现过程写出以。
用VC建立一个Win32 Application工程。在工程中加入stdafx.h文件在其中加入#include<afxwin.h>和 #include<math.h>。在工程加入资源文件。使用Alt+F7调出设置对话框。在General下的Microsoft Foundation Classes选择use MFX inaStatic Libarary。为工程建立一个窗口类。在窗口类的头文件中把构造函数声明修改为public,例如:protected: cbruceFrame()改为public:cbruceFrame()。在窗口类的头文件中定义变量:
CDC *mdc,*bgmdc; CBitmap *bitmap,*bgmap; RECT rect; CFont newf,*oldf; 自定义一个函数:
void fp(); 为工程定义全局数组变量:
struct pk //扑克基本信息 { int pkbmp; int h; int f; }pkdata[52];
其中pkbmp用来存放扑克图像编号,h用来保存扑克的花色编码、f用来保存此扑克是否也发出过。 其中扑克图像编号从1--52,扑克花色编码黑为0;红桃为1;梅花为2;方块为3。
struct pkno { int pkbmpo; int ho; }a[5],b[5],c[5],d[5]; 为工程定义全局变量:
int an=0,bn=0,cn=0,dn=0,ao=0,bo=0,co=0,ddo=0,j,m=3;
其中后加n的为各块的计数器,后加o的为各块的计分数,j为暂存变量,m为pass的次数。
定义两个字符数组:
f[255],cs[255];
在构造函数中加入下面程序代码:(cbruceFrame.cpp中)
int i; Create(NULL,"扑克游戏"); CClientDC dc(this); int width=dc.GetDeviceCaps(HORZRES); //取得屏幕区宽 int height=dc.GetDeviceCaps(VERTRES); //取得屏幕区高 GetWindowRect(&rect); //取得窗口区矩形大小 width=(width-(rect.right-rect.left))/2; height=(height-(rect.bottom-rect.top))/2; MoveWindow(width,height,500,450,true); bgmdc=new CDC; mdc=new CDC; //建立内存DC对象 bgmap=new CBitmap; ffor(i=1;i<53;i++) { pkdata[i-1].pkbmp=i; if((i-1)<13) pkdata[i-1].h=0;//根据扑克图像编号设置扑克的花色编码 if((i-1)>=13&&(i-1)<26) pkdata[i-1].h=1; if((i-1)>=26&&(i-1)<39) pkdata[i-1].h=2; if((i-1)>=39&&(i-1)<52) pkdata[i-1].h=3; pkdata[i-1].f=0; }//将标志设为没有发出
bgmdc->CreateCompatibleDC(&dc); mdc->CreateCompatibleDC(&dc); //转换成与dc相容的DC bgmap->LoadBitmap(BG); bgmdc->SelectObject(bgmap); newf.CreateFont(20,10,0,0,0,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_CHARACTER_PRECIS, CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH|FF_MODERN,"楷体"); /设置字体 CPoint *p=new CPoint(50,35); ClientToScreen(p); ::SetCursorPos(p->x,p->y); //设置鼠标的范围 srand((unsigned)time(NULL)); //发牌 t=rand()%52; bitmap=new CBitmap; bitmap->LoadBitmap(pkdata[t].pkbmp); mdc->SelectObject(bitmap); dc.BitBlt(10,10,100,100,mdc,0,0,SRCCOPY); pkdata[t].f=1; j=(t+1); for(i=0;i<5;i++) { a[i].pkbmpo=c[i].pkbmpo=b[i].pkbmpo=d[i].pkbmpo=0; } 使用插入---->新建类建立应用程序类,在Class type对话框中选择Generic Class在Name中输入类名(cbruceApp)在Base class(es)中的Derived From中输入CWinApp。在cbruceApp.h文件中加入程序初始函数的声明:
public:BOOL Initinstance(); 在cbruceApp.cpp文件中加入如下代码:
cbruceApp bruce; CBruceApp::InitInstance() { m_pMainWnd= new CBruceFrame; m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); return true; } 这样工程的框架就组建完成了。下一步加入具体代码。
为工程加入WM_PAINT消息实现绘图:
oldf=dc.SelectObject(&newf); //选择新新字体。 dc.SetTextColor(RGB(0,255,0)); //设置文本颜色 dc.SetBkColor(1); //设置背景颜色 GetClientRect(&rect); dc.BitBlt(0,0,rect.right,rect.bottom,bgmdc,0,0,SRCCOPY);//载入背景图 dc.BitBlt(10,10,100,100,mdc,0,0,SRCCOPY); //载入扑克图像 dc.BitBlt(10,190,110,190,bgmdc,0,0,WHITENESS); //绘制空白处 dc.BitBlt(130,190,110,190,bgmdc,0,0,WHITENESS); dc.BitBlt(250,190,110,190,bgmdc,0,0,WHITENESS); dc.BitBlt(370,190,110,190,bgmdc,0,0,WHITENESS); if(an>0) { int i; for(i=0;i<=an;i++) { if(a[i].pkbmpo!=0) { bitmap=new CBitmap; bitmap->LoadBitmap(a[i].pkbmpo); mdc->SelectObject(bitmap); dc.BitBlt(15,195+i*20,100,100,mdc,0,0,SRCCOPY); } } if(ao==21) { dc.TextOut(5,150,"恭喜您赢了!"); } if(ao>21) { dc.TextOut(5,150,"已超出21分!"); } if(ao<21) { sprintf(f,"数分为:%d",ao); dc.TextOut(5,150,f); } } if(bn>0) { int i; for(i=0;i<=bn;i++) { if(b[i].pkbmpo!=0) { bitmap=new CBitmap; bitmap->LoadBitmap(b[i].pkbmpo); mdc->SelectObject(bitmap); dc.BitBlt(135,195+i*20,100,100,mdc,0,0,SRCCOPY); } } if(bo==21) { dc.TextOut(135,150,"恭喜您赢了!"); } if(bo>21) { dc.TextOut(135,150,"已超出21分!"); } if(bo<21) { sprintf(f,"数分为:%d",bo); dc.TextOut(135,150,f); } } if(cn>0) { int i; for(i=0;i<=cn;i++) { if(c[i].pkbmpo!=0) { bitmap=new CBitmap; bitmap->LoadBitmap(c[i].pkbmpo); mdc->SelectObject(bitmap); dc.BitBlt(255,195+i*20,100,100,mdc,0,0,SRCCOPY); } } if(co==21) { dc.TextOut(255,150,"恭喜您赢了!"); } if(co>21) { dc.TextOut(255,150,"已超出21分!"); } if(co<21) { sprintf(f,"数分为:%d",co); dc.TextOut(255,150,f); } } if(dn>0) { int i; for(i=0;i<=dn;i++) { if(d[i].pkbmpo!=0) { bitmap=new CBitmap; bitmap->LoadBitmap(d[i].pkbmpo); mdc->SelectObject(bitmap); dc.BitBlt(375,195+i*20,100,100,mdc,0,0,SRCCOPY); } } if(ddo==21) { dc.TextOut(375,150,"恭喜您赢了!"); } if(ddo>21) { dc.TextOut(375,150,"已超出21分!"); } if(ddo<21) { sprintf(f,"数分为:%d",ddo); dc.TextOut(375,150,f); } } dc.TextOut(150,50,"F2重新开始游戏!"); sprintf(cs,"右键PASS当前牌:%d",m); dc.TextOut(150,100,cs); dc.SelectObject(oldf); 为工程加入WM_LBUTTONDOWN消息:
CClientDC dc(this); //建立客户区DC int zn; //用来存放坐标 oldf=dc.SelectObject(&newf); dc.SetTextColor(RGB(0,255,0)); dc.SetBkColor(1); zn=(int)floor(point.x/10); //计算作标值 if(zn<=11) //在第一个空白处 { if((ao<21)&&(an<5)) { bitmap=new CBitmap; //加载扑克图像 bitmap->LoadBitmap(pkdata[t].pkbmp); dc.BitBlt(15,195+an*20,100,100,mdc,0,0,SRCCOPY); a[an].pkbmpo=j; //扑克面值 ao=j-(13*pkdata[t].h))+ao; //计算分数 if(ao==21) { dc.TextOut(5,150,"恭喜您赢了!"); } if(ao>21) { dc.TextOut(5,150,"已超出21分!"); } if(ao<21) { sprintf(f,"数分为:%d",ao); dc.TextOut(5,150,f); an++; } fp(); } else { Beep(150,100); //错误报警 } }
if(zn>11&&zn<=23) { if((bo<21)&&(bn<5)) { bitmap=new CBitmap; bitmap->LoadBitmap(pkdata[t].pkbmp); mdc->SelectObject(bitmap); dc.BitBlt(135,195+bn*20,100,100,mdc,0,0,SRCCOPY); b[bn].pkbmpo=j; bo=j-(13*pkdata[t].h))+bo; if(bo==21) { dc.TextOut(135,150,"恭喜您赢了!"); } if(bo>21) { dc.TextOut(135,150,"已超出21分!"); } if(bo<21) { sprintf(f,"数分为:%d",bo); dc.TextOut(135,150,f); bn++; } fp(); } else { Beep(150,100); } }
if(zn>23&&zn<=35) { if((co<21)&&(cn<5)) { bitmap=new CBitmap; bitmap->LoadBitmap(pkdata[t].pkbmp); dc.BitBlt(255,195+cn*20,100,100,mdc,0,0,SRCCOPY); c[cn].pkbmpo=j; co=j-(13*pkdata[t].h))+co; if(co==21) { dc.TextOut(255,150,"恭喜您赢了!"); } if(co>21) { dc.TextOut(255,150,"已超出21分!"); } if(co<21) { sprintf(f,"数分为:%d",co); dc.TextOut(255,150,f); cn++; } fp(); } else { Beep(150,100); }
}
if(zn>35&&zn<=47) { if((ddo<21)&&(dn<5)) { bitmap=new CBitmap; bitmap->LoadBitmap(pkdata[t].pkbmp); mdc->SelectObject(bitmap); dc.BitBlt(375,195+dn*20,100,100,mdc,0,0,SRCCOPY); d[dn].pkbmpo=j; ddo=j-(13*pkdata[t].h)+ddo; if(ddo==21) { dc.TextOut(375,150,"恭喜您赢了!"); } if(ddo>21) { dc.TextOut(375,150,"已超出21分!"); } if(ddo<21) { sprintf(f,"数分为:%d",ddo); dc.TextOut(375,150,f); dn++; } fp(); } else { Beep(150,100); } } 为工程加入WM_KEYDOWN消息:
CClientDC dc(this); int i; if(nChar==VK_F2) //当玩家按下F2键时,重新开始游戏。使之复位。 { oldf=dc.SelectObject(&newf); dc.SetTextColor(RGB(0,255,0)); dc.SetBkColor(1); GetClientRect(&rect); dc.BitBlt(0,0,rect.right,rect.bottom,bgmdc,0,0,SRCCOPY); dc.BitBlt(10,10,100,100,mdc,0,0,SRCCOPY); dc.BitBlt(10,190,110,190,bgmdc,0,0,WHITENESS); dc.BitBlt(130,190,110,190,bgmdc,0,0,WHITENESS); dc.BitBlt(250,190,110,190,bgmdc,0,0,WHITENESS); dc.BitBlt(370,190,110,190,bgmdc,0,0,WHITENESS); an=bn=cn=dn=0; ao=bo=co=ddo=0; for(i=0;i<52;i++) { pkdata[i].f=0; } srand((unsigned)time(NULL)); //发牌 t=rand()%52; bitmap=new CBitmap; bitmap->LoadBitmap(pkdata[t].pkbmp); mdc->SelectObject(bitmap); dc.BitBlt(10,10,100,100,mdc,0,0,SRCCOPY); pkdata[t].f=1; j=(t+1); m=3; dc.TextOut(150,50,"F2重新开始游戏!"); sprintf(cs,"右键PASS当前牌:%d",m); dc.TextOut(150,100,cs); for(i=0;i<5;i++) { a[i].pkbmpo=c[i].pkbmpo=b[i].pkbmpo=d[i].pkbmpo=0; } } dc.SelectObject(oldf); 为工程加入WM_RBUTTONDOWN消息(PASS当前牌):
CClientDC dc(this); oldf=dc.SelectObject(&newf); dc.SetTextColor(RGB(0,255,0)); dc.SetBkColor(1); if(m>0) { fp(); m--; sprintf(cs,"右键PASS当前牌:%d",m); dc.TextOut(150,100,cs); } else { Beep(150,100); } dc.SelectObject(oldf); 编辑fp函数(发牌):
CClientDC dc(this); srand((unsigned)time(NULL));
loop1: t=rand()%52; if(pkdata[t].f!=1) { bitmap=new CBitmap; bitmap->LoadBitmap(pkdata[t].pkbmp); mdc->SelectObject(bitmap); dc.BitBlt(10,10,100,100,mdc,0,0,SRCCOPY); pkdata[t].f=1; j=(t+1); } else { goto loop1; } 这样一个小的扑克游戏就成完。我不并不是什么名校毕业的。也没有上过大学。只是自己非常喜欢编程,一切都是自学的。所以有错误的地方请大家指出。最后我想说句话:兴趣是你最好的老师,没有兴趣你是学不好一样东西。编程并没有什么难,只要努力你也能编出好的程序来的。 本程序在Windows 2000+VC6.0中编译通过。
|