www.gusucode.com > VC++拼图游戏源代码源码程序 > VC++拼图游戏源代码源码程序\code\skyblue_PinTuDoc.cpp
//Download by http://www.NewXing.com /*++ Copyright (c) AFE(Active-Free-Elegance) Module Name: skyblue_PinTuDoc.cpp Abstract: Document , manage game's data-calculation and seralization Author: Weijian Luo (Arthur Luo) 15-Jun-2005 E-mail: skybluehacker@yahoo.com.cn Revision History: 1.0 --*/ #include "stdafx.h" #include "skyblue_PinTu.h" #include "skyblue_PinTuDoc.h" #include "skyblue_PinTuView.h" #include "MainFrm.h" #include "SettingDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CSkyblue_PinTuDoc IMPLEMENT_DYNCREATE(CSkyblue_PinTuDoc, CDocument) BEGIN_MESSAGE_MAP(CSkyblue_PinTuDoc, CDocument) //{{AFX_MSG_MAP(CSkyblue_PinTuDoc) ON_COMMAND(IDM_NEWGAME, OnNewgame) ON_COMMAND(IDM_SET, OnConfig) ON_COMMAND(IDM_USERPIC, OnUserpic) ON_COMMAND(IDM_PIC1, OnPic1) ON_COMMAND(IDM_PIC2, OnPic2) ON_COMMAND(IDM_PIC3, OnPic3) ON_COMMAND(IDM_PIC4, OnPic4) ON_COMMAND(ID_MENU_ORG_PIC_SHOW, OnMenuOrgPicShow) ON_UPDATE_COMMAND_UI(ID_MENU_ORG_PIC_SHOW, OnUpdateMenuOrgPicShow) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSkyblue_PinTuDoc construction/destruction CSkyblue_PinTuDoc::CSkyblue_PinTuDoc() { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); //读取注册表游戏参数信息 m_BMP_WIDTH=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("m_BMP_WIDTH"),300); m_BMP_HEIGHT=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("m_BMP_HEIGHT"),250); hnums=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("hnums"),4); vnums=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("vnums"),3); m_gamePicID=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("m_gamePicID"),IDB_BITMAP3); m_bMusic=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("m_bMusic"),FALSE); m_bShowOrgPic=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("m_bShowOrgPic"),TRUE); m_szMusicFileName=AfxGetApp()->GetProfileString(_T("游戏参数"),_T("m_szMusicFileName"),""); m_blankPos.row =hnums; m_blankPos.col =vnums; } CSkyblue_PinTuDoc::~CSkyblue_PinTuDoc() { //释放位图资源 DeleteObject(m_bitmap); //写入注册表游戏参数信息 AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("m_BMP_WIDTH"),m_BMP_WIDTH); AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("m_BMP_HEIGHT"),m_BMP_HEIGHT); AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("hnums"),hnums); AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("vnums"),vnums); AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("m_gamePicID"),m_gamePicID); AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("m_bMusic"),m_bMusic); AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("m_bShowOrgPic"),m_bShowOrgPic); AfxGetApp()->WriteProfileString(_T("游戏参数"),_T("m_szMusicFileName"),m_szMusicFileName); } ///////////////////////////////////////////////////////////////////////////// // CSkyblue_PinTuDoc serialization void CSkyblue_PinTuDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { // TODO: add storing code here } else { // TODO: add loading code here } } ///////////////////////////////////////////////////////////////////////////// // CSkyblue_PinTuDoc diagnostics #ifdef _DEBUG void CSkyblue_PinTuDoc::AssertValid() const { CDocument::AssertValid(); } void CSkyblue_PinTuDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CSkyblue_PinTuDoc commands // // 核心地图数据的初始化 // void CSkyblue_PinTuDoc::MapInitial() { int i,j; //将原来各个位置的数据填好其所在的行ID,列ID for(i=1;i<=hnums;i++) { for(j=1;j<=vnums;j++) { m_map[i][j].row =i; m_map[i][j].col =j; } } } // // 处理键盘事件 // void CSkyblue_PinTuDoc::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { //根据按键作移动操作 GameMove(nChar); //更新视图 CObArray HintArray; //利用这个物件作更新的提示"hint" UpdateAllViews(NULL,0,&HintArray); //当该动作不为游戏初始化自动移动才再检测是否胜利 if(/*(!m_bAutoMove) && */IsWin()) { //胜利提示显示 MessageBox(NULL,"成功闯关","拼图",MB_OK|MB_ICONINFORMATION); } } // // 根据按键输入指示命令作移动操作 // void CSkyblue_PinTuDoc::GameMove(UINT nChar) { pos tempPos; //根据用户的按键置换移动方块图片 switch(nChar) { case VK_LEFT: if(m_blankPos.row>1) {//移动方向保证不超出边界才移动置换 //引用一个临时变量的方法做方块图片位置数据交还 tempPos.row =m_blankPos.row-1; tempPos.col =m_blankPos.col ; m_map[m_blankPos.row][m_blankPos.col].row = m_map[tempPos.row][tempPos.col].row; m_map[m_blankPos.row][m_blankPos.col].col = m_map[tempPos.row][tempPos.col].col; tempPos.row = m_map[m_blankPos.row][m_blankPos.col].row; tempPos.col = m_map[m_blankPos.row][m_blankPos.col].col; //修改移动后的空白方块位置 m_blankPos.row = m_blankPos.row - 1; } break; case VK_RIGHT: if(m_blankPos.row<hnums) { tempPos.row =m_blankPos.row+1; tempPos.col =m_blankPos.col ; m_map[m_blankPos.row][m_blankPos.col].row = m_map[tempPos.row][tempPos.col].row; m_map[m_blankPos.row][m_blankPos.col].col = m_map[tempPos.row][tempPos.col].col; tempPos.row = m_map[m_blankPos.row][m_blankPos.col].row; tempPos.col = m_map[m_blankPos.row][m_blankPos.col].col; m_blankPos.row = m_blankPos.row + 1; } break; case VK_UP: if(m_blankPos.col>1) { tempPos.row =m_blankPos.row; tempPos.col =m_blankPos.col-1 ; m_map[m_blankPos.row][m_blankPos.col].row = m_map[tempPos.row][tempPos.col].row; m_map[m_blankPos.row][m_blankPos.col].col = m_map[tempPos.row][tempPos.col].col; tempPos.row = m_map[m_blankPos.row][m_blankPos.col].row; tempPos.col = m_map[m_blankPos.row][m_blankPos.col].col; m_blankPos.col = m_blankPos.col - 1; } break; case VK_DOWN: if(m_blankPos.col<vnums) { tempPos.row =m_blankPos.row; tempPos.col =m_blankPos.col+1 ; m_map[m_blankPos.row][m_blankPos.col].row = m_map[tempPos.row][tempPos.col].row; m_map[m_blankPos.row][m_blankPos.col].col = m_map[tempPos.row][tempPos.col].col; tempPos.row = m_map[m_blankPos.row][m_blankPos.col].row; tempPos.col = m_map[m_blankPos.row][m_blankPos.col].col; m_blankPos.col = m_blankPos.col + 1; } break; } } // // 开始一个新游戏 // void CSkyblue_PinTuDoc::OnNewgame() { //根据当前图片的尺寸设置窗口大小 SetWindow_N_ViewSize(); //地图的初始化 MapInitial(); //打乱前将空白块起点放在右下角 m_blankPos.row =hnums; m_blankPos.col =vnums; //打乱地图(随机移动n步) // m_bAutoMove = TRUE; GameMixMove(); // m_bAutoMove = FALSE; //更新视图 UpdateAllViews(NULL); } // // 游戏初始化,随机打乱图像 // void CSkyblue_PinTuDoc::GameMixMove() { int i,temp; //以当前系统时间为随机种子 srand(time(NULL)); //随机走300步 for(i=1;i<300;i++) { temp=rand()%4+1; switch(temp) { case 1: GameMove(VK_RIGHT); break; case 2: GameMove(VK_LEFT); break; case 3: GameMove(VK_UP); break; case 4: GameMove(VK_DOWN); break; } } } // // 参数配置 // void CSkyblue_PinTuDoc::OnConfig() { //弹出设置对话框 CSettingDlg set; if(set.DoModal()==IDOK) {//确认则修改参数 hnums=set.m_iCols; vnums=set.m_iRows; m_bMusic=set.m_bMusic; m_szMusicFileName=set.m_strMusicFileName; //音乐操作 //根据配置对MCI设备发送播放或停止播放的指令 if(m_bMusic==TRUE) { PlayMusic(); } else { MCI_GENERIC_PARMS mciGP; mciSendCommand(m_wID,MCI_STOP,MCI_NOTIFY,(DWORD)(LPVOID)&mciGP); } OnNewgame(); } } // // 检测是否胜利 // BOOL CSkyblue_PinTuDoc::IsWin(void) { int i,j; //胜利的检测方法是判断地图的所有方块的内部 //数据是否全为其行列数,是则表示排列好,胜利 for(i = 1;i<=hnums;i++) { for(j = 1;j<=vnums;j++) { if(i !=m_blankPos.row || j != m_blankPos.col) if(m_map[i][j].row !=i || m_map[i][j].col !=j) return FALSE; } } return TRUE; } // // 播放背景音乐 // //说明: 利用MCI机制控制媒体设备放音 void CSkyblue_PinTuDoc::PlayMusic() { //前停止并关闭以前打开的设备(如果正在使用) MCI_GENERIC_PARMS mciGP; mciSendCommand(m_wID,MCI_CLOSE,MCI_NOTIFY,(DWORD)(LPVOID)&mciGP); //错误返回码定义 DWORD dwReturn; //定义并填写打开设备的命令参数 MCI_OPEN_PARMS mciOP; mciOP.lpstrDeviceType=NULL; mciOP.lpstrElementName=m_szMusicFileName; //打开设备 dwReturn=mciSendCommand(NULL,MCI_OPEN, MCI_OPEN_ELEMENT,(DWORD)(LPVOID)&mciOP); if(dwReturn==0) { m_wID=mciOP.wDeviceID; } //播放 MCI_PLAY_PARMS mciPP; mciSendCommand(m_wID,MCI_PLAY, MCI_NOTIFY,(DWORD)(LPVOID)&mciPP); } // // 用户选择路径自定义图片 // void CSkyblue_PinTuDoc::OnUserpic() { //用文件对话框的方式选择播放的音乐 CString filter="BMP文件(*.bmp)|*.bmp"; CFileDialog picfile(TRUE,NULL,NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,filter); if(picfile.DoModal()==IDOK) {//确定后读入位图并开始游戏 HBITMAP hbitmap; //按照尺寸m_BMP_WIDTH,m_BMP_HEIGHT读 //入位图文件(根据源图比例放大与缩小) hbitmap=(HBITMAP)::LoadImage(NULL, picfile.GetPathName(),IMAGE_BITMAP, m_BMP_WIDTH,m_BMP_HEIGHT,LR_LOADFROMFILE); //弃旧选新 m_bitmap.Detach(); m_bitmap.Attach(hbitmap); //开始游戏 CSkyblue_PinTuDoc::OnNewgame(); } } // // 根据ID选取游戏的图片 // void CSkyblue_PinTuDoc::PicSelect(UINT BMP_ID) { //记录当前所算的位图ID,并写入注册表 //(以便下次运行可以直接用该图片) m_gamePicID = BMP_ID; AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("m_gamePicID"), BMP_ID); //卸载旧的,重新载入新的选取位图 m_bitmap.Detach(); m_bitmap.LoadBitmap(BMP_ID); //开始游戏 CSkyblue_PinTuDoc::OnNewgame(); } // // 图像选取 1 // void CSkyblue_PinTuDoc::OnPic1() { PicSelect(IDB_BITMAP1); } void CSkyblue_PinTuDoc::OnPic2() { PicSelect(IDB_BITMAP2); } void CSkyblue_PinTuDoc::OnPic3() { PicSelect(IDB_BITMAP3); } void CSkyblue_PinTuDoc::OnPic4() { PicSelect(IDB_BITMAP4); } // // 设置窗口与两视图的大小 // void CSkyblue_PinTuDoc::SetWindow_N_ViewSize() { BITMAP bmp; //获取当前选定的位图信息(目的:尺寸大小数据) GetObject(m_bitmap.m_hObject,sizeof(BITMAP), (LPSTR)&bmp); m_bmpWidth = bmp.bmWidth; m_bmpHeight = bmp.bmHeight; //按照当前的行列数切割,计算每块方块单元cell的宽度和高度 m_cellWidth=m_bmpWidth/hnums; m_cellHeight=m_bmpHeight/vnums; int winWidth; int winHeight; if(m_bShowOrgPic) { //计算子窗口的大小(2个位图的空间+边框空间) winWidth = m_bmpWidth*2+20; winHeight = m_bmpHeight+55; } else { //计算子窗口的大小(1个位图的空间+边框空间) winWidth = m_bmpWidth+20; winHeight = m_bmpHeight+55; } //立刻设置游戏窗口的大小,以最佳方式显示 ::AfxGetMainWnd()->SetWindowPos(NULL,0,0,winWidth,winHeight,SWP_NOMOVE ); //修改目标样板图像与游戏区域图像的2个子视图空间大小 CMainFrame *pMainFrame = (CMainFrame *)::AfxGetMainWnd(); //行信息 pMainFrame->m_wndSplitter.SetRowInfo(0,m_bmpHeight+20,m_bmpHeight); //列信息 pMainFrame->m_wndSplitter.SetColumnInfo(0,m_bmpWidth,m_bmpWidth); pMainFrame->m_wndSplitter.SetColumnInfo(1,m_bmpWidth,m_bmpWidth); //呼叫修改生效 pMainFrame->m_wndSplitter.RecalcLayout(); } // // 修改窗口是否显示源图的菜单消息处理 // void CSkyblue_PinTuDoc::OnMenuOrgPicShow() { //修改原来的显示 m_bShowOrgPic = !m_bShowOrgPic; //重设窗口大小与视图分布 SetWindow_N_ViewSize(); } void CSkyblue_PinTuDoc::OnUpdateMenuOrgPicShow(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_bShowOrgPic); }