How to draw a rectangle in console application? - c#

I need to draw a rectangle, with a number inside, in a C# console app and using extended ASCII. How do I go about it?
This is for a demo.

public class ConsoleRectangle
{
private int hWidth;
private int hHeight;
private Point hLocation;
private ConsoleColor hBorderColor;
public ConsoleRectangle(int width, int height, Point location, ConsoleColor borderColor)
{
hWidth = width;
hHeight = height;
hLocation = location;
hBorderColor = borderColor;
}
public Point Location
{
get { return hLocation; }
set { hLocation = value; }
}
public int Width
{
get { return hWidth; }
set { hWidth = value; }
}
public int Height
{
get { return hHeight; }
set { hHeight = value; }
}
public ConsoleColor BorderColor
{
get { return hBorderColor; }
set { hBorderColor = value; }
}
public void Draw()
{
string s = "╔";
string space = "";
string temp = "";
for (int i = 0; i < Width; i++)
{
space += " ";
s += "═";
}
for (int j = 0; j < Location.X ; j++)
temp += " ";
s += "╗" + "\n";
for (int i = 0; i < Height; i++)
s += temp + "║" + space + "║" + "\n";
s += temp + "╚";
for (int i = 0; i < Width; i++)
s += "═";
s += "╝" + "\n";
Console.ForegroundColor = BorderColor;
Console.CursorTop = hLocation.Y;
Console.CursorLeft = hLocation.X;
Console.Write(s);
Console.ResetColor();
}
}

This is an extension method to String, which will draw a console box around a given string. Multi-line support included.
i.e.
string tmp = "some value"; Console.Write(tmp.DrawInConsoleBox());
public static string DrawInConsoleBox(this string s)
{
string ulCorner = "╔";
string llCorner = "╚";
string urCorner = "╗";
string lrCorner = "╝";
string vertical = "║";
string horizontal = "═";
string[] lines = s.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
int longest = 0;
foreach(string line in lines)
{
if (line.Length > longest)
longest = line.Length;
}
int width = longest + 2; // 1 space on each side
string h = string.Empty;
for (int i = 0; i < width; i++)
h += horizontal;
// box top
StringBuilder sb = new StringBuilder();
sb.AppendLine(ulCorner + h + urCorner);
// box contents
foreach (string line in lines)
{
double dblSpaces = (((double)width - (double)line.Length) / (double)2);
int iSpaces = Convert.ToInt32(dblSpaces);
if (dblSpaces > iSpaces) // not an even amount of chars
{
iSpaces += 1; // round up to next whole number
}
string beginSpacing = "";
string endSpacing = "";
for (int i = 0; i < iSpaces; i++)
{
beginSpacing += " ";
if (! (iSpaces > dblSpaces && i == iSpaces - 1)) // if there is an extra space somewhere, it should be in the beginning
{
endSpacing += " ";
}
}
// add the text line to the box
sb.AppendLine(vertical + beginSpacing + line + endSpacing + vertical);
}
// box bottom
sb.AppendLine(llCorner + h + lrCorner);
// the finished box
return sb.ToString();
}
Output like this

Like this?
This worked for me:
Console.OutputEncoding = Encoding.GetEncoding(866);
Console.WriteLine("┌─┐");
Console.WriteLine("│1│");
Console.WriteLine("└─┘");
[EDIT]
Answer to the sub-question in the comment:
Console.OutputEncoding = Encoding.GetEncoding(866);
Console.WriteLine(" ┌─┐");
Console.WriteLine(" │1│");
Console.WriteLine("┌─┼─┘");
Console.WriteLine("│1│");
Console.WriteLine("└─┘");

You can use CsConsoleFormat† to draw with ASCII border symbols in console.
Drawing a number within a rectangle with "double" lines:
ConsoleRenderer.RenderDocument(
new Document()
.AddChildren(
new Border {
Stroke = LineThickness.Wide,
Align = HorizontalAlignment.Left
}
.AddChildren(1337)
)
);
You can change Stroke = LineThickness.Wide line to change the style of lines. LineThickness.Single would produce thin single lines, new LineThickness(LineWidth.Single, LineWidth.Wide) would produce single vertical and double horizontal lines.
Here's what it looks like:
You can also use ConsoleBuffer class to draw lines explicitly (argument names added for clarity):
using static System.ConsoleColor;
var buffer = new ConsoleBuffer(width: 6);
buffer.DrawHorizontalLine(x: 0, y: 0, width: 6, color: White);
buffer.DrawHorizontalLine(x: 0, y: 2, width: 6, color: White);
buffer.DrawVerticalLine(x: 0, y: 0, height: 3, color: White);
buffer.DrawVerticalLine(x: 5, y: 0, height: 3, color: White);
buffer.DrawString(x: 1, y: 1, color: White, text: "1337");
new ConsoleRenderTarget().Render(buffer);
† CsConsoleFormat was developed by me.

Problem with above code is extra spaces, if you draw multiple rectangles, it causes mess.
here is a code which draw rectangles recursively without extra spaces.
public class AsciDrawing
{
public static void TestMain() {
var w = Console.WindowWidth;
var h = Console.WindowHeight;
RecursiveDraw(16, 8, new Point(w/2-8, h/2-4), ConsoleColor.Black);
Console.CursorTop = h;
Console.CursorLeft = 0;
}
public static void RecursiveDraw(int Width, int Height, Point Location, ConsoleColor BorderColor) {
if(Width < 4 || Height < 2) return;
Draw(Width, Height, Location, BorderColor); //Commnet this draw and and Uncomment Draw bellow to see the difference.
Thread.Sleep(500);
//Comment or Uncomment to see how many recursive calls you want to make
//The best is to comment all execpt 1 and then uncomment 1 by 1
RecursiveDraw(Width/2, Height/2, new Point(Location.X-Width/4, Location.Y-Height/4), ConsoleColor.Green); //Left Top
RecursiveDraw(Width / 2, Height / 2, new Point(Location.X + 3* Width / 4, Location.Y + 3* Height / 4), ConsoleColor.Red); //Right Bottom
RecursiveDraw(Width / 2, Height / 2, new Point(Location.X + 3* Width / 4, Location.Y - Height / 4), ConsoleColor.Blue); //Right Top
RecursiveDraw(Width / 2, Height / 2, new Point(Location.X - Width / 4, Location.Y + 3* Height / 4), ConsoleColor.DarkMagenta); // Left Bottom
//Draw(Width, Height, Location, BorderColor);
}
public static void Draw(int Width, int Height, Point Location, ConsoleColor BorderColor)
{
Console.ForegroundColor = BorderColor;
string s = "╔";
string temp = "";
for (int i = 0; i < Width; i++)
s += "═";
s += "╗" + "\n";
Console.CursorTop = Location.Y;
Console.CursorLeft = Location.X;
Console.Write(s);
for (int i = 0; i < Height; i++) {
Console.CursorTop = Location.Y + 1 + i;
Console.CursorLeft = Location.X;
Console.WriteLine("║");
Console.CursorTop = Location.Y + 1 + i;
Console.CursorLeft = Location.X + Width+1;
Console.WriteLine("║");
}
s = temp + "╚";
for (int i = 0; i < Width; i++)
s += "═";
s += "╝" + "\n";
Console.CursorTop = Location.Y+Height;
Console.CursorLeft = Location.X;
Console.Write(s);
Console.ResetColor();
}
}
public record Point(int X, int Y);

Related

Creating an isosceles triangle in C3

The code below only makes a right angle triangle, how would I make it into an isosceles triangle?
int height = 4;
string star = "";
for (int i = 0; int i < height; i++)
{
star += "*";
Console.WriteLine(star);
}
Console.ReadLine();
This only displays a right angle triangle. What I attempted to make was a pyramid.
Here you have a cleaner code:
int numberoflayer = 4;
int empty;
int number;
for (int i = 1; i <= numberoflayer; i++)
{
for (empty = 1; empty <= (numberoflayer - i); empty++)
Console.Write(" ");
for (number = 1; number <= i; number++)
Console.Write('*');
for (number = (i - 1); number >= 1; number--)
Console.Write('*');
Console.WriteLine();
}
This draws your christmas tree:
int height = 4;
for (int i = 0; i < height; i++)
{
int countSpaces = (int)Math.Ceiling((height * 2 / 2d) - i);
int countStars = 1 + (i * 2);
string line = new string(' ', countSpaces) + new string('*', countStars);
Console.WriteLine(line);
}
Dirty code but there you go
int height = 4;
string empty = " ";
String star = "";
for(int i = 0; i<height; i++)
{
star += " *";
empty = empty.Length > 0 ? empty.Remove(0,1) : " ";
Console.WriteLine(empty + star);
}
Console.ReadLine();

String should get split on the right side of the page

I have a path saved in string (datn1, datn2) and want to print the path on a page. So I have to look, if the string is too long for the width of the page and if it is too long, it should begin with a new line.
First of all I split the string and saved it in a string array:
String datn1 = dateiName1, datn2 = dateiName1;
char[] Trennzeichen = { '\\' };
String[] folders1 = datn1.Split(Trennzeichen);
String[] folders2 = datn2.Split(Trennzeichen);
I also have the margins of the page in variables:
float leftMargin, rightMargin, topMargin, bottomMargin, width, height;
Now I want to add a new string to parts of the string array and look, if it's on the page. When it reaches the right site it should make a new line... how can i do that?
my idea:
string path_new;
for (int i = 0; i <= folders1.Length; i++)
{
If()//How can i say that he should look if the string is inside the margins?
{
path_new= folders1[i]+"//";
}
else
{
path_new= "\n" + folders1[i]+ "//";
}
}
now i found a solution:
private void DrawGraphic(Graphics g)
{
g.PageUnit = GraphicsUnit.Millimeter;
String datn1 = dateiName1, datn2 = dateiName2;
char[] Trennzeichen = { '\\' };
String[] folders1, folders2;
if (vergl.X == 1)
folders1 = datn1.Split(Trennzeichen);
else
folders1 = new String[0];
if (vergl.Y == 1)
folders2 = datn2.Split(Trennzeichen);
else
folders2 = new String[0];
if (pageSetupDialog1.PageSettings.Landscape == false)
{
string path_new = "";
string path_new2 = "";
for (int i = 0; i < folders1.Length; i++)
{
string path_temp = path_new + folders1[i] + "//";
System.Drawing.Size size_path_temp = TextRenderer.MeasureText(path_temp, new Font("Verdana", 8f)); // get size of string path_temp (in pixel)
double size_path_temp_width = Convert.ToDouble(size_path_temp.Width);
double variable = Convert.ToDouble(rightMargin.ToString())*96/25.4d; //96 = dpi Anzahl
if (size_path_temp_width < variable)
{
path_new += folders1[i] + "//";
}
else
{
path_new += System.Environment.NewLine + folders1[i] + "//";
}
}
for (int i = 0; i < folders2.Length; i++)
{
string path_temp = path_new2 + folders2[i] + "//";
System.Drawing.Size size_path_temp = TextRenderer.MeasureText(path_temp, new Font("Verdana", 8f)); // get size of string path_temp (in pixel)
double size_path_temp_width = Convert.ToDouble(size_path_temp.Width);
double variable = Convert.ToDouble(rightMargin.ToString()) * 96 / 25.4d; //96 = dpi
if (size_path_temp_width < variable)
{
path_new2 += folders2[i] + "//";
}
else
{
path_new2 += System.Environment.NewLine + folders2[i] + "//";
}
}
g.DrawString(path_new, new Font("Verdana", 8f), new SolidBrush(Color.Black), leftMargin, topMargin+10);
g.DrawString(path_new2, new Font("Verdana", 8f), new SolidBrush(Color.Black), 20, topMargin + 10 + bmp1.Height / 6 + 25);
}
dateiName1 and dateiName2 is a string in which the paths are saved.
vergl.X and vergl.Y checks if there is a path read in

WPF - Set Images to Grid

I am trying to set images to a grid I gave created, I am a noob, so please don't get mad at my coding :). I was wondering if there is a way to say set image to grid row 1, grid row 2, etc. I am trying to make a whack a mole game.
private void PopulateGrid()
{
double NumofImages = TUtils.GetIniInt(Moleini, "NumPictures", "pictures", 8);
int ImageSize = TUtils.GetIniInt(Moleini, "ImageSize", "imageSize", 50);
int ImageBorderSize = TUtils.GetIniInt(Moleini, "ImageBorder", "imageBorder", 2);
double NumberOfColumns = TUtils.GetIniInt(Moleini, "NumRowsColumns", "columnNum", 4);
// More Columns than Rows \\
if (NumberOfColumns > NumofImages)
{
MessageBox.Show("There is something wrong with the .ini file.");
Window1.Close();
}
// Math - Get Necessary Variables \\
int ColumnSize = (ImageSize + (4 * ImageBorderSize));
int RowSize = (ImageSize + (4 * ImageBorderSize));
int NumberofRows = (int)Math.Ceiling(NumofImages / NumberOfColumns);
int MainWindowWidth = (TUtils.ToInt(NumberOfColumns.ToString(), 4) * ColumnSize) + 15;
int MainWindowHeight = (NumberofRows * RowSize) + 35;
// Set Window Size \\
Window1.Width = MainWindowWidth;
Window1.Height = MainWindowHeight;
// Create Grid \\
Window1.Content = grid_Main;
grid_Main.Height = MainWindowHeight;
grid_Main.Width = MainWindowWidth;
// Grid Properties \\
for (int i = 0; i < NumberofRows; i++)
{
ColumnDefinition newColumn = new ColumnDefinition();
newColumn.Width = new GridLength(ColumnSize, GridUnitType.Pixel);
grid_Main.ColumnDefinitions.Add(newColumn);
}
for (int i = 0; i < NumberofRows; i++)
{
RowDefinition Row = new RowDefinition();
Row.Height = new GridLength(RowSize, GridUnitType.Pixel);
grid_Main.RowDefinitions.Add(Row);
}
// Fill Grid \\
int RowCount = 0;
int ColumnCount = 0;
for (int i = 0; i < NumofImages; i++)
{
grid_Main.Children.Add(grid_Main);
if (RowCount < NumberofRows)
{
if (ColumnCount < NumberOfColumns)
{
Console.WriteLine("ColumnCount: " + ColumnCount.ToString());
Grid.SetRow(grid_Main, ColumnCount);
Grid.SetColumn(grid_Main, ColumnCount);
ColumnCount++;
}
else
{
RowCount++;
ColumnCount = 0;
Grid.SetRow(grid_Main, ColumnCount);
Grid.SetColumn(grid_Main, ColumnCount);
ColumnCount++;
Console.WriteLine("RowCount: " + RowCount.ToString());
}
}
else
{
break;
}
}
}
...
private Image CreateImage(int ImageNum)
{
// Gets/Sets Necessary Variables \\
double ImageHeight = ImageSize * 0.7;
// Initialize Image \\
System.Windows.Controls.Image newImage = new Image();
// Image Properties \\
newImage.Width = ImageSize;
newImage.Height = ImageHeight;
// Define Name and Content \\
newImage.Name = "Image_" + ImageNum;
String ImageFunction = TUtils.GetIniString(Moleini, "Image" + ImageNum, "PictureFile", Root + "mole2.png");
if (File.Exists(ImageFunction))
{
newImage.Source = new BitmapImage(new Uri(ImageFunction));
}
else
{
MessageBox.Show("Cannot find " + ImageFunction + ".", "Please fix the ini file");
}
return newImage;
}

How to handle: Argument out of range?

When I load a picture in the picturebox and don't click on the picturebox first it break.
When I put the return back in the code it goes to an endless loop and when I remove it the code breaks.
Here is the code. It always breaks at point1 and I dont know how to handle it.
private void buttonNoiseAvr_Click(object sender, EventArgs e)
{
Point Zeko = new Point(25, 25);
if (pictureBoxSourcePicture.Image == null)
{
MessageBox.Show("No picture loaded");
return;
}
if (pictureBoxSourcePicture.Height != clickedY || pictureBoxSourcePicture.Width != clickedX)
{
MessageBox.Show("Adeekll");
//return;
}
Color oPoint = ((Bitmap)pictureBoxSourcePicture.Image).GetPixel(clickedX, clickedY);
Color point1 = ((Bitmap)pictureBoxSourcePicture.Image).GetPixel(clickedX - 1, clickedY - 1);
Color point2 = ((Bitmap)pictureBoxSourcePicture.Image).GetPixel(clickedX, clickedY - 1);
Color point3 = ((Bitmap)pictureBoxSourcePicture.Image).GetPixel(clickedX + 1, clickedY - 1);
Color point4 = ((Bitmap)pictureBoxSourcePicture.Image).GetPixel(clickedX - 1, clickedY + 1);
Color point5 = ((Bitmap)pictureBoxSourcePicture.Image).GetPixel(clickedX, clickedY + 1);
Color point6 = ((Bitmap)pictureBoxSourcePicture.Image).GetPixel(clickedX + 1, clickedY + 1);
Color point7 = ((Bitmap)pictureBoxSourcePicture.Image).GetPixel(clickedX - 1, clickedY);
Color point8 = ((Bitmap)pictureBoxSourcePicture.Image).GetPixel(clickedX + 1, clickedY);
//int[] XOR = new int[] { oPoint.R };
//int[] XOG = new int[] { oPoint.G };
//int[] XOB = new int[] { oPoint.B };
int[] XR = new int[] { point1.R, point2.R, point3.R, point4.R, point5.R, point6.R, point7.R, point8.R };
int[] XG = new int[] { point1.G, point2.G, point3.G, point4.G, point5.G, point6.G, point7.G, point8.G };
int[] XB = new int[] { point1.B, point2.B, point3.B, point4.B, point5.B, point6.B, point7.B, point8.B };
double SumRed = 0;
double SumGreen = 0;
double SumBlue = 0;
for (int i = 0; i < XR.Length; i++)
{
SumRed += (Math.Abs(oPoint.R - XR[i])) * (Math.Abs(oPoint.R - XR[i]));
SumGreen += (Math.Abs(oPoint.G - XG[i])) * (Math.Abs(oPoint.G - XG[i]));
SumBlue += (Math.Abs(oPoint.B - XB[i])) * (Math.Abs(oPoint.B - XB[i]));
}
MessageBox.Show("The Average Difference of Red is = "
+ Math.Sqrt(SumRed) + "\n"
+ "The Average Difference of Green is = "
+ Math.Sqrt(SumGreen) + "\n"
+ "The Average Difference of Blue is = "
+ Math.Sqrt(SumBlue) + "\n");
}
You can calculate your points as follow:
Color[] points = new Color[8];
int[] xPos = { -1, 0, 1, -1, 0, 1, -1, 1 };
int[] yPos = { -1, -1, -1, 1, 1, 1, 0, 0 };
for (int i = 0; i < 8; i++)
points[i] = ((Bitmap)pictureBoxSourcePicture.Image).GetPixel(clickedX + xPos[i], clickedY + yPos[i]);
And then calculate the sumRed, sumGreen and SumBlue:
for (int i = 0; i < points.Length; i++)
{
SumRed += Math.Pow( (Math.Abs(oPoint.R - points[i].R)),2);
SumGreen += Math.Pow((Math.Abs(oPoint.R - points[i].G)), 2);
SumBlue += Math.Pow((Math.Abs(oPoint.R - points[i].B)), 2);
}
It's more short and easy to understand.
Hope this will be useful

Overload method error in c# console application

I have a class that creates a Box that have different colors on the border. I get an error on my code that says "No overload for method 'SetCursorPosition' takes 3 arguments. Here is my code:
class TitledBox : ColoredBox
{
private string title;
private ConsoleColor titleColor;
public TitledBox(Point p, int width, int height, ConsoleColor backColor, string title, ConsoleColor titleColor)
: base(p, width, height, backColor)
{
if (title.Length > width)
this.title = title.Substring(0, width);
else
this.title = title;
this.titleColor = titleColor;
}
public override void Draw()
{
for (int j = 0; j < height; j++)
{
Console.SetCursorPosition(p.X, p.Y, + j);
Console.BackgroundColor = backColor;
if ( j == 0)
{
Console.ForegroundColor = titleColor;
Console.Write(title);
for (int i = 0; i < width - title.Length; i++)
{
Console.Write(' ');
}
}
else
{
for (int i = 0; i < width; i++)
Console.Write(' ');
}
}
}
}
Any ideas on what I'm doing wrong?
Your Console.SetCursorPosition should be like below
Console.SetCursorPosition(int Left, int Top);
The Method Console.SetCursorPosition gets only 2 int parameters.
You specified 3 parameters. I think you meant to say:
//the second comma was deleted
Console.SetCursorPosition(p.X, p.Y + j);
source: http://msdn.microsoft.com/en-us/library/system.console.setcursorposition.aspx
Console.SetCursorPosition(p.X, p.Y, + j);
should be
Console.SetCursorPosition(p.X, p.Y + j);

Categories