WPF应用程序之最小生成树

这其实就是一个课程设计,我选的第三个,用C#做过一个,刚学了WPF,用WPF做个简单的,有向图的最小生成树我不知道怎么用画图表示,就先不做了。

界面:鼠标在有色区域取点,取点后可以移动点,取点和移动点时点会自动靠近大整数坐标,也就是你可以调整所有点到一个规则的五边形。

取完点后用鼠标滚轮取权值,权值越大,连线颜色越深,权值为0时透明度为0.05

也可以点击连线在输入框里面输入

滚轮输入:

image

输入框输入

image

权值是通过鼠标浮在连线上滚轮取值的,结果:

image

 

点和直线用的是Shapes里面的Ellipse和Line

程序过于简单,看WPF时看了数据绑定,自定义空间风格,依赖属性,但是这个里面都没有用到。

 

实现就很简单了:

取点一次加一个Ellipse,n-1个Line

输入权值,我没仔细做权值对应透明度的部分,所以权值超过9就没分别了,粗糙。

最小生成树的算法也很拙劣,没优化。

 

数学系的想做程序,自学至此,努力的空间很大。

 

代码:

XAML代码:

   1:  <Window x:Class="WpfAppMathmeticalModelEx3.MainWindow"
   2:          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:          Title="数学模型课程设计 无向图的最小生成树" Height="580" Width="800" WindowStartupLocation="CenterScreen" Loaded="Window_Loaded">
   5:      
   6:      <Grid Name="gridBord">
   7:          <Grid.RowDefinitions>
   8:              <RowDefinition Height="20"></RowDefinition>
   9:              <RowDefinition Height="300"></RowDefinition>
  10:              <RowDefinition Height="100"></RowDefinition>
  11:              <RowDefinition Height="100"></RowDefinition>
  12:              <RowDefinition></RowDefinition>
  13:          </Grid.RowDefinitions>
  14:          <Grid.ColumnDefinitions>
  15:              <ColumnDefinition Width="20"></ColumnDefinition>
  16:              <ColumnDefinition Width="500"></ColumnDefinition>
  17:              <ColumnDefinition></ColumnDefinition>
  18:          </Grid.ColumnDefinitions>
  19:          <Border Grid.Column="1" Grid.Row="1" Grid.RowSpan="3">
  20:              <Canvas Name="canvasBord" Width="500" Height="500">
  21:                  <Rectangle Name="rectangleBord" Width="500" Height="500" Fill="Beige"></Rectangle>
  22:              </Canvas>
  23:          </Border>
  24:          <Border Grid.Column="2" Grid.Row="1" BorderBrush="YellowGreen" BorderThickness="3" Margin="10">
  25:              <Canvas Name="canvasSummary" Grid.Column="2" Grid.Row="1" Margin="20">
  26:                  <TextBlock Name="tBSummary" FontSize="12" Width="190" Height="235" TextWrapping="WrapWithOverflow"></TextBlock>
  27:              </Canvas>
  28:          </Border>
  29:          <Border Grid.Column="2" Grid.Row="2" Margin="10">
  30:              <Canvas Name="canvasModel" Margin="20">
  31:                  <Button Name="btnModel" Width="190" Height="35" Click="btnModel_Click">计算最小生成树</Button>
  32:              </Canvas>
  33:          </Border>
  34:          <Border Grid.Column="2" Grid.Row="3" BorderBrush="YellowGreen" BorderThickness="3" Margin="10">
  35:              <Canvas Name="canvasResult" Margin="20">
  36:                  <TextBlock Name="tBResult" Width="190" Height="35" TextWrapping="WrapWithOverflow"></TextBlock>
  37:              </Canvas>
  38:          </Border>
  39:      </Grid>
  40:  </Window>
CS代码:
   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Windows;
   4:  using System.Windows.Controls;
   5:  using System.Windows.Input;
   6:  using System.Windows.Media;
   7:  using System.Text;
   8:  using System.Windows.Shapes;
   9:   
  10:  namespace WpfAppMathmeticalModelEx3
  11:  {
  12:      /// <summary>
  13:      /// MainWindow.xaml 的交互逻辑
  14:      /// </summary>
  15:      public partial class MainWindow : Window
  16:      {
  17:          public MainWindow()
  18:          {
  19:              InitializeComponent();
  20:              rectangleBord.MouseLeftButtonDown += rectangleBord_MouseLeftButtonDown;
  21:              rectangleBord.MouseLeftButtonUp += rectangleBord_MouseLeftButtonUp;
  22:          }
  23:   
  24:          private void Window_Loaded(object sender, RoutedEventArgs e)
  25:          {
  26:              listPoints = new List<Point>();
  27:              listEllipses = new List<Ellipse>();
  28:              tBInputW = new TextBox { Height = 20, Width = 80, Background = Brushes.YellowGreen };
  29:              canvasBord.Children.Add(tBInputW);
  30:              tBInputW.Visibility = Visibility.Hidden;
  31:              tBInputW.KeyUp += new KeyEventHandler(tBInputW_KeyUp);
  32:   
  33:              StringBuilder strBuilder = new StringBuilder();
  34:              strBuilder.AppendLine("操作步骤:\n");
  35:              strBuilder.AppendLine("1.用鼠标在左侧区域取点\n");
  36:              strBuilder.AppendLine("2.用鼠标调整点的位置\n");
  37:              strBuilder.AppendLine("3.把鼠标放在两个点之间的连线上滑动滚轮,即可调整这两个点之间的权值\n");
  38:              strBuilder.AppendLine("4.权值越大,连线颜色越深\n");
  39:              strBuilder.AppendLine("5.确定权值后点击 计算最小生成树 按钮\n");
  40:              tBSummary.Text = strBuilder.ToString();
  41:          }
  42:   
  43:          TextBox tBInputW;
  44:          List<Ellipse> listEllipses;
  45:          Point canvasBordStartPoint;
  46:   
  47:          void rectangleBord_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  48:          {
  49:              canvasBordStartPoint = e.GetPosition(canvasBord);
  50:          }
  51:   
  52:          void rectangleBord_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  53:          {
  54:              if (e.ClickCount > 1)
  55:                  return;
  56:              if (canvasBordStartPoint.X != e.GetPosition(canvasBord).X || canvasBordStartPoint.Y != e.GetPosition(canvasBord).Y)
  57:                  return;
  58:   
  59:              Point tmpPoint = e.GetPosition(canvasBord);
  60:              tmpPoint.X = ConvertToInt(autoMoveRadius, tmpPoint.X);
  61:              tmpPoint.Y = ConvertToInt(autoMoveRadius, tmpPoint.Y);
  62:              listPoints.Add(tmpPoint);
  63:              addNewPoint(tmpPoint);
  64:              addNewLine();
  65:          }
  66:   
  67:          bool isMouseDown;
  68:          Point startPoint;
  69:          Point currentPoint;
  70:          Point ellipseStartPoint;
  71:          //Point
  72:          const double radius = 10;
  73:          const int autoMoveRadius = 15;
  74:          readonly Brush pointBrush = Brushes.BlueViolet;
  75:          List<Point> listPoints;
  76:          //Line
  77:          const double lineWidth = 10;
  78:   
  79:          void ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  80:          {
  81:              isMouseDown = true;
  82:              startPoint = e.GetPosition(canvasBord);
  83:              ellipseStartPoint = new Point(Canvas.GetLeft((Ellipse)sender), Canvas.GetTop((Ellipse)sender));
  84:          }
  85:   
  86:          void ellipse_MouseMove(object sender, MouseEventArgs e)
  87:          {
  88:              if (isMouseDown && e.LeftButton == MouseButtonState.Pressed)
  89:              {
  90:                  currentPoint = e.GetPosition(canvasBord);
  91:                  Ellipse ellipse = (Ellipse)sender;
  92:                  Canvas.SetLeft(ellipse, ellipseStartPoint.X + currentPoint.X - startPoint.X);
  93:                  Canvas.SetTop(ellipse, ellipseStartPoint.Y + currentPoint.Y - startPoint.Y);
  94:                  listPoints[int.Parse(ellipse.Name.Substring(5))] = new Point(Canvas.GetLeft(ellipse) + radius, Canvas.GetTop(ellipse) + radius);
  95:                  AutoMoveLine(sender);
  96:              }
  97:          }
  98:   
  99:          void ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
 100:          {
 101:              isMouseDown = false;
 102:              Ellipse ellipse = (Ellipse)sender;
 103:              Point tmpPoint = listPoints[int.Parse(ellipse.Name.Substring(5))];
 104:              tmpPoint.X = ConvertToInt(autoMoveRadius, tmpPoint.X);
 105:              tmpPoint.Y = ConvertToInt(autoMoveRadius, tmpPoint.Y);
 106:              Canvas.SetLeft(ellipse, tmpPoint.X - radius);
 107:              Canvas.SetTop(ellipse, tmpPoint.Y - radius);
 108:              listPoints[int.Parse(ellipse.Name.Substring(5))] = tmpPoint;
 109:              AutoMoveLine(sender);
 110:          }
 111:   
 112:          void addNewPoint(Point newPoint)
 113:          {
 114:              Ellipse ellipse = new Ellipse();
 115:              ellipse.Name = "point" + (listPoints.Count - 1);
 116:              ellipse.Width = 2 * radius; ellipse.Height = 2 * radius;
 117:              ellipse.Stroke = pointBrush;
 118:              ellipse.Fill = pointBrush;
 119:              ellipse.ToolTip = "Point " + (listPoints.Count - 1);
 120:              Canvas.SetLeft(ellipse, newPoint.X - radius);
 121:              Canvas.SetTop(ellipse, newPoint.Y - radius);
 122:              Canvas.SetZIndex(ellipse, 99);
 123:              canvasBord.Children.Add(ellipse);
 124:              listEllipses.Add(ellipse);
 125:              ellipse.MouseLeftButtonDown += ellipse_MouseLeftButtonDown;
 126:              ellipse.MouseMove += ellipse_MouseMove;
 127:              ellipse.MouseLeftButtonUp += ellipse_MouseLeftButtonUp;
 128:          }
 129:   
 130:          void addNewLine()
 131:          {
 132:              for (int i = 0; i < listPoints.Count - 1; i++)
 133:              {
 134:                  Line line = new Line { Stroke = pointBrush, Opacity = 0.05, StrokeThickness = lineWidth, 
 135:                      X1 = listPoints[i].X, Y1 = listPoints[i].Y, 
 136:                      X2 = listPoints[listPoints.Count - 1].X, Y2 = listPoints[listPoints.Count - 1].Y, 
 137:                      Name = String.Format("i{0}j{1}", i, (listPoints.Count - 1)), 
 138:                      ToolTip = "0" };
 139:                  line.MouseWheel += line_MouseWheel;
 140:                  line.MouseLeftButtonDown += line_MouseLeftButtonDown;
 141:                  canvasBord.Children.Add(line);
 142:              }
 143:          }
 144:   
 145:          void line_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 146:          {
 147:              Canvas.SetLeft(tBInputW, e.GetPosition(canvasBord).X);
 148:              Canvas.SetTop(tBInputW, e.GetPosition(canvasBord).Y);
 149:              tBInputW.Visibility = Visibility.Visible;
 150:              Line line = (Line)sender;
 151:              tBInputW.Text = line.ToolTip.ToString();
 152:              tBInputW.Tag = sender;
 153:          }
 154:   
 155:          void tBInputW_KeyUp(object sender, KeyEventArgs e)
 156:          {
 157:              if (e.Key==Key.Enter)
 158:              {
 159:                  int w;
 160:                  if (int.TryParse(tBInputW.Text,out w))
 161:                  {
 162:                      Line line = (Line)tBInputW.Tag;
 163:                      line.ToolTip = w;
 164:                      line.Opacity = 0.05 + 0.1 * w;
 165:                      tBInputW.Visibility = Visibility.Hidden;
 166:                  }
 167:                  else { MessageBox.Show("Input error", "Error", MessageBoxButton.OK, MessageBoxImage.Error); }
 168:              }
 169:          }
 170:          
 171:          void line_MouseWheel(object sender, MouseWheelEventArgs e)
 172:          {
 173:              Line line = (Line)sender;
 174:              int currentW = int.Parse(line.ToolTip.ToString());
 175:              if (e.Delta > 0)
 176:              {
 177:                  currentW++;
 178:                  if (line.Opacity == 0.95) { return; } else { line.Opacity += 0.1; }
 179:              }
 180:              else
 181:              {
 182:                  if (currentW > 0) { currentW--; line.Opacity -= 0.1; }
 183:              }
 184:              if (currentW < 0) { line.Opacity = 0.05; }
 185:              line.ToolTip = currentW;
 186:          }
 187:   
 188:          private void btnModel_Click(object sender, RoutedEventArgs e)
 189:          {
 190:              int count=0;
 191:              foreach (UIElement tmp in canvasBord.Children)
 192:              {
 193:                  if (tmp is Ellipse) { count++; }
 194:              }
 195:              int[,] matrix = new int[count, count];
 196:              int[,] minSpanningTree = new int[count, count];
 197:              for (int i = 0; i < count; i++) { matrix[i, i] = 0; }
 198:              Line line = null;
 199:              foreach (UIElement tmp in canvasBord.Children)
 200:              {
 201:                  if (tmp is Line)
 202:                  {
 203:                      line = (Line)tmp;
 204:                      int i, j;
 205:                      i = int.Parse(line.Name.Substring(1, line.Name.IndexOf("j") - 1));
 206:                      j = int.Parse(line.Name.Substring(line.Name.IndexOf("j") + 1));
 207:                      if (line.ToolTip.ToString() == "0")
 208:                      { matrix[i, j] = -1; matrix[j, i] = -1; }
 209:                      else
 210:                      { matrix[i, j] = int.Parse(line.ToolTip.ToString()); matrix[j, i] = matrix[i, j]; }
 211:                  }
 212:              }
 213:              minSpanningTree = PrimMinSpanningTree(matrix);
 214:              int minSpanningTreeW = 0;
 215:              for (int i = 0; i < count; i++)
 216:              {
 217:                  for (int j = i; j < count; j++)
 218:                  {
 219:                      if (minSpanningTree[i, j] != 0 && minSpanningTree[i, j] != -1)
 220:                      {
 221:                          line = FindLineInCanvasByName(canvasBord, String.Format("i{0}j{1}", i, j));
 222:                          line.Opacity = 1;
 223:                          line.Stroke = Brushes.Brown;
 224:                          minSpanningTreeW += minSpanningTree[i, j];
 225:                      }
 226:                  }
 227:              }
 228:              tBResult.Text = "最小生成树的权值为:" + minSpanningTreeW;
 229:          }
 230:   
 231:          /// <summary>
 232:          /// Find Shape Line in a Canvas By Line Property Name
 233:          /// </summary>
 234:          /// <param name="canvas">Shapes container:canvas</param>
 235:          /// <param name="name">Line property:name</param>
 236:          /// <returns>Return a Line Object</returns>
 237:          static Line FindLineInCanvasByName(Canvas canvas, string name)
 238:          {
 239:              foreach (UIElement tmp in canvas.Children)
 240:              {
 241:                  Line line = null;
 242:                  if (tmp is Line)
 243:                  {
 244:                      line = (Line)tmp;
 245:                      if (line.Name == name) { return line; }
 246:                  }
 247:              }
 248:              return null;
 249:          }
 250:   
 251:          static Ellipse FindEllipseInCanvasByName(Canvas canvas, string name)
 252:          {
 253:              foreach (UIElement tmp in canvas.Children)
 254:              {
 255:                  Ellipse ellipse = null;
 256:                  if (tmp is Ellipse)
 257:                  {
 258:                      ellipse = (Ellipse)tmp;
 259:                      if (ellipse.Name == name) { return ellipse; }
 260:                  }
 261:              }
 262:              return null;
 263:          }
 264:   
 265:          static int ConvertToInt(int container, double i)
 266:          {
 267:              int k = (int)(i / container) * container;
 268:              if (k + 1 - i > i - k)
 269:                  return k;
 270:              else
 271:                  return k + 1;
 272:          }
 273:   
 274:          void AutoMoveLine(object sender)
 275:          {
 276:              Ellipse ellipse = (Ellipse)sender;
 277:              int k = int.Parse(ellipse.Name.Substring(5));  //Selected Ellipse index
 278:              for (int i = 0; i < listPoints.Count; i++)
 279:              {
 280:                  //i k
 281:                  if (k == i) { continue; }
 282:                  int m = i; int n = k;
 283:                  if (m > n)
 284:                  { int tmp = m; m = n; n = tmp; }
 285:                  string lineName = String.Format("i{0}j{1}", m, n);
 286:                  Line line = FindLineInCanvasByName(canvasBord, lineName);
 287:                  line.X1 = listPoints[m].X; line.Y1 = listPoints[m].Y;
 288:                  line.X2 = listPoints[n].X; line.Y2 = listPoints[n].Y;
 289:              }
 290:          }
 291:   
 292:          static int[,] PrimMinSpanningTree(int[,] matrix)
 293:          {
 294:              int[,] MinSpanningTree = new int[matrix.GetLength(0), matrix.GetLength(0)];
 295:              int[] num = new int[matrix.GetLength(0)];
 296:              //Initialize MinSpanning Tree
 297:              //Initialize num to 0
 298:              for (int i = 0; i < MinSpanningTree.GetLength(0); i++)
 299:              {
 300:                  num[i] = 0;
 301:                  for (int j = 0; j < MinSpanningTree.GetLength(0); j++)
 302:                  {
 303:                      MinSpanningTree[i, j] = -1;
 304:                      MinSpanningTree[i, j] = -1;
 305:                  }
 306:                  MinSpanningTree[i, i] = 0;
 307:              }
 308:              num[0] = 1;
 309:              bool check = false;
 310:              int a = -1, b = -1, k;
 311:              do
 312:              {
 313:                  int minW = int.MaxValue;
 314:                  for (k = 0; k < num.GetLength(0); k++)
 315:                  {
 316:                      if (num[k] == 1)//U
 317:                          //Find the minimum number
 318:                          for (int j = 0; j < matrix.GetLength(0); j++)
 319:                          {
 320:                              //if point j has included,jump to next
 321:                              if (num[j] == 1 || j == k) { continue; }
 322:                              if (matrix[k, j] != -1) { if (matrix[k, j] < minW) { minW = matrix[k, j]; a = k; b = j; } }
 323:                          }
 324:                  }
 325:                  num[b] = 1;
 326:                  MinSpanningTree[a, b] = matrix[a, b];
 327:                  MinSpanningTree[b, a] = matrix[a, b];
 328:                  //check if all points included
 329:                  check = true;
 330:                  for (int i = 0; i < num.Length; i++)
 331:                  {
 332:                      if (num[i] == 0) { check = false; break; }
 333:                  }
 334:              } while (!check);
 335:              return MinSpanningTree;
 336:          }
 337:      }
 338:  }

 

我自己都觉得这篇文章没有多大价值,做的东西也才粗糙简单了,但是改进方向在哪里?

硬啃开源项目?还是先把计算机学科基础包括数据结构、计算机组成原理、操作系统、计算机网络基础扎实了?

时间不多了,争分夺秒吧。

posted @ 2011-06-10 23:05  L Cooper  阅读(547)  评论(0编辑  收藏  举报