程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 八皇後問題求解動態圖形演示

八皇後問題求解動態圖形演示

編輯:關於C語言

    這是我以前用Delphi寫的一個教學軟件。內容是關於“八皇後”問題的求解動態圖形演示。這個軟件采用多線程設計,包含了遞歸回溯與非遞歸回溯兩種算法,還可隨時調整演示速度,界面共有五種前景和五種背景圖形。包含所有源程序和資源文件。
    以下是軟件截圖:

    其中的核心Unit如下: 

  1. unit Unit2;  
  2.  
  3. interface  
  4.  
  5. uses  
  6.   Windows, Messages, Classes, SysUtils, StdCtrls, Graphics;  
  7.  
  8. type  
  9.   TQS = function(n: integer): boolean of object;  
  10.   TQueenThread = class(TThread)  
  11.   private  
  12.     FBackgroundBitmap: TBitmap;  
  13.     FQueenIcon, FSeekIcon, FClashIcon: TIcon;  
  14.     FCanvas: TCanvas;  
  15.     FCounter: integer;  
  16.     FQueen: integer;  
  17.     FDemo: boolean;  
  18.     FDelay: integer;  
  19.     FClashRestoreIcon, FSeekQueenIcon: TIcon;  
  20.     FRecursion: boolean;  
  21.     QS: TQS;  
  22.     procedure SeekFinish(Sender: TObject);  
  23.     function QSeek(n: integer): boolean;  
  24.     function QSeekNonrecursion(n: integer): boolean;  
  25.     function QClash(n: integer): boolean;  
  26.     procedure ShowDelete;  
  27.     procedure ShowDraw;  
  28.     procedure ShowClashRestore;  
  29.     procedure SetRecursion(Value: boolean);  
  30.   protected  
  31.     procedure Execute; override;  
  32.   public 
  33.     constructor Create(ABackgroundBitmap: TBitmap; AQueenIcon, ASeekIcon, AClashIcon: TIcon; ACanvas: TCanvas);  
  34.     procedure ShowResult;  
  35.     property Demo: boolean write FDemo;  
  36.     property Delay: integer write FDelay;  
  37.     property Recursion: boolean write SetRecursion;  
  38.   end;  
  39.  
  40. implementation  
  41.  
  42. uses Unit1;  
  43.  
  44. constructor TQueenThread.Create(ABackgroundBitmap: TBitmap; AQueenIcon, ASeekIcon, AClashIcon: TIcon; ACanvas: TCanvas);  
  45. begin 
  46.   FBackgroundBitmap := ABackgroundBitmap;  
  47.   FQueenIcon := AQueenIcon;  
  48.   FSeekIcon := ASeekIcon;  
  49.   FClashIcon := AClashIcon;  
  50.   FCanvas := ACanvas;  
  51.   FCounter := 0;  
  52.   FDemo := true;  
  53.   FDelay := 400;  
  54.   SetRecursion(true);  
  55.   OnTerminate := SeekFinish;  
  56.   inherited Create(true);  
  57. end;  
  58.  
  59. procedure TQueenThread.SetRecursion(Value: boolean);  
  60. begin 
  61.   FRecursion := Value;  
  62.   if FRecursion then 
  63.     QS := QSeek  
  64.   else 
  65.     QS := QSeekNonrecursion;  
  66. end;  
  67.  
  68. procedure TQueenThread.SeekFinish(Sender: TObject);  
  69. begin 
  70.   PostMessage(Form1.Handle, WM_SEEKFINISH, 0, 0);  
  71. end;  
  72.  
  73. procedure TQueenThread.ShowClashRestore;  
  74. var  
  75.   i: integer;  
  76.   t: TRect;  
  77. begin 
  78.   for i := 1 to FQueen - 1 do  
  79.   begin 
  80.     if (Q[FQueen] = Q[i]) or (Abs(Q[FQueen] - Q[i]) = (FQueen - i)) then 
  81.     begin 
  82.       t := Rect((Q[i] - 1) * CellWidth, (i - 1) * CellHeight, Q[i] * CellWidth, i * CellHeight);  
  83.       FCanvas.CopyRect(t, FBackgroundBitmap.Canvas, t);  
  84.       FCanvas.Draw((Q[i] - 1) * CellWidth, (i - 1) * CellHeight, FClashRestoreIcon);  
  85.     end;  
  86.   end;  
  87. end;  
  88.  
  89. procedure TQueenThread.ShowDelete;  
  90. var  
  91.   t: TRect;  
  92. begin 
  93.   t := Rect((Q[FQueen] - 1) * CellWidth, (FQueen - 1) * CellHeight, Q[FQueen] * CellWidth, FQueen * CellHeight);  
  94.   FCanvas.CopyRect(t, FBackgroundBitmap.Canvas, t);  
  95. end;  
  96.  
  97. procedure TQueenThread.ShowDraw;  
  98. begin 
  99.   FCanvas.Draw((Q[FQueen] - 1) * CellWidth, (FQueen - 1) * CellHeight, FSeekQueenIcon);  
  100. end;  
  101.  
  102. procedure TQueenThread.ShowResult;  
  103. var  
  104.   i: integer;  
  105. begin 
  106.   FCanvas.Draw(0, 0, FBackgroundBitmap);  
  107.   FSeekQueenIcon := FQueenIcon;  
  108.   for i := 1 to 8 do  
  109.   begin 
  110.     FQueen := i;  
  111.     ShowDraw;  
  112.   end;  
  113. end;  
  114.  
  115. function TQueenThread.QSeek(n: integer): boolean;  
  116. begin 
  117.   if n > 0 then 
  118.   begin 
  119.     //==========demo begin==========  
  120.     if FDemo then 
  121.     begin 
  122.       FQueen := n; //Setup variable for call synchronize  
  123.       Synchronize(ShowDelete);  
  124.     end;  
  125.     //==========demo end============  
  126.     inc(Q[n]);  
  127.     //==========demo begin==========  
  128.     if FDemo then 
  129.     begin 
  130.       FSeekQueenIcon := FSeekIcon;  
  131.       Synchronize(ShowDraw);  
  132.       sleep(FDelay);  
  133.     end;  
  134.     //==========demo end============  
  135.     if Q[n] <= 8 then 
  136.       if QClash(n) then 
  137.       begin 
  138.         //==========demo begin==========  
  139.         if FDemo then 
  140.         begin 
  141.           FClashRestoreIcon := FClashIcon;  
  142.           Synchronize(ShowClashRestore);  
  143.           sleep(FDelay);  
  144.           FClashRestoreIcon := FQueenIcon;  
  145.           Synchronize(ShowClashRestore);  
  146.         end;  
  147.         //==========demo end============  
  148.         result := QSeek(n);  
  149.       end 
  150.       else 
  151.       begin 
  152.         //==========demo begin==========  
  153.         if FDemo then 
  154.         begin 
  155.           Synchronize(ShowDelete);  
  156.           FSeekQueenIcon := FQueenIcon;  
  157.           Synchronize(ShowDraw);  
  158.           sleep(FDelay);  
  159.         end;  
  160.         //==========demo end============  
  161.         result := true 
  162.       end 
  163.     else 
  164.     begin 
  165.       Q[n] := 0;  
  166.       if QSeek(n - 1) then 
  167.         result := Qseek(n)  
  168.       else 
  169.         result := false;  
  170.     end;  
  171.   end 
  172.   else 
  173.     result := false;  
  174. end;  
  175.  
  176. function TQueenThread.QSeekNonrecursion(n: integer): boolean;  
  177. var  
  178.   flag: boolean;  
  179.   m: integer;  
  180. begin 
  181.   m := n;  
  182.   flag := false;  
  183.   repeat  
  184.     //==========demo begin==========  
  185.     if FDemo then 
  186.     begin 
  187.       FQueen := n;  
  188.       Synchronize(ShowDelete);  
  189.     end;  
  190.     //==========demo end============  
  191.     inc(Q[n]);  
  192.     //==========demo begin==========  
  193.     if FDemo then 
  194.     begin 
  195.       FSeekQueenIcon := FSeekIcon;  
  196.       Synchronize(ShowDraw);  
  197.       sleep(FDelay);  
  198.     end;  
  199.     //==========demo end============  
  200.     if Q[n] > 8 then 
  201.     begin 
  202.       Q[n] := 0;  
  203.       dec(n);  
  204.     end 
  205.     else 
  206.       if not QClash(n) then 
  207.       begin 
  208.         //==========demo begin==========  
  209.         if FDemo then 
  210.         begin 
  211.           Synchronize(ShowDelete);  
  212.           FSeekQueenIcon := FQueenIcon;  
  213.           Synchronize(ShowDraw);  
  214.           sleep(FDelay);  
  215.         end;  
  216.         //==========demo end============  
  217.         if m = n then 
  218.           flag := true 
  219.         else 
  220.           inc(n);  
  221.       end 
  222.       else 
  223.         //==========demo begin==========  
  224.         if FDemo then 
  225.         begin 
  226.           FClashRestoreIcon := FClashIcon;  
  227.           Synchronize(ShowClashRestore);  
  228.           sleep(FDelay);  
  229.           FClashRestoreIcon := FQueenIcon;  
  230.           Synchronize(ShowClashRestore);  
  231.         end;  
  232.         //==========demo end============  
  233.   until flag or (n < 1);  
  234.   result := flag;  
  235. end;  
  236.  
  237. function TQueenThread.QClash(n: integer): boolean;  
  238. var  
  239.   flag: boolean;  
  240.   i: integer;  
  241. begin 
  242.   flag := false;  
  243.   i := 1;  
  244.   while (i < n) and not flag do  
  245.   begin 
  246.     flag := (Q[n] = Q[i]) or (Abs(Q[n] - Q[i]) = (n - i));  
  247.     inc(i);  
  248.   end;  
  249.   result := flag;  
  250. end;  
  251.  
  252. procedure TQueenThread.Execute;  
  253. var  
  254.   i: integer;  
  255. begin 
  256.   for i := 1 to 7 do  
  257.     QS(i);  
  258.   while QS(8) do  
  259.   begin 
  260.     if FDemo then 
  261.       Beep  
  262.     else 
  263.       Synchronize(ShowResult);  
  264.     inc(FCounter);  
  265.     PostMessage(Form1.Handle, WM_SEEKSUSPEND, 0, 0);  
  266.     Suspend;  
  267.   end;  
  268. end;  
  269.  
  270. end. 

    這個程序雖然是一個教學軟件,但涉及到許多方面的知識,比如Win32下的圖像處理、多線程等等。這裡並沒有使用信號量,而是使用了用戶自定義消息來完成多線程的同步、等待、掛起等操作。
下面是另一個Unit的源碼: 

  1. unit Unit1;  
  2.  
  3. interface  
  4.  
  5. uses  
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  7.   Dialogs, StdCtrls, ExtCtrls, ImgList, ComCtrls;  
  8.  
  9. const  
  10.   WM_SEEKFINISH = WM_USER + $1;  
  11.   WM_SEEKSUSPEND = WM_USER + $2;  
  12.   CellWidth = 50;  
  13.   CellHeight = 50;  
  14.  
  15. type  
  16.   TForm1 = class(TForm)  
  17.     GroupBox1: TGroupBox;  
  18.     GroupBox2: TGroupBox;  
  19.     GroupBox3: TGroupBox;  
  20.     GroupBox4: TGroupBox;  
  21.     GroupBox5: TGroupBox;  
  22.     GroupBox6: TGroupBox;  
  23.     Panel1: TPanel;  
  24.     Image1: TImage;  
  25.     Label1: TLabel;  
  26.     Label2: TLabel;  
  27.     Label3: TLabel;  
  28.     Label4: TLabel;  
  29.     Label5: TLabel;  
  30.     CheckBox1: TCheckBox;  
  31.     CheckBox2: TCheckBox;  
  32.     TrackBar1: TTrackBar;  
  33.     ComboBox1: TComboBox;  
  34.     ComboBox2: TComboBox;  
  35.     ListBox1: TListBox;  
  36.     Button1: TButton;  
  37.     ImageList1: TImageList;  
  38.     procedure FormCreate(Sender: TObject);  
  39.     procedure FormDestroy(Sender: TObject);  
  40.     procedure Button1Click(Sender: TObject);  
  41.     procedure CheckBox1Click(Sender: TObject);  
  42.     procedure CheckBox2Click(Sender: TObject);  
  43.     procedure TrackBar1Change(Sender: TObject);  
  44.     procedure ComboBox1Change(Sender: TObject);  
  45.     procedure ComboBox2Change(Sender: TObject);  
  46.     procedure ListBox1DblClick(Sender: TObject);  
  47.   private  
  48.     BG: TBitmap;  
  49.     QIcon, SIcon, CIcon: TIcon;  
  50.     QResult: array of array[1..8] of integer;  
  51.     RunFlag: boolean;  
  52.   public 
  53.     procedure MsgSeekSuspend(var Msg: TMessage); message WM_SEEKSUSPEND;  
  54.     procedure MsgSeekFinish(var Msg: TMessage); message WM_SEEKFINISH;  
  55.   end;  
  56.  
  57. var  
  58.   Form1: TForm1;  
  59.   Q: array[1..8] of integer;  
  60.  
  61. implementation  
  62.  
  63. {$R *.dfm}  
  64.  
  65. uses Unit2;  
  66.  
  67. var  
  68.   QueenThread: TQueenThread;  
  69.   CurrentResultIndex: integer;  
  70.  
  71. procedure TForm1.MsgSeekSuspend(var Msg: TMessage);  
  72. var  
  73.   i: integer;  
  74. begin 
  75.   CurrentResultIndex := high(QResult) + 1;  
  76.   setlength(QResult, CurrentResultIndex + 1);  
  77.   for i := 1 to 8 do  
  78.     QResult[CurrentResultIndex, i] := Q[i];  
  79.   with ListBox1 do  
  80.   begin 
  81.     Items.Add(format('%u, %u, %u, %u, %u, %u, %u, %u [%u]', [Q[1], Q[2], Q[3], Q[4], Q[5], Q[6], Q[7], Q[8], CurrentResultIndex + 1]));  
  82.     ItemIndex := Count - 1;  
  83.   end;  
  84.   RunFlag := false;  
  85.   Button1.Caption := '&Seek';  
  86. end;  
  87.  
  88. procedure TForm1.MsgSeekFinish(var Msg: TMessage);  
  89. begin 
  90.   MessageBox(Handle, 'End of seek.'+ #13#10#13#10 + 'Restart seek from first queen.', PWChar(Caption), MB_ICONINFORMATION or MB_OK);  
  91.   ListBox1.Clear;  
  92.   Image1.Canvas.Draw(0, 0, BG);  
  93.   QueenThread := nil;  
  94.   CurrentResultIndex := -1;  
  95.   setlength(QResult, 0);  
  96.   Button1.Caption := '&Seek';  
  97. end;  
  98.  
  99. procedure TForm1.Button1Click(Sender: TObject);  
  100. var  
  101.   i: integer;  
  102. begin 
  103.   if not Assigned(QueenThread) then 
  104.   begin 
  105.     QueenThread := TQueenThread.Create(BG, QIcon, SIcon, CIcon, Image1.Canvas);  
  106.     QueenThread.Demo := CheckBox1.Checked;  
  107.     QueenThread.Delay := TrackBar1.Position;  
  108.     QueenThread.Recursion := CheckBox2.Checked;  
  109.   end;  
  110.   if QueenThread.Suspended then 
  111.   begin 
  112.     with ListBox1 do  
  113.     begin 
  114.       if (CurrentResultIndex <> high(QResult)) and not RunFlag then 
  115.       begin 
  116.         for i := 1 to 8 do  
  117.           Q[i] := QResult[high(QResult), i];  
  118.         QueenThread.ShowResult;  
  119.       end;  
  120.       ItemIndex := Count - 1;  
  121.     end;  
  122.     QueenThread.Resume;  
  123.     Button1.Caption := '&Pause';  
  124.   end 
  125.   else 
  126.   begin 
  127.     QueenThread.Suspend;  
  128.     Button1.Caption := '&Resume';  
  129.   end;  
  130.   RunFlag := true;  
  131. end;  
  132.  
  133. procedure TForm1.CheckBox1Click(Sender: TObject);  
  134. begin 
  135.   TrackBar1.Enabled := CheckBox1.Checked;  
  136.   if Assigned(QueenThread) then 
  137.     QueenThread.Demo := CheckBox1.Checked;  
  138. end;  
  139.  
  140. procedure TForm1.CheckBox2Click(Sender: TObject);  
  141. begin 
  142.   if Assigned(QueenThread) then 
  143.     QueenThread.Recursion := CheckBox2.Checked;  
  144. end;  
  145.  
  146. procedure TForm1.ComboBox1Change(Sender: TObject);  
  147. var  
  148.   n: integer;  
  149. begin 
  150.   n :=  + ComboBox1.ItemIndex * 3;  
  151.   ImageList1.GetIcon(0 + n, QIcon);  
  152.   ImageList1.GetIcon(1 + n, SIcon);  
  153.   ImageList1.GetIcon(2 + n, CIcon);  
  154.   if Assigned(QueenThread) then 
  155.     QueenThread.ShowResult;  
  156. end;  
  157.  
  158. procedure TForm1.ComboBox2Change(Sender: TObject);  
  159. begin 
  160.   BG.LoadFromResourceName(hInstance, 'BG' + IntToStr(ComboBox2.ItemIndex + 1));  
  161.   if Assigned(QueenThread) then 
  162.     QueenThread.ShowResult  
  163.   else 
  164.     Image1.Canvas.Draw(0, 0, BG);  
  165. end;  
  166.  
  167. procedure TForm1.TrackBar1Change(Sender: TObject);  
  168. begin 
  169.   if Assigned(QueenThread) then 
  170.     QueenThread.Delay := TrackBar1.Position;  
  171. end;  
  172.  
  173. procedure TForm1.ListBox1DblClick(Sender: TObject);  
  174. var  
  175.   i: integer;  
  176. begin 
  177.   if Assigned(QueenThread) and not RunFlag then 
  178.   begin 
  179.     CurrentResultIndex := ListBox1.ItemIndex;  
  180.     for i := 1 to 8 do  
  181.       Q[i] := QResult[CurrentResultIndex, i];  
  182.     QueenThread.ShowResult;  
  183.   end;  
  184. end;  
  185.  
  186. procedure TForm1.FormCreate(Sender: TObject);  
  187. var  
  188.   i: integer;  
  189. begin 
  190.   for i := 1 to 8 do  
  191.     Q[i] := 0;  
  192.   BG := TBitmap.Create;  
  193.   QIcon := TIcon.Create;  
  194.   SIcon := TIcon.Create;  
  195.   CIcon := TIcon.Create;  
  196.   ComboBox1Change(self);  
  197.   ComboBox2Change(self);  
  198.   CurrentResultIndex := -1;  
  199. end;  
  200.  
  201. procedure TForm1.FormDestroy(Sender: TObject);  
  202. begin 
  203.   BG.Free;  
  204.   QIcon.Free;  
  205.   SIcon.Free;  
  206.   CIcon.Free;  
  207. end;  
  208.  
  209. end. 

    可以從後面的附件或者如下鏈接下載完整的源碼項目包含一個編譯好的可執行文件):
http://img1.51cto.com/attachment/201101/876134_1293891480.rar

本文出自 “夢遼軟件工作室” 博客,請務必保留此出處http://mengliao.blog.51cto.com/876134/470620

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved