2016-07-21 8 views
10

मैं कोई तरीका होना चाहिएकंसोल चार्ट ड्राइंग

Dictionary<int, int> chartList = new Dictionary<int, int>() 
{ 
     {50,31}, // x = 50, y = 31 
     {71,87}, 
     {25,66}, 
     {94,15}, 
     {33,94} 
}; 
DrawChart(chartList); 

की तरह एक सांत्वना आवेदन में एक Dictionary<int,int> आकर्षित करने के लिए

enter image description here

की तरह कुछ में परिणाम चाहिए मैं इस आए हैं अब तक, लेकिन मैं कर रहा हूँ IsHit विधि पर फंस गया, जो निर्धारित करता है कि मौजूदा निर्देशांक पर एक बिंदु निर्धारित किया जाना चाहिए या नहीं। क्या कोई इस बिंदु पर मेरी मदद कर सकता है? यह हमेशा सच रहता है।

public static void DrawChart(Dictionary<int, int> dict) 
{ 
    int consoleWidth = 78; 
    int consoleHeight = 20; 

    Console.WriteLine(dict.Max(x => x.Key).ToString()); 

    Func<int, int, bool> IsHit = (hx, hy) => dict.Any(dct => dct.Key/dict.Max(x => x.Key) == hx/dict.Max(x => x.Key) && dct.Value/dict.Max(x => x.Value) == hy/dict.Max(x => x.Value)); 

    for (int i = 0; i < consoleHeight; i++) 
    { 
     Console.Write(i == 0 ? '┌' : '│'); 
     for (int j = 0; j < consoleWidth; j++) 
     { 
      int actualheight = i * 2; 

      if (IsHit(j, actualheight) && IsHit(j, actualheight + 1)) 
      { 
       Console.ForegroundColor = ConsoleColor.Red; 
       Console.BackgroundColor = ConsoleColor.Black; 
       Console.Write('█'); 
      } 
      else if (IsHit(j, actualheight)) 
      { 
       Console.ForegroundColor = ConsoleColor.Red; 
       Console.BackgroundColor = ConsoleColor.Black; 
       Console.Write('▀'); 
      } 
      else if (IsHit(j, actualheight + 1)) 
      { 
       Console.ForegroundColor = ConsoleColor.Black; 
       Console.BackgroundColor = ConsoleColor.Red; 
       Console.Write('▀'); 
      } 
     } 
     Console.ResetColor(); 
     Console.WriteLine(); 
    } 
    Console.WriteLine('└' + new string('─', (consoleWidth/2) - 1) + '┴' + new string('─', (consoleWidth/2) - 1) + '┘'); 
    Console.Write((dict.Min(x => x.Key) + "/" + dict.Min(x => x.Value)).PadRight(consoleWidth/3)); 
    Console.Write((dict.Max(x => x.Value)/2).ToString().PadLeft(consoleWidth/3/2).PadRight(consoleWidth/3)); 
    Console.WriteLine(dict.Max(x => x.Value).ToString().PadLeft(consoleWidth/3)); 
} 
+0

फ़ंक्शन सेटपॉइंट (पंक्ति, कॉल, चार, रंग) क्यों नहीं लिखें? आप आसानी से [कर्सर को किसी भी समन्वय में सेट कर सकते हैं] (https://msdn.microsoft.com/en-us/library/system.console.setcursorposition (v = vs.110) .aspx) सभी के बाद .. – TaW

+0

क्या ' आप बस शब्दकोश पर लूप और केवल हिट पॉइंट आकर्षित करते हैं ..? – TaW

+0

निश्चित रूप से मैं सिर्फ http://stackoverflow.com/a/33604540/1315444 – fubo

उत्तर

7

नीचे कोड आपको कुछ विचार देना चाहिए। क्योंकि Dictionary के साथ काम करने सबसे पहले, एक Point शुरू करने की जरूरत है और यह Key है और X और Y की तरह सामान्य नाम के बजाय Value गुण एक बुरा सपना है। साथ ही, शब्दकोश में आप एक ही X समन्वय के साथ एकाधिक बिंदुओं को स्टोर नहीं कर सकते हैं, जो कम समझ में आता है।

public struct Point { 
    public Point(int x, int y) { 
     this.X = x; 
     this.Y = y; 
    } 

    public int X { get; } 
    public int Y { get; } 
} 

फिर थोड़ा संशोधित DrawChart:

public static void DrawChart(List<Point> dict) 
    { 
     int consoleWidth = 78; 
     int consoleHeight = 20; 
     int actualConsoleHeight = consoleHeight * 2; 
     var minX = dict.Min(c => c.X); 
     var minY = dict.Min(c => c.Y);    
     var maxX = dict.Max(c => c.X); 
     var maxY = dict.Max(c => c.Y); 

     Console.WriteLine(maxX); 
     // normalize points to new coordinates 
     var normalized = dict. 
      Select(c => new Point(c.X - minX, c.Y - minY)). 
      Select(c => new Point((int)Math.Round((float) (c.X)/(maxX - minX) * (consoleWidth - 1)), (int)Math.Round((float) (c.Y)/(maxY - minY) * (actualConsoleHeight - 1)))).ToArray(); 
     Func<int, int, bool> IsHit = (hx, hy) => { 
      return normalized.Any(c => c.X == hx && c.Y == hy); 
     }; 

     for (int y = actualConsoleHeight - 1; y > 0; y -= 2) 
     { 
      Console.Write(y == actualConsoleHeight - 1 ? '┌' : '│'); 
      for (int x = 0; x < consoleWidth; x++) 
      { 
       bool hitTop = IsHit(x, y); 
       bool hitBottom = IsHit(x, y - 1);      
       if (hitBottom && hitTop) 
       { 
        Console.ForegroundColor = ConsoleColor.Red; 
        Console.BackgroundColor = ConsoleColor.Black; 
        Console.Write('█'); 
       } 
       else if (hitTop) 
       { 
        Console.ForegroundColor = ConsoleColor.Red; 
        Console.BackgroundColor = ConsoleColor.Black; 
        Console.Write('▀'); 
       } 
       else if (hitBottom) 
       { 
        Console.ForegroundColor = ConsoleColor.Black; 
        Console.BackgroundColor = ConsoleColor.Red; 
        Console.Write('▀'); 
       } 
       else 
       { 
        Console.ForegroundColor = ConsoleColor.Black; 
        Console.BackgroundColor = ConsoleColor.Black; 
        Console.Write('▀'); 
       }      
      }     
      Console.ResetColor(); 
      Console.WriteLine(); 
     } 
     Console.WriteLine('└' + new string('─', (consoleWidth/2) - 1) + '┴' + new string('─', (consoleWidth/2) - 1) + '┘'); 
     Console.Write((dict.Min(x => x.X) + "/" + dict.Min(x => x.Y)).PadRight(consoleWidth/3)); 
     Console.Write((dict.Max(x => x.Y)/2).ToString().PadLeft(consoleWidth/3/2).PadRight(consoleWidth/3)); 
     Console.WriteLine(dict.Max(x => x.Y).ToString().PadLeft(consoleWidth/3)); 
    } 

और उपयोग:

static void Main(string[] args) { 
    var chartList = new List<Point> { 
     new Point(50, 31), // x = 50, y = 31 
     new Point(71, 87), 
     new Point(71, 89), 
     new Point(25, 66), 
     new Point(94, 15), 
     new Point(33, 94) 
    }; 
    DrawChart(chartList); 
    Console.ReadKey(); 
} 

परिणाम:

Result

+0

@ फ़ूबो ने ध्यान नहीं दिया कि आपको (0,0) से शुरू करने की आवश्यकता नहीं है। एक बार फिर से अद्यतन उत्तर। – Evk

1

कम से कम मैं एक जवाब है कि आपकी समस्या नहीं सुलझती है, लेकिन कुछ संकेत नहीं है कि हो सकता है मुसीबत का कारण बनता है:

  1. आपका समन्वय प्रणाली गलत है। IsHit() विधि निर्देशांक 0/0 के शीर्ष बाएं कोने (जहां आप ड्राइंग शुरू करते हैं) के लिए प्राप्त करते हैं, लेकिन यह 0/19 होना चाहिए और अंतिम तत्व 77/19 होना चाहिए, लेकिन यह 77/0 होना चाहिए।
  2. गणना के लिए आप पूर्णांक विभाजित करते हैं, जो इस तथ्य की ओर जाता है कि सभी अंश खो जाते हैं और आपकी क्वेरी हमेशा सत्य होती है।

शायद आपको एक अनुवाद विधि लिखनी चाहिए, जो कर्सर की स्थिति से एक्स/वाई मान में अनुवाद करेगी और फिर एक चरण में दोनों करने की कोशिश करने के बजाय अनुवादित स्थिति के खिलाफ परीक्षण करेगी। मुझे लगता है कि उस दृष्टिकोण का उपयोग करके आप स्वयं को समस्या से निपटने में सक्षम होंगे।

+0

से अनुमोदित दृष्टिकोण रखना चाहता था ठीक है आपके विचारों के लिए धन्यवाद। मुझे यह भी लगता है कि एक मैपिंग विधि में जटिलता को तोड़ना बेहतर है। इस मामले को संभालने के लिए कि 'कंसोल' मानों की तुलना में 'शब्दकोश' मानों की सीमा कम है – fubo

2

असली गलती बहुत लंबी, एक-पंक्ति समारोह है। इससे इसे पढ़ना मुश्किल हो जाता है, और यह आपके जैसे बुद्धिमान व्यक्ति के लिए भी समस्याएं पैदा करता है।

IsHit() एक काफी जटिल कार्य है, तो यह फैल ...

आप निर्देशांक पैमाने पर करने की जरूरत है, ताकि वे कंसोल विंडो में फिट।
मैं मान लिया है खिड़की निर्देशांक (1,1) - (consoleWidth, consoleHeight)

private static bool IsConsoleHit(Dictionary<int, int> dict, 
            int consoleWidth, 
            int consoleHeight, 
            int hx, 
            int hy) 
    { 
     int minX = dict.Min(x => x.Key); 
     int maxX = dict.Max(x => x.Key); 
     int minY = dict.Min(x => x.Value); 
     int maxY = dict.Max(x => x.Value); 

     foreach (KeyValuePair<int, int> pair in dict) 
     { 
      // (x,y) starting at (0,0) 
      int x = pair.Key - minX; 
      int y = pair.Value - minY; 

      // convert to (0..1.0, 0..1.0) 
      double dx = x/Math.Max(maxX - minX, 1.0); 
      double dy = y/Math.Max(maxY - minY, 1.0); 

      // Scale to (1,1) upto (consoleWidth, consoleHeight) 
      int sx = (int)(dx * (consoleWidth - 1)) + 1; 
      int sy = (int)(dy * (consoleHeight - 1)) + 1; 

      if (hx == sx && hy == sy) 
      { 
       return true;  // Its a hit 
      } 
     } 

     return false; 
    } 

और फिर इसे से बाहर एक लैम्ब्डा समारोह बनाने के लिए:

Func<int, int, bool> IsHit = ((hx, hy) => IsConsoleHit(dict, consoleWidth, consoleHeight, hx, hy); 
भविष्य में

तो, मैं करूंगा चीजों की गणना करने के लिए कभी भी एक-पंक्ति कार्यों का उपयोग न करें। एक सामान्य विधि का प्रयोग करें, जिससे आप फैलाने और काम करने के लिए कमरा दे रहे हैं।

संबंधित मुद्दे