为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

双人版俄罗斯方块游戏实验报告

2017-09-01 31页 doc 133KB 34阅读

用户头像

is_215732

暂无简介

举报
双人版俄罗斯方块游戏实验报告双人版俄罗斯方块游戏实验报告 西安科技大学 《Visual C++程序设计》 实验报告 题 目 双人版俄罗斯方块游戏 院、系(部) 计算机科学与技术学院 专业及班级 软件工程1101班 姓 名 张XX 日 期 2012/12/14 一( 功能需求: 1. 能进行双人模式: 这是程序的主要功能。 2. 能进行下一砖块的预测: 这也是俄罗斯方块游戏的基本功能,可以在这个基础上进行扩展其他功能,如不同 于经典模式的砖块显示等来增加难度。 二( 总体设计计: 1.矩形框类的设计: 设计CBin类描述Tetri...
双人版俄罗斯方块游戏实验报告
双人版俄罗斯方块游戏实验 西安科技大学 《Visual C++程序设计》 实验报告 题 目 双人版俄罗斯方块游戏 院、系(部) 计算机科学与技术学院 专业及班级 软件1101班 姓 名 张XX 日 期 2012/12/14 一( 功能需求: 1. 能进行双人模式: 这是程序的主要功能。 2. 能进行下一砖块的预测: 这也是俄罗斯方块游戏的基本功能,可以在这个基础上进行扩展其他功能,如不同 于经典模式的砖块显示等来增加难度。 二( 总体设计计: 1.矩形框类的设计: 设计CBin类描述Tetris游戏的矩形框,用image的二维数组来描述这 。 个矩形框。设置不同的值显示不同颜色的矩形,若没有砖块则为02.砖块的设计: 设计CBrick抽象类来设计砖块,应用多态性的原理,其他不同类型的砖 块类继承CBrick,来设计不同的砖块。 3.砖块在面板中的显示设计: 在视图类中设计并显示砖块。 三( 详细设计: 1.矩形框类的设计: 设计CBin类描述Tetris游戏的矩形框,用image的二维数组来描述这个矩形框。设置不同的值显示不同颜色的矩形,若没有砖块则为0。 CBin类的五个成员函数: (1) CBin(unsigned int unsigned int h) 构造函数,用来初始化数据成员,width和height,并为image 分配空间并初始化。 (2) ~CBin() 析构函数,删除在构造函数中为image分配的空间。 (3) Void getImage(unsigned char*destImage) 将image的数据拷贝到destImage,你可以假设destimage指向的 空间足够容纳image的空间。 (4) Void setImage(unsigned char**srcImage) 把srcImage中的数据拷贝到image,你可以假设srcImage是一个 合法的指针。 (5) Unsigned int removeFullLines() 检查image,如果任何一行完全填满,则删除这一行,并让上面一 行的数据下移,返回删除的总行数。 设计代码如下: class CBin { private: unsigned char** image; unsigned int width; unsigned int height; public: CBin(unsigned int w, unsigned int h); ~CBin(); unsigned int getWidth() { return width; }; unsigned int getHeight() { return height; }; void getImage(unsigned char** destImage); void setImage(unsigned char** srcImage); unsigned int removeFullLines(); }; CBin::CBin(unsigned int w, unsigned int h) { width=w; height=h; image = new unsigned char* [height]; for (unsigned int i = 0; i0; m--) { for (j=0; j>,通过设置映射到游戏矩形的二维数组binImage, 设置砖块的颜色,这里假设binimage是一个合法的大侠合适的二 维数组。 (7) void operator>>(unsigned char *binimage) (8) putAtTop(unsigned int newOrient,unsigned int newPosX) 通过设置砖块特定点的Y坐标(posY)是的砖块位于矩形的最上方, 砖块的X坐标和砖块的状态由newPosX和newOrient确定。注意 posY的值依赖于砖块的状态 (9) putAtMid(unsigned int newOrient,unsigned int newPosX) 与putAtTop一致,只是将坐标设置在面板中间。 下面是一个具体的砖块设计代码: class CCBrick : public CBrick { public: int shiftLeft(CBin* bin); int shiftRight(CBin* bin); int shiftDown(CBin* bin); int rotateClockwise(CBin* bin); int checkCollision(CBin* bin); void operator>>(unsigned char** binImage); void putAtTop(int newOrient, int newPosX); void putAtMid(int newOrient, int newPosX); }; ///////////////////////// int CCBrick::shiftLeft(CBin* bin) { int posX; posX=getPosX(); setPosX(posX-1); if (checkCollision(bin)== 0) { setPosX(posX); return 0; } return 1; } int CCBrick::shiftDown(CBin* bin) { int posY; posY=getPosY(); setPosY(posY+1); if (checkCollision(bin)== 0) { setPosY(posY); return 0; } return 1; } int CCBrick::shiftRight(CBin* bin) { int posX; posX=getPosX(); setPosX(posX+1); if (checkCollision(bin)==0) { setPosX(posX); return 0; } return 1; } int CCBrick::rotateClockwise(CBin* bin) { int orientation,oldOrientation; orientation=getOrientation(); oldOrientation=orientation; if (orientation==3) orientation=0; else orientation=orientation+1; setOrientation(orientation); if (checkCollision(bin)== 0) { setOrientation(oldOrientation); return 0; } return 1; } int CCBrick::checkCollision(CBin* bin) { int width; int height; unsigned char** image; int orientation; int posX; int posY; width=bin->getWidth(); height=bin->getHeight(); image = new unsigned char* [height]; for (int i = 0; igetImage(image); orientation=getOrientation(); posX=getPosX(); posY=getPosY(); if (orientation==0) { if((posX<0)|| ((posX+1)>width-1)|| (posY<1)|| (posY+1>height-1)) return 0; if ( (image[posY-1][posX]!=0)|| (image[posY-1][posX+1]!=0)|| (image[posY][posX]!=0)|| (image[posY+1][posX]!=0)|| (image[posY+1][posX+1]!=0)) return 0; } if (orientation==1) { if( (posX<1)|| ((posX+1)>width-1)|| (posY<0)|| ((posY+1)>height-1)) return 0; if ( (image[posY+1][posX+1]!=0)|| (image[posY][posX+1]!=0)|| (image[posY][posX]!=0)|| (image[posY][posX-1]!=0)|| (image[posY+1][posX-1]!=0)) return 0; } if (orientation==2) { if((posX<1)|| (posX>width-1)|| (posY<1)|| ((posY+1)>height-1)) return 0; if ( (image[posY-1][posX-1]!=0)|| (image[posY-1][posX]!=0)|| (image[posY][posX]!=0)|| (image[posY+1][posX]!=0)|| (image[posY+1][posX-1]!=0)) return 0; } if (orientation==3) { if( (posX<1)|| (posX+1>width-1)|| (posY<1)|| ((posY)>height-1)) return 0; if ( (image[posY-1][posX+1]!=0)|| (image[posY][posX+1]!=0)|| (image[posY][posX]!=0)|| (image[posY][posX-1]!=0)|| (image[posY-1][posX-1]!=0)) return 0; } return 1; } void CCBrick::operator>>(unsigned char** binImage) { int orientation; int posX; int posY; unsigned char colour; posX=getPosX(); posY=getPosY(); orientation=getOrientation(); colour=getColour(); if (orientation==0) { binImage[posY-1][posX+1]=colour; binImage[posY-1][posX]=colour; binImage[posY][posX]=colour; binImage[posY+1][posX]=colour; binImage[posY+1][posX+1]=colour; } if (orientation==1) { binImage[posY+1][posX+1]=colour; binImage[posY][posX+1]=colour; binImage[posY][posX]=colour; binImage[posY][posX-1]=colour; binImage[posY+1][posX-1]=colour; } if (orientation==2) { binImage[posY-1][posX-1]=colour; binImage[posY][posX]=colour; binImage[posY-1][posX]=colour; binImage[posY+1][posX]=colour; binImage[posY+1][posX-1]=colour; } if (orientation==3) { binImage[posY-1][posX+1]=colour; binImage[posY][posX+1]=colour; binImage[posY][posX]=colour; binImage[posY][posX-1]=colour; binImage[posY-1][posX-1]=colour; } } void CCBrick::putAtTop(int newOrient, int newPosX) { setPosX(newPosX); setOrientation(newOrient); switch(newOrient) { case 0: setPosY(1); break; case 1: setPosY(0); break; case 2: setPosY(1); break; case 3: setPosY(1); break; } } void CCBrick::putAtMid(int newOrient, int newPosX) { setPosX(newPosX-3); setOrientation(newOrient); switch(newOrient) { case 0: setPosY(9); break; case 1: setPosY(8); break; case 2: setPosY(9); break; case 3: setPosY(9); break; } } 3.砖块在面板中的显示设计: 在视图类中设计并显示砖块。 (1).定义相关的变量并在构造函数中初始化。 (2).添加DrawImage(CBin*bin,unsigned char**image,CDC*pDC) 函数,用来绘制游戏砖块。 这其中要绘制四个面板,传递四个参数。两个主面板,两个与侧面板。 部分代码如下: void CNewTerisView::DrawImage(CBin *bin,CBin *bin1,CBin *bin2,CBin *bin3, unsigned char **image, unsigned char **image1, unsigned char **image2, unsigned char **image3,CDC *pDC) CRect rect; //创建背景位图画刷 CBitmap bitmap; bitmap.LoadBitmap(IDB_BITMAP24); CBrush brush; brush.CreatePatternBrush(&bitmap); GetClientRect(&rect); pDC->FillRect(rect,&brush); //右边玩家分数的输出 CRect re; pDC->FillSolidRect(re,RGB(210,255,255)); char buf[100]; sprintf(buf," %d ",numLines*10); pDC->TextOut(330,90,buf); //左边玩家分数的输出 CRect re1; pDC->FillSolidRect(re1,RGB(230,255,100)); char buf1[100]; sprintf(buf1," %d ",numLines1*10); pDC->TextOut(440,90,buf1); CRect rc,rc1,rc2,rc3; //将载入的位图资源放在数组中 int Bit[8]={IDB_BITMAP11,IDB_BITMAP12,IDB_BITMAP13,IDB_BITMAP14 ,IDB_BITMAP15,IDB_BITMAP16,IDB_BITMAP17,IDB_BITMAP18}; int b,b1,b2; for(i=0;iFillRect(rc1,&brush1); } } } for(i=0;iFillRect(rc,&brush1); } } } (3).在菜单中添加“开始”、“难度”、“暂停”、“游戏模式”等菜单, A(为“开始”菜单添加消息响应函数。 初始化面板,并设置定时器。 代码如下: void CNewTerisView::OnGameStart() { // TODO: Add your command handler code here gameOver=0; brickInFlight=0; numLines=0; //------------ gameOver1=0; brickInFlight1=0; numLines1=0; for(unsigned int i=0;i<20;i++) { for(unsigned int j=0;j<10;j++) { outputImage[i][j]=0; outputImage1[i][j]=0; outputImage2[i][j]=0; outputImage3[i][j]=0; } } bin->setImage(outputImage); bin1->setImage(outputImage1); bin2->setImage(outputImage2); bin3->setImage(outputImage3); /////////////加背景音乐 res=FindResource(::AfxGetApp()->m_hInstance,MAKEINTRESOURCE (IDR_WAVE1),"WAVE"); hSound1=LoadResource(::AfxGetApp()->m_hInstance,res); lpSound1=(LPSTR)LockResource(hSound1); sndPlaySound(lpSound1,SND_LOOP|SND_ASYNC|SND_MEMORY); // SetTimer(0,difficulty,NULL); } B.“难度”菜单中有容易、中等与高级三个等级。通过设置砖块下落的速 度来设置难度。 C.“暂停”菜单中设置标志变量,是程序执行时,不执行shiftDown()函 数即可。 void CNewTerisView::OnPause() //暂停 { // TODO: Add your command handler code here if(!p) //原先没有暂停则暂停 { Pause1=TRUE; //设置暂停为真 Pause2=TRUE; p=TRUE; } else //若原先暂停,按下后继续游戏 { Pause1=FALSE; Pause2=FALSE; p=FALSE; } } D(“游戏模式”菜单可以设置游戏为“经典模式”或“奇幻模式”。 用于设定两大不同类的砖块。 (4).为视图类添加WM_TIMER的消息响应函数。(此相当于C++中所执行 的主函数中的代码) A在此函数中,随机产生不同的砖块,并显示出来,还要判断是否冲突 或游戏是否结束,若游戏没结束也不冲突则砖块下移一格,之后还要 判断是否应消行等。 B.预测功能的实现,是将预测面板上一次随机产生的砖块类型值赋给本 次的主程序面板。 C(双人模式的实现很简单,只是重新绘制了一个矩形框(CBin),并绘 制一个面板,将其显示在不同的区域。预测与此类似,只不过预测没 有判断冲突等,只是显示即可。 具体代码如下: if(!brickInFlight&&!gameOver) //判断左边游戏是否结束及砖块 是否在飞 { if(!RandomFlag) //若是第一次产生主界面砖块类型,则执行下面 语句(第一次产生的砖块不是预测的)下面语句只执行一次 { brickType=((unsigned int)rand()%NUM_BRICK_TYPES)+1; initOrientation=(unsigned int)(rand()%4); RandomFlag=TRUE; } else //第二次以后,主界面的砖块都是上一次预测砖块的类型 { brickType=brickType1; initOrientation=initOrientation1; } CTime time=CTime::GetCurrentTime(); //预测砖块类型的产生 int q=int(time.GetSecond()); brickType1=(q%NUM_BRICK_TYPES)+1; initOrientation1=(unsigned int)(q%4); if(!modal) //若不是经典模式,则为奇幻模式 { if(brickType==1) //左边主界面砖块的动态产生 activeBrick=new CtBrick; else if(brickType==2) activeBrick=new CsBrick; else if(brickType==3) activeBrick=new CCBrick; else if(brickType==4) activeBrick=new CPointBrick; else if(brickType==5) activeBrick=new CiBrick; else if(brickType==6) activeBrick=new C10Brick; else if(brickType==7) activeBrick=new C7Brick; /////////000000 if(brickType1==1) activeBrick1=new CtBrick;//左边预测界面砖块的动态产生 else if(brickType1==2) activeBrick1=new CsBrick; else if(brickType1==3) activeBrick1=new CCBrick; else if(brickType1==4) activeBrick1=new CPointBrick; else if(brickType1==5) activeBrick1=new CiBrick; else if(brickType1==6) activeBrick1=new C10Brick; else if(brickType1==7) activeBrick1=new C7Brick; } else //若不是奇幻模式,则为经典模式 { if(brickType==1) activeBrick=new CTBrick; else if(brickType==2) activeBrick=new CABrick; else if(brickType==3) activeBrick=new CSBrick; else if(brickType==4) activeBrick=new CLBrick; else if(brickType==5) activeBrick=new COBrick; else if(brickType==6) activeBrick=new CIBrick; else if(brickType==7) activeBrick=new CJBrick; ///////////////// if(brickType1==1) activeBrick1=new CTBrick; else if(brickType1==2) activeBrick1=new CABrick; else if(brickType1==3) activeBrick1=new CLBrick; else if(brickType1==4) activeBrick1=new CSBrick; else if(brickType1==5) activeBrick1=new COBrick; else if(brickType1==6) activeBrick1=new CIBrick; else if(brickType1==7) activeBrick1=new CJBrick; } activeBrick->setColour((unsigned char)brickType); //左边主 界面设置颜色 activeBrick->putAtTop(initOrientation,binWidth/2);//将产生 的砖块置顶 //----- activeBrick1->setColour((unsigned char)brickType1); //左边 预测砖块设置颜色 activeBrick1->putAtMid(initOrientation1,binWidth1/2);//将 预测产生的砖块放置在面板中间 ///****************************************** notCollide=activeBrick->checkCollision(bin); //判断是否冲突 if(notCollide) //判断是否冲突 { brickInFlight=1; bin->getImage(outputImage); activeBrick->operator>>(outputImage); bin1->getImage(outputImage1); activeBrick1->operator>>(outputImage1); Invalidate(FALSE); } else //冲突则游戏设置游戏结束变量,删除new的东西 { gameOver=1; delete activeBrick; delete activeBrick1; brickInFlight=0; } } //////////////////////////////////////////////////// if(brickInFlight&&!gameOver) { if(!Pause1) notCollide=activeBrick->shiftDown(bin); //砖块下移一格 if(notCollide){ bin->getImage(outputImage); //不冲突获得画面 activeBrick->operator>>(outputImage); //显示画面 } else { brickInFlight=0; bin->getImage(outputImage); activeBrick->operator>>(outputImage); bin->setImage(outputImage); Invalidate(FALSE); numLines=numLines+bin->removeFullLines(); //消行分数增 加 bin->getImage(outputImage); } Invalidate(FALSE); } ////////////////////////////// if(gameOver){ //左边游戏是否结束 KillTimer(0); res1=FindResource(::AfxGetApp()->m_hInstance,MAKEINTRESOUR CE(IDR_WAVE2),"WAVE"); hSound2=LoadResource(::AfxGetApp()->m_hInstance,res1); lpSound2=(LPSTR)LockResource(hSound2); sndPlaySound(lpSound2,SND_ASYNC|SND_MEMORY); if(MessageBox("左边的兄弟,得加油啊~还玩吗?","提示 ",MB_YESNO)==IDYES) OnGameStart(); else exit(0); } (6) 在OnDraw()函数中调用DrawImage()函数,即可显示面板。 (7) 当然还得添加WM_KEYDOWON的消息响应函数,以响应用户按键。 代码如下: void CNewTerisView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default ////////左边玩家的控制键 if(nChar==VK_NUMPAD0) OnPause(); if(nChar==VK_RIGHT) activeBrick->shiftRight(bin); else if(nChar==VK_LEFT) activeBrick->shiftLeft(bin); else if(nChar==VK_UP) activeBrick->rotateClockwise(bin); else if(nChar==VK_DOWN) activeBrick->shiftDown(bin); //////////右边玩家的控制键 if(nChar==VK_NUMPAD6) activeBrick2->shiftRight(bin2); else if(nChar==VK_NUMPAD4) activeBrick2->shiftLeft(bin2); else if(nChar==VK_NUMPAD8) >rotateClockwise(bin2); activeBrick2- else if(nChar==VK_NUMPAD5) activeBrick2->shiftDown(bin2); Invalidate(FALSE); CView::OnKeyDown(nChar, nRepCnt, nFlags); } 四(测试与实现: 奇幻模式: 经典模式: 单人模式: 游戏结束: 五( : 通过本次双人版俄罗斯方块游戏的开发,使我对VC可视化编程产生了更大的兴趣,也激发了我开发游戏的强烈兴趣。以前在dos环境下编写的俄罗斯方块游戏与此相比,能够充分体现出可视化编程的优势,界面比dos下的好看多了。而且其操作简便,用户体验很好。 这次的开发过程没有前几次那么曲折,可能是我的编程能力真的有了提高,当然,这也主要是因为老师已经把俄罗斯方块的实现写好了,我们只是做一些修改。你想要修改成自己想要的东西,首先,你得看懂程序,否则你不知道在那里修改,怎么修改。通过修改程序,实现双人版俄罗斯方块,在这一过程中,我们也学到了很多东西,有技巧性的代码,也有思维上的模式与创新等。只有你不断的改,不断地练习,你的编程能力在不知不觉中提高。 通过自己的修修改改,不知不觉就实现了你所想要的东西。当然,这其中一定会有挫折,会有BUG,当你真的编出你所想要的东西时,这种成就感将以前的所有痛苦、bug都化为乌有。就是在不断的出现问题,解决问题的过程中学习。 很多人都知难而退,也许只有坚持到底,你才会解决解决所遇到的困难,你才会成功。 本程序的优点:具有较好的界面,实现了双人版俄罗斯方块的同时,实现了预测及不同于经典模式砖块的选择,还加了音乐。 本程序的缺点:游戏的控制不够灵活,反应较慢,还有很多有待提高的地方。
/
本文档为【双人版俄罗斯方块游戏实验报告】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索