当前位置:文档之家› C++课程设计——五子棋

C++课程设计——五子棋

《面向对象程序设计课程设计》————五子棋学号:201201051738学院:信息科学与工程学院班级:网络工程2班指导老师:学生姓名:日期:2013 年06 月24 日C++课程设计——五子棋一、功能描述设计一个五子棋游戏,实现双人对战,通过鼠标进行操作,具有悔棋功能,可以多次进行游戏,界面美观,有音效。

重要的是按键进行弹窗提醒,由用户进行确认。

二、概要设计窗口注册:向系统注册窗口。

建立窗口:初始化并建立窗口。

处理消息:等待消息传入,调用处理函数。

POINT_类:记录一个点及其处理函数,包括点的位置规范化函数。

Chess类:记录棋子相关信息及其处理函数,包括落子,起子函数。

GameGolbal类:记录一个五子棋游戏的整体信息及其处理函数,包括定义了POINT_类,Chess类的成员,及一些游戏中会用到的整体变量。

主要函数包括如下:窗口刷新函数:通过储存的数据重新绘制窗口。

新游戏函数:对游戏的变量进行初始化的处理。

悔棋函数:对储存数据修改,达到悔棋的目的,会调用窗口刷新函数。

声音播放函数:播放效果声音。

结果判断函数:每次落子后判断结果。

结果显示函数:绘制游戏胜利的结果。

程序运行流程及函数调用关系如下:建立窗口绘制棋子注册窗口悔棋ID_BACK标准化并记录坐标窗口刷新判断并累加操作的棋子判断是否棋子覆盖修改数据调用声音函数关于IDM_ABOUT退出IDM_EXIT鼠标左单击 WM_LBUTTODOWN新的一局 ID_NEW数据初始化窗口菜单命令WM_COMMAND判断胜负判断胜负显示结果等待信息三、详细设计窗口注册:声明窗口结构与类别,对窗口的信息进行描述建立窗口:通过窗口的描述,初始化窗口,显示窗口。

处理消息:等待消息传入,调用处理函数处理信息。

POINT_类:储存棋子在棋盘上的位置,其中的void STAND(int X,int Y)函数负责将输入的点规范为棋盘格上对应位置。

Chess类:棋子类储存棋子信息,包括棋子颜色,阴线阳线上的棋子个数,同时其中包含落子函数,起子函数来对相应的数据进行操作。

落子函数除了对数据进行记录之外,还负责棋子的绘制,绘制棋子时,主要是加载棋子贴图,由于为了使棋子落在边缘时不会遮挡棋盘边缘的纹理,所以对贴图边缘要进行透明化处理,应用的是简单的图形运算,通过异或处理,使图片与背景贴合。

最后悔棋函数用棋子类建立一个二维矩阵,其横纵坐标与棋盘上的位置对应。

GameGolbal类:记录一个五子棋游戏的整体信息及其处理函数,包括定义了POINT_类,Chess类的成员,及一些游戏中会用到的整体变量。

主要函数包括如下:窗口刷新函数:通过储存的数据绘制窗口,屏幕刷新时调用,或者主动调用,比如开始新的一局,悔棋时。

新游戏函数:对游戏的变量进行初始化的处理,之后调用窗口刷新函数。

悔棋函数:对储存数据修改,将棋盘矩阵的相应纵坐标减一,同时调用棋子类二维数组中对应的元素起子函数。

之后调用窗口刷新函数,棋子会在棋盘上消失。

声音播放函数:主要是产生落子声音和胜利的声音,播放声音函数将完成建立DirectSound对象,创建缓存区,设置文件格式,读取文件,播放声音,清空缓存区等一系列操作,完成声音的播放。

结果判断函数:每次落子后调用,通过判断相邻的阴线,阳线上是否存在5 个连续的同色棋子,判断是否一方已胜利,若存在胜利的一方,返回的结果是胜利的一方的整形数据代号,否则返回的是无关整形数据。

结果显示函数:绘制游戏胜利的结果,加载贴图。

弹窗:弹窗的目的主要是对让用户先前做出的行为进行确认,通过调用系统的int MessageBox(HWND hWnd,LPCTSTRlpText,LPCTSTRlpCaption,UINT uType)函数,弹出一个窗口,由用户对输入消息确认,通过返回值获取用户结果,进行相应的操作。

四、效果及存在问题效果图如下:进入后界面落子效果悔棋后结果显示选项菜单帮助菜单弹窗提示关于窗口不足之处1、不能进行存档,学习文件流之后可以进一步改进。

2、不能进行人机对战,这属于策略型游戏AI,我本身对五子棋不是很擅长,确实有一定难度,这方面有时间可以参考相关资料的算法进行改进。

3、弹出的窗口比较简单,只是调用了MessageBox命令,而已,对API窗口的建立和调用以及其他资源文件的加载还是不够了解。

4、因为本程序不需要改变窗口大小,游戏全屏后部分地方为白色,改变之后反而有可能会影响美观,因此可以去掉最大化窗口和改变窗口大小的功能,但我对窗口的建立不是很熟悉,因此暂时还没有去掉。

五、心得体会通过对这个五子棋程序的编写,我在一定的程度上对VC的API可视化编程有了一定的了解,对Windows下程序运行流程有了简单的认识,修正了一些以前对程序运行的错误观念。

在编程的过程中,我认识到编程前对程序整体结构的分析,对各个部分的联系的把握的重要性,否则在编程中就会产生混乱,耽误时间。

同时,编程一定要仔细,在关键的地方或者有疑惑的地方写下备注,以备以后查看或者修改,一个小小的错误就要花上大量的时间去寻找,这是很不值得的。

虽然这个程序对类的应用不是很多,但是仍然可以看到类的应用使程序的编写更加的方便,增加了程序的可移植性。

同时系统自定义的一些类的熟练运用无疑会极大地提高编程速度。

六、附录窗口的注册,初始化,以及消息获取与循环函数有系统自动生成,在此不再显示。

POINT_类:class POINT_{public:int x,y;public:POINT_(){x=0;y=0;}POINT_(int x_,int y_){x=x_;y=y_;}~POINT_ (){}void STAND(int X,int Y){int dis=36,x_=17,y_=18;x=X+(dis+3)/2-x_;y=Y+dis/2-y_;x=x/(dis+3)*(dis+3)+x_;y=y/dis*dis+y_;}};Chess类:class Chess{private:int NS,WE,WN,EN,color;friend class GameGlobal;public:Chess(){NS=0;WE=0;WN=0;EN=0;color=2;}~Chess (){}void down( int c ,HWND hWnd,POINT_ p){HDC hdc,mdc;HBITMAP dra;int X=p.x,Y=p.y;NS=1;WE=1;WN=1;EN=1;color=c;hdc = GetDC(hWnd);mdc = CreateCompatibleDC (hdc);if(c == 0) //黑子{dra = (HBITMAP) LoadImage (NULL,"drabchess.bmp",IMAGE_BITMAP,72,36,LR_LOADFROMFILE) ;}else //白子{dra = (HBITMAP) LoadImage (NULL,"drawchess.bmp",IMAGE_BITMAP,72,36,LR_LOADFROMFILE) ;}SelectObject (mdc,dra);BitBlt (hdc,X-18,Y-18,36,36,mdc,36,0,SRCAND);BitBlt (hdc,X-18,Y-18,36,36,mdc,0,0,SRCPAINT);ReleaseDC (hWnd,hdc);}void up (){NS=0;WE=0;WN=0;EN=0;color=2;}int showcolor (){return color;}};GameGlobal类:class GameGlobal{private:HWND hWnd;HDC mdc,hdc;int color;//颜色int winer;int ax_i,ax_j; //二维矩阵参数HBITMAP hbmp,dra;POINT_ circle[2][16*16/2];Chess chess[16][16]; //棋子类,储存棋子周围信息及其颜色public:GameGlobal(){color=0;ax_i=0;ax_j=0;winer = 2;}GameGlobal(HWND h) {hWnd = h;}~GameGlobal(){}void getHWND(HWND h){hWnd = h;}int getwiner(){return winer;}void changewiner(int w){winer = w;}void back();int downchess(int L,int H);BOOL Result(int x,int y);void ShowResult (int winer);void MyPaint ();void newgame();void PlaySound (int song);};//结果判断函数int GameGlobal::Result(int x,int y){int c,n=15;c=chess[x][y].showcolor();int re;for (re=1;x-re>=0;re++)////////////////////判断横向{if (chess[x-re][y].WE==0||chess[x-re][y].color!=c)break;elsechess[x][y].WE++;}for (re=1;x+re<n;re++){if (chess[x+re][y].WE==0||chess[x+re][y].color!=c)break;elsechess[x][y].WE++;}for (re=1;y-re>=0;re++)////////////////////判断纵向{if (chess[x][y-re].NS==0||chess[x][y-re].color!=c)break;elsechess[x][y].NS++;}for (re=1;y+re<n;re++){if (chess[x][y+re].NS==0||chess[x][y+re].color!=c)break;elsechess[x][y].NS++;}for (re=1;x-re>=0&&y-re>=0;re++)////////////////////判断西北{if (chess[x-re][y-re].WN==0||chess[x-re][y-re].color!=c)break;elsechess[x][y].WN++;}for (re=1;x+re<n&&y+re<n;re++){if (chess[x+re][y+re].WN==0||chess[x+re][y+re].color!=c)break;elsechess[x][y].WN++;}for (re=1;x-re>=0&&y+re<n;re++)////////////////////判断东北{if (chess[x-re][y+re].EN==0||chess[x-re][y+re].color!=c)break;elsechess[x][y].EN++;}for (re=1;x+re<n,y-re>=0;re++){if (chess[x+re][y-re].EN==0||chess[x+re][y-re].color!=c)break;elsechess[x][y].EN++;}if (chess[x][y].NS>4||chess[x][y].WE>4||chess[x][y].WN>4||chess[x][y].EN>4)return c;elsereturn 2;}//窗口刷新函数void GameGlobal::MyPaint (){hdc = GetDC (hWnd);mdc = CreateCompatibleDC (hdc);if (winer != 2){if (winer==1)hbmp=(HBITMAP)LoadImage(NULL,"whbmp.bmp",IMAGE_BITMAP,600,550,LR_LOADFROMFILE) ;elsehbmp=(HBITMAP)LoadImage(NULL,"bhbmp.bmp",IMAGE_BITMAP,600,550,LR_LOADFROMFILE) ;SelectObject (mdc,hbmp);BitBlt (hdc,0,0,600,550,mdc,0,0,SRCCOPY);ReleaseDC (hWnd,hdc);}else{int i;hbmp=(HBITMAP)LoadImage(NULL,"hbmp.bmp",IMAGE_BITMAP,585,543,LR_LOADFROMFILE) ;SelectObject (mdc,hbmp);BitBlt (hdc,0,0,600,600,mdc,0,0,SRCCOPY);dra=(HBITMAP)LoadImage(NULL,"drawchess.bmp",IMAGE_BITMAP,72,36,LR_LOADFROMFILE) ;SelectObject (mdc,dra);for (i=0;i<ax_i;i++){BitBlt (hdc,circle[1][i].x-18,circle[1][i].y-18,36,36,mdc,36,0,SRCAND);BitBlt (hdc,circle[1][i].x-18,circle[1][i].y-18,36,36,mdc,0,0,SRCPAINT);}dra=(HBITMAP)LoadImage(NULL,"drabchess.bmp",IMAGE_BITMAP,72,36,LR_LOADFROMFILE) ;SelectObject (mdc,dra);for (i=0;i<ax_j;i++){BitBlt (hdc,circle[0][i].x-18,circle[0][i].y-18,36,36,mdc,36,0,SRCAND);BitBlt (hdc,circle[0][i].x-18,circle[0][i].y-18,36,36,mdc,0,0,SRCPAINT);}ReleaseDC (hWnd,hdc);}}//结果显示函数void GameGlobal::ShowResult (int winer){hdc = GetDC(hWnd);mdc = CreateCompatibleDC (hdc);if (winer==1)hbmp=(HBITMAP)LoadImage(NULL,"whbmp.bmp",IMAGE_BITMAP,600,550,LR_LOADFROMFILE) ;elsehbmp=(HBITMAP)LoadImage(NULL,"bhbmp.bmp",IMAGE_BITMAP,600,550,LR_LOADFROMFILE) ;SelectObject (mdc,hbmp);BitBlt (hdc,0,0,600,550,mdc,0,0,SRCCOPY);ReleaseDC (hWnd,hdc);}//重新开始函数void GameGlobal::newgame (){for (int i=0;i<16;i++)for (int j=0;j<16;j++)chess[i][j].up();color = 0;winer = 2;ax_i=0;ax_j=0;}int GameGlobal::downchess(int L,int H){int ax_,x,y,dis=36,pd;POINT_ O(17,18);if (color == 1){ax_ = ax_i;ax_i++;}else{ax_ = ax_j;ax_j++;}circle[color][ax_].STAND(L,H);x = (circle[color][ax_].x-O.x)/(dis+3); //对应的棋子类二维数组的中成员y = (circle[color][ax_].y-O.y)/dis;if (chess[x][y].showcolor()==2) //避免重复落子{chess[x][y].down (color,hWnd,circle[color][ax_]);PlaySound (1);color=color==1?0:1;}pd=Game.Result (x,y);return pd;}//悔棋函数void GameGlobal::back(){POINT_ O(17,18);int dis = 36,x,y;if (color == 0){if (ax_i > 0){color = 1;ax_i = ax_i - 1;x = (circle [color][ax_i].x-O.x)/(dis+3); //对应的棋子类二维数组的中成员y = (circle [color][ax_i].y-O.y)/dis;}}else{if (ax_j > 0){color = 0;ax_j = ax_j - 1;x = (circle [color][ax_j].x-O.x)/(dis+3); //对应的棋子类二维数组的中成员y = (circle [color][ax_j].y-O.y)/dis;}}chess[x][y].up();Game.MyPaint ();}//播放声音void GameGlobal::PlaySound (int song){LPDIRECTSOUND pDS;HRESULT result;LPDIRECTSOUNDBUFFER pPBuf;DSBUFFERDESC dsdesc;WAVEFORMATEX pwfmt;WAVEFORMATEX swfmt;MMCKINFO ckRiff;MMCKINFO ckInfo;MMRESULT mmresult;HMMIO hmmio;DWORD size;LPDIRECTSOUNDBUFFER pSBuf;LPVOID pAudio;DWORD bytesAudio;result = DirectSoundCreate( NULL, &pDS, NULL ); //建立DirectSoundif(result != DS_OK)MessageBox(NULL,"","建立DirectSound 对象失败!",MB_OK);result = pDS->SetCooperativeLevel( hWnd, DSSCL_PRIORITY );if(result != DS_OK)MessageBox(NULL,"","设定协调层级失败!",MB_OK);memset( &dsdesc,0, sizeof(dsdesc) );dsdesc.dwSize = sizeof(dsdesc);dsdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;dsdesc.dwBufferBytes = 0;dsdesc.lpwfxFormat = NULL;result = pDS->CreateSoundBuffer( &dsdesc, &pPBuf, NULL );if(result != DS_OK)MessageBox(NULL,"","建立主缓存区失败!",MB_OK);memset( &pwfmt,0, sizeof(pwfmt) );pwfmt.wFormatTag = WAVE_FORMAT_PCM;pwfmt.nChannels = 2;pwfmt.nSamplesPerSec = 44100;pwfmt.wBitsPerSample = 16; //位元pwfmt.nBlockAlign = pwfmt.wBitsPerSample / 8 * pwfmt.nChannels; pwfmt.nAvgBytesPerSec = pwfmt.nSamplesPerSec * pwfmt.nBlockAlign; result = pPBuf->SetFormat(&pwfmt); //设定播放格式if(result != DS_OK)MessageBox(NULL,"","设定播放格式失败!",MB_OK);if (song == 1)hmmio = mmioOpen("1.wav", NULL, MMIO_ALLOCBUF|MMIO_READ );//文件名称elsehmmio = mmioOpen("2.wav", NULL, MMIO_ALLOCBUF|MMIO_READ ); //开启文件if(hmmio == NULL) //判断是否为空MessageBox(NULL,"","档案不存在!",MB_OK);ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E');//设定档案类型mmresult = mmioDescend(hmmio,&ckRiff,NULL,MMIO_FINDRIFF);//if(mmresult != MMSYSERR_NOERROR)MessageBox(NULL,"","档案格式错误!",MB_OK);ckInfo.ckid = mmioFOURCC('f','m','t',' ');mmresult = mmioDescend(hmmio,&ckInfo,&ckRiff,MMIO_FINDCHUNK);//if(mmresult != MMSYSERR_NOERROR)MessageBox(NULL,"","档案格式错误!",MB_OK);if(mmioRead(hmmio,(HPSTR)&swfmt,sizeof(swfmt)) == -1) //读取档案格式MessageBox(NULL,"","读取格式失败!",MB_OK);mmresult = mmioAscend(hmmio,&ckInfo,0);ckInfo.ckid = mmioFOURCC('d','a','t','a');mmresult = mmioDescend(hmmio,&ckInfo,&ckRiff,MMIO_FINDCHUNK);//if(mmresult != MMSYSERR_NOERROR)MessageBox(NULL,"","档案格式错误!",MB_OK);size = ckInfo.cksize; //取得资料大小memset( &dsdesc,0,sizeof(dsdesc)); //清空结构內容dsdesc.dwSize = sizeof(dsdesc); //配置结构大小dsdesc.dwFlags = DSBCAPS_STATIC |DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME| DSBCAPS_GLOBALFOCUS;dsdesc.dwBufferBytes = size; //设定档案大小dsdesc.lpwfxFormat = &swfmt; //设定缓存区格式result = pDS->CreateSoundBuffer( &dsdesc, &pSBuf, NULL );if(result != DS_OK)MessageBox(NULL,"","建立此缓存区失败!",MB_OK);result =pSBuf->Lock (0,size,&pAudio,&bytesAudio,NULL,NULL,NULL);//if(result != DS_OK)MessageBox(NULL,"","锁定缓存区失败!",MB_OK);mmresult = mmioRead(hmmio,(HPSTR)pAudio,bytesAudio);//if(mmresult == -1)MessageBox(NULL,"","读取音频失败!",MB_OK);result =pSBuf->Unlock(pAudio,bytesAudio,NULL,NULL);//解除缓存区if(result != DS_OK)MessageBox(NULL,"","解除锁定缓存区失败失败!",MB_OK);mmioClose(hmmio,0);pSBuf->Play(0,0,0);}七、参考文献《VisualC++游戏编程基础》电子工业出版社肖永亮主编《C++面向对象程序设计》电子工业出版社杜茂康李昌兵曹慧英王永编著。

相关主题