writeline visual studio pause online mundo imprimir hola ejemplos consola application c# console

c# - visual - Gráfico de la consola



imprimir en consola c# (3)

Necesito una forma de dibujar un Dictionary<int,int> en una aplicación de consola como

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

debería resultar en algo así como

He llegado hasta aquí, pero estoy atascado en el método IsHit , que determina si en las coordenadas actuales se debe establecer un punto o no. ¿Alguien podría ayudarme en este punto? Vuelve siempre verdadero.

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)); }


Al menos no tengo una respuesta que resuelva tu problema, pero algunas pistas, que quizás causen el problema:

  1. Tu sistema de coordenadas está mal. El método IsHit() recibe para la esquina superior izquierda (donde comienza a dibujar) las coordenadas 0/0, pero debería ser 0/19 y para el último elemento 77/19, pero debería ser 77/0.
  2. Para el cálculo, divide números enteros, lo que lleva al hecho de que todas las fracciones se pierden y su consulta siempre devuelve verdadero.

Tal vez deberías escribir un método de traducción, que se trasladará de la posición del cursor al valor x / y, y luego se comparará con la posición traducida, en lugar de intentar hacer ambas cosas en un solo paso. Creo que al usar ese enfoque podrás abordar el problema contigo mismo.


El siguiente código debería darte una idea. Primero es necesario introducir un Point , porque trabajar con Dictionary y sus propiedades de Key y Value en lugar de nombres normales como X e Y es una pesadilla. Además, en el diccionario no puede almacenar múltiples puntos con la misma coordenada X , lo que tiene poco sentido.

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

Luego, un DrawChart modificado:

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)); }

Y el uso:

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(); }

Resultado:


El verdadero error es tener una función muy larga de una línea. Eso dificulta la lectura, y eso causa problemas incluso para una persona inteligente como usted.

IsHit () es una función bastante complicada, así que extiéndelo ...

Necesita escalar las coordenadas para que quepan en la ventana de la consola.
He asumido que las coordenadas de la ventana son (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; }

Y luego para hacer una función lambda de esto:

Func<int, int, bool> IsHit = ((hx, hy) => IsConsoleHit(dict, consoleWidth, consoleHeight, hx, hy);

Entonces, en el futuro, nunca usaría funciones de una línea para calcular cosas. Usa un método normal, dándote espacio para separarte y trabajar.