有道难题,我的OO解法

本文背景是下面3篇文章:

"有道难题"之ealget的算法

看有道难题比赛有恶心感 ,付源码挑战,博客园目前纯速度最快。

有道难题之OO

 

正文:

第一个类是Cell类(萝卜坑):
ContractedBlock.gif ExpandedBlockStart.gif Code
 1     public class Cell
 2     {
 3         private class EmptyCell : Cell
 4         {
 5             public override Int32 Count
 6             {
 7                 get { return 0; }
 8                 set { }
 9             }
10         }
11 
12         public static readonly Cell Empty;
13 
14         static Cell()
15         {
16             Empty = new EmptyCell();
17         }
18 
19         public virtual Int32 Count { getset; }
20 
21         public Cell North { getset; }
22         public Cell South { getset; }
23         public Cell East { getset; }
24         public Cell West { getset; }
25         public Cell NorthWest { getset; }
26         public Cell NorthEast { getset; }
27         public Cell SouthWest { getset; }
28         public Cell SouthEast { getset; }
29 
30         public Cell(Int32 count)
31         {
32             this.Count = count;
33             North = South = East = West = NorthEast = NorthWest = SouthEast = SouthWest = Cell.Empty;
34         }
35 
36         public Cell()
37             : this(0)
38         {
39         }
40 
41         public Int32 Degree
42         {
43             get { return North.Count + South.Count + East.Count + West.Count + NorthWest.Count + NorthEast.Count + SouthWest.Count + SouthEast.Count; }
44         }
45     }

 

每一个萝卜坑维护有它和别的萝卜坑之间的关系。这样,每一个萝卜坑的Degree属性即是它的特殊程度,很容易算,不必知道萝卜坑在农田中的坐标。这样,萝卜坑就不必知道农田的存在了。为了避免边界条件,这里引入空对象,即EmptyCell。

然后是农田类Farmland:

ContractedBlock.gif ExpandedBlockStart.gif Code
  1     public class Farmland
  2     {
  3         Cell[][] _cells;
  4 
  5         public Int32 Width { getprivate set; }
  6         public Int32 Length { getprivate set; }
  7 
  8         public Farmland(Int32 length, Int32 width)
  9         {
 10             if (length < 0throw new ArgumentOutOfRangeException("length");
 11             if (width < 0throw new ArgumentOutOfRangeException("width");
 12 
 13             Length = length;
 14             Width = width;
 15             InitCells();
 16         }
 17 
 18         private void InitCells()
 19         {
 20             _cells = new Cell[Length][];
 21             for (Int32 x = 0; x < Length; x++)
 22             {
 23                 Cell[] line = new Cell[Width];
 24                 for (Int32 y = 0; y < Width; y++)
 25                 {
 26                     line[y] = new Cell();
 27                 }
 28                 _cells[x] = line;
 29             }
 30 
 31             InitRelationships();
 32         }
 33 
 34         private void InitRelationships()
 35         {
 36             for (Int32 i = 0; i < Length; i++)
 37             {
 38                 for (Int32 j = 0; j < Width; j++)
 39                 {
 40                     InitRelationship(i, j);
 41                 }
 42             }
 43         }
 44 
 45         private void InitRelationship(Int32 x, Int32 y)
 46         {
 47             Cell cell = GetCell(x, y);
 48             cell.North = GetCell(x, y - 1);
 49             cell.South = GetCell(x, y + 1);
 50             cell.West = GetCell(x - 1, y);
 51             cell.East = GetCell(x + 1, y);
 52             cell.NorthWest = GetCell(x - 1, y - 1);
 53             cell.NorthEast = GetCell(x + 1, y - 1);
 54             cell.SouthEast = GetCell(x + 1, y + 1);
 55             cell.SouthWest = GetCell(x - 1, y + 1);
 56         }
 57 
 58         private Cell GetCell(Int32 x, Int32 y)
 59         {
 60             if (x >= 0 && y >= 0 && x < Length && y < Width)
 61                 return this[x][y];
 62             else
 63                 return Cell.Empty;
 64         }
 65 
 66         public Cell[] this[Int32 index]
 67         {
 68             get { return _cells[index]; }
 69         }
 70 
 71         public Int32 CountDegree(Int32 min, Int32 max)
 72         {
 73             Int32 count = 0;
 74             for (Int32 x = 0; x < this.Length; x++)
 75             {
 76                 for (Int32 y = 0; y < this.Width; y++)
 77                 {
 78                     Int32 c = this[x][y].Degree;
 79                     if (c >= min && c <= max) count++;
 80                 }
 81             }
 82             return count;
 83         }
 84 
 85         public static Farmland Create(String[] fields)
 86         {
 87             Farmland farmland = new Farmland(fields[0].Length, fields.Length);
 88 
 89             for (Int32 y = 0; y < fields.Length; y++)
 90             {
 91                 String tmp = fields[y];
 92                 for (Int32 x = 0; x < tmp.Length; x++)
 93                 {
 94                     farmland[x][y].Count = tmp[x] - '0';
 95                 }
 96             }
 97 
 98             return farmland;
 99         }
100     }

 

农田在初始化时就自动将萝卜坑之间的关系确定了。

哦,测试一下:

ContractedBlock.gif ExpandedBlockStart.gif Code
1         static void Main(string[] args)
2         {
3             Farmland land0 = Farmland.Create(new string[] { "924""231""390""910""121" });
4             Console.WriteLine("land0: " + land0.CountDegree(31,36));
5             Farmland land1 = Farmland.Create(new string[] { "2309""0239""2314" });
6             Console.WriteLine("land1: " + land1.CountDegree(57));
7             Console.Read();
8         }

 

结果:

1  land0:  0
2  land1:  3

 

这样写是不是更容易扩展,更容易维护?OO是朴素的,而不是教条的。

 --------------------------------------------------------------------------------------------------

似乎无法2小时内再发第二篇,那就接着这个向下写吧。

下面,使用泛型将这个问题再一般化。这里没有萝卜坑,没有农田,只有Cell和Cell容器MatrixCellContainer。

亮代码 :

ContractedBlock.gif ExpandedBlockStart.gif Code
  1     public class Cell<T>
  2     {
  3         private class EmptyCell : Cell<T>
  4         {
  5             public override T Entity
  6             {
  7                 get { return default(T); }
  8                 set { }
  9             }
 10         }
 11 
 12         public static readonly Cell<T> Empty;
 13 
 14         static Cell()
 15         {
 16             Empty = new EmptyCell();
 17         }
 18 
 19         public virtual T Entity { getset; }
 20 
 21         public Cell<T> North { getset; }
 22         public Cell<T> South { getset; }
 23         public Cell<T> East { getset; }
 24         public Cell<T> West { getset; }
 25         public Cell<T> NorthWest { getset; }
 26         public Cell<T> NorthEast { getset; }
 27         public Cell<T> SouthWest { getset; }
 28         public Cell<T> SouthEast { getset; }
 29 
 30         public Cell(T entity)
 31         {
 32             this.Entity = entity;
 33             North = South = East = West = NorthEast = NorthWest = SouthEast = SouthWest = Cell<T>.Empty;
 34         }
 35 
 36         public Cell()
 37             : this(default(T))
 38         {
 39         }
 40     }
 41 
 42     public class MatrixCellContainer<T> : IEnumerable<List<Cell<T>>>
 43     {
 44         List<List<Cell<T>>> _cells;
 45         public Int32 Width { getprivate set; }
 46         public Int32 Length { getprivate set; }
 47 
 48         public MatrixCellContainer(Int32 length, Int32 width)
 49         {
 50             if (length < 0throw new ArgumentOutOfRangeException("length");
 51             if (width < 0throw new ArgumentOutOfRangeException("width");
 52 
 53             Length = length;
 54             Width = width;
 55             InitCells();
 56         }
 57 
 58         private void InitCells()
 59         {
 60             _cells = new List<List<Cell<T>>>(Length);
 61             for (Int32 x = 0; x < Length; x++)
 62             {
 63                 List<Cell<T>> line = new List<Cell<T>>(Width);
 64                 for (Int32 y = 0; y < Width; y++)
 65                 {
 66                     line.Add(new Cell<T>());
 67                 }
 68                 _cells.Add(line);
 69             }
 70 
 71             InitRelationships();
 72         }
 73 
 74         private void InitRelationships()
 75         {
 76             for (Int32 i = 0; i < Length; i++)
 77             {
 78                 for (Int32 j = 0; j < Width; j++)
 79                 {
 80                     InitRelationship(i, j);
 81                 }
 82             }
 83         }
 84 
 85         private void InitRelationship(Int32 x, Int32 y)
 86         {
 87             Cell<T> cell = GetCell(x, y);
 88             cell.North = GetCell(x, y - 1);
 89             cell.South = GetCell(x, y + 1);
 90             cell.West = GetCell(x - 1, y);
 91             cell.East = GetCell(x + 1, y);
 92             cell.NorthWest = GetCell(x - 1, y - 1);
 93             cell.NorthEast = GetCell(x + 1, y - 1);
 94             cell.SouthEast = GetCell(x + 1, y + 1);
 95             cell.SouthWest = GetCell(x - 1, y + 1);
 96         }
 97 
 98         private Cell<T> GetCell(Int32 x, Int32 y)
 99         {
100             if (x >= 0 && y >= 0 && x < Length && y < Width)
101                 return this[x][y];
102             else
103                 return Cell<T>.Empty;
104         }
105 
106         public List<Cell<T>> this[Int32 index]
107         {
108             get { return _cells[index]; }
109         }
110 
111         //public static CellContainer<T> Create<T>(String[] fields)
112         //{
113         //    CellContainer farmland = new CellContainer(fields[0].Length, fields.Length);
114 
115         //    for (Int32 y = 0; y < fields.Length; y++)
116         //    {
117         //        String tmp = fields[y];
118         //        for (Int32 x = 0; x < tmp.Length; x++)
119         //        {
120         //            farmland[x][y].Count = tmp[x] - '0';
121         //        }
122         //    }
123 
124         //    return farmland;
125         //}
126 
127         #region IEnumerable<List<Cell<T>>> Members
128 
129         public IEnumerator<List<Cell<T>>> GetEnumerator()
130         {
131             return _cells.GetEnumerator();
132         }
133 
134         #endregion
135 
136         #region IEnumerable Members
137 
138         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
139         {
140             return _cells.GetEnumerator();
141         }
142 
143         #endregion
144     }

 

这样这代码的抽象度是不是更高些了?在上面泛型类基础上,用扩展方法也好,lambda表达式也好,要计算有道第一题是相当容易了。并且,这两个泛型类的用途远远不止有道第一题那种用途。讨论一下:

(1)想要在这个基础上计算新的测量,很容易;

(2)Cell<T>中的T不仅仅只限于int或double,也可以是任何其它类型,它维护的是一个抽象的类型实例之间的微观关系;

(3)MatrixCellContainer<T>维护的是类型实例之间的宏观关系;

(4)这两个类是不是也可以建模mud游戏的地图?是不是也可以用来建模俄罗斯方块之类的小游戏?。。。。

 

BTW. 我反对用OO来研究算法 写这篇文章的目的只是 ... 好玩 ...

转载于:https://www.cnblogs.com/xiaotie/archive/2009/06/03/1495593.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值