EightQueenDlg.cpp
上传用户:hncsjd
上传日期:2022-07-08
资源大小:3772k
文件大小:11k
源码类别:

其他智力游戏

开发平台:

Visual C++

  1. // EightQueenDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "EightQueen.h"
  5. #include "EightQueenDlg.h"
  6. #include "QueenPanel.h"
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CAboutDlg dialog used for App About
  14. class CAboutDlg : public CDialog
  15. {
  16. public:
  17. CAboutDlg();
  18. // Dialog Data
  19. //{{AFX_DATA(CAboutDlg)
  20. enum { IDD = IDD_ABOUTBOX };
  21. //}}AFX_DATA
  22. // ClassWizard generated virtual function overrides
  23. //{{AFX_VIRTUAL(CAboutDlg)
  24. protected:
  25. virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  26. //}}AFX_VIRTUAL
  27. // Implementation
  28. protected:
  29. //{{AFX_MSG(CAboutDlg)
  30. virtual BOOL OnInitDialog();
  31. //}}AFX_MSG
  32. DECLARE_MESSAGE_MAP()
  33. };
  34. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  35. {
  36. //{{AFX_DATA_INIT(CAboutDlg)
  37. //}}AFX_DATA_INIT
  38. }
  39. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  40. {
  41. CDialog::DoDataExchange(pDX);
  42. //{{AFX_DATA_MAP(CAboutDlg)
  43. //}}AFX_DATA_MAP
  44. }
  45. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  46. //{{AFX_MSG_MAP(CAboutDlg)
  47. //}}AFX_MSG_MAP
  48. END_MESSAGE_MAP()
  49. /////////////////////////////////////////////////////////////////////////////
  50. // CEightQueenDlg dialog
  51. CEightQueenDlg::CEightQueenDlg(CWnd* pParent /*=NULL*/)
  52. : CDialog(CEightQueenDlg::IDD, pParent)
  53. {
  54. //{{AFX_DATA_INIT(CEightQueenDlg)
  55. //}}AFX_DATA_INIT
  56. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  57. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  58. }
  59. void CEightQueenDlg::DoDataExchange(CDataExchange* pDX)
  60. {
  61. CDialog::DoDataExchange(pDX);
  62. //{{AFX_DATA_MAP(CEightQueenDlg)
  63. DDX_Control(pDX, IDC_QUEEN_PANEL, m_panel);
  64. //}}AFX_DATA_MAP
  65. }
  66. BEGIN_MESSAGE_MAP(CEightQueenDlg, CDialog)
  67. //{{AFX_MSG_MAP(CEightQueenDlg)
  68. ON_WM_SYSCOMMAND()
  69. ON_WM_PAINT()
  70. ON_WM_QUERYDRAGICON()
  71. ON_BN_CLICKED(IDC_START, OnStart)
  72. ON_BN_CLICKED(IDC_PAUSE, OnPause)
  73. ON_BN_CLICKED(IDC_CONTINUE, OnContinue)
  74. ON_WM_CLOSE()
  75. ON_BN_CLICKED(IDC_STEP_BY, OnStepBy)
  76. ON_BN_CLICKED(IDC_ABOUT, OnAbout)
  77. ON_BN_CLICKED(IDC_STOP, OnStop)
  78. ON_BN_CLICKED(IDC_NO_INT, OnNoInt)
  79. //}}AFX_MSG_MAP
  80. END_MESSAGE_MAP()
  81. /////////////////////////////////////////////////////////////////////////////
  82. // CEightQueenDlg message handlers
  83. BOOL CEightQueenDlg::OnInitDialog()
  84. {
  85. CDialog::OnInitDialog();
  86. // Add "About..." menu item to system menu.
  87. // IDM_ABOUTBOX must be in the system command range.
  88. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  89. ASSERT(IDM_ABOUTBOX < 0xF000);
  90. CMenu* pSysMenu = GetSystemMenu(FALSE);
  91. if (pSysMenu != NULL)
  92. {
  93. CString strAboutMenu;
  94. strAboutMenu.LoadString(IDS_ABOUTBOX);
  95. if (!strAboutMenu.IsEmpty())
  96. {
  97. pSysMenu->AppendMenu(MF_SEPARATOR);
  98. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  99. }
  100. }
  101. // Set the icon for this dialog.  The framework does this automatically
  102. //  when the application's main window is not a dialog
  103. SetIcon(m_hIcon, TRUE); // Set big icon
  104. SetIcon(m_hIcon, FALSE); // Set small icon
  105. // TODO: Add extra initialization her
  106. this_mutex = CreateMutex(NULL,FALSE,NULL);
  107. pause_event = CreateEvent( 
  108. NULL,     // no security attributes
  109. TRUE,    // manual-reset event
  110. FALSE,     // initial state is signaled
  111. NULL);  
  112. GetDlgItem(IDC_BOARD_SIZE)->SetWindowText("8");
  113. m_panel.SetSize(8);
  114. CButton *step = (CButton *)GetDlgItem(IDC_STEP_BY);
  115. m_step = (step->GetCheck()==BST_CHECKED)?TRUE:FALSE;
  116. CButton *no_int = (CButton *)GetDlgItem(IDC_NO_INT);
  117. m_no_int = (step->GetCheck()==BST_CHECKED)?TRUE:FALSE;
  118. canceling = running = FALSE;
  119. UpdateUI();
  120. return TRUE;  // return TRUE  unless you set the focus to a control
  121. }
  122. void CEightQueenDlg::OnSysCommand(UINT nID, LPARAM lParam)
  123. {
  124. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  125. {
  126. CAboutDlg dlgAbout;
  127. dlgAbout.DoModal();
  128. }
  129. else
  130. {
  131. CDialog::OnSysCommand(nID, lParam);
  132. }
  133. }
  134. // If you add a minimize button to your dialog, you will need the code below
  135. //  to draw the icon.  For MFC applications using the document/view model,
  136. //  this is automatically done for you by the framework.
  137. void CEightQueenDlg::OnPaint() 
  138. {
  139. if (IsIconic())
  140. {
  141. CPaintDC dc(this); // device context for painting
  142. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  143. // Center icon in client rectangle
  144. int cxIcon = GetSystemMetrics(SM_CXICON);
  145. int cyIcon = GetSystemMetrics(SM_CYICON);
  146. CRect rect;
  147. GetClientRect(&rect);
  148. int x = (rect.Width() - cxIcon + 1) / 2;
  149. int y = (rect.Height() - cyIcon + 1) / 2;
  150. // Draw the icon
  151. dc.DrawIcon(x, y, m_hIcon);
  152. }
  153. else
  154. {
  155. CDialog::OnPaint();
  156. }
  157. }
  158. // The system calls this to obtain the cursor to display while the user drags
  159. //  the minimized window.
  160. HCURSOR CEightQueenDlg::OnQueryDragIcon()
  161. {
  162. return (HCURSOR) m_hIcon;
  163. }
  164. void CEightQueenDlg::OnStart() 
  165. {
  166. // TODO: Add your control notification handler code here
  167. DWORD dwThreadId; 
  168.     HANDLE hThread;    
  169. CString str;
  170. GetDlgItem(IDC_BOARD_SIZE)->GetWindowText(str);
  171. int newn = atoi(str);
  172. if( newn<=0 )
  173. {
  174. MessageBox("大小不能小于1", "警告", MB_OK);
  175. return;
  176. }
  177. else  n = newn;
  178. m_panel.SetSize(n);
  179. step = m_step;
  180. no_int = m_no_int;
  181. running = TRUE;
  182. pausing = canceling = FALSE;
  183. UpdateUI();
  184.     hThread = CreateThread( 
  185.         NULL,                        // default security attributes 
  186.         0,                           // use default stack size  
  187.         ThreadGo,                  // thread function 
  188.         this,                // argument to thread function 
  189.         0,                           // use default creation flags 
  190.         &dwThreadId);                // returns the thread identifier 
  191. // Check the return value for success. 
  192. if (hThread == NULL)
  193. MessageBox( NULL, "CreateThread failed.", MB_OK );
  194. }
  195. DWORD WINAPI CEightQueenDlg::ThreadGo( LPVOID lpParam )
  196. CEightQueenDlg *dlg = (CEightQueenDlg *)lpParam;    
  197. dlg->Go();
  198.     return 0; 
  199. void WINAPI CEightQueenDlg::Go( )
  200. {
  201.     count = 0;
  202.     queen = new int[n];
  203.     rk = new BOOLEAN[2 * n - 1];
  204.     lk = new BOOLEAN[2 * n - 1];
  205.     mk = new BOOLEAN[n];
  206.     for(int i = 0; i < n; i++)
  207. queen[i] = -1;
  208. memset(rk, 0, (2*n-1)*sizeof(BOOLEAN));
  209. memset(lk, 0, (2*n-1)*sizeof(BOOLEAN));
  210. memset(mk, 0, n*sizeof(BOOLEAN));
  211. ResetEvent(pause_event);
  212.     Step(0);
  213. delete [] queen;
  214. delete [] rk;
  215. delete [] lk;
  216. delete [] mk;
  217. if(!canceling)
  218. {
  219. TCHAR msg[30];
  220. sprintf(msg, "找到%d种组合。", count);
  221. MessageBox(msg, "八皇后", MB_OK);
  222. }
  223. count = 0;
  224. canceling = running = FALSE;
  225. UpdateUI();
  226. }
  227. /**
  228. * 安排皇后的递归算法:   
  229. */
  230. void WINAPI CEightQueenDlg::Step(int i)
  231. {
  232.     for( int j = 0; j < n; j++ )
  233. {
  234. WaitForSingleObject(this_mutex, INFINITE);
  235. if(canceling)  return;
  236. ReleaseMutex(this_mutex);
  237. if( !mk[j] && !rk[i + j]  && !lk[n - 1 + i - j] )
  238. {
  239. queen[i] = j;
  240. rk[i + j] = TRUE;
  241. lk[n - 1 + i - j] = TRUE;
  242. mk[j] = TRUE;
  243. if( i == n - 1 )
  244. {
  245. count++;          
  246. UpdateQPanel(i, queen[i]);   
  247. WaitForSingleObject(this_mutex,INFINITE);
  248. if(!step&&!no_int)
  249. {
  250. ReleaseMutex(this_mutex);
  251. UpdateUI();
  252. DoPause();   
  253. }
  254. else
  255. {
  256. ReleaseMutex(this_mutex);
  257. }
  258. }
  259. else
  260. {
  261. UpdateQPanel(i, queen[i]);
  262. Step(i + 1);
  263. }
  264. queen[i] = -1;
  265. rk[i + j] = FALSE;
  266. lk[i + n - 1 - j] = FALSE;
  267. mk[j] = FALSE;
  268. UpdateQPanel(i, queen[i]);
  269. }
  270.     }
  271. }
  272. void CEightQueenDlg::OnPause() 
  273. {
  274. // TODO: Add your control notification handler code here
  275. WaitForSingleObject(this_mutex,INFINITE);
  276. step = TRUE;
  277. if(pausing)  SetEvent(pause_event);
  278. ReleaseMutex(this_mutex);    
  279. UpdateUI();
  280. }
  281. void CEightQueenDlg::OnContinue()
  282. {
  283. // TODO: Add your control notification handler code here
  284. WaitForSingleObject(this_mutex,INFINITE);
  285. step = FALSE;
  286. if(pausing)  SetEvent(pause_event);
  287. ReleaseMutex(this_mutex);
  288. UpdateUI();
  289. }
  290. void CEightQueenDlg::OnClose() 
  291. {
  292. // TODO: Add your message handler code here and/or call default
  293. if(running)
  294. this->MessageBox("正在运行,请先按“停止”按钮停止。", "警告");
  295. else  CDialog::EndDialog(0);
  296. }
  297. void CEightQueenDlg::OnStepBy() 
  298. {
  299. CButton *step = (CButton *)GetDlgItem(IDC_STEP_BY);
  300. m_step = (step->GetCheck()==BST_CHECKED)?TRUE:FALSE;
  301. if(m_step)
  302. {
  303. CButton *autoBtn = (CButton *)GetDlgItem(IDC_NO_INT);
  304. autoBtn->SetCheck(FALSE);
  305. m_no_int = FALSE;
  306. }
  307. }
  308. void CEightQueenDlg::UpdateUI()
  309. {
  310. WaitForSingleObject(this_mutex, INFINITE);
  311. GetDlgItem(IDC_BOARD_SIZE)->EnableWindow(!running&&!canceling);
  312. GetDlgItem(IDC_NO_INT)->EnableWindow(!running&&!canceling);
  313. GetDlgItem(IDC_STEP_BY)->EnableWindow(!running&&!canceling);
  314. GetDlgItem(IDC_START)->EnableWindow(!running&&!canceling);
  315. GetDlgItem(IDC_PAUSE)->EnableWindow(running&&!canceling);
  316. GetDlgItem(IDC_CONTINUE)->EnableWindow(running&&!canceling&&pausing);
  317. GetDlgItem(IDC_STOP)->EnableWindow(running&&!canceling);
  318. ReleaseMutex(this_mutex);
  319. }
  320. void CEightQueenDlg::OnAbout() 
  321. {
  322. // TODO: Add your control notification handler code here
  323. CAboutDlg dlgAbout;
  324. dlgAbout.DoModal();
  325. }
  326. void CEightQueenDlg::UpdateQPanel(int *queen)
  327. {
  328. m_panel.SetQueen(queen);
  329. WaitForSingleObject(this_mutex, INFINITE);
  330. if( step )
  331. {
  332. ReleaseMutex(this_mutex);
  333. DoPause();
  334. else  ReleaseMutex(this_mutex);
  335. }
  336. void CEightQueenDlg::UpdateQPanel(int row, int col)
  337. {
  338. m_panel.SetQueen(row, col);
  339. if(step)
  340. {
  341. ReleaseMutex(this_mutex);
  342. DoPause();
  343. else  ReleaseMutex(this_mutex);
  344. }
  345. void CEightQueenDlg::DoPause()
  346. {
  347. WaitForSingleObject(this_mutex, INFINITE);
  348. pausing = TRUE;
  349. ReleaseMutex(this_mutex);
  350. UpdateUI();
  351. WaitForSingleObject(pause_event,INFINITE);
  352. ResetEvent(pause_event);
  353. WaitForSingleObject(this_mutex, INFINITE);
  354. pausing  = FALSE;
  355. ReleaseMutex(this_mutex);
  356. UpdateUI();
  357. }
  358. void CEightQueenDlg::OnStop() 
  359. {
  360. // TODO: Add your control notification handler code here
  361. WaitForSingleObject(this_mutex, INFINITE);
  362. step = FALSE;
  363. canceling = TRUE;
  364. if(pausing)  SetEvent(pause_event);
  365. ReleaseMutex(this_mutex);
  366. UpdateUI();
  367. }
  368. void CEightQueenDlg::OnNoInt() 
  369. {
  370. // TODO: Add your control notification handler code here
  371. CButton *autoBtn = (CButton *)GetDlgItem(IDC_NO_INT);
  372. m_no_int = (autoBtn->GetCheck()==BST_CHECKED)?TRUE:FALSE;
  373. if( m_no_int )
  374. {
  375. CButton *step = (CButton *)GetDlgItem(IDC_STEP_BY);
  376. step->SetCheck(FALSE);
  377. m_step = FALSE;
  378. }
  379. }
  380. BOOL CAboutDlg::OnInitDialog() 
  381. {
  382. CDialog::OnInitDialog();
  383. // TODO: Add extra initialization here
  384. return TRUE;
  385. }