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

其他智力游戏

开发平台:

Visual C++

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