diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b9d6bd9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,215 @@ +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +############# +## Windows detritus +############# + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac crap +.DS_Store + + +############# +## Python +############# + +*.py[co] + +# Packages +*.egg +*.egg-info +dist/ +build/ +eggs/ +parts/ +var/ +sdist/ +develop-eggs/ +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg diff --git a/PipesSolver.sln b/PipesSolver.sln new file mode 100644 index 0000000..912cab9 --- /dev/null +++ b/PipesSolver.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PipesSolver", "PipesSolver\PipesSolver.csproj", "{6AF1A9B0-979C-47E3-A8E1-45C6F3DFF969}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6AF1A9B0-979C-47E3-A8E1-45C6F3DFF969}.Debug|x86.ActiveCfg = Debug|x86 + {6AF1A9B0-979C-47E3-A8E1-45C6F3DFF969}.Debug|x86.Build.0 = Debug|x86 + {6AF1A9B0-979C-47E3-A8E1-45C6F3DFF969}.Release|x86.ActiveCfg = Release|x86 + {6AF1A9B0-979C-47E3-A8E1-45C6F3DFF969}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/PipesSolver/Brainteaser.cs b/PipesSolver/Brainteaser.cs new file mode 100644 index 0000000..3bbd35a --- /dev/null +++ b/PipesSolver/Brainteaser.cs @@ -0,0 +1,225 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Drawing; + +namespace PipesSolver +{ + /// + /// Класс головоломки + /// + class Brainteaser + { + /// + /// Количнство колонок поля + /// + private int _ColCount; + /// + /// Количество строк поля + /// + private int _RowCount; + /// + /// Точка входа + /// + private Point _Enter; + /// + /// Точка выхода + /// + private Point _Exit; + /// + /// Поле + /// + private Pipe[,] _Field; + + /// + /// Конструктор класса + /// + /// Поле + /// количество колонок + /// количество строк + /// точка входа + /// точка выхода + public Brainteaser(Pipe[,] parField, int parColCount, int parRowCount, Point parEnter, Point parExit) + { + _ColCount = parColCount; + _RowCount = parRowCount; + _Enter = parEnter; + _Exit = parExit; + + _Field = parField; + } + + /// + /// Поиск в глубину + /// + /// + public bool DepthSolve() + { + //создаем дерево решения + SolutionThree solutionThree = new SolutionThree(null, null, _Enter, 0); + //назначаем текущей точкой точку входа + Point currentPoint = _Enter; + // помечаем, что задача еще не решена + bool complete = false; + + //создаем начальное направление движения + Orientation direction = Orientation.Up; + if (_Enter.X == 0) + { + direction = Orientation.Right; + } + else if (_Enter.X == _ColCount + 1) + { + direction = Orientation.Left; + } + else if (_Enter.Y == 0) + { + direction = Orientation.Down; + } + else if (_Enter.Y == _RowCount + 1) + { + direction = Orientation.Up; + } + + //рекурсивный вызов метода поиска в глубину + complete = DepthSolve(currentPoint, direction, solutionThree); + + return complete; + } + + + + private bool DepthSolve(Point parCurrentPoint, Orientation parDirection, SolutionThree parSolutionNode) + { + //решение еще не найдено + bool complete = false; + //добавляем узел в дерево решений + SolutionThree solutionThree = parSolutionNode; + //назначаем текущую точку + Point currentPoint = parCurrentPoint; + //назначаем направление движения + Orientation direction = parDirection; + //исходя из текущего положения и направления движения вычисляем следующую точку + Point nextPoint = new Point(currentPoint.X + direction.X, currentPoint.Y + direction.Y); + //Если следующая точка является точкой выхода, + if (nextPoint == _Exit) + { + //то решение найдено, алгоритм завершен + complete = true; + } + //если текущая труба вывела нас за границы поля + else if ((nextPoint.X < 1) || (nextPoint.X > _ColCount) || (nextPoint.Y < 1) || (nextPoint.Y > _RowCount)) + { + //тупик + complete = false; + + } + else + { + //если в следующей точки нету трубы + if ((object) _Field[nextPoint.X, nextPoint.Y] == null) + { + //тупик + complete = false; + } + //если в ледующей точке есть труба, то смотрим ее + else + { + //если следующая труба уже задействована в текущем рассматриваемом пути, + if (_Field[nextPoint.X, nextPoint.Y].PartOfPath == true) + { + //тупик + complete = false; + } + //если следующая труба еще не задействована + else + { + //получаем следующую трубу + Pipe nextPipe = _Field[nextPoint.X, nextPoint.Y]; + //разворачиваем ее так, какой-то из ее входов выходил на текущую точку + nextPipe.RotateTo(currentPoint); + //добавляем в дерево решений новую ветку рассмотрения + solutionThree.AddChildNode(nextPipe.Clone(), currentPoint); + //получаем новое направление движение (куда смотрит второй вход следующей трубы) + Orientation nextDirection = direction; + if (direction == -nextPipe.FirstHole) + { + nextDirection = nextPipe.SecondHole.Clone(); + } + else + { + nextDirection = nextPipe.FirstHole.Clone(); + } + //помечаем, что труба занята в решении + nextPipe.PartOfPath = true; + //вызываем рекурсивный методи рассматриваем все со следующей точки со следующим направлением + complete = DepthSolve(nextPoint, nextDirection, solutionThree.ChildNodes[0]); + //если поиск в глубину завершился неудачей и поворачивать еще можно + //(т.е. следующая труба не прямая, ведь ее разворот приведет к томуже результату) + if ((complete == false) && (nextPipe.FirstHole != -nextPipe.SecondHole)) + { + //удаляем текущую ветвь дерева решений + solutionThree.ChildNodes.RemoveAt(0); + //поворачиваем трубу второй раз, другим входом к текущей точке + nextPipe.RotateTo(currentPoint); + //добавляем в дерево решений новую ветвь + solutionThree.AddChildNode(nextPipe, currentPoint); + //вычисляем новое направление движения + if (direction == -nextPipe.FirstHole) + { + nextDirection = nextPipe.SecondHole; + } + else + { + nextDirection = nextPipe.FirstHole; + } + //и вызываем поиск в глубину в новом направлении (это уже второй вызов) + complete = DepthSolve(nextPoint, nextDirection, solutionThree.ChildNodes[0]); + //если и в эту сторону решение не находится + if (complete == false) + { + //то следующая труба - безперспективна + nextPipe.PartOfPath = false; + } + } + } + } + } + + return complete; + } + + /// + /// Метод добавления отдельной трубы на поле + /// + /// добавляемая труба + public void AddPipe(Pipe parNewPipe) + { + _Field[parNewPipe.Position.X, parNewPipe.Position.Y] = parNewPipe; + } + + /// + /// Количество столбцов поля + /// + public int ColCount + { + get { return _ColCount;} + } + /// + /// Количество строк поля + /// + public int RowCount + { + get { return _RowCount; } + } + + /// + /// Поле + /// + public Pipe[,] Field + { + get { return _Field; } + } + } +} diff --git a/PipesSolver/FormPipeSolver.Designer.cs b/PipesSolver/FormPipeSolver.Designer.cs new file mode 100644 index 0000000..6f99f5e --- /dev/null +++ b/PipesSolver/FormPipeSolver.Designer.cs @@ -0,0 +1,323 @@ +namespace PipesSolver +{ + partial class FormPipeSolver + { + /// + /// Требуется переменная конструктора. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Освободить все используемые ресурсы. + /// + /// истинно, если управляемый ресурс должен быть удален; иначе ложно. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Код, автоматически созданный конструктором форм Windows + + /// + /// Обязательный метод для поддержки конструктора - не изменяйте + /// содержимое данного метода при помощи редактора кода. + /// + private void InitializeComponent() + { + this.buttonApplyDim = new System.Windows.Forms.Button(); + this.textBoxColCount = new System.Windows.Forms.TextBox(); + this.textBoxRowCount = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.dataGridViewField = new System.Windows.Forms.DataGridView(); + this.buttonMarkEnter = new System.Windows.Forms.Button(); + this.buttonMarkExit = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.dataGridViewTemplate = new System.Windows.Forms.DataGridView(); + this.Column1 = new System.Windows.Forms.DataGridViewImageColumn(); + this.Column2 = new System.Windows.Forms.DataGridViewImageColumn(); + this.Column3 = new System.Windows.Forms.DataGridViewImageColumn(); + this.Column4 = new System.Windows.Forms.DataGridViewImageColumn(); + this.Column5 = new System.Windows.Forms.DataGridViewImageColumn(); + this.Column6 = new System.Windows.Forms.DataGridViewImageColumn(); + this.buttonDepthSolve = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.button4 = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.dataGridViewField)).BeginInit(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.dataGridViewTemplate)).BeginInit(); + this.SuspendLayout(); + // + // buttonApplyDim + // + this.buttonApplyDim.Location = new System.Drawing.Point(162, 36); + this.buttonApplyDim.Name = "buttonApplyDim"; + this.buttonApplyDim.Size = new System.Drawing.Size(119, 23); + this.buttonApplyDim.TabIndex = 0; + this.buttonApplyDim.Text = "Применить"; + this.buttonApplyDim.UseVisualStyleBackColor = true; + this.buttonApplyDim.Click += new System.EventHandler(this.buttonApplyDim_Click); + // + // textBoxColCount + // + this.textBoxColCount.Location = new System.Drawing.Point(19, 36); + this.textBoxColCount.Name = "textBoxColCount"; + this.textBoxColCount.Size = new System.Drawing.Size(41, 22); + this.textBoxColCount.TabIndex = 2; + this.textBoxColCount.Text = "3"; + // + // textBoxRowCount + // + this.textBoxRowCount.Location = new System.Drawing.Point(97, 36); + this.textBoxRowCount.Name = "textBoxRowCount"; + this.textBoxRowCount.Size = new System.Drawing.Size(41, 22); + this.textBoxRowCount.TabIndex = 3; + this.textBoxRowCount.Text = "3"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(70, 38); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(17, 17); + this.label1.TabIndex = 4; + this.label1.Text = "X"; + // + // dataGridViewField + // + this.dataGridViewField.AllowUserToAddRows = false; + this.dataGridViewField.AllowUserToDeleteRows = false; + this.dataGridViewField.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataGridViewField.Location = new System.Drawing.Point(321, 12); + this.dataGridViewField.Name = "dataGridViewField"; + this.dataGridViewField.ReadOnly = true; + this.dataGridViewField.RowTemplate.Height = 24; + this.dataGridViewField.Size = new System.Drawing.Size(623, 550); + this.dataGridViewField.TabIndex = 6; + this.dataGridViewField.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridViewField_CellContentClick); + this.dataGridViewField.CellContentDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridViewField_CellContentDoubleClick); + this.dataGridViewField.MouseClick += new System.Windows.Forms.MouseEventHandler(this.dataGridViewField_MouseClick); + // + // buttonMarkEnter + // + this.buttonMarkEnter.Location = new System.Drawing.Point(12, 96); + this.buttonMarkEnter.Name = "buttonMarkEnter"; + this.buttonMarkEnter.Size = new System.Drawing.Size(156, 23); + this.buttonMarkEnter.TabIndex = 7; + this.buttonMarkEnter.Text = "Отметить вход"; + this.buttonMarkEnter.UseVisualStyleBackColor = true; + this.buttonMarkEnter.Click += new System.EventHandler(this.buttonMarkEnter_Click); + // + // buttonMarkExit + // + this.buttonMarkExit.Location = new System.Drawing.Point(174, 96); + this.buttonMarkExit.Name = "buttonMarkExit"; + this.buttonMarkExit.Size = new System.Drawing.Size(141, 23); + this.buttonMarkExit.TabIndex = 8; + this.buttonMarkExit.Text = "Отметить выход"; + this.buttonMarkExit.UseVisualStyleBackColor = true; + this.buttonMarkExit.Click += new System.EventHandler(this.buttonMarkExit_Click); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.textBoxColCount); + this.groupBox1.Controls.Add(this.buttonApplyDim); + this.groupBox1.Controls.Add(this.textBoxRowCount); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(12, 13); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(303, 77); + this.groupBox1.TabIndex = 9; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Размерность"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.dataGridViewTemplate); + this.groupBox2.Location = new System.Drawing.Point(12, 191); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(303, 91); + this.groupBox2.TabIndex = 10; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Трубы"; + // + // dataGridViewTemplate + // + this.dataGridViewTemplate.AllowUserToAddRows = false; + this.dataGridViewTemplate.AllowUserToDeleteRows = false; + this.dataGridViewTemplate.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Sunken; + this.dataGridViewTemplate.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataGridViewTemplate.ColumnHeadersVisible = false; + this.dataGridViewTemplate.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.Column1, + this.Column2, + this.Column3, + this.Column4, + this.Column5, + this.Column6}); + this.dataGridViewTemplate.EnableHeadersVisualStyles = false; + this.dataGridViewTemplate.Location = new System.Drawing.Point(37, 30); + this.dataGridViewTemplate.Name = "dataGridViewTemplate"; + this.dataGridViewTemplate.ReadOnly = true; + this.dataGridViewTemplate.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.None; + this.dataGridViewTemplate.RowHeadersVisible = false; + this.dataGridViewTemplate.RowTemplate.Height = 24; + this.dataGridViewTemplate.Size = new System.Drawing.Size(244, 43); + this.dataGridViewTemplate.TabIndex = 0; + this.dataGridViewTemplate.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridViewTemplate_CellContentClick); + // + // Column1 + // + this.Column1.HeaderText = "Column1"; + this.Column1.ImageLayout = System.Windows.Forms.DataGridViewImageCellLayout.Stretch; + this.Column1.Name = "Column1"; + this.Column1.ReadOnly = true; + this.Column1.Resizable = System.Windows.Forms.DataGridViewTriState.True; + this.Column1.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic; + this.Column1.Width = 40; + // + // Column2 + // + this.Column2.HeaderText = "Column2"; + this.Column2.ImageLayout = System.Windows.Forms.DataGridViewImageCellLayout.Stretch; + this.Column2.Name = "Column2"; + this.Column2.ReadOnly = true; + this.Column2.Resizable = System.Windows.Forms.DataGridViewTriState.True; + this.Column2.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic; + this.Column2.Width = 40; + // + // Column3 + // + this.Column3.HeaderText = "Column3"; + this.Column3.ImageLayout = System.Windows.Forms.DataGridViewImageCellLayout.Stretch; + this.Column3.Name = "Column3"; + this.Column3.ReadOnly = true; + this.Column3.Resizable = System.Windows.Forms.DataGridViewTriState.True; + this.Column3.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic; + this.Column3.Width = 40; + // + // Column4 + // + this.Column4.HeaderText = "Column4"; + this.Column4.ImageLayout = System.Windows.Forms.DataGridViewImageCellLayout.Stretch; + this.Column4.Name = "Column4"; + this.Column4.ReadOnly = true; + this.Column4.Resizable = System.Windows.Forms.DataGridViewTriState.True; + this.Column4.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic; + this.Column4.Width = 40; + // + // Column5 + // + this.Column5.HeaderText = "Column5"; + this.Column5.ImageLayout = System.Windows.Forms.DataGridViewImageCellLayout.Stretch; + this.Column5.Name = "Column5"; + this.Column5.ReadOnly = true; + this.Column5.Resizable = System.Windows.Forms.DataGridViewTriState.True; + this.Column5.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic; + this.Column5.Width = 40; + // + // Column6 + // + this.Column6.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.Column6.HeaderText = "Column6"; + this.Column6.ImageLayout = System.Windows.Forms.DataGridViewImageCellLayout.Stretch; + this.Column6.Name = "Column6"; + this.Column6.ReadOnly = true; + this.Column6.Resizable = System.Windows.Forms.DataGridViewTriState.True; + this.Column6.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic; + // + // buttonDepthSolve + // + this.buttonDepthSolve.Location = new System.Drawing.Point(12, 343); + this.buttonDepthSolve.Name = "buttonDepthSolve"; + this.buttonDepthSolve.Size = new System.Drawing.Size(156, 23); + this.buttonDepthSolve.TabIndex = 11; + this.buttonDepthSolve.Text = "Поиск в глубину"; + this.buttonDepthSolve.UseVisualStyleBackColor = true; + this.buttonDepthSolve.Click += new System.EventHandler(this.button1_Click); + // + // button2 + // + this.button2.Location = new System.Drawing.Point(12, 395); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(156, 23); + this.button2.TabIndex = 12; + this.button2.Text = "button2"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button3 + // + this.button3.Location = new System.Drawing.Point(12, 449); + this.button3.Name = "button3"; + this.button3.Size = new System.Drawing.Size(156, 23); + this.button3.TabIndex = 13; + this.button3.Text = "button3"; + this.button3.UseVisualStyleBackColor = true; + // + // button4 + // + this.button4.Location = new System.Drawing.Point(12, 507); + this.button4.Name = "button4"; + this.button4.Size = new System.Drawing.Size(156, 23); + this.button4.TabIndex = 14; + this.button4.Text = "button4"; + this.button4.UseVisualStyleBackColor = true; + // + // FormPipeSolver + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(956, 574); + this.Controls.Add(this.button4); + this.Controls.Add(this.button3); + this.Controls.Add(this.button2); + this.Controls.Add(this.buttonDepthSolve); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.buttonMarkExit); + this.Controls.Add(this.buttonMarkEnter); + this.Controls.Add(this.dataGridViewField); + this.Name = "FormPipeSolver"; + this.Text = "Решатель труб"; + this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseClick); + ((System.ComponentModel.ISupportInitialize)(this.dataGridViewField)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.dataGridViewTemplate)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button buttonApplyDim; + private System.Windows.Forms.TextBox textBoxColCount; + private System.Windows.Forms.TextBox textBoxRowCount; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.DataGridView dataGridViewField; + private System.Windows.Forms.Button buttonMarkEnter; + private System.Windows.Forms.Button buttonMarkExit; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.DataGridView dataGridViewTemplate; + private System.Windows.Forms.DataGridViewImageColumn Column1; + private System.Windows.Forms.DataGridViewImageColumn Column2; + private System.Windows.Forms.DataGridViewImageColumn Column3; + private System.Windows.Forms.DataGridViewImageColumn Column4; + private System.Windows.Forms.DataGridViewImageColumn Column5; + private System.Windows.Forms.DataGridViewImageColumn Column6; + private System.Windows.Forms.Button buttonDepthSolve; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.Button button4; + } +} + diff --git a/PipesSolver/FormPipeSolver.cs b/PipesSolver/FormPipeSolver.cs new file mode 100644 index 0000000..c8c42ce --- /dev/null +++ b/PipesSolver/FormPipeSolver.cs @@ -0,0 +1,468 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System.Runtime.InteropServices; + +namespace PipesSolver +{ + /// + /// Класс главной формы + /// + public partial class FormPipeSolver : Form + { + /// + /// структура, хранящая параметры изображения + /// + public struct IconInfo + { + public bool fIcon; + public int xHotspot; + public int yHotspot; + public IntPtr hbmMask; + public IntPtr hbmColor; + } + + /// + /// Множество возможных действий + /// + private enum Actions + { + MarkEnter, + MarkExit, + AdditionPipe, + None + } + + /// + /// Ширина ячейки поля + /// + const int FIELD_CELL_WIDTH = 40; + /// + /// Высота ячейки поля + /// + const int FIELD_CELL_HEIGTH = 40; + + /// + /// Точка входа + /// + private Point _Enter; + /// + /// Точка выхода + /// + private Point _Exit; + /// + /// Количество колонок поля + /// + private int _ColCount; + /// + /// Количество строк поля + /// + private int _RowCount; + /// + /// Добавляемая на поле труба + /// + private Pipe _AddedPipe; + + /// + /// Массив труб расположенные на поле + /// + private Pipe[,] _PipesOnField; + + /// + /// Текущее действие + /// + Actions _Action; + + /// + /// Конструктор формы + /// + public FormPipeSolver() + { + InitializeComponent(); + + //инициализируем точку входа и выхода + _Enter = _Exit = new Point(0, 0); + //Инициализируем текущее действие + _Action = Actions.None; + //Инициализируем поле + _PipesOnField = new Pipe[0,0]; + //создаем табличку с шаблонами труб + CreatePipeTemplate(); + } + + + + /// + /// Создание таблицы шаблонов труб + /// + public void CreatePipeTemplate() + { + dataGridViewTemplate.RowTemplate.Height = FIELD_CELL_HEIGTH; + dataGridViewTemplate.Rows.Add(); + dataGridViewTemplate.Rows[0].Cells[0].Value = Properties.Resources.angle1; + dataGridViewTemplate.Rows[0].Cells[1].Value = Properties.Resources.angle2; + dataGridViewTemplate.Rows[0].Cells[2].Value = Properties.Resources.angle3; + dataGridViewTemplate.Rows[0].Cells[3].Value = Properties.Resources.angle4; + dataGridViewTemplate.Rows[0].Cells[4].Value = Properties.Resources.direct1; + dataGridViewTemplate.Rows[0].Cells[5].Value = Properties.Resources.direct2; + + } + + + //Магия... + [DllImport("user32.dll")] + public static extern IntPtr CreateIconIndirect(ref IconInfo icon); + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo); + //задание курсора в виде выбранной трубы + public static System.Windows.Forms.Cursor CreateCursor(Bitmap bmp, int xHotSpot, int yHotSpot) + { + IconInfo tmp = new IconInfo(); + GetIconInfo(bmp.GetHicon(), ref tmp); + tmp.xHotspot = xHotSpot; + tmp.yHotspot = yHotSpot; + tmp.fIcon = false; + return new System.Windows.Forms.Cursor(CreateIconIndirect(ref tmp)); + } + + /// + /// Установить курсор по умолчанию + /// + public void SetDefaultCuror() + { + Cursor = Cursors.Default; + dataGridViewField.Cursor = Cursors.Default; + } + + /// + /// Нажатие на кнопку применить + /// + /// + /// + private void buttonApplyDim_Click(object sender, EventArgs e) + { + try + { + //Получаем введенное количество строк и столбцов поля + _ColCount = Convert.ToInt32(textBoxColCount.Text); + _RowCount = Convert.ToInt32(textBoxRowCount.Text); + + //создаем массив труб на поле + _PipesOnField = new Pipe[_ColCount + 2, _RowCount + 2]; + //если п олях введены значения больше 0 + if ((_ColCount != 0) && (_RowCount != 0)) + { + //очищаем поле + dataGridViewField.Columns.Clear(); + //опять же обнуляем точку входа и выхода + _Enter = _Exit = new Point(0, 0); + //действие - ничего + _Action = Actions.None; + //создаем поле + CreateTaskField(); + } + // если чтото случилось не так, выбрасываем исключение + else throw new Exception(); + } + catch + { + //перехватываем исключения здесь + MessageBox.Show("Введите корректно значения размеров поля"); + } + } + /// + /// Создание поля задачи + /// + public void CreateTaskField() + { + DataGridViewImageColumn col = new DataGridViewImageColumn(); + col.Image = Properties.Resources.border; + col.Width = FIELD_CELL_WIDTH / 2; + col.ImageLayout = DataGridViewImageCellLayout.Stretch; + dataGridViewField.Columns.Add(col); + for (int i = 0; i < _ColCount; i++) + { + col = new DataGridViewImageColumn(); + col.Width = FIELD_CELL_WIDTH; + col.Image = Properties.Resources.fieldsegment; + col.ImageLayout = DataGridViewImageCellLayout.Stretch; + dataGridViewField.Columns.Add(col); + } + col = new DataGridViewImageColumn(); + col.Width = FIELD_CELL_WIDTH / 2; + col.Image = Properties.Resources.border; + col.ImageLayout = DataGridViewImageCellLayout.Stretch; + dataGridViewField.Columns.Add(col); + + + dataGridViewField.RowTemplate.Height = FIELD_CELL_HEIGTH / 2; + dataGridViewField.RowCount += 1; + dataGridViewField.RowTemplate.Height = FIELD_CELL_HEIGTH; + dataGridViewField.RowCount += _RowCount; + dataGridViewField.RowTemplate.Height = FIELD_CELL_HEIGTH / 2; + dataGridViewField.RowCount += 1; + + for (int i = 0; i <= _ColCount + 1; i++) + { + dataGridViewField.Rows[0].Cells[i].Value = Properties.Resources.border; + dataGridViewField.Rows[_RowCount + 1].Cells[i].Value = Properties.Resources.border; + } + } + + /// + /// Создание поля решения + /// + private void CreateSolveField() + { + dataGridViewField.RowCount= _RowCount + 2; + dataGridViewField.RowTemplate.Height = FIELD_CELL_HEIGTH / 2; + dataGridViewField.RowCount += 1; + dataGridViewField.RowTemplate.Height = FIELD_CELL_HEIGTH; + dataGridViewField.RowCount += _RowCount; + dataGridViewField.RowTemplate.Height = FIELD_CELL_HEIGTH / 2; + dataGridViewField.RowCount += 1; + + for (int i = 0; i <= _ColCount; i++) + { + dataGridViewField.Rows[_RowCount+2].Cells[i].Value = Properties.Resources.border; + dataGridViewField.Rows[_RowCount * 2 + 3].Cells[i].Value = Properties.Resources.border; + } + } + /// + /// Нажатие кнопки "Отметить вход" + /// + /// + /// + private void buttonMarkEnter_Click(object sender, EventArgs e) + { + //Действие задаем - указание точки входа + _Action = Actions.MarkEnter; + //отключаем кнопу "Отметить вход" + buttonMarkEnter.Enabled = false; + //курсор меняем на вид руки + Cursor = Cursors.Hand; + dataGridViewField.Cursor = Cursors.Hand; + //включаем кнопу "Отметить выход" + buttonMarkExit.Enabled = true; + } + /// + /// Нажатие на кнопку "Отметить выход" + /// + /// + /// + private void buttonMarkExit_Click(object sender, EventArgs e) + { + //Действие задаем - указание точки выхода + _Action = Actions.MarkExit; + //отключаем кнопу "Отметить выход" + buttonMarkExit.Enabled = false; + //курсор меняем на вид руки + Cursor = Cursors.Hand; + dataGridViewField.Cursor = Cursors.Hand; + //включаем кнопу "Отметить вход" + buttonMarkEnter.Enabled = true; + } + + /// + /// Нажате по ячейке таблицы шаблонов труб + /// + /// + /// + private void dataGridViewTemplate_CellContentClick(object sender, DataGridViewCellEventArgs e) + { + //Действие задаем -добавление трубы на поле + _Action = Actions.AdditionPipe; + //Создаем новую трубу по образу и подобию той, на которую нажали в табличке шаблонов + _AddedPipe = Pipe.TemplatePipes[e.ColumnIndex].Clone(); + //видоизменяем курсор...немного магии + Bitmap img = new Bitmap(_AddedPipe.Image, new Size(FIELD_CELL_WIDTH, FIELD_CELL_HEIGTH)); + Cursor = CreateCursor(img, 2, 2); + dataGridViewField.Cursor = CreateCursor(img, 2, 2); + + //на всякий случай активируем кнопки "Отметить вход" и "Отметиь выход" + buttonMarkEnter.Enabled = true; + buttonMarkExit.Enabled = true; + } + + /// + /// Нажате на ячейку в поле с трубами + /// + /// + /// + private void dataGridViewField_CellContentClick(object sender, DataGridViewCellEventArgs e) + { + //если нажали на бордюр поля + if (((e.ColumnIndex == 0) || (e.ColumnIndex == dataGridViewField.ColumnCount - 1) || + (e.RowIndex == 0) || (e.RowIndex == dataGridViewField.RowCount - 1))&&(e.ColumnIndex != e.RowIndex)) + { + //если в данный момент действие - указание выхода, + if ((_Action == Actions.MarkEnter) && ((_Exit.X != e.ColumnIndex) || (_Exit.Y != e.RowIndex))) + { + //на всякий случай закрашиваем старую точку входа (если она уже была отмечена ранее) в цвет бордюра + dataGridViewField.Rows[_Enter.Y].Cells[_Enter.X].Value = Properties.Resources.border; + //задаем новую точку входа + _Enter = new Point(e.ColumnIndex, e.RowIndex); + //и окрашиваем бордюр в нажатой точке цветом точки входа + dataGridViewField.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Properties.Resources.enter; + //Действие задаем - никакое + _Action = Actions.None; + //Включаем кнопку "отметить вход" + buttonMarkEnter.Enabled = true; + //задаем курсор по умолчанию + SetDefaultCuror(); + } + //если дейстиве - указание выхода, то делаем все тоже самое что и со входом + if ((_Action == Actions.MarkExit) && ((_Enter.X != e.ColumnIndex) || (_Enter.Y != e.RowIndex))) + { + dataGridViewField.Rows[_Exit.Y].Cells[_Exit.X].Value = Properties.Resources.border; + _Exit = new Point(e.ColumnIndex, e.RowIndex); + dataGridViewField.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Properties.Resources.exit; + + _Action = Actions.None; + buttonMarkExit.Enabled = true; + SetDefaultCuror(); + } + } + //если мы нажали по ячейке "игровой" области + else + { + try + { + //если текущее действие - добавление трубы, то + if (_Action == Actions.AdditionPipe) + { + //задаем добавляемой трубе положение соответственно тому, по какой ячейке поля мы нажали + _AddedPipe.Position = new Point(e.ColumnIndex, e.RowIndex); + //задаем картинку в ячейке на поле соответсвующую добавляемой трубе + dataGridViewField.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = _AddedPipe.Image; + //добавляем новую трубу в массив труб на поле + _PipesOnField[e.ColumnIndex, e.RowIndex] = _AddedPipe; + //ну и удаляем из памяти добавляемую трубу + _AddedPipe = null; + //действие задаем - ни какое + _Action = Actions.None; + //устанавливаем курсор по умолчанию + SetDefaultCuror(); + } + } + catch + { + } + } + } + + /// + /// Клик по форме + /// + /// + /// + private void Form1_MouseClick(object sender, MouseEventArgs e) + { + //Если нажата правая кнопки мыши этот момент мы добавляли трубу + if ((e.Button == System.Windows.Forms.MouseButtons.Right) && (_Action == Actions.AdditionPipe)) + { + //отменяем действие + _Action = Actions.None; + SetDefaultCuror(); + } + } + /// + /// Клик по таблице + /// + /// + /// + private void dataGridViewField_MouseClick(object sender, MouseEventArgs e) + { + //Если нажата правая кнопки мыши этот момент мы добавляли трубу + if ((e.Button == System.Windows.Forms.MouseButtons.Right) && (_Action == Actions.AdditionPipe)) + { + _Action = Actions.None; + Cursor = Cursors.Default; + dataGridViewField.Cursor = Cursors.Default; + } + } + + /// + /// Двойной клик по ячейке таблицы + /// + /// + /// + private void dataGridViewField_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e) + { + //Если мы нечего не делали и в клетке, по которой был клик, есть труба, + if ((_Action == Actions.None)&&((object)_PipesOnField[e.ColumnIndex,e.RowIndex] != null)) + { + //удаляем ту трубу + _PipesOnField[e.ColumnIndex, e.RowIndex] = null; + dataGridViewField.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Properties.Resources.fieldsegment; + } + } + + private void buttonDepthSolve_Click(object sender, EventArgs e) + { + Pipe[,] testField = GetCopeField(); + + Brainteaser br = new Brainteaser(testField, _ColCount, _RowCount, _Enter, _Exit); + bool complete = br.DepthSolve(); + OutputSolve(br); + + if (complete) + { + MessageBox.Show("Решено"); + } + else + { + MessageBox.Show("Не решено"); + } + } + + private void OutputSolve(Brainteaser parTask) + { + CreateSolveField(); + + for (int j = 0; j < _RowCount + 2; j++) + { + + for (int i = 0; i < _ColCount + 2; i++) + { + if ((object)parTask.Field[i, j] != null) + { + dataGridViewField.Rows[j+_RowCount + 2].Cells[i].Value = parTask.Field[i, j].Image; + } + } + } + } + + /// + /// Получить копию поля + /// + /// + public Pipe[,] GetCopeField() + { + Pipe[,] field = new Pipe[_ColCount + 2, _RowCount + 2]; + for (int i = 0; i < _ColCount + 2; i++) + for (int j = 0; j < _RowCount + 2; j++) + { + if ((object)_PipesOnField[i, j] != null) + { + field[i, j] = _PipesOnField[i, j].Clone(); + } + } + + return field; + } + + private void button2_Click(object sender, EventArgs e) + { + CreateSolveField(); + } + + + } +} diff --git a/PipesSolver/FormPipeSolver.resx b/PipesSolver/FormPipeSolver.resx new file mode 100644 index 0000000..b851021 --- /dev/null +++ b/PipesSolver/FormPipeSolver.resx @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + True + + + True + + + True + + + True + + + True + + \ No newline at end of file diff --git a/PipesSolver/Orientation.cs b/PipesSolver/Orientation.cs new file mode 100644 index 0000000..297d040 --- /dev/null +++ b/PipesSolver/Orientation.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Drawing; + +namespace PipesSolver +{ + /// + /// Класс вектора направления + /// + public class Orientation + { + /// + /// Направление вверх + /// + public static Orientation Up + { get { return new Orientation(new Point(0, -1)); } } + /// + /// Направление вниз + /// + public static Orientation Down + { get { return new Orientation(new Point(0, 1)); } } + /// + /// Направление влево + /// + public static Orientation Left + { get { return new Orientation(new Point(-1, 0)); } } + /// + /// Направление вправо + /// + public static Orientation Right + { get { return new Orientation(new Point(1, 0)); } } + + /// + /// Горизонтальная составляющая вектора направления + /// + private int _X; + /// + /// Вертикальная составляющая вектора направления + /// + private int _Y; + + /// + /// Массив направлений по умолчанию(вверх, вниз, влево, вправо. Используются для поворота вектора + /// + private List _Orientations = new List(); + + /// + /// Конструктор класса + /// + private Orientation() + { + _Orientations.Add(new Point(1, 0)); + _Orientations.Add(new Point(0, 1)); + _Orientations.Add(new Point(-1, 0)); + _Orientations.Add(new Point(0, -1)); + + _X = _Orientations[0].X; + _Y = _Orientations[0].Y; + } + /// + /// Конструктор класса + /// + /// Горизонтальная составляющая вектора направления + /// Вертикальная составляющая вектора направления + private Orientation(int parX, int parY) + { + _Orientations.Add(new Point(1, 0)); + _Orientations.Add(new Point(0, 1)); + _Orientations.Add(new Point(-1, 0)); + _Orientations.Add(new Point(0, -1)); + + _X = parX; + _Y = parY; + } + + /// + /// Конструктор формы + /// + /// вектор направления + private Orientation(Point parVector) + { + _Orientations.Add(new Point(1, 0)); + _Orientations.Add(new Point(0, 1)); + _Orientations.Add(new Point(-1, 0)); + _Orientations.Add(new Point(0, -1)); + _X = parVector.X; + _Y = parVector.Y; + } + /// + /// Повернуть вектор направления + /// + /// + public void Rotate(bool parClockwise) + { + + int i = 0; + //Если поворачиваем по часовой стрелке + if (parClockwise) + { + //Перебираем шаблонные векторы в прямую сторону + for (i = 0; i < _Orientations.Count; i++) + { + //Как только нашли тот, что соответствует текущему + //выходим из цикла и запоминаем индекс шаблонного вектора + if ((_Orientations[i].X == _X) && (_Orientations[i].Y == _Y)) + break; + } + //если индекс оказался последним в массиве шаблонов, то следующим будет тот, что в начале массива шаблонов + if (i == _Orientations.Count - 1) + i = 0; + //иначе просто увеличиваем индекс, получая следующего по часовой стрелке вектора + else + i++; + + } + //аналогичным образом просматриваем если поворот против часовой + else + { + //индексы смотрим в обратном порядке + for (i = 0; i < _Orientations.Count; i--) + { + if ((_Orientations[i].X == _X) && (_Orientations[i].Y == _Y)) + break; + } + if (i == 0) + i = _Orientations.Count - 1; + else + i--; + } + + _X = _Orientations[i].X; + _Y = _Orientations[i].Y; + } + + /// + /// создаем копию текущего объекта + /// + /// + public Orientation Clone() + { + return new Orientation(_X, _Y); + } + /// + /// перегруженный оператор минус + /// + /// + /// + public static Orientation operator -(Orientation parOrientation) + { + return new Orientation(new Point(-parOrientation.X, -parOrientation.Y)); + } + /// + /// перегруженный оператор равно + /// + /// + /// + /// + public static bool operator ==(Orientation parFirstOrientation, Orientation parSecondOrientation) + { + if ((parFirstOrientation.X == parSecondOrientation.X) && (parFirstOrientation.Y == parSecondOrientation.Y)) + return true; + else + return false; + } + /// + /// перегруженный оператор не равно + /// + /// + /// + /// + public static bool operator !=(Orientation parFirstOrientation, Orientation parSecondOrientation) + { + if (!((parFirstOrientation.X == parSecondOrientation.X) && (parFirstOrientation.Y == parSecondOrientation.Y))) + return true; + else + return false; + } + + + /// + /// Горизонтальная составляющая вектора направления + /// + public int X + { get { return _X; } } + /// + /// Вертикальная составляющая вектора направления + /// + public int Y + { get { return _Y; } } + + } +} diff --git a/PipesSolver/Pipe.cs b/PipesSolver/Pipe.cs new file mode 100644 index 0000000..e10b46d --- /dev/null +++ b/PipesSolver/Pipe.cs @@ -0,0 +1,206 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Drawing; + +namespace PipesSolver +{ + /// + /// Класс трубы + /// + public class Pipe + { + /// + /// Массив шаблонов труб + /// + public static List TemplatePipes = new List { + new Pipe(new Point(0, 0), Orientation.Up, Orientation.Right, Properties.Resources.angle1), + new Pipe(new Point(0, 0), Orientation.Right, Orientation.Down, Properties.Resources.angle2), + new Pipe(new Point(0, 0), Orientation.Down, Orientation.Left, Properties.Resources.angle3), + new Pipe(new Point(0, 0), Orientation.Left, Orientation.Up, Properties.Resources.angle4), + new Pipe(new Point(0, 0), Orientation.Up, Orientation.Down, Properties.Resources.direct1), + new Pipe(new Point(0, 0), Orientation.Left, Orientation.Right, Properties.Resources.direct2) + }; + + /// + /// Первое отверстие трубы + /// + private Orientation _FirstHole; + /// + /// Второе отверстие трубы + /// + private Orientation _SecondHole; + /// + /// Положение трубы на поле + /// + private Point _Position; + /// + /// Изображение трубы + /// + private Bitmap _Image; + /// + /// Является ли частью рассматриваемого пути + /// + private bool _PartOfPath; + + /// + /// Конструктор класса + /// + /// Положение на поле + /// Первое отверстие + /// Второе отверстие + /// Изображение трубы + public Pipe(Point parPosition, Orientation parFirstHole, Orientation parSecondHole, Bitmap parImage) + { + _Position = parPosition; + _FirstHole = parFirstHole; + _SecondHole = parSecondHole; + _Image = parImage; + _PartOfPath = false; + } + + /// + /// Создание копии текущего объекта + /// + /// + public Pipe Clone() + { + return new Pipe(new Point(_Position.X, _Position.Y), _FirstHole.Clone(), _SecondHole.Clone(), _Image); + } + + /// + /// Поворот трубы + /// + /// по часовой(true) или против часовой(false) + public void Rotate(bool parClockwise) + { + //поворачиваем первое и второе отверстие + _FirstHole.Rotate(parClockwise); + _SecondHole.Rotate(parClockwise); + + //просматриваем список шаблонов труб + for (int i = 0; i < TemplatePipes.Count; i++) + { + //как только среди шаблонов находим с отверстиями, ориентированными также как у текущего объекта(трубы) + if (((_FirstHole == TemplatePipes[i].FirstHole)&&(_SecondHole == TemplatePipes[i].SecondHole)) + ||((_FirstHole == TemplatePipes[i].SecondHole)&&(_SecondHole == TemplatePipes[i].FirstHole))) + { + //меняем картинку текущего объекта(трубы) на картинку найденного шаблона + _Image = TemplatePipes[i].Image; + break; + } + } + } + + /// + /// Перегруженный оператор сравнения + /// + /// + /// + /// + public static bool operator == (Pipe parFirstPipe, Pipe parSecondPipe) + { + if ((parFirstPipe.FirstHole.X == parSecondPipe.FirstHole.X) && (parFirstPipe.FirstHole.Y == parSecondPipe.FirstHole.Y) && + (parFirstPipe.SecondHole.X == parSecondPipe.SecondHole.X) && (parFirstPipe.SecondHole.X == parSecondPipe.SecondHole.X)) + { + return true; + } + else + { + return false; + } + } + + /// + /// Перегруженный оператор сравнения + /// + /// + /// + /// + public static bool operator != (Pipe parFirstPipe, Pipe parSecondPipe) + { + if ((object)parSecondPipe == null) + if ((object)parFirstPipe == null) + { + return true; + } + else + { + return false; + } + else + if (!(parFirstPipe.FirstHole.X == parSecondPipe.FirstHole.X) && (parFirstPipe.FirstHole.Y == parSecondPipe.FirstHole.Y) && + (parFirstPipe.SecondHole.X == parSecondPipe.SecondHole.X) && (parFirstPipe.SecondHole.X == parSecondPipe.SecondHole.X)) + { + return true; + } + else + { + return false; + } + } + + /// + /// Поворот трубы ближайшим отверстием по направлению к заданной точке + /// + /// + public void RotateTo(Point parEnterPoint) + { + //поворачиваем трубу, не долго думая + Rotate(true); + //пока + while (true) + { + //первое или второе отверстие не станут смотреть в сторону заданной точки + if (((parEnterPoint.X == _Position.X + _FirstHole.X) && (parEnterPoint.Y == _Position.Y + _FirstHole.Y)) || + ((parEnterPoint.X == _Position.X + _SecondHole.X) && (parEnterPoint.Y == _Position.Y + _SecondHole.Y))) + { + //если повернули как надо, выходим из цикла + break; + } + //иначе + else + { + //продолжаем поворачивать + Rotate(true); + } + } + } + + /// + /// Первое отверстие трубы + /// + public Orientation FirstHole + { get { return _FirstHole; } } + /// + /// Второе отверстие трубы + /// + public Orientation SecondHole + { get { return _SecondHole; } } + /// + /// Положение трубы на поле + /// + public Point Position + { + get { return _Position; } + set { _Position = value; } + } + /// + /// Изображение трубы + /// + public Bitmap Image + { + get { return _Image; } + set { _Image = value; } + } + /// + /// Является ли труба частью + /// + public bool PartOfPath + { + get { return _PartOfPath; } + set { _PartOfPath = value; } + } + } +} diff --git a/PipesSolver/PipeListCircle.cs b/PipesSolver/PipeListCircle.cs new file mode 100644 index 0000000..50744b3 --- /dev/null +++ b/PipesSolver/PipeListCircle.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PipesSolver +{ + class PipeListCircle + { + private List _Pipes; + private int _Pointer; + + public PipeListCircle() + { + _Pipes = new List(); + _Pointer = 0; + + } + + public void Add(Pipe parNewPipe) + { + _Pipes.Add(parNewPipe); + } + + public Pipe Next() + { + Pipe resPipe = _Pipes[_Pointer]; + _Pointer++; + + if (_Pointer >= _Pipes.Count) + _Pointer = 0; + + return resPipe; + } + + } +} diff --git a/PipesSolver/PipesSolver.csproj b/PipesSolver/PipesSolver.csproj new file mode 100644 index 0000000..85a49d6 --- /dev/null +++ b/PipesSolver/PipesSolver.csproj @@ -0,0 +1,130 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {6AF1A9B0-979C-47E3-A8E1-45C6F3DFF969} + WinExe + Properties + PipesSolver + PipesSolver + v4.0 + Client + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + Form + + + FormPipeSolver.cs + + + + + + + True + True + Resources.resx + + + + + FormPipeSolver.cs + + + ResXFileCodeGenerator + Designer + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PipesSolver/Program.cs b/PipesSolver/Program.cs new file mode 100644 index 0000000..5a08a29 --- /dev/null +++ b/PipesSolver/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace PipesSolver +{ + static class Program + { + /// + /// Главная точка входа для приложения. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new FormPipeSolver()); + } + } +} diff --git a/PipesSolver/Properties/AssemblyInfo.cs b/PipesSolver/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0fc5721 --- /dev/null +++ b/PipesSolver/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Управление общими сведениями о сборке осуществляется с помощью +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("PipesSolver")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PipesSolver")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми +// для COM-компонентов. Если требуется обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM +[assembly: Guid("152d4195-dc0b-40d5-bffa-623c9cf14c2e")] + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер построения +// Редакция +// +// Можно задать все значения или принять номер построения и номер редакции по умолчанию, +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/PipesSolver/Properties/Resources.Designer.cs b/PipesSolver/Properties/Resources.Designer.cs new file mode 100644 index 0000000..faca552 --- /dev/null +++ b/PipesSolver/Properties/Resources.Designer.cs @@ -0,0 +1,163 @@ +//------------------------------------------------------------------------------ +// +// Этот код создан программой. +// Исполняемая версия:4.0.30319.18051 +// +// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае +// повторной генерации кода. +// +//------------------------------------------------------------------------------ + +namespace PipesSolver.Properties { + using System; + + + /// + /// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д. + /// + // Этот класс создан автоматически классом StronglyTypedResourceBuilder + // с помощью такого средства, как ResGen или Visual Studio. + // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen + // с параметром /str или перестройте свой проект VS. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PipesSolver.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Перезаписывает свойство CurrentUICulture текущего потока для всех + /// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap angle1 { + get { + object obj = ResourceManager.GetObject("angle1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap angle2 { + get { + object obj = ResourceManager.GetObject("angle2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap angle3 { + get { + object obj = ResourceManager.GetObject("angle3", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap angle4 { + get { + object obj = ResourceManager.GetObject("angle4", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap border { + get { + object obj = ResourceManager.GetObject("border", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap direct1 { + get { + object obj = ResourceManager.GetObject("direct1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap direct2 { + get { + object obj = ResourceManager.GetObject("direct2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap enter { + get { + object obj = ResourceManager.GetObject("enter", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap exit { + get { + object obj = ResourceManager.GetObject("exit", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap fieldsegment { + get { + object obj = ResourceManager.GetObject("fieldsegment", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/PipesSolver/Properties/Resources.resx b/PipesSolver/Properties/Resources.resx new file mode 100644 index 0000000..2b11e58 --- /dev/null +++ b/PipesSolver/Properties/Resources.resx @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\angle1.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\angle2.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\angle3.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\angle4.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\border.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\direct1.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\direct2.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\enter.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\output.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\fieldsegment.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/PipesSolver/Properties/Settings.Designer.cs b/PipesSolver/Properties/Settings.Designer.cs new file mode 100644 index 0000000..90e94d8 --- /dev/null +++ b/PipesSolver/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.18051 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace PipesSolver.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/PipesSolver/Properties/Settings.settings b/PipesSolver/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/PipesSolver/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/PipesSolver/Resources/angle1.gif b/PipesSolver/Resources/angle1.gif new file mode 100644 index 0000000..8f71675 Binary files /dev/null and b/PipesSolver/Resources/angle1.gif differ diff --git a/PipesSolver/Resources/angle2.gif b/PipesSolver/Resources/angle2.gif new file mode 100644 index 0000000..37fcb1e Binary files /dev/null and b/PipesSolver/Resources/angle2.gif differ diff --git a/PipesSolver/Resources/angle3.gif b/PipesSolver/Resources/angle3.gif new file mode 100644 index 0000000..ca46615 Binary files /dev/null and b/PipesSolver/Resources/angle3.gif differ diff --git a/PipesSolver/Resources/angle4.gif b/PipesSolver/Resources/angle4.gif new file mode 100644 index 0000000..8ade947 Binary files /dev/null and b/PipesSolver/Resources/angle4.gif differ diff --git a/PipesSolver/Resources/border.gif b/PipesSolver/Resources/border.gif new file mode 100644 index 0000000..98e65ba Binary files /dev/null and b/PipesSolver/Resources/border.gif differ diff --git a/PipesSolver/Resources/direct1.gif b/PipesSolver/Resources/direct1.gif new file mode 100644 index 0000000..8925a27 Binary files /dev/null and b/PipesSolver/Resources/direct1.gif differ diff --git a/PipesSolver/Resources/direct2.gif b/PipesSolver/Resources/direct2.gif new file mode 100644 index 0000000..270f1e6 Binary files /dev/null and b/PipesSolver/Resources/direct2.gif differ diff --git a/PipesSolver/Resources/enter.gif b/PipesSolver/Resources/enter.gif new file mode 100644 index 0000000..7d259ac Binary files /dev/null and b/PipesSolver/Resources/enter.gif differ diff --git a/PipesSolver/Resources/fieldsegment.gif b/PipesSolver/Resources/fieldsegment.gif new file mode 100644 index 0000000..a39cc36 Binary files /dev/null and b/PipesSolver/Resources/fieldsegment.gif differ diff --git a/PipesSolver/Resources/input.gif b/PipesSolver/Resources/input.gif new file mode 100644 index 0000000..7d259ac Binary files /dev/null and b/PipesSolver/Resources/input.gif differ diff --git a/PipesSolver/Resources/output.gif b/PipesSolver/Resources/output.gif new file mode 100644 index 0000000..08770e4 Binary files /dev/null and b/PipesSolver/Resources/output.gif differ diff --git a/PipesSolver/Resources/testimage.gif b/PipesSolver/Resources/testimage.gif new file mode 100644 index 0000000..920e859 Binary files /dev/null and b/PipesSolver/Resources/testimage.gif differ diff --git a/PipesSolver/SolutionNode.cs b/PipesSolver/SolutionNode.cs new file mode 100644 index 0000000..649e639 --- /dev/null +++ b/PipesSolver/SolutionNode.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PipesSolver +{ + class SolutionNode + { + } +} diff --git a/PipesSolver/SolutionThree.cs b/PipesSolver/SolutionThree.cs new file mode 100644 index 0000000..a09231e --- /dev/null +++ b/PipesSolver/SolutionThree.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Drawing; + + +namespace PipesSolver +{ + /// + /// Класс дерева решений + /// + class SolutionThree + { + /// + /// Дочерние узлы дерева + /// + private List _ChildNodes; + /// + /// Родительский узел + /// + private SolutionThree _Root; + /// + /// Уровень узла + /// + private int _Level; + /// + /// Труба,выбранная для хода и уже повернутая в нужном направлении + /// + private Pipe _Pipe; + /// + /// Точка входа + /// + private Point _Enter; + + /// + /// Конструктор + /// + /// Родиельский узел + /// Уровень + public SolutionThree(Pipe parCurrentPipe, SolutionThree parRoot, Point parEnter, int parLevel) + { + _Root = parRoot; + _Level = parLevel; + _Enter = parEnter; + _ChildNodes = new List(); + } + + /// + /// Добавить дочерний узел в дерево + /// + /// + /// + public void AddChildNode(Pipe parCurrentPipe, Point parEneter) + { + _ChildNodes.Add(new SolutionThree(parCurrentPipe, this, parEneter, _Level++)); + } + + /// + /// Удалить дочерний узел с указанным индексом + /// + /// Индекс удаляемого дочернего узла + public void DeleteChildNode(int parChildIndex) + { + _ChildNodes.RemoveAt(parChildIndex); + } + + + /// + /// Дочерние узлы дерева + /// + public List ChildNodes + { + get { return _ChildNodes; } + } + /// + /// Родительский узел + /// + private SolutionThree Root + { + get { return _Root; } + } + /// + /// Уровень узла + /// + private int Level + { + get { return _Level; } + } + /// + /// Труба,выбранная для хода и уже повернутая в нужном направлении + /// + private Pipe Pipe + { + get { return _Pipe; } + } + /// + /// Точка входа + /// + private Point Enter + { + get { return _Enter; } + } + + } +}