x01.Weiqi.8: 一点改进

原来的代码全部删除,进行了深层次重构,得其意而忘其言。得意之处有二:

1.关于显示

以 StoneSize 属性为依托,在 set 中加了一句:Width = Height = m_StoneSize * 19;以此来控制棋盘大小。所有的对象在 Init() 方法中创建,而具体的渲染在 Redraw() 方法中完成。这种创建与重绘相分开的办法,使调整大小时进行重绘更简单易行。这两个方法的代码如下:

 1 void Init()
 2         {
 3             // 线
 4             for (int i = 0; i < 19; i++) {
 5                 m_LinesH[i] = new Line();
 6                 m_LinesH[i].Stroke = Brushes.Black;
 7                 m_Canvas.Children.Add(m_LinesH[i]);
 8 
 9                 m_LinesV[i] = new Line();
10                 m_LinesV[i].Stroke = Brushes.Black;
11                 m_Canvas.Children.Add(m_LinesV[i]);
12             }
13 
14             //
15             for (int j = 0; j < 3; j++) {
16                 for (int i = 0; i < 3; i++) {
17                     m_Stars[i, j] = new Ellipse();
18                     m_Stars[i, j].Fill = Brushes.Black;
19                     m_Canvas.Children.Add(m_Stars[i, j]);
20                 }
21             }
22 
23             for (int i = 0; i < 19; i++) {
24                 for (int j = 0; j < 19; j++) {
25                     m_Stones[i, j] = new Ellipse();
26                     m_Stones[i, j].Visibility = Visibility.Hidden;
27                     m_Canvas.Children.Add(m_Stones[i, j]);
28 
29                     m_Numbers[i, j] = new TextBlock();
30                     m_Numbers[i, j].Background = Brushes.Transparent;
31                     m_Numbers[i, j].Visibility = Visibility.Hidden;
32                     m_Canvas.Children.Add(m_Numbers[i, j]);
33 
34                     m_Steps[i, j] = new Step();
35                     m_Steps[i, j].Row = i;
36                     m_Steps[i, j].Col = j;
37                     m_EmptySteps.Add(m_Steps[i, j]);
38                     m_AllSteps.Add(m_Steps[i, j]);
39                 }
40             }
41 
42             // 当前标志
43             m_CurrentRect.Visibility = System.Windows.Visibility.Hidden;
44             m_CurrentRect.Fill = Brushes.Red;
45             m_Canvas.Children.Add(m_CurrentRect);
46 
47             for (int i = 0; i < 19; i++) {
48                 for (int j = 0; j < 19; j++) {
49                     Rectangle rect = new Rectangle();
50                     rect.Visibility = System.Windows.Visibility.Hidden;
51                     m_EmptyRects[i, j] = rect;
52                     m_Canvas.Children.Add(m_EmptyRects[i,j]);
53 
54                 }
55             }
56         }
Init()
  1 public void Redraw()
  2         {
  3             // 画线
  4             for (int i = 0; i < 19; i++) {
  5                 Line l = m_LinesH[i];
  6                 int y = i * StoneSize + StoneSize / 2;
  7                 l.X1 = StoneSize / 2;
  8                 l.Y1 = y;
  9                 l.X2 = 19 * StoneSize - StoneSize / 2;
 10                 l.Y2 = y;
 11 
 12                 l = m_LinesV[i];
 13                 int x = i * StoneSize + StoneSize / 2;
 14                 l.X1 = x;
 15                 l.Y1 = StoneSize / 2;
 16                 l.X2 = x;
 17                 l.Y2 = 19 * StoneSize - StoneSize / 2;
 18             }
 19 
 20             // 画星
 21             for (int j = 0; j < 3; j++) {
 22                 for (int i = 0; i < 3; i++) {
 23                     Ellipse e = m_Stars[i, j];
 24                     e.Width = e.Height = StoneSize / 3;
 25                     double left = 4 * StoneSize + j * 6 * StoneSize - StoneSize / 2 - e.Width / 2;
 26                     double top = 4 * StoneSize + i * 6 * StoneSize - StoneSize / 2 - e.Height / 2;
 27                     Canvas.SetLeft(e, left);
 28                     Canvas.SetTop(e, top);
 29                 }
 30             }
 31 
 32             // Stones and Numbers
 33             for (int i = 0; i < 19; i++) {
 34                 for (int j = 0; j < 19; j++) {
 35                     var stone = m_Stones[i, j];
 36                     stone.Width = stone.Height = StoneSize;
 37                     Canvas.SetLeft(stone, j * StoneSize);
 38                     Canvas.SetTop(stone, i * StoneSize);
 39 
 40                     ShowNumber(i, j, m_Steps[i, j].StepCount);
 41                 }
 42             }
 43 
 44             // 点目标志
 45             if (IsShowMesh)
 46                 for (int i = 0; i < 19; i++) {
 47                     for (int j = 0; j < 19; j++) {
 48                         var rect = m_EmptyRects[i, j];
 49                         rect.Width = rect.Height = m_CurrentRect.Width;
 50                         double offset = (StoneSize - rect.Width) / 2.0;
 51                         Canvas.SetLeft(rect, j * StoneSize + offset);
 52                         Canvas.SetTop(rect, i * StoneSize + offset);
 53                     }
 54                 }
 55         }
 56 
 57         public bool NextOne(int row, int col)
 58         {
 59             if (m_Steps[row, col].StoneColor != StoneColor.Empty)
 60                 return false;
 61             if (m_BanOnce.Row == row && m_BanOnce.Col == col) {
 62                 return false;
 63             }
 64             m_BanOnce.Row = m_BanOnce.Col = -1;
 65 
 66             DrawStep(row, col);
 67             bool isBlack;
 68             if (m_Steps[row, col].StoneColor == StoneColor.Black) {
 69                 m_BlackSteps.Add(m_Steps[row, col]);
 70                 isBlack = true;
 71             } else {
 72                 m_WhiteSteps.Add(m_Steps[row, col]);
 73                 isBlack = false;
 74             }
 75             m_EmptySteps.Remove(m_Steps[row, col]);
 76 
 77             UpdateBlackBlocks();
 78             UpdateWhiteBlocks();
 79             if (isBlack) {
 80                 if (!UpdateDeadBlocks(m_WhiteBlocks))
 81                     UpdateDeadBlocks(m_BlackBlocks);
 82             } else {
 83                 if (!UpdateDeadBlocks(m_BlackBlocks))
 84                     UpdateDeadBlocks(m_WhiteBlocks);
 85             }
 86 
 87             MoveCurrentRect();
 88 
 89             m_StepCount++;
 90 
 91             StoneColor selfColor = isBlack ? StoneColor.Black : StoneColor.White;
 92             bool isKillSelf = m_DeadBlocks.ContainsKey(m_StepCount - 1)
 93                     && m_DeadBlocks[m_StepCount - 1].Steps.Count == 1
 94                     && m_DeadBlocks[m_StepCount - 1].Steps[0].StoneColor == selfColor;
 95             if (isKillSelf) {
 96                 m_DeadBlocks.Remove(m_StepCount - 1);
 97                 BackOne();
 98                 return false;
 99             }
100 
101             return true;
102         }
Redraw()

2.关于提子

以 LinkSteps()方法为依托,提子不再是上下左右一通乱吃了,而是采用集合的办法,只需看看一块棋有没有气即可。其代码如下:

 1 //   +
 2         // + + +    与 step 相连的棋子,包含自身
 3         //   +        根据 color 参数决定是所有,同色,黑色,白色,还是空色。
 4         List<Step> LinkSteps(Step step, StoneColor color = StoneColor.Empty)
 5         {
 6             List<Step> links = new List<Step>();
 7             for (int i = -1; i < 2; i++) {
 8                 for (int j = -1; j < 2; j++) {
 9                     if (i == j || i == -j) {
10                         continue;
11                     }
12                     if (InRange(step.Row + i, step.Col + j)) {
13                         links.Add(m_Steps[step.Row + i, step.Col + j]);
14                     }
15                 }
16             }
17             links.Add(step);
18             if (color == StoneColor.All) {
19                 return links;
20             } else {
21                 links.RemoveAll(l => l.StoneColor != color);
22                 return links;
23             }
24         }
LinkSteps()

当然,关于劫争,关于悔棋,非深入代码,不能明白。但 LinkSteps()是构成集合的基础。从集合的观点,研究围棋,相信比其他方法更为可行。

原文地址:https://www.cnblogs.com/china_x01/p/4522618.html