MFC开发拼图游戏实验报告.docx
《MFC开发拼图游戏实验报告.docx》由会员分享,可在线阅读,更多相关《MFC开发拼图游戏实验报告.docx(92页珍藏版)》请在冰豆网上搜索。
MFC开发拼图游戏实验报告
计算机科学与工程学院
《Windows程序设计》实验报告(四)
专业班级信技2班实验地点411机房实验时间12周
指导教师张俊本组人数4人
学生学号0905060223090506021209050602010905060224
学生姓名杨赛蒋巧云蔡倪叶丽丽
实验项目综合应用设计—拼图游戏
实验类别基础性()设计性()综合性(√)其它()
实1.掌握对话框和常用控件的应用
验2.掌握文档串行化和打印的技术
目3.熟练应用动态链接库及其开发
的4.综合应用各种可视化元素和交互技术实现一个典型的Windows应用
及程序
要5.通过本程序掌握VisualC++位图操作
求
成绩评定表
类别评分标准分值得分合计
积极出勤、遵守纪律
上机表现
按要求完成设计任务
程序代码规范、功能正确
程序与报告
报告详实完整、体现收获
30分
具体评分请
见项目记录
表
70分
说明:
评阅教师:
日期:
2011年月日
计算机科学与工程学院
实验内容
项目功能及结构组成
一、项目介绍
“拼图”游戏的核心规则是将一张整图分成N小块,随机打乱,让用户拼回原图,根据用户所花费的时间和步数的多少来评价其玩游戏的水平。
游戏的具体规则如下:
1.运行程序后,用户需按F2开始游戏,在此期间需要输入一个名字;然后用户可以
选择应用程序提供的位图资源或自定义的位图作为游戏使用的图片。
2.用户可以选择游戏的难度,若选择“容易”,程序将图片分成9块;若选择“困难”
则分成16块。
3.单击“重置”菜单项会弹出一个对话框让用户确认是否重置游戏。
4.单击任一图格,图像将随机排列,并开始计时;用户可单击空格周围的图格来改变
其位置,每当用户单击一次,步数将增加一次。
5.用户在游戏时可以通过单击“提示”菜单项来查看当前图片的缩略图。
6.拼图成功,程序将在状态栏给出提示信息和所花费的时间及步数,用户可以选择另
外一幅图片重新开始游戏。
二、结构组成
本程序基于对话框程序组成,包括一个菜单栏,状态栏和显示游戏图片的游戏区。
游戏开始界面如下图所示:
《Windows程序设计》实验报告2
计算机科学与工程学院
小组成员及分工
小组成员:
杨赛,蒋巧云,蔡倪,叶丽丽
分工详情:
杨赛:
负责程序框架构建及功能代码的输入,并调试程序。
(主要完成设计过程中的第一部分、第三部分、第四部分)
蒋巧云:
负责查找相关代码的资料,并完成一部分实验报告。
(主要完成设计过程中的第三部分)
蔡倪:
负责输入部分代码,完善程序的细节,并测试程序。
(主要完成设计过程中的第二部分、第三部分、第四部分)
叶丽丽:
负责输入部分代码,并完成一部分的实验报告。
(主要完成设计过程中的第三部分)
详细设计过程(包含关键代码及截图)
一、创建初始界面
(本部分由杨赛完成)
新建一个MFCAppWizard(exe)工程,将其命名为Picture,在第一步选择Dialogbased,如图1-1所示,接下来直接点Finish。
在Workspace的Resource标签中加入菜单资源,方法是在Pictureresources上右击,在弹出的快捷菜单中选择insert…,如图1-2所示;然后在弹出的对话框中选中menu项,单击New,完成后的效果如图1-3所示。
图1-1
《Windows程序设计》实验报告3
计算机科学与工程学院
图1-2
图1-3
添加如图1-4所示的菜单项。
图1-4
“游戏“菜单下的子菜单项的ID及设置如图1-5至图1-10所示(其它的将在后面给出):
《Windows程序设计》实验报告4
计算机科学与工程学院
图1-5
图1-6
图1-7
图1-8
《Windows程序设计》实验报告5
计算机科学与工程学院
图1-9
图1-10
以上完成后,右击打开对话框的属性(Properties),将对话框的ID号设为
IDD_PICTURE_DIALOG,Caption设置为“拼图游戏”,并为Menu属性对应的下拉框选择
IDR_MENU1,如图12所示;这样菜单就可以在程序运行时显示在主对话框的顶部了。
图1-11
运行后的效果如图1-12所示:
《Windows程序设计》实验报告6
计算机科学与工程学院
图1-12
在ClassView标签中为CPictureDlg类添加两个CMenu类型的成员变量如图1-13和图1-14所示:
图1-13
图1-14
《Windows程序设计》实验报告7
计算机科学与工程学院
实验内容
CMenu类为WindowsHMENU的封装类。
它提花了成员函数以用于创建、跟踪、更新及撤消菜单。
另外,视图中是没有菜单的,在框架窗口中才有菜单,所以只有用AfxGetApp()->m_pMain->GetMenu()才能得到菜单指针。
二、位图的读入和显示
(本部分工作由蔡倪完成)
在程序中,需要由用户来选择游戏中使用的图片,同时还需要将整幅图片分成不同的小
块。
因此,采用(Picture)Static控件作为位图的载体,分别显示图片的不同部分。
首先,需要读入位图资源。
单击VC6.0菜单栏上的“Insert—Resource…”子菜单,在
弹出的对话框中选中Bitmap,再单击“import…”,在弹出的对话框中找到你需要添加进来
的图片(注意在文件类型下拉框中选择“所有文件(*.*)”,否则你将找不到“*.bmp”的图
片),单击“import”后将弹出如图2-1所示的确认框,单击“确定”即可。
图2-1
依次添加四个位图文件(ID默认)后,在ResourceView中将看到如图2-2所示效果:
图2-2
为对话框的“图片”菜单添加五个菜单项,如图2-3所示,ID分别为:
ID_PICTURE1,ID_PICTURE2,ID_PICTURE3,ID_PICTURE4,ID_ADVAN。
《Windows程序设计》实验报告8
计算机科学与工程学院
图2-3
接下来为CPictureDlg类添加一个CBitmap类型的成员变量Bitmap,如图2-4所示。
CBitmap封装了Windows图形设备接口(GDI)中的位图,并且提供了操纵位图的成员函数。
图2-4
为了实现不同位图资源的加载,我们需要为类CPictureDialog添加一个成员函数VoidOnRun(UINTnBitmapID,UINTnMenuID),如图2-5所示:
图2-5
参数nBitmapID指定位图资源的ID号,nMenuID指定菜单项的ID号。
在函数中,我们首先用GetSubMenu得到指向弹出菜单对象的指针,然后用CheckMenuItem方法为nMenuID所指定的菜单项放置选中标记。
接下来用CBitmap对象的LoadBitmap方法将nBitmapID所指定的位图载入。
相应代码如下:
voidCPictureDlg:
:
OnRun(UINTnBitmapID,UINTnMenuID)
{
pSubMenu=pMainMenu->GetSubMenu
(1);
pSubMenu->CheckMenuItem(ID_PICTURE1,MF_UNCHECKED);
pSubMenu->CheckMenuItem(ID_PICTURE2,MF_UNCHECKED);
pSubMenu->CheckMenuItem(ID_PICTURE3,MF_UNCHECKED);
pSubMenu->CheckMenuItem(ID_PICTURE4,MF_UNCHECKED);
pSubMenu->CheckMenuItem(ID_ADVAN,MF_UNCHECKED);
pSubMenu->CheckMenuItem(nMenuID,MF_CHECKED);
Bitmap.DeleteObject();
Bitmap.LoadBitmap(nBitmapID);
《Windows程序设计》实验报告9
计算机科学与工程学院
}
载入位图时,首先调用函数CGdiObject:
:
DeleteObject删除由LoadBitmap加载过的位图,然后用LoadBitmap方法载入新的位图对象。
用类向导(ClassWizard,“View”菜单下的第一个子菜单,也可按Ctrl+W快捷键打开)依次为对话框中的“图像”菜单中的子菜单项添加消息响应函数,如图2-6所示;并调用OnRun函数加载位图。
图2-6
四张图片对应菜单的消息响应代码如下:
voidCPictureDlg:
:
OnPicture1()
{
//TODO:
AddyourcommandhandlercodehereOnRun(IDB_BITMAP1,ID_PICTURE1);
}
voidCPictureDlg:
:
OnPicture2()
{
//TODO:
AddyourcommandhandlercodehereOnRun(IDB_BITMAP2,ID_PICTURE2);
}
voidCPictureDlg:
:
OnPicture3()
{
//TODO:
AddyourcommandhandlercodehereOnRun(IDB_BITMAP3,ID_PICTURE3);
}
voidCPictureDlg:
:
OnPicture4()
{
//TODO:
AddyourcommandhandlercodehereOnRun(IDB_BITMAP4,ID_PICTURE4);
}
《Windows程序设计》实验报告10
计算机科学与工程学院
“自定义…”菜单项的消息响应代码由于需要打开一个新的位图文件,所以需要先为CPictureDlg类添加一个HBITMAP类型的成员变量hBitmap,用来表示指向位图资源的句柄。
其次,还需要添加两个INT型变量Width,Height来表示用户打开图片的大小;BOOL型变量IsLong来表示图片属于长大于宽型还是宽大于长型,BOOL型变量Advan表示该图片是否是自定义型。
如图2-7所示:
图2-7
“自定义..”菜单项的消息响应代码如下:
voidCPictureDlg:
:
OnAdvan()
{
//TODO:
Addyourcommandhandlercodehere
CFileDialogdlg(TRUE,NULL,NULL,NULL,"位图文件(*.bmp)|*.bmp");INTResult=dlg.DoModal();
if(Result==IDOK)
{
Advan=TRUE;
hBitmap=(HBITMAP):
:
LoadImage(NULL,dlg.GetFileName(),IMAGE_BITMAP,
0,0,LR_LOADFROMFILE);
BITMAPbm;
:
:
GetObject(hBitmap,sizeof(BITMAP),&bm);if(bm.bmWidth>=bm.bmHeight)
{
hBitmap=(HBITMAP):
:
LoadImage(NULL,dlg.GetFileName(),
IMAGE_BITMAP,350,280,LR_LOADFROMFILE);
Width=350;Height=280;
IsLong=FALSE;
}
elseif(bm.bmWidth{
hBitmap=(HBITMAP):
:
LoadImage(NULL,dlg.GetFileName(),
IMAGE_BITMAP,200,310,LR_LOADFROMFILE);
Width=200;Height=280;
IsLong=TRUE;
}
}
elseif(Result==IDCANCEL)
return;
}
在上面的代码中,用LoadImage方法来加载自定义文件中的位图资源,然后用GetObject
《Windows程序设计》实验报告11
计算机科学与工程学院
方法得到其BITMAP对象。
三、用(Picture)Static控件显示位图
(本部分为此项目中最重要部分,工作由四人共同完成)
在游戏程序中,采用StaticText即静态文本控件来显示位图。
静态文本控件的功能比较简单,可显示字符串,图标,位图。
先为对话框的“游戏”中的菜单项“容易”和“困难”添加消息响应,如图3-2所示;
另外还需为CPictureDlg类添加BOOL型变量Easy来标识游戏的难度(分为9格或16格),
同时添加BOOL型变量IsRnd用来标识图格是否进行了随机位置的初始化,如图3-3所示。
图3-2
图3-3
相应代码如下:
voidCPictureDlg:
:
OnEasy()
{
//TODO:
Addyourcommandhandlercodehere
pSubMenu=pMainMenu->GetSubMenu(0);
pSubMenu->CheckMenuItem(ID_HARD,MF_UNCHECKED);
pSubMenu->CheckMenuItem(ID_EASY,MF_CHECKED);
《Windows程序设计》实验报告12
计算机科学与工程学院
Easy=TRUE;IsRnd=FALSE;
}
voidCPictureDlg:
:
OnHard()
{
//TODO:
Addyourcommandhandlercodehere
pSubMenu=pMainMenu->GetSubMenu(0);
pSubMenu->CheckMenuItem(ID_EASY,MF_UNCHECKED);
pSubMenu->CheckMenuItem(ID_HARD,MF_CHECKED);
Easy=FALSE;IsRnd=FALSE;
}
接下来为CPictureDlg对话框添加16个Static控件(可以先设置好一个控件后,再通过复制得到其它的控件),如图3-4所示;并设置它们的属性:
ID设为IDC_IMAGE0到IDC_IMAGE15,Tabstop请勾上,Type属性设为Bitmap;尤为重要的是Styles标签里的如图3-5和图3-6所示。
图3-4
《Windows程序设计》实验报告13
计算机科学与工程学院
图3-5
图3-6
控件添加好了后,我们需要添加一个CStatic类型的数组m_Image[16]((如图3-7所示)与这16个Static控件相关联,通过这个操作这个数组的下标来控制这16个控件对图像进行分格显示。
建立关联的代码应写在CPictureDlg类中系统生成的OnInitDialog()函数体内,这个函数是整个对话框程序运行的入口,相当于一个main函数,在这个函数体里,我们也需要为之前声明的变量提供初始值,即将变量初始化,变量没有初始化的后果通常会造成内存泄露,使程序在运行时出现莫名奇妙的错误。
图3-7
OnInitDialog函数的代码如下:
BOOLCPictureDlg:
:
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
《Windows程序设计》实验报告14
计算机科学与工程学院
SetIcon(m_hIcon,FALSE);//Setsmallicon
//TODO:
Addextrainitializationhere
pMainMenu=GetMenu();//获取菜单
IsLong=FALSE;
Advan=FALSE;
Easy=TRUE;
SetWindowPos(NULL,0,0,356,352,SWP_NOMOVE);//控制窗口大小
m_Image[0].SubclassDlgItem(IDC_IMAGE0,this);
m_Image[1].SubclassDlgItem(IDC_IMAGE1,this);
m_Image[2].SubclassDlgItem(IDC_IMAGE2,this);
m_Image[3].SubclassDlgItem(IDC_IMAGE3,this);
m_Image[4].SubclassDlgItem(IDC_IMAGE4,this);
m_Image[5].SubclassDlgItem(IDC_IMAGE5,this);
m_Image[6].SubclassDlgItem(IDC_IMAGE6,this);
m_Image[7].SubclassDlgItem(IDC_IMAGE7,this);
m_Image[8].SubclassDlgItem(IDC_IMAGE8,this);
m_Image[9].SubclassDlgItem(IDC_IMAGE9,this);
m_Image[10].SubclassDlgItem(IDC_IMAGE10,this);
m_Image[11].SubclassDlgItem(IDC_IMAGE11,this);
m_Image[12].SubclassDlgItem(IDC_IMAGE12,this);
m_Image[13].SubclassDlgItem(IDC_IMAGE13,this);
m_Image[14].SubclassDlgItem(IDC_IMAGE14,this);
m_Image[15].SubclassDlgItem(IDC_IMAGE15,this);
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
}
接下来要为CPictureDlg类添加两个INT型的成员变量x和y,用来计算Static控件的位置,如图3-8所示。
为CPictureDlg类添加一个成员函数SetPos,用来对Static控件的位置进行初始代,如图3-9所示。
图3-8
《Windows程序设计》实验报告15
计算机科学与工程学院
图3-9
SetPos函数的代码如下:
voidCPictureDlg:
:
SetPos()
{
BITMAPbm;
INTcon,move;
if(Advan==FALSE)
{
Bitmap.GetObject(sizeof(BITMAP),&bm);
Width=bm.bmWidth;Height=bm.bmHeight;
}
if(Easy)
{x=Width/3;y=Height/3;con=2;}elseif(!
Easy)
{x=Width/4;y=Height/4;con=3;}if(IsLong)move=70;
elsemove=0;
for(inti=0;i<=con;i++)
{
m_Image[i].SetWindowPos(NULL,x*i+move,0,0,0,SWP_NOSIZE);
m_Image[i].SetWindowPos(NULL,0,0,x,y,SWP_NOMOVE);
}
for(intj=0;j<=con;j++)
{
m_Image[con+1+j].SetWindowPos(NULL,x*j+move,y,0,0,SWP_NOSIZE);
m_Image[con+1+j].SetWindowPos(NULL,0,0,x,y,SWP_NOMOVE);