浏览代码

D17 Bonus, the same but better. But the same.

bastien.monsarrat 6 年之前
父节点
当前提交
12ce81948b
共有 1 个文件被更改,包括 58 次插入24 次删除
  1. 58 24
      D17.Bonus/Program.cs

+ 58 - 24
D17.Bonus/Program.cs

@@ -1,6 +1,7 @@
 using Accord.Video.FFMPEG;
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Drawing;
 using System.IO;
 using System.Linq;
@@ -26,7 +27,7 @@ namespace D17.Bonus
             var reg = new Regex(@"[xy]=(\d+), [xy]=(\d+)[.][.](\d+)");
 
             var map = new Dictionary<(int x, int y), EnumType>();
-            var rwater = new Dictionary<(int x, int y), (int x, int y)>();
+            var rwater = new Accord.Collections.OrderedDictionary<(int x, int y), (int x, int y)>();
 
             int MAXY = 0;
             int MINX = int.MaxValue;
@@ -43,11 +44,13 @@ namespace D17.Bonus
                 CreateMap(map, ref MAXY, ref MINX, ref MINY, ref MAXX, line, result);
 
             } while (true);
+            file.Close();
 
             // Start with river
             rwater.Add((500, 0), (500, 0));
             map.Add((500, 0), EnumType.RunningWater);
 
+            Console.SetOut(TextWriter.Null);
             VideoFileWriter writer = new VideoFileWriter();
 
             var width = MAXX - MINX + 2;
@@ -58,10 +61,11 @@ namespace D17.Bonus
 
             writer.Open("out.avi", width, height);
 
+            int rr = 0;
             while (rwater.Count > 0)
             {
+                rr++;
                 if (rwater.Any(r => r.Key.y > panY + tpy)) panY++;
-                PrintMap(map, writer, MINX, MAXX, MAXY, width, height);
 
                 var enumer = rwater.FirstOrDefault();
                 var water = enumer.Key;
@@ -73,14 +77,17 @@ namespace D17.Bonus
                     continue;
                 }
 
+                bool renderMap = false;
                 if (map.ContainsKey((water.x, water.y + 1)) == false || map[(water.x, water.y + 1)] == EnumType.RunningWater)
                 {
                     RaindropsOnRoses(map, rwater, water);
+                    renderMap = true;
                 }
 
                 else
                 {
                     ExpandToBothSides(map, rwater, water, source);
+                    renderMap = true;
 
                     int maxX, minX;
                     bool canConvert = CanConvertToStillWater(map, rwater, water, source, out maxX, out minX);
@@ -90,12 +97,29 @@ namespace D17.Bonus
                     else
                         rwater.Remove(water);
                 }
+
+                if (renderMap)
+                {
+                    if (rr < rwater.Count) continue;
+                    RenderMap(map, writer, MINX, MAXY, width, height);
+                    rr = 1;
+                }
             }
 
-            PrintMap(map, writer, MINX, MAXX, MAXY, width, height);
+            var lastBitmap = RenderMap(map, writer, MINX, MAXY, width, height);
+
+            var countEx1 = map.Count(m => (m.Key.y >= MINY && m.Key.y <= MAXY) && (m.Value == EnumType.RunningWater || m.Value == EnumType.StillWater));
+            var countEx2 = map.Count(m => (m.Key.y >= MINY && m.Key.y <= MAXY) && (m.Value == EnumType.StillWater));
+            var answer = $"The answer is {countEx1}m3 flooded,\n and {countEx2}m3 still water ☺";
+            using (var gd = Graphics.FromImage(lastBitmap))
+            using (var font = new Font(FontFamily.GenericSerif, 12, FontStyle.Regular))
+            {
+                gd.DrawString(answer, font, Brushes.IndianRed, 10, tpy + 10);
+                writer.WriteVideoFrame(lastBitmap);
+            }
         }
 
-        private static void RaindropsOnRoses(Dictionary<(int x, int y), EnumType> map, Dictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water)
+        private static void RaindropsOnRoses(Dictionary<(int x, int y), EnumType> map, IDictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water)
         {
             rwater.Remove(water);
 
@@ -104,7 +128,7 @@ namespace D17.Bonus
             map[drop] = EnumType.RunningWater;
         }
 
-        private static void ConvertToStillWater(Dictionary<(int x, int y), EnumType> map, Dictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water, (int x, int y) source, int maxX, int minX)
+        private static void ConvertToStillWater(Dictionary<(int x, int y), EnumType> map, IDictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water, (int x, int y) source, int maxX, int minX)
         {
             for (var x = minX; x <= maxX; ++x)
             {
@@ -120,7 +144,7 @@ namespace D17.Bonus
             if (!rwater.ContainsKey(source)) rwater.Add(source, (source.x, source.y - 1));
         }
 
-        private static bool CanConvertToStillWater(Dictionary<(int x, int y), EnumType> map, Dictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water, (int x, int y) source, out int maxX, out int minX)
+        private static bool CanConvertToStillWater(Dictionary<(int x, int y), EnumType> map, IDictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water, (int x, int y) source, out int maxX, out int minX)
         {
             bool canConvert = true;
             maxX = 0;
@@ -132,7 +156,7 @@ namespace D17.Bonus
                 if (res == false)
                 {
                     canConvert = false;
-                    //rwater.TryAdd((x - 1, water.y), source);
+                    if (!rwater.ContainsKey((x - 1, water.y))) rwater.Add((x - 1, water.y), source);
                 }
                 else if (type == EnumType.Clay) break;
             }
@@ -143,7 +167,7 @@ namespace D17.Bonus
                 if (res == false)
                 {
                     canConvert = false;
-                    //rwater.TryAdd((x + 1, water.y), source);
+                    if (!rwater.ContainsKey((x + 1, water.y))) rwater.Add((x + 1, water.y), source);
                 }
                 else if (type == EnumType.Clay) break;
             }
@@ -151,7 +175,7 @@ namespace D17.Bonus
             return canConvert;
         }
 
-        private static void ExpandToBothSides(Dictionary<(int x, int y), EnumType> map, Dictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water, (int x, int y) source)
+        private static void ExpandToBothSides(Dictionary<(int x, int y), EnumType> map, IDictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water, (int x, int y) source)
         {
             var next = water;
 
@@ -192,7 +216,7 @@ namespace D17.Bonus
             }
         }
 
-        private static void CreateMap(Dictionary<(int x, int y), EnumType> map, ref int MAXY, ref int MINX, ref int MINY, ref int MAXX, string line, Match result)
+        private static void CreateMap(IDictionary<(int x, int y), EnumType> map, ref int MAXY, ref int MINX, ref int MINY, ref int MAXX, string line, Match result)
         {
             var c1 = int.Parse(result.Groups[1].Value);
             var rmin = int.Parse(result.Groups[2].Value);
@@ -227,25 +251,35 @@ namespace D17.Bonus
             }
         }
 
-        private static void PrintMap(Dictionary<(int x, int y), EnumType> map, VideoFileWriter writer, int MINX, int MAXX, int MAXY, int width, int height)
+        static Bitmap _REFBMP = null;
+        private static Bitmap RenderMap(Dictionary<(int x, int y), EnumType> map, VideoFileWriter writer, int MINX, int MAXY, int width, int height)
         {
-            var bmp = new Bitmap(width, height);
+            if (_REFBMP == null)
+            {
+                _REFBMP = new Bitmap(width, height);
+                for (int x = 0; x < width; ++x)
+                    for (int y = 0; y < height; ++y)
+                        _REFBMP.SetPixel(x, y, Color.FloralWhite);
+            }
+
+            var bmp = new Bitmap(_REFBMP);
 
-            for (int y = panY; y < height + panY; ++y)
+            var hh = Math.Min(height + panY, MAXY);
+            var sortedMap = map.OrderBy(m => m.Key.y).Where(m => m.Key.y > panY && m.Key.y <= hh);
+
+            foreach (var res in sortedMap)
             {
-                int px = 0;
-                int py = y - panY;
-                for (int x = MINX - 1; x < MAXX + 1; ++x)
-                {
-                    var res = map.TryGetValue((x, y), out var type);
-                    if (res == false) bmp.SetPixel(px, py, Color.White);
-                    else if (type == EnumType.Clay) bmp.SetPixel(px, py, Color.Maroon);
-                    else if (type == EnumType.RunningWater) bmp.SetPixel(px, py, Color.Aqua);
-                    else if (type == EnumType.StillWater) bmp.SetPixel(px, py, Color.Aquamarine);
-                    px++;
-                }
+                var type = res.Value;
+                var px = res.Key.x - MINX + 1;
+                var py = res.Key.y - panY - 1;
+
+                if (type == EnumType.Clay) bmp.SetPixel(px, py, Color.Maroon);
+                else if (type == EnumType.RunningWater) bmp.SetPixel(px, py, Color.Aqua);
+                else if (type == EnumType.StillWater) bmp.SetPixel(px, py, Color.Aquamarine);
             }
+
             writer.WriteVideoFrame(bmp);
+            return bmp;
         }
     }
 }