用C++做的拼图游戏.docx
《用C++做的拼图游戏.docx》由会员分享,可在线阅读,更多相关《用C++做的拼图游戏.docx(29页珍藏版)》请在冰点文库上搜索。
用C++做的拼图游戏
青岛理工大学
C++面向对象课程设计报告
院(系):
计算机工程学院
专业:
计算机科学与技术
学生姓名:
__
班级:
___学号:
题目:
__拼图游戏设计_____
起迄日期:
__2011.7.4—2011.7.
设计地点:
指导教师:
完成日期:
2010年月日
一、课程设计目的
(1)通过拼图游戏设计加强对C++课程基础知识点的理解和掌握,培养对基础知识综合运用能力、实际分析问题能力,养成良好的编程习惯。
(2)通过拼图游戏设计进一步领会程序设计的特点和应用,提高运用C++以及面向对
象知识解决实际问题的能力,初步掌握MFC编程的基本功能,掌握一种可视化编程的方法,加强对C++面向对象程序设计的理解。
(3)通过拼图游戏设计掌握用C++编写面向对象的实用程序的设计方法,对面向对象方法和思想增加感性的认识,学会利用C++程序设计语言编写出一些短小、可靠的Windows实用程序,切实提高面向对象的程序设计能力,为后续的相关课程的学习打下基础。
(4)通过拼图游戏设计锻炼实际的编程能力,提高调查资料、查阅技术文献、资料以及编写软件设计文档的能力,初步接触自学编程的思想,转变死读的观念。
二、课程设计内容与实现的功能
(1)课程设计内容
将一张图片切分成若干小片,打乱顺序任意显示,用户通过操作各小片到正确位置以恢复原来的图像,要求有不同的等级,切分成不同的片数,完成拼图后程序可以判断是否完成,游戏还应有显示原图片的功能。
(2)实现的功能
①本程序除了实现了拼图所要求的基本功能外,还添加了背景音乐和游戏所用的时间,当游戏开始时背景音乐自动播放,时间自动增加。
②为了制作拼图游戏,首先要动态创建一组静态控件,这些控件将作为拼图块进行移动。
用户用户需要选择拼图图像,可以使用程序中自带的图像,亦可以自己选则择图像,然后程序将根据用户选择的游戏级别设置静态控件的大小和位置,并将用户选择的图像绘制到静态控件上。
当用户选择开始游戏以后,程序将隐藏右下角的拼图块,使拼图空出一个位置,用
户可以使用上、下、左、右键来控制剩余拼图块的移动,在移动的过程中,用户可以通过菜单栏的游戏助手来查看原图片。
当用户完成拼图时,游戏提示用户胜利,这样完成了拼图游戏的设计。
三、系统分析与设计
1、系统分析
(1)信息:
系统主要可以处理用户的图片选择、等级选择、游戏中图片移动等信息。
(2)行为:
游戏开始前,用户选择图片和等级后,程序将弹出相应的信息、给出相应的变化,当游戏开始后,状态栏的时间应该按秒增加,当用户按下上下左右四个键中的某一个后,程序将判断按键并进行相应的移动操作,若用户完成整个图片,程序将弹出成功提示,并且时间停止。
若用户在游戏过程中按下游戏助手按钮,则系统将给出所选图片的原图片。
(3)表示:
利用基于对话框的MFC编程,菜单选项可以选择自带的三个图片或自定义图片,可以选择初、中、高三个等级,可以选择开始游戏、游戏助手和退出游戏。
2、系统设计:
系统设计方案:
游戏应包括图像、级别和系统三个选择来为用户提供图片、级别和游戏开始、助手和退出等操作。
当用户选择其中的某一项时,系统将给出相应的操作。
为完成拼图游戏设计,需要将一张完整的图片根据等级分割成不同的个数,并将其中的一小块隐藏(此处选择右下角)来供用户移动其他的方块拼凑出原来的图片,在此过程中,系统应提供游戏助手来显示原来的图片,当完成后系统应提示成功。
2.1、模块设计:
2.2、数据结构说明:
应用数组:
空间数组、程序根目录路径、图片完成位置、控件区域都是应用数组来存储的。
2.3、算法流程图:
主程序算法流程图:
图片选择算法流程图:
主程序调用关系图:
函数调用关系图:
四、系统测试与调试分析
1、系统测试
●测试方法:
黑盒
●测试技术:
功能测试
●测试数据:
包括正确的输入及其输出结果和含有错误的输入及其输出结果。
●测试报告:
必须包含最终测试结果:
列出你的测试结果,包括输入和输出。
这里的测试数据应该完整和严格。
功能测试应用背景:
它是从使用者的角度来编写的,它关注系统提供的功能特征及其不同的处理条件;测试功能的不同处理流程(包括正常处理的和异常处理);一个功能测试用例仅用于测试一个功能,一个功能可能需要多个功能测试用例来覆盖。
所以,报告这部分的撰写首先是要确定你所要采取的测试技术,然后对此进行介绍,最后根据所选择的技术设计测试用例,填写好下表,其中测试用例不止一个。
测试说明
测试名称
拼图游戏设计
测试目的
验证系统对于游戏选择的处理流程
测试技术
功能测试
测试方法
黑盒测试法
测试用例
测试内容
图像的选择
测试步骤
输入正确用户名与密码
输入正确用户名与错误密码
输入错误用户名与密码
测试数据
Admin,正确密码
Admin,错误密码
错误用户名,密码
预期结果
正常进入系统
显示密码错误
显示用户不存在
测试结果
与预期相符
与预期相符
与预期相符
3、调试分析:
程序中遇到的问题及解决方案:
(1)开始的程序对于图像1的选择不出现相应的结果,重新改写此段代码后出现预期结果。
(2)开始建立了时间函数OnTimer,但是游戏运行后时间并不增加,在开始游戏对应的函数中增加SetTimer函数,得到想要的结果。
(3)开始程序,拼图完成后并不给出成功的提示,后增加GameWin函数,在每移动一步后调用此函数判断是否成功,这样,一旦用户完成拼图则程序立马自动显示出成功的相应信息。
设计与实现的回顾与讨论:
(1)原本设想的程序的移动是用鼠标来实现,但在编码时感觉不大好弄,需要确定用户点击的方块到底在空白方块的哪个位置,因此就使用了键盘上的四个键来代替。
(2)设想可以用户完成拼图后将给出用户的排名,但此功能没能实现,需要加强。
(3)虽然程序中添加了背景音乐,但是没能实现用户移动图片是移动的声音,此处有待加强。
四、用户手册
(1)打开PinTu文件夹,双击PinTu.dsw标志即
打开程序,然后运行。
(2)开始程序会出现以下界面:
图1:
开始界面
(3)用户需要选择图片和等级:
点击图像,选择自带的1、2、3或自定义图片,点击级别,选择初级、中级或高级,然后点击系统选择开始游戏,会出现类似以下界面:
(图像为图象2,等级为初级)
图2:
游戏开始后的界面
(4)用户需要根据键盘上的上下左右四个键移动方块来完成拼图,在此过程中可以点击系统里的游戏助手来显示原图片:
图3:
游戏助手
(5)当完成拼图后系统会自动给出成功提示
图4:
拼图完成界面
六、程序清单
初始化:
BOOLCPinTuDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
//Add"About..."menuitemtosystemmenu.
//IDM_ABOUTBOXmustbeinthesystemcommandrange.
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE);//Setbigicon
SetIcon(m_hIcon,FALSE);//Setsmallicon
//TODO:
Addextrainitializationhere
:
:
GetCurrentDirectory(256,m_Path);//获取程序根目录路径
m_Start=FALSE;
UINTarray[2]={12301,12302};
m_Statusbar.Create(this);//创建状态栏窗口
m_Statusbar.SetIndicators(array,sizeof(array)/sizeof(UINT));//添加面板
CRectrect;
GetWindowRect(rect);//获得窗口区域
m_Statusbar.SetPaneInfo(0,array[0],0,rect.Width()/2);//设置面板宽度
m_Statusbar.SetPaneInfo(1,array[1],0,rect.Width()/2);
CStringgTime;
m_Time=0;
gTime.Format("游戏时间:
%d",m_Time);//设置游戏时间
m_Statusbar.SetPaneText(0,gTime);//设置状态栏显示游戏时间
m_Statusbar.SetPaneText(1,"加油!
");//设状态栏显示文本
RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);//显示状态栏
for(inti=0;i<25;i++)
{
m_Picture[i].Create("",WS_CHILD|WS_CLIPSIBLINGS|WS_EX_TOOLWINDOW|WS_BORDER,
CRect(0,0,50,50),this,1200+i);//创建静态控件
}
dlg=newCHelpDlg;//声明对话框指针
dlg->Create(IDD_HELP_DIALOG,this);//创建模态对话框
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
}
重绘函数:
voidCPinTuDlg:
:
OnPaint()
{
if(IsIconic())
{
CPaintDCdc(this);//devicecontextforpainting
SendMessage(WM_ICONERASEBKGND,(WPARAM)dc.GetSafeHdc(),0);
//Centericoninclientrectangle
intcxIcon=GetSystemMetrics(SM_CXICON);
intcyIcon=GetSystemMetrics(SM_CYICON);
CRectrect;
GetClientRect(&rect);
intx=(rect.Width()-cxIcon+1)/2;
inty=(rect.Height()-cyIcon+1)/2;
//Drawtheicon
dc.DrawIcon(x,y,m_hIcon);
}
else
{
CDialog:
:
OnPaint();
}
ShowPicture(m_Num,m_Size);
}
//Thesystemcallsthistoobtainthecursortodisplaywhiletheuserdrags
//theminimizedwindow.
HCURSORCPinTuDlg:
:
OnQueryDragIcon()
{
return(HCURSOR)m_hIcon;
}
设置等级:
voidCPinTuDlg:
:
SetGrade(intn)
{
CRectrcdlg;
GetClientRect(rcdlg);//获得窗口客户区域
m_Size=rcdlg.Width()/n;//获得每个控件的宽度和高度
for(inti=0;i{
for(intj=0;j{
CRectrect(0+j*m_Size,0+i*m_Size,m_Size+j*m_Size,m_Size+i*m_Size);//设置控件区域
m_Picture[j+i*n].MoveWindow(&rect);//移动控件
m_Picture[j+i*n].ShowWindow(SW_SHOW);//显示区域
m_MovePoint.x=rect.left;//记录右下角控件的左上角横坐标
m_MovePoint.y=rect.top;//记录右下角控件的左上角纵坐标
}
}
ShowPicture(n,m_Size);//绘制图片
for(i=n*n;i<25;i++)
{
m_Picture[i].ShowWindow(SW_HIDE);//设置剩余控件隐藏
m_Picture[i].EnableWindow(FALSE);//设置剩余控件不可用
}
}
显示图片函数:
voidCPinTuDlg:
:
ShowPicture(intm,intn)//将用户设置的图片绘制到控件上
{
HBITMAPm_hBitmap;
m_hBitmap=(HBITMAP):
:
LoadImage(AfxGetInstanceHandle(),m_pPath,
IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_DEFAULTCOLOR|LR_DEFAULTSIZE);//加载位图资源
intx=0,y=0,i=0,j=0;
CDC*pDC=m_Picture[0].GetDC();//控件设备上下文
//将位图选进设备场景中
CDCmemdc;
memdc.CreateCompatibleDC(pDC);//创建一个与内存兼容的设备环境
memdc.SelectObject(m_hBitmap);//将位图选入内存设备环境
BITMAPbmp;
GetObject(m_hBitmap,sizeof(bmp),&bmp);//获得图片信息
x=bmp.bmWidth/m;//设置绘制图片的宽度
y=bmp.bmHeight/m;//设置绘制图片的高度
pDC->StretchBlt(0,0,n,n,&memdc,0,0,x,y,SRCCOPY);//将位图复制到实际的设备环境中
UpdateWindow();//更新窗口显示
for(i=0;i{
for(j=0;j{
CDC*pDC=m_Picture[j+i*m].GetDC();
pDC->StretchBlt(0,0,n,n,&memdc,x*j,y*i,x,y,SRCCOPY);
//pDC->Draw3dRect(0,0,n,n,RGB(0,0,0),RGB(0,0,0));
}
}
memdc.DeleteDC();
UpdateWindow();
}
选择图片1
voidCPinTuDlg:
:
OnMenubmap1()//选择图片1
{
//TODO:
Addyourcommandhandlercodehere
CStringstr=m_Path;
str=str+"\\res\\1.bmp";
m_pPath=str;
SetGrade(3);
}
选择图片2:
voidCPinTuDlg:
:
OnMenubmap2()//选择图片2
{
//TODO:
Addyourcommandhandlercodehere
CStringstr=m_Path;
str=str+"\\res\\2.bmp";
m_pPath=str;
SetGrade(3);
}
选择图片3:
voidCPinTuDlg:
:
OnMenubmap3()//选择图片3
{
//TODO:
Addyourcommandhandlercodehere
CStringstr=m_Path;
str=str+"\\res\\3.bmp";
m_pPath=str;
SetGrade(3);
}
选择自定义图片:
voidCPinTuDlg:
:
OnMenucustom()//选择自定义图片
{
//TODO:
Addyourcommandhandlercodehere
CFileDialogdlg(TRUE,"bmp",NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"位图文件(*.bmp)",this);//构造打开对话框
if(dlg.DoModal()==IDOK)//显示打开对话框
{
m_pPath=dlg.GetPathName();//获得图片路径
m_Num=3;
SetGrade(m_Num);//设置当前级别对应显示的控件
}
}
选择等级为初级:
voidCPinTuDlg:
:
OnMenueasy()//设置等级为初级
{
//TODO:
Addyourcommandhandlercodehere
KillTimer
(1);//关闭定时器
m_Time=0;//设置用时为0
CStringgTime;
gTime.Format("游戏时间:
%d",m_Time);//格式化游戏事件
m_Statusbar.SetPaneText(0,gTime);//显示游戏时间
m_Num=3;
SetGrade(m_Num);
}
选择等级为中级:
voidCPinTuDlg:
:
OnMenumid()//设置等级为中级
{
//TODO:
Addyourcommandhandlercodehere
KillTimer
(1);
m_Time=0;
CStringgTime;
gTime.Format("游戏时间:
%d",m_Time);
m_Statusbar.SetPaneText(0,gTime);
m_Num=4;
SetGrade(m_Num);
}
选择等级为高级:
voidCPinTuDlg:
:
OnMenuhard()//设置等级为高级
{
//TODO:
Addyourcommandhandlercodehere
KillTimer
(1);
m_Time=0;
CStringgTime;
gTime.Format("游戏时间:
%d",m_Time);
m_Statusbar.SetPaneText(0,gTime);
m_Num=5;
SetGrade(m_Num);
}
打乱原图片:
voidCPinTuDlg:
:
RandPlace(inta,intb)//打乱原图片
{
intnum[25];
intn,m=0,k=1;
CTimetime=CTime:
:
GetCurrentTime();//获得系统时间
srand(time.GetSecond());//设置随机数种子
num[0]=rand()%(a*a-1);//求随机数
while(k!
=(a*a-1))
{
n=rand()%(a*a-1);//获得随机数
for(inti=0;i{
if(num[i]==n)//随机数存在
{
m=1;
}
}
if(m==0)//此随机数以前不存在
{
k++;//随机数的数量加1
num[k-1]=n;//保存此随机数
}
m=0;
}
for(inti=0;i{
for(intj=0;j{
m_Point[j+i*a].x=j*b;//记录控件左上角的横坐标
m_Point[j+i*a].y=i*b;//记录控件左上角的纵坐标
}
}
for(i=0;i<(a*a-1);i++)
{
intp;
p=num[i];//获得随机数
m_Rect[i].left=m_Point[p].x;//记录随机显示后的控件左边界
m_Rect[i].top=m_Point[p].y;//记录随机显示后的控件的上边界
m_Rect[i].right=m_Rect[i].left+b;
m_Rect[i].bottom=m_Rect[i].top+b;
m_Picture[i].MoveWindow(&m_Rect[i]);//移动控件位置
}
}
开始函数:
voidCPinTuDlg:
:
OnMenustart()//使游戏开始
{
//TODO:
Addyourcommandhandlercodehere
if(m_pPath.IsEmpty())
{
MessageBox("请选择图片!
");
return;
}
SetGrade(m_Num);
m_Time=0;
SetTimer(1,1000,NULL);//设置定时器
sndPlaySound("秋日私语.wav",SND_LOOP|SND_ASYNC);//音乐异步、循环播放
m_Start=TRUE;
CRectrcdlg;
GetClientRect(rcdlg);//获得窗口客户区域
m_Size=rcdlg.Width()/m_Num;//设置图像的大小
RandPlace(m_Num,m_Size);//随机变化控件位置
m_Picture[m_Num*m_Num-1].ShowWindow(SW_HIDE);//隐藏右下角的控件
}
设定时间函数:
voidCPinTuDlg:
:
OnTimer(UINTnIDEvent)//设置游戏进行时间
{
//TODO:
Add