Advertisement
Matixs

Untitled

May 13th, 2023
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 15.75 KB | None | 0 0
  1. unit Main;
  2.  
  3. interface
  4.  
  5. uses
  6.   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  7.   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, Vcl.StdCtrls, Vcl.ComCtrls,
  8.   Vcl.ExtCtrls, Vcl.NumberBox, Vcl.Grids, DirectionalList, System.Generics.Collections, System.StrUtils,
  9.   System.IOUtils;
  10.  
  11.  
  12. type
  13.  
  14.     TVertexArray = array of TVertexList;
  15.  
  16.   TMainForm = class(TForm)
  17.     MainMenu: TMainMenu;
  18.     FileMenu: TMenuItem;
  19.     ImportSubmenu: TMenuItem;
  20.     ExportSubmenu: TMenuItem;
  21.     InstructionMenu: TMenuItem;
  22.     AboutDeveloperMenu: TMenuItem;
  23.     N1: TMenuItem;
  24.     N2: TMenuItem;
  25.     N3: TMenuItem;
  26.     N4: TMenuItem;
  27.     PageControl: TPageControl;
  28.     PageAddLists: TTabSheet;
  29.     PageViewGraph: TTabSheet;
  30.     PageMain: TTabSheet;
  31.     Label1: TLabel;
  32.     Label2: TLabel;
  33.     PaintBox: TPaintBox;
  34.     Label3: TLabel;
  35.     Label4: TLabel;
  36.     Label5: TLabel;
  37.     UpDown: TUpDown;
  38.     StringGridList: TStringGrid;
  39.     ButtonSaveList: TButton;
  40.     NumberBoxVertex: TNumberBox;
  41.     OpenDialog: TOpenDialog;
  42.     SaveDialog: TSaveDialog;
  43.     PopupMenu: TPopupMenu;
  44.     procedure FormCreate(Sender: TObject);
  45.     procedure NumberBoxVertexChangeValue(Sender: TObject);
  46.     procedure UpdateVertex();
  47.     procedure StringGridListKeyPress(Sender: TObject; var Key: Char);
  48.     procedure ButtonSaveListClick(Sender: TObject);
  49.     procedure UpDownClick(Sender: TObject; Button: TUDBtnType);
  50.     procedure N4Click(Sender: TObject);
  51.     procedure N3Click(Sender: TObject);
  52.     procedure PaintBoxPaint(Sender: TObject);
  53.     procedure Button1Click(Sender: TObject);
  54.     procedure ImportSubmenuClick(Sender: TObject);
  55.     procedure ImportAdjList(OpenFileDialog : TOpenDialog);
  56.     procedure ExportSubmenuClick(Sender: TObject);
  57.     procedure N1Click(Sender: TObject);
  58.     procedure AboutDeveloperMenuClick(Sender: TObject);
  59.     procedure InstructionMenuClick(Sender: TObject);
  60.     procedure FileMenuClick(Sender: TObject);
  61.     procedure N2Click(Sender: TObject);
  62.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  63.     procedure StringGridListKeyDown(Sender: TObject; var Key: Word;
  64.       Shift: TShiftState);
  65.  
  66.   private
  67.     { Private declarations }
  68.   public
  69.     { Public declarations }
  70.     procedure InitPageAddLists();
  71.   end;
  72.  
  73. var
  74.     MainForm: TMainForm;
  75.     VertexArray : TVertexArray;
  76.     VertexCount : Integer;
  77.     CoverList : TList<Integer>;
  78.  
  79. implementation
  80.  
  81. {$R *.dfm}
  82.  
  83. Function GetVertexCover(const Graph : TVertexArray) : TList<Integer>;
  84. var
  85.     I : Integer;
  86.     Cover : TList<Integer>;
  87.     DeletedVertex : TList<Integer>;
  88.     Vertex, Neighbor : Integer;
  89.     TempGraph : TVertexArray;
  90. begin
  91.     Cover := TList<Integer>.Create; // Шаг 1
  92.     DeletedVertex := TList<Integer>.Create;
  93.  
  94.     TempGraph := Graph;
  95.  
  96.     for I := Low(TempGraph) to High(TempGraph) do // Шаг 2
  97.     begin
  98.         Vertex := I + 1;
  99.         if not DeletedVertex.Contains(Vertex) then
  100.         begin
  101.             if not Cover.Contains(Vertex) then // Шаг 3
  102.             begin
  103.                 Cover.Add(Vertex);
  104.  
  105.                 // Удалить смежные вершины
  106.                 while TempGraph[i].Head <> NIL do
  107.                 begin
  108.                     DeletedVertex.Add(TempGraph[I].Head.Vertex);
  109.                     TempGraph[I].Head := TempGraph[I].Head^.Next;
  110.                 end;
  111.             end;
  112.         end;
  113.     end;
  114.  
  115.     GetVertexCover := Cover;
  116. end;
  117.  
  118. procedure TMainForm.AboutDeveloperMenuClick(Sender: TObject);
  119. begin
  120.     Application.MessageBox('Разработал студент группы 251005, Федорцов Вадим.','О разработчике',MB_OK+MB_ICONINFORMATION);
  121. end;
  122.  
  123. procedure TMainForm.Button1Click(Sender: TObject);
  124. begin
  125.     PaintBox.OnPaint(NIL);
  126. end;
  127.  
  128. procedure TMainForm.ButtonSaveListClick(Sender: TObject);
  129. var
  130.     I, J : Integer;
  131. begin
  132.  
  133.     With StringGridList do
  134.     begin
  135.         VertexCount := RowCount;
  136.         SetLength(VertexArray, VertexCount);
  137.  
  138.         for I := 0 to RowCount - 1 do
  139.         begin
  140.             VertexArray[I] := TVertexList.Create;
  141.  
  142.             for J := 0 to ColCount - 1 do
  143.             begin
  144.                 if Cells[J+1,I] <> '' then
  145.                 begin
  146.                     VertexArray[I].AddNewVertexInList(Cells[J+1,I].ToInteger);
  147.                 end
  148.                 else
  149.                     break;
  150.             end;
  151.  
  152.         end;
  153.     end;
  154.  
  155.     CoverList := GetVertexCover(VertexArray);
  156. end;
  157.  
  158. procedure TMainForm.ExportSubmenuClick(Sender: TObject);
  159. var
  160.   StreamWriter: TStreamWriter;
  161.   i: Integer;
  162. begin
  163.  
  164.     if SaveDialog.Execute() then
  165.     begin
  166.         try
  167.             if not ForceDirectories(ExtractFilePath(SaveDialog.FileName)) then
  168.                 raise Exception.Create('Невозможно создать директорию.');
  169.  
  170.             if FileExists(SaveDialog.FileName) then
  171.             begin
  172.                 if NOT DeleteFile(PChar(SaveDialog.FileName)) then
  173.                     raise Exception.Create('Отказ в доступе к файлу.');
  174.             end;
  175.             StreamWriter := TStreamWriter.Create(SaveDialog.FileName);
  176.             try
  177.                 StreamWriter.WriteLine('Вершинное покрытие графа:');
  178.                 for i := 0 to CoverList.Count - 1 do
  179.                 begin
  180.                   if (CoverList[i] < 0) then
  181.                     raise Exception.Create('Вершина должна быть положительной.');
  182.  
  183.                   StreamWriter.WriteLine(IntToStr(CoverList[i]));
  184.                 end;
  185.             finally
  186.                 StreamWriter.Free;
  187.             end;
  188.         Except
  189.             On E : Exception do
  190.                 Application.MessageBox(PCHAR('Ошибка: ' + E.Message),'Экспорт',MB_OK+MB_ICONERROR);
  191.         end;
  192.     end;
  193. end;
  194.  
  195. procedure TMainForm.FileMenuClick(Sender: TObject);
  196. begin
  197.     if VertexArray = NIL then
  198.     begin
  199.         ExportSubmenu.Enabled := false;
  200.     end
  201.     else
  202.     begin
  203.         ExportSubmenu.Enabled := true;
  204.     end;
  205. end;
  206.  
  207. procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  208. begin
  209.     CanClose :=  Application.MessageBox('Действительно закрыть программу?','Закрытие программы',MB_YESNO + MB_ICONQUESTION) = IDYES ;
  210. end;
  211.  
  212. procedure TMainForm.FormCreate(Sender: TObject);
  213. begin
  214.     InitPageAddLists;
  215.     VertexCount := 0;
  216.     CoverList := TList<Integer>.Create;
  217.     PageControl.ActivePageIndex := 2;
  218. end;
  219.  
  220. function IsAdjListValid(const VertexArray : TVertexArray; Count : Integer) : Boolean;
  221. var
  222.     Visited : array of Boolean;
  223.     Vertex, Neighbor : Integer;
  224. begin
  225.     IsAdjListValid := False;
  226.  
  227.     if Count = 0  then
  228.         Exit;
  229.  
  230.     SetLength(Visited, Count);
  231.  
  232.     for Vertex := 0 to Count - 1 do
  233.     begin
  234.  
  235.         if (Vertex < 0) OR (Vertex >= Count) then
  236.             Exit;
  237.  
  238.         Visited[Vertex] := True;
  239.  
  240.         while VertexArray[Vertex].Head <> NIL do
  241.         begin
  242.  
  243.             Neighbor := VertexArray[Vertex].Head.Vertex;
  244.  
  245.             if Visited[Neighbor] then
  246.                 Exit;
  247.  
  248.             Visited[Neighbor] := True;
  249.  
  250.             VertexArray[Vertex].Head := VertexArray[Vertex].Head^.Next;
  251.         end;
  252.     end;
  253.  
  254.  
  255.     IsAdjListValid := True;
  256.  
  257. end;
  258.  
  259. procedure TMainForm.ImportAdjList(OpenFileDialog : TOpenDialog);
  260. var
  261.     StreamReader: TStreamReader;
  262.     VertexList : TVertexList;
  263.     Line, StrNeighbor: string;
  264.     TempVertexArr : TVertexArray;
  265.     Count, I, J, Vertex, Neighbor: Integer;
  266. begin
  267.  
  268.     if (OpenFileDialog.Execute()) then
  269.     begin
  270.         try
  271.             PageControl.ActivePageIndex := 0;
  272.             Count := 0;
  273.             StreamReader := TStreamReader.Create(OpenFileDialog.FileName);
  274.  
  275.             SetLength(TempVertexArr, 5); // Базово задаем 5, потом поменяем
  276.  
  277.             Try
  278.                 While NOT StreamReader.EndOfStream do
  279.                 Begin
  280.  
  281.                     if Count > 5 then
  282.                         Break;
  283.  
  284.                     Line := StreamReader.ReadLine;
  285.  
  286.                     TempVertexArr[Count] := TVertexList.Create;
  287.  
  288.                     for StrNeighbor in SplitString(Line, ' ') do
  289.                     begin
  290.                         Neighbor := StrToInt(StrNeighbor);
  291.                         if Neighbor = 0 then
  292.                             Exit;
  293.                         TempVertexArr[Count].AddNewVertexInList(Neighbor);
  294.                     end;
  295.  
  296.                     Inc(Count);
  297.                 End;
  298.             Finally
  299.                 StreamReader.Free;
  300.             End;
  301.  
  302.             SetLength(TempVertexArr, Count);
  303.  
  304.             NumberBoxVertex.Text := Count.ToString;
  305.             UpDown.Position := Count;
  306.             StringGridList.RowCount := Count;
  307.             StringGridList.ColCount := Count;
  308.  
  309.             for I := Low(TempVertexArr) to High(TempVertexArr) do
  310.             begin
  311.                 J := 1;
  312.                 while TempVertexArr[I].Head <> NIL do
  313.                 begin
  314.                     StringGridList.Cells[J, I] := TempVertexArr[I].Head.Vertex.ToString;
  315.                     Inc(J);
  316.                     TempVertexArr[I].Head := TempVertexArr[I].Head^.Next;
  317.                 end;
  318.             end;
  319.  
  320.         Except
  321.             On E : EInOutError do
  322.             begin
  323.                 Application.MessageBox('Импорт отменен. Ошибка работы с файлом.','Импорт',MB_OK+MB_ICONWARNING);
  324.             end;
  325.             On E : Exception do
  326.             begin
  327.                 Application.MessageBox(PChar('Импорт отменен. Ошибка: ' + E.Message),'Импорт',MB_OK+MB_ICONWARNING);
  328.             end;
  329.         end;
  330.     end
  331.     else
  332.     begin
  333.         Application.MessageBox('Импорт отменен пользователем.','Импорт',MB_OK+MB_ICONWARNING)
  334.     end;
  335.  
  336. end;
  337.  
  338. procedure TMainForm.ImportSubmenuClick(Sender: TObject);
  339. begin
  340.     ImportAdjList(OpenDialog);
  341. end;
  342.  
  343. Procedure TMainForm.InitPageAddLists();
  344. begin
  345.     UpDown.Associate := NumberBoxVertex;
  346.     NumberBoxVertexChangeValue(NIL);
  347. end;
  348.  
  349. procedure TMainForm.InstructionMenuClick(Sender: TObject);
  350. begin
  351.     Application.MessageBox('Задайте список смежности. Доступные цифры: 1, 0. После этого, вы можете визуализировать граф и получить вершинное покрытие'
  352.                            + #13#10'Импортировать список смежности, инструкция:'
  353.                            + #13#10'1. Файл должен содержать только нули и единицы.'#13#10
  354.                            + '2. Файл должен быть прямоугольной таблицей, то есть все строки должны иметь одинаковую длину.'#13#10
  355.                            + '3. Для неориентированного графа матрица смежности должна быть симметричной относительно главной диагонали.'#13#10
  356.                            + 'Пример:'#13#10
  357.                            + '0 1 1 0'#13#10
  358.                            + '1 0 1 1'#13#10
  359.                            + '1 1 0 1'#13#10,'Инструкция к программе',MB_OK+MB_ICONINFORMATION);
  360. end;
  361.  
  362. Procedure TMainForm.UpdateVertex();
  363. var
  364.     I : Integer;
  365. begin
  366.     for I := 0 to StringGridList.RowCount - 1 do
  367.     begin
  368.         StringGridList.Cells[0, I] := (I + 1).ToString;
  369.     end;
  370. end;
  371.  
  372. procedure TMainForm.UpDownClick(Sender: TObject; Button: TUDBtnType);
  373. begin
  374.     if Button = btPrev then
  375.     begin
  376.         StringGridList.Rows[UpDown.Position].Clear;
  377.         StringGridList.Cols[UpDown.Position].Clear;
  378.     end;
  379. end;
  380.  
  381. procedure TMainForm.N1Click(Sender: TObject);
  382. begin
  383.     Application.MessageBox('Граф задан списками инцидентности. Разработать программу, находящую вершинное покрытие графа. Граф визуализировать. Найденные вершины выделить цветом и вывести на форму.','Задание',MB_OK+MB_ICONINFORMATION);
  384. end;
  385.  
  386. procedure TMainForm.N2Click(Sender: TObject);
  387. begin
  388.     if VertexArray = NIL then
  389.     begin
  390.         N4.Enabled := False
  391.     end
  392.     else
  393.     begin
  394.         N4.Enabled := True;
  395.     end;
  396. end;
  397.  
  398. procedure TMainForm.N3Click(Sender: TObject);
  399. begin
  400.     PageControl.ActivePageIndex := 0;
  401. end;
  402.  
  403. procedure TMainForm.N4Click(Sender: TObject);
  404. begin
  405.     PageControl.ActivePageIndex := 1;
  406.     PaintBoxPaint(NIL);
  407. end;
  408.  
  409. procedure TMainForm.NumberBoxVertexChangeValue(Sender: TObject);
  410. begin
  411.     StringGridList.RowCount := NumberBoxVertex.Value.ToString.ToInteger;
  412.     StringGridList.ColCount := NumberBoxVertex.Value.ToString.ToInteger;
  413.     if StringGridList.ColCount > 1 then
  414.     begin
  415.         StringGridList.FixedCols := 1;
  416.         StringGridList.Enabled := True;
  417.     end
  418.     else
  419.         if StringGridList.ColCount = 1 then
  420.             StringGridList.Enabled := False;
  421.     UpdateVertex();
  422. end;
  423.  
  424. Procedure PaintGraph(const Graph : TVertexArray; PaintBox : TPaintBox);
  425. const
  426.     Scale = 15;
  427.     R = 50;
  428.     ScalesArr : array [0..4,0..1] of Integer = ((120,200),(450,90),(120,350),(810, 275),(450,460));
  429. var
  430.     I, J : Integer;
  431.     X, Y : Integer;
  432.     TempList : PVertexList;
  433. begin
  434.  
  435.     for I := 0 to VertexCount - 1 do
  436.     begin
  437.         TempList := VertexArray[I].Head;
  438.  
  439.         while Templist <> NIL do
  440.         begin
  441.             PaintBox.Canvas.MoveTo(ScalesArr[I,0],ScalesArr[I,1]);
  442.             PaintBox.Canvas.LineTo(ScalesArr[TempList.Vertex-1,0],ScalesArr[TempList.Vertex-1,1]);
  443.             TempList := TempList^.Next;
  444.         end;
  445.     end;
  446.  
  447.     for I := 0 to VertexCount - 1 do
  448.     begin
  449.  
  450.         PaintBox.Canvas.Pen.Width := 5;
  451.  
  452.         if CoverList.Contains(I + 1) then
  453.             PaintBox.Canvas.Pen.Color := clGreen
  454.         else
  455.             PaintBox.Canvas.Pen.Color := clBlack;
  456.  
  457.         x := ScalesArr[I,0];
  458.         y := ScalesArr[I,1];
  459.  
  460.         PaintBox.Canvas.Ellipse(x - R, y - R, x + R, y + R);
  461.         PaintBox.Canvas.Font.Size := 22;
  462.         PaintBox.Canvas.TextOut(X-Scale, Y-Scale-10, (I + 1).ToString);
  463.     end;
  464. end;
  465.  
  466.  
  467. procedure TMainForm.PaintBoxPaint(Sender: TObject);
  468. begin
  469.     PaintGraph(VertexArray, PaintBox);
  470. end;
  471.  
  472. Function CheckOnRepeat(StringGrid : TStringGrid; Key : Char) : Boolean;
  473. var
  474.     R : Word;
  475.     J, K, Counter : Integer;
  476. begin
  477.  
  478.     CheckOnRepeat := False;
  479.  
  480.     R := StringGrid.Row;
  481.     Counter := 0;
  482.  
  483.     for J := 0 to StringGrid.ColCount - 1 do
  484.     begin
  485.  
  486.         if Key = StringGrid.Cells[J,R] then
  487.             Inc(Counter);
  488.     end;
  489.  
  490.     if Counter > 0 then
  491.         CheckOnRepeat := True;
  492. end;
  493.  
  494. procedure TMainForm.StringGridListKeyDown(Sender: TObject; var Key: Word;
  495.   Shift: TShiftState);
  496. begin
  497.     If (SsShift In Shift) And (Key = VK_Insert) Then
  498.         Abort;
  499. end;
  500.  
  501. procedure TMainForm.StringGridListKeyPress(Sender: TObject; var Key: Char);
  502. var
  503.     C, R : Word;
  504.     MaxLength : Char;
  505. begin
  506.  
  507.  
  508.     C := StringGridList.Col;
  509.     R := StringGridList.Row;
  510.  
  511.     MaxLength := char(StringGridList.RowCount+48);
  512.  
  513.     if NOT (Key in ['1'..MaxLength,#8]) then
  514.     begin
  515.         Key := #0;
  516.     end
  517.     else
  518.         if (Key <> #8) AND (StringGridList.Cells[C,R].Length > 0) then
  519.         begin
  520.             Key := #0
  521.         end
  522.         else
  523.         begin
  524.             if (C > 1) AND (StringGridList.Cells[C - 1, R] = '') then
  525.                 StringGridList.Col := C - 1
  526.             else
  527.                 if CheckOnRepeat(StringGridList, Key) then
  528.                 begin
  529.                     Key := #0;
  530.                 end;
  531.         end;
  532. end;
  533.  
  534.  
  535.  
  536. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement