你的位置:首页 > ASP.net教程

[ASP.net教程]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()是构成集合的基础。从集合的观点,研究围棋,相信比其他方法更为可行。