skyblue_PinTuDoc.cpp
上传用户:hbrsgg1
上传日期:2014-05-08
资源大小:2826k
文件大小:12k
源码类别:

其他智力游戏

开发平台:

C/C++

  1. /*++
  2. Copyright (c) AFE(Active-Free-Elegance)
  3. Module Name:
  4.     skyblue_PinTuDoc.cpp
  5. Abstract:
  6. Document , manage game's data-calculation and seralization
  7. Author:
  8.     Weijian Luo (Arthur Luo)   15-Jun-2005
  9. E-mail: skybluehacker@yahoo.com.cn
  10. Revision History:      1.0
  11. --*/
  12. #include "stdafx.h"
  13. #include "skyblue_PinTu.h"
  14. #include "skyblue_PinTuDoc.h"
  15. #include "skyblue_PinTuView.h"
  16. #include "MainFrm.h"
  17. #include "SettingDlg.h"
  18. #ifdef _DEBUG
  19. #define new DEBUG_NEW
  20. #undef THIS_FILE
  21. static char THIS_FILE[] = __FILE__;
  22. #endif
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CSkyblue_PinTuDoc
  25. IMPLEMENT_DYNCREATE(CSkyblue_PinTuDoc, CDocument)
  26. BEGIN_MESSAGE_MAP(CSkyblue_PinTuDoc, CDocument)
  27. //{{AFX_MSG_MAP(CSkyblue_PinTuDoc)
  28. ON_COMMAND(IDM_NEWGAME, OnNewgame)
  29. ON_COMMAND(IDM_SET, OnConfig)
  30. ON_COMMAND(IDM_USERPIC, OnUserpic)
  31. ON_COMMAND(IDM_PIC1, OnPic1)
  32. ON_COMMAND(IDM_PIC2, OnPic2)
  33. ON_COMMAND(IDM_PIC3, OnPic3)
  34. ON_COMMAND(IDM_PIC4, OnPic4)
  35. ON_COMMAND(ID_MENU_ORG_PIC_SHOW, OnMenuOrgPicShow)
  36. ON_UPDATE_COMMAND_UI(ID_MENU_ORG_PIC_SHOW, OnUpdateMenuOrgPicShow)
  37. //}}AFX_MSG_MAP
  38. END_MESSAGE_MAP()
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CSkyblue_PinTuDoc construction/destruction
  41. CSkyblue_PinTuDoc::CSkyblue_PinTuDoc()
  42. {
  43. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  44. //读取注册表游戏参数信息
  45. m_BMP_WIDTH=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("m_BMP_WIDTH"),300);
  46. m_BMP_HEIGHT=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("m_BMP_HEIGHT"),250);
  47. hnums=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("hnums"),4);
  48. vnums=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("vnums"),3);
  49. m_gamePicID=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("m_gamePicID"),IDB_BITMAP3);
  50. m_bMusic=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("m_bMusic"),FALSE);
  51. m_bShowOrgPic=AfxGetApp()->GetProfileInt(_T("游戏参数"),_T("m_bShowOrgPic"),TRUE);
  52. m_szMusicFileName=AfxGetApp()->GetProfileString(_T("游戏参数"),_T("m_szMusicFileName"),"");
  53. m_blankPos.row =hnums;
  54. m_blankPos.col =vnums;
  55. }
  56. CSkyblue_PinTuDoc::~CSkyblue_PinTuDoc()
  57. {
  58. //释放位图资源
  59. DeleteObject(m_bitmap);
  60. //写入注册表游戏参数信息
  61. AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("m_BMP_WIDTH"),m_BMP_WIDTH);
  62. AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("m_BMP_HEIGHT"),m_BMP_HEIGHT);
  63. AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("hnums"),hnums);
  64. AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("vnums"),vnums);
  65. AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("m_gamePicID"),m_gamePicID);
  66. AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("m_bMusic"),m_bMusic);
  67. AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("m_bShowOrgPic"),m_bShowOrgPic);
  68. AfxGetApp()->WriteProfileString(_T("游戏参数"),_T("m_szMusicFileName"),m_szMusicFileName);
  69. }
  70. /////////////////////////////////////////////////////////////////////////////
  71. // CSkyblue_PinTuDoc serialization
  72. void CSkyblue_PinTuDoc::Serialize(CArchive& ar)
  73. {
  74. if (ar.IsStoring())
  75. {
  76. // TODO: add storing code here
  77. }
  78. else
  79. {
  80. // TODO: add loading code here
  81. }
  82. }
  83. /////////////////////////////////////////////////////////////////////////////
  84. // CSkyblue_PinTuDoc diagnostics
  85. #ifdef _DEBUG
  86. void CSkyblue_PinTuDoc::AssertValid() const
  87. {
  88. CDocument::AssertValid();
  89. }
  90. void CSkyblue_PinTuDoc::Dump(CDumpContext& dc) const
  91. {
  92. CDocument::Dump(dc);
  93. }
  94. #endif //_DEBUG
  95. /////////////////////////////////////////////////////////////////////////////
  96. // CSkyblue_PinTuDoc commands
  97. //
  98. // 核心地图数据的初始化
  99. //
  100. void CSkyblue_PinTuDoc::MapInitial()
  101. {
  102. int i,j;
  103. //将原来各个位置的数据填好其所在的行ID,列ID
  104. for(i=1;i<=hnums;i++)
  105. {
  106. for(j=1;j<=vnums;j++)
  107. {
  108. m_map[i][j].row =i;
  109. m_map[i][j].col =j;
  110. }
  111. }
  112. }
  113. //
  114. //  处理键盘事件
  115. //
  116. void CSkyblue_PinTuDoc::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  117. {
  118. //根据按键作移动操作
  119. GameMove(nChar);
  120. //更新视图
  121. CObArray HintArray; //利用这个物件作更新的提示"hint"
  122. UpdateAllViews(NULL,0,&HintArray);
  123. //当该动作不为游戏初始化自动移动才再检测是否胜利
  124. if(/*(!m_bAutoMove) && */IsWin())
  125. {
  126. //胜利提示显示
  127. MessageBox(NULL,"成功闯关","拼图",MB_OK|MB_ICONINFORMATION);
  128. }
  129. }
  130. //
  131. //   根据按键输入指示命令作移动操作
  132. //
  133. void CSkyblue_PinTuDoc::GameMove(UINT nChar)
  134. {
  135. pos tempPos;
  136. //根据用户的按键置换移动方块图片
  137. switch(nChar)
  138. {
  139. case VK_LEFT:
  140. if(m_blankPos.row>1)
  141. {//移动方向保证不超出边界才移动置换
  142. //引用一个临时变量的方法做方块图片位置数据交还
  143. tempPos.row =m_blankPos.row-1;
  144. tempPos.col =m_blankPos.col ;
  145. m_map[m_blankPos.row][m_blankPos.col].row = m_map[tempPos.row][tempPos.col].row;
  146.             m_map[m_blankPos.row][m_blankPos.col].col = m_map[tempPos.row][tempPos.col].col;
  147.             
  148. tempPos.row = m_map[m_blankPos.row][m_blankPos.col].row;
  149.             tempPos.col = m_map[m_blankPos.row][m_blankPos.col].col;
  150.             
  151. //修改移动后的空白方块位置
  152. m_blankPos.row = m_blankPos.row - 1;
  153. }
  154. break;
  155. case VK_RIGHT:
  156. if(m_blankPos.row<hnums)
  157. {
  158. tempPos.row =m_blankPos.row+1;
  159. tempPos.col =m_blankPos.col ;
  160. m_map[m_blankPos.row][m_blankPos.col].row = m_map[tempPos.row][tempPos.col].row;
  161.             m_map[m_blankPos.row][m_blankPos.col].col = m_map[tempPos.row][tempPos.col].col;
  162.             tempPos.row = m_map[m_blankPos.row][m_blankPos.col].row;
  163.             tempPos.col = m_map[m_blankPos.row][m_blankPos.col].col;
  164.   
  165.             m_blankPos.row = m_blankPos.row + 1;
  166. }
  167. break;
  168. case VK_UP:
  169. if(m_blankPos.col>1)
  170. {
  171. tempPos.row =m_blankPos.row;
  172. tempPos.col =m_blankPos.col-1 ;
  173. m_map[m_blankPos.row][m_blankPos.col].row = m_map[tempPos.row][tempPos.col].row;
  174.             m_map[m_blankPos.row][m_blankPos.col].col = m_map[tempPos.row][tempPos.col].col;
  175.             tempPos.row = m_map[m_blankPos.row][m_blankPos.col].row;
  176.             tempPos.col = m_map[m_blankPos.row][m_blankPos.col].col;
  177.  
  178.             m_blankPos.col = m_blankPos.col - 1;
  179. }
  180. break;
  181. case VK_DOWN:
  182. if(m_blankPos.col<vnums)
  183. {
  184. tempPos.row =m_blankPos.row;
  185. tempPos.col =m_blankPos.col+1 ;
  186. m_map[m_blankPos.row][m_blankPos.col].row = m_map[tempPos.row][tempPos.col].row;
  187.             m_map[m_blankPos.row][m_blankPos.col].col = m_map[tempPos.row][tempPos.col].col;
  188.             tempPos.row = m_map[m_blankPos.row][m_blankPos.col].row;
  189.             tempPos.col = m_map[m_blankPos.row][m_blankPos.col].col;
  190.             m_blankPos.col = m_blankPos.col + 1;
  191. }
  192. break;
  193. }
  194. }
  195. //
  196. //  开始一个新游戏
  197. //
  198. void CSkyblue_PinTuDoc::OnNewgame() 
  199. {
  200. //根据当前图片的尺寸设置窗口大小
  201. SetWindow_N_ViewSize();
  202. //地图的初始化
  203. MapInitial();
  204. //打乱前将空白块起点放在右下角
  205. m_blankPos.row =hnums;
  206. m_blankPos.col =vnums;
  207. //打乱地图(随机移动n步)
  208. // m_bAutoMove = TRUE;
  209. GameMixMove();
  210. // m_bAutoMove = FALSE;
  211. //更新视图
  212. UpdateAllViews(NULL);
  213. }
  214. //
  215. // 游戏初始化,随机打乱图像
  216. //
  217. void CSkyblue_PinTuDoc::GameMixMove()
  218. {
  219. int i,temp;
  220. //以当前系统时间为随机种子
  221. srand(time(NULL));
  222. //随机走300步
  223. for(i=1;i<300;i++)
  224. {
  225. temp=rand()%4+1;
  226. switch(temp)
  227. {
  228. case 1:
  229. GameMove(VK_RIGHT);
  230. break;
  231. case 2:
  232. GameMove(VK_LEFT);
  233. break;
  234. case 3:
  235. GameMove(VK_UP);
  236. break;
  237. case 4:
  238. GameMove(VK_DOWN);
  239. break;
  240. }
  241. }
  242. }
  243. //
  244. //  参数配置
  245. //
  246. void CSkyblue_PinTuDoc::OnConfig() 
  247. {
  248. //弹出设置对话框
  249. CSettingDlg set;
  250. if(set.DoModal()==IDOK)
  251. {//确认则修改参数
  252. hnums=set.m_iCols;
  253. vnums=set.m_iRows;
  254. m_bMusic=set.m_bMusic;
  255. m_szMusicFileName=set.m_strMusicFileName;
  256. //音乐操作
  257. //根据配置对MCI设备发送播放或停止播放的指令
  258. if(m_bMusic==TRUE)
  259. {
  260. PlayMusic();
  261. }
  262. else
  263. {
  264. MCI_GENERIC_PARMS mciGP;
  265. mciSendCommand(m_wID,MCI_STOP,MCI_NOTIFY,(DWORD)(LPVOID)&mciGP);
  266. }
  267. OnNewgame();
  268. }
  269. }
  270. //
  271. //   检测是否胜利
  272. //
  273. BOOL CSkyblue_PinTuDoc::IsWin(void)
  274. {
  275. int i,j;
  276. //胜利的检测方法是判断地图的所有方块的内部
  277. //数据是否全为其行列数,是则表示排列好,胜利
  278. for(i = 1;i<=hnums;i++)
  279. {
  280. for(j = 1;j<=vnums;j++)
  281. {
  282. if(i !=m_blankPos.row || j != m_blankPos.col)
  283. if(m_map[i][j].row !=i || m_map[i][j].col !=j)
  284. return FALSE;
  285. }
  286. }
  287. return TRUE;
  288. }
  289. //
  290. //  播放背景音乐
  291. //
  292. //说明: 利用MCI机制控制媒体设备放音
  293. void CSkyblue_PinTuDoc::PlayMusic()
  294. {
  295. //前停止并关闭以前打开的设备(如果正在使用)
  296. MCI_GENERIC_PARMS mciGP;
  297. mciSendCommand(m_wID,MCI_CLOSE,MCI_NOTIFY,(DWORD)(LPVOID)&mciGP);
  298. //错误返回码定义
  299. DWORD dwReturn;
  300. //定义并填写打开设备的命令参数
  301. MCI_OPEN_PARMS mciOP;
  302. mciOP.lpstrDeviceType=NULL;
  303. mciOP.lpstrElementName=m_szMusicFileName;
  304. //打开设备
  305. dwReturn=mciSendCommand(NULL,MCI_OPEN,
  306. MCI_OPEN_ELEMENT,(DWORD)(LPVOID)&mciOP);
  307. if(dwReturn==0)
  308. {
  309. m_wID=mciOP.wDeviceID;
  310. }
  311. //播放
  312. MCI_PLAY_PARMS mciPP;
  313. mciSendCommand(m_wID,MCI_PLAY,
  314.    MCI_NOTIFY,(DWORD)(LPVOID)&mciPP);
  315. }
  316. //
  317. //   用户选择路径自定义图片
  318. //
  319. void CSkyblue_PinTuDoc::OnUserpic() 
  320. {
  321. //用文件对话框的方式选择播放的音乐
  322. CString filter="BMP文件(*.bmp)|*.bmp";
  323. CFileDialog picfile(TRUE,NULL,NULL,
  324. OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,filter);
  325. if(picfile.DoModal()==IDOK)
  326. {//确定后读入位图并开始游戏
  327. HBITMAP hbitmap;
  328. //按照尺寸m_BMP_WIDTH,m_BMP_HEIGHT读
  329. //入位图文件(根据源图比例放大与缩小)
  330. hbitmap=(HBITMAP)::LoadImage(NULL,
  331. picfile.GetPathName(),IMAGE_BITMAP,
  332. m_BMP_WIDTH,m_BMP_HEIGHT,LR_LOADFROMFILE);
  333. //弃旧选新
  334. m_bitmap.Detach();
  335. m_bitmap.Attach(hbitmap);
  336. //开始游戏
  337. CSkyblue_PinTuDoc::OnNewgame();
  338. }
  339. }
  340. //
  341. //   根据ID选取游戏的图片
  342. //
  343. void CSkyblue_PinTuDoc::PicSelect(UINT BMP_ID)
  344. {
  345. //记录当前所算的位图ID,并写入注册表
  346. //(以便下次运行可以直接用该图片)
  347. m_gamePicID = BMP_ID;
  348. AfxGetApp()->WriteProfileInt(_T("游戏参数"),_T("m_gamePicID"), BMP_ID);
  349. //卸载旧的,重新载入新的选取位图
  350. m_bitmap.Detach();
  351. m_bitmap.LoadBitmap(BMP_ID);
  352. //开始游戏
  353. CSkyblue_PinTuDoc::OnNewgame();
  354. }
  355. //
  356. // 图像选取 1
  357. //
  358. void CSkyblue_PinTuDoc::OnPic1() 
  359. {
  360. PicSelect(IDB_BITMAP1);
  361. }
  362. void CSkyblue_PinTuDoc::OnPic2() 
  363. {
  364. PicSelect(IDB_BITMAP2);
  365. }
  366. void CSkyblue_PinTuDoc::OnPic3() 
  367. {
  368. PicSelect(IDB_BITMAP3);
  369. }
  370. void CSkyblue_PinTuDoc::OnPic4() 
  371. {
  372. PicSelect(IDB_BITMAP4);
  373. }
  374. //
  375. // 设置窗口与两视图的大小
  376. //
  377. void CSkyblue_PinTuDoc::SetWindow_N_ViewSize()
  378. {
  379. BITMAP bmp;
  380. //获取当前选定的位图信息(目的:尺寸大小数据)
  381. GetObject(m_bitmap.m_hObject,sizeof(BITMAP), (LPSTR)&bmp);
  382. m_bmpWidth = bmp.bmWidth;
  383. m_bmpHeight = bmp.bmHeight;
  384. //按照当前的行列数切割,计算每块方块单元cell的宽度和高度
  385. m_cellWidth=m_bmpWidth/hnums;
  386. m_cellHeight=m_bmpHeight/vnums;
  387. int winWidth;
  388. int winHeight;
  389. if(m_bShowOrgPic)
  390. {
  391. //计算子窗口的大小(2个位图的空间+边框空间)
  392. winWidth = m_bmpWidth*2+20;
  393. winHeight = m_bmpHeight+55;
  394. }
  395. else
  396. {
  397. //计算子窗口的大小(1个位图的空间+边框空间)
  398. winWidth = m_bmpWidth+20;
  399. winHeight = m_bmpHeight+55;
  400. }
  401. //立刻设置游戏窗口的大小,以最佳方式显示
  402. ::AfxGetMainWnd()->SetWindowPos(NULL,0,0,winWidth,winHeight,SWP_NOMOVE );
  403. //修改目标样板图像与游戏区域图像的2个子视图空间大小
  404. CMainFrame *pMainFrame = (CMainFrame *)::AfxGetMainWnd();
  405. //行信息
  406. pMainFrame->m_wndSplitter.SetRowInfo(0,m_bmpHeight+20,m_bmpHeight);
  407. //列信息
  408. pMainFrame->m_wndSplitter.SetColumnInfo(0,m_bmpWidth,m_bmpWidth);
  409. pMainFrame->m_wndSplitter.SetColumnInfo(1,m_bmpWidth,m_bmpWidth);
  410. //呼叫修改生效
  411. pMainFrame->m_wndSplitter.RecalcLayout();
  412. }
  413. //
  414. //  修改窗口是否显示源图的菜单消息处理
  415. //
  416. void CSkyblue_PinTuDoc::OnMenuOrgPicShow() 
  417. {
  418. //修改原来的显示
  419. m_bShowOrgPic = !m_bShowOrgPic;
  420. //重设窗口大小与视图分布
  421. SetWindow_N_ViewSize();
  422. }
  423. void CSkyblue_PinTuDoc::OnUpdateMenuOrgPicShow(CCmdUI* pCmdUI) 
  424. {
  425. pCmdUI->SetCheck(m_bShowOrgPic);
  426. }