I'm writing a small program to automate clicks on a browser game. Using the code bellow the mouse always moves to the right location, however the click on the button only works about 50% of the times. Why does it not work every time and how do i fix it?
EDIT: Here is the updated code (2 methods about image recognition left in blank due to code block size restrictions):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace CICautoplayer
{
public partial class CICplayer : Form
{
public CICplayer()
{
InitializeComponent();
}
[DllImport("user32.dll", EntryPoint = "SetCursorPos")]
private static extern bool SetCursorPos(int x, int y);
[DllImport("user32.dll")]
public static extern void mouse_event(int dwflags, int dx, int dy, int cButtons, int dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
Random rnd = new Random();
bool run = false;
int[] corner = new int[] { 0, 0 };
int[] pos = new int[] { 0, 0 };
int level = 0;
string[] logbook = new string[9] { " ", " ", " ", " ", " ", " ", " ", " ", " " };
private void runner()
{
while (run)
{
// =================================================================== identify level
bool n1found = false;
bool n2found = false;
int n1 = 9;
int n2 = 9;
while (!n1found)
{
string name = "n" + n1.ToString();
pos = new int[] { 0, 0 };
pos = position_of_level(name, corner[0] + 0, corner[0] + 15, corner[1] + 10, corner[1] + 40);
if (pos[0] > 0 && pos[1] > 0) { n1found = true; }
else if (n1 > 0) { n1--; }
else { n1found = true;}
}
while (!n2found)
{
string name = "n" + n2.ToString();
pos = new int[] { 0, 0 };
pos = position_of_level(name, corner[0] + 15, corner[0] + 40, corner[1] + 10, corner[1] + 40);
if (pos[0] > 0 && pos[1] > 0){ n2found = true; }
else if (n2 > 0) { n2--; }
else { n2found = true; n2 = 1000; }
}
level = n1 * 10 + n2;
addentry("LVL " + level.ToString() + " => ");
// ================================================================ target rewards
if (level > 5)
{
click_on(new int[] { corner[0] + 20, corner[1] + 20 });
Thread.Sleep(1100 + rnd.Next(1, 100));
//string[] targetlist = new string[] { "saltpeter", "jewels", "tools", "magnificent", "steel", "bolts", "diamond", "lore"};
string[] targetlist = new string[] { "saltpeter", "jewels", "magnificent", "bolts", "diamond", "lore" };
int[] temp_pos = new int[] { 0, 0 };
temp_pos = position_of("corner_slider", corner[0] + 200, corner[0] + 250, corner[1] + 250, corner[1] + 550);
bool chosen = false;
int n = 0;
while (n < targetlist.Count() && !chosen)
{
pos = new int[] { 0, 0 };
pos = position_of(targetlist[n], temp_pos[0] + 200, temp_pos[0] + 550, temp_pos[1], temp_pos[1] + 50);
if (pos[0] != 0 && pos[1] != 0)
{
click_on(new int[] { pos[0] + 10, pos[1] + 10 });
chosen = true;
}
n++;
}
if (chosen)
{
addentry("Rwrd: " + targetlist[n - 1] + " => ");
}
else
{
addentry("Rwrd: NONE! => ");
}
// fecher o menu das rewards
Thread.Sleep(1000 + rnd.Next(1, 100));
click_on(new int[] { corner[0] + 50, corner[1] + 400 });
}
// =============================================================== wait time
int wtime = 0;
if (level < 30) { wtime = 4000 + level * 200;
} else if (level < 60)
{
wtime = 10000 + level * 250;
} else
{
wtime = 25000;
}
addentry("Wait: " + (wtime/1000).ToString() + " sec => ");
Thread.Sleep(wtime);
// ================================================================ reset
if (run) // condition in case the stop button is pressed meanwhile
{
addentry("reseting... \r\n");
click_on(new int[] { corner[0] + 20, corner[1] + 20 });
Thread.Sleep(2000 + rnd.Next(1, 500));
// select restart
int[] p_but = new int[] { 0, 0 };
p_but = position_of("button_restart", corner[0] + 450, corner[0] + 550, corner[1] + 200, corner[1] + 400);
p_but[0] += 10; p_but[1] += 10;
click_on(p_but);
Thread.Sleep(4000 + rnd.Next(1, 500));
click_on(new int[] { corner[0] + 700, corner[1] + (level < 6 ? 335 : 385)});
Thread.Sleep(5000);
}
}
}
public void click_on(int[] coor)
{
SetCursorPos(coor[0], coor[1]);
Application.DoEvents();
mouse_event(MOUSEEVENTF_LEFTDOWN, coor[0], coor[1], 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, coor[0], coor[1], 0, 0);
}
private void addentry(string text)
{
if (InvokeRequired)
{
this.Invoke(new Action<string>(addentry), new object[] { text });
return;
}
for (int i = 0; i < 8; i++) { logbook[i] = logbook[i + 1]; }
logbook[8] = text;
logtext.Text = "";
for (int i = 0; i < 9; i++)
{
logtext.Text += logbook[i];
}
}
private int[] position_of(string what, int xmin, int xmax, int ymin, int ymax)
{
// code to identify a picture in a specified area of the screen
// returns int[2] with the coordinates
}
private int[] position_of_level(string what, int xmin, int xmax, int ymin, int ymax)
{
// code to identify a number in a specified area of the screen
// returns int[2] with the coordinates
}
private void but_play_Click(object sender, EventArgs e)
{
Thread.Sleep(3000);
corner = position_of("corner", 0, 500, 0, 600);
addentry("Corner found at " + corner[0].ToString() + " , " + corner[1].ToString() + "\r\n");
run = true;
var thread = new Thread(new ThreadStart(runner));
thread.Start();
}
private void but_stop_Click(object sender, EventArgs e)
{
run = false;
}
}
}
Related
I have struggled this for a few hours, I am trying to generate all possible combinations of all indicator parameters.
Assume I have indicators
Name possible value
sma5 5, 7, 9
sma10 10, 15
sma20 20, 25, 30
It can generate all combinations with a simple nested for loop
for(sma5=5;sma5<=9;sma5=sma5+2)
for(sma10=10;sma10<=15;sma10=sma10+5)
for(sma20=20;sma20<=30;sma20=sma20+5)
It would give 18 possible combinations
but I want to do a bit more than this, saying sma5 and sma20 can be switched over
sma5 range is now 20-30
sma20 range now is 5-9
This would give 6 more combinations if I am correct, which is 3!, 2x3
So in total would be 6 x 18 = 108 combinations
How do I write this in a clean code?
I want this as clean as possible, but can't figure it out, cuz I might possible add few more indicators
give my program more flexibility to modify
class StrObject
{
public string indicName { get; set; }
public int numbegin { get; set; }
public int numend { get; set; }
public int gap { get; set; }
}
class StrObjects : IEnumerable
{
ArrayList mylist = new ArrayList();
public StrObject this[int index]
{
get { return (StrObject)mylist[index]; }
set { mylist.Insert(index, value); }
}
IEnumerator IEnumerable.GetEnumerator()
{
return mylist.GetEnumerator();
}
}
class Program
{
static IEnumerable<IEnumerable<T>>
GetPermutations<T>(IEnumerable<T> list, int length)
{
if (length == 1) return list.Select(t => new T[] { t });
return GetPermutations(list, length - 1)
.SelectMany(t => list.Where(o => !t.Contains(o)),
(t1, t2) => t1.Concat(new T[] { t2 }));
}
private static void Main()
{
int countP = 0, countC = 0;
const int k = 3;
StrObjects myObjects = new StrObjects();
myObjects[0] = new StrObject() { indicName = "sma_5", numbegin = 5, numend=9, gap=2 };
myObjects[1] = new StrObject() { indicName = "sma_20", numbegin = 20, numend = 30, gap = 5 };
myObjects[2] = new StrObject() { indicName = "sma_50", numbegin = 50, numend = 60, gap = 5 };
var n = new[] { myObjects[0].indicName, myObjects[1].indicName, myObjects[2].indicName };
Console.Write("n: ");
foreach (var item in n)
{
Console.Write("{0} ", item);
}
Console.WriteLine();
Console.WriteLine("k: {0}", k);
Console.WriteLine();
Console.WriteLine("===============================");
Console.WriteLine("Permutations");
Console.WriteLine("===============================");
foreach (IEnumerable<string> i in GetPermutations(n, k))
{
Console.WriteLine(string.Join(" ", i));
countC++;
}
Console.WriteLine("Count : " + countC);
Console.ReadKey();
}
}
'''
finally able to pull some working code, it's a I don't know why it works but it works kind of code. at least it gets what I want
sma_day, 5,7,9
sma_day10, 10,15
sma_day50, 50,55,60
sma_vol5, 5,7,9
sma_vol10, 10,15,20
sma_vol20, 20,25,30
psyvalue 30,35,40,45,50
This should yield all 87480 combinations
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using System.Data.SqlClient;
using System.Collections;
namespace optimization
{
class indiObject
{
public string indicName { get; set; }
public int numbegin { get; set; }
public int numend { get; set; }
public int gap { get; set; }
}
class IndiObjects : IEnumerable
{
ArrayList mylist = new ArrayList();
public indiObject this[int index]
{
get { return (indiObject)mylist[index]; }
set { mylist.Insert(index, value); }
}
IEnumerator IEnumerable.GetEnumerator()
{
return mylist.GetEnumerator();
}
}
class Program
{
public static List<Task> tasks;
private const string pythonpath = #"C:\Python\Scripts\python.exe";
private const string scriptpath = #"C:\psy-Optimizer.py";
private const string connectionstr = #"SERVER =localhost;DATABASE=Stock;Trusted_Connection=True";
public delegate void strategy(Dictionary<string, string> dict);
public static int processcount = 0;
public static Task[] tasksArray;
static void Main(string[] args)
{
Dictionary<string, string> dict = new Dictionary<string, string>();
tasks = new List<Task>();
int countC = 0;
const int k = 3;
IndiObjects myObjects = new IndiObjects();
myObjects[0] = new indiObject() { indicName = "sma_day5", numbegin = 5, numend = 9, gap = 2 };
myObjects[1] = new indiObject() { indicName = "sma_day20", numbegin = 20, numend = 30, gap = 5 };
myObjects[2] = new indiObject() { indicName = "sma_day50", numbegin = 50, numend = 60, gap = 5 };
IndiObjects myObjects2 = new IndiObjects();
myObjects2[0] = new indiObject() { indicName = "sma_vol5", numbegin = 5, numend = 9, gap = 2 };
myObjects2[1] = new indiObject() { indicName = "sma_vol10", numbegin = 10, numend = 19, gap = 5 };
myObjects2[2] = new indiObject() { indicName = "sma_vol20", numbegin = 20, numend = 30, gap = 5 };
var var1 = new[] { myObjects[0].indicName, myObjects[1].indicName, myObjects[2].indicName };
var var2 = new[] { myObjects2[0].indicName, myObjects2[1].indicName, myObjects2[2].indicName };
foreach (IEnumerable<string> i in GetPermutations(var1, k))
{
int[,] loopcount0 = new int[3, 3];
int count0 = 0;
foreach (string s in i)
{
//Console.WriteLine(s);
switch (s)
{
case "sma_day5":
loopcount0[count0, 0] = myObjects[0].numbegin;
loopcount0[count0, 1] = myObjects[0].numend;
loopcount0[count0, 2] = myObjects[0].gap;
break;
case "sma_day20":
loopcount0[count0, 0] = myObjects[1].numbegin;
loopcount0[count0, 1] = myObjects[1].numend;
loopcount0[count0, 2] = myObjects[1].gap;
break;
case "sma_day50":
loopcount0[count0, 0] = myObjects[2].numbegin;
loopcount0[count0, 1] = myObjects[2].numend;
loopcount0[count0, 2] = myObjects[2].gap;
break;
}
count0++;
}
for (int f1 = loopcount0[0, 0]; f1 <= loopcount0[0, 1]; f1 += loopcount0[0, 2])
for (int f2 = loopcount0[1, 0]; f2 <= loopcount0[1, 1]; f2 += loopcount0[1, 2])
for (int f3 = loopcount0[2, 0]; f3 <= loopcount0[2, 1]; f3 += loopcount0[2, 2])
foreach (IEnumerable<string> i2 in GetPermutations(var2, k))
{
int[,] loopcount = new int [3,3];
int count = 0;
//Console.WriteLine("sma_day5 " + f1 + "sma_day20" + f2 + "sma_day50" + f3);
foreach (string s in i2)
{
//Console.WriteLine(s);
switch (s)
{
case "sma_vol5":
loopcount[count, 0] = myObjects2[0].numbegin;
loopcount[count, 1] = myObjects2[0].numend;
loopcount[count, 2] = myObjects2[0].gap;
break;
case "sma_vol10":
loopcount[count, 0] = myObjects2[1].numbegin;
loopcount[count, 1] = myObjects2[1].numend;
loopcount[count, 2] = myObjects2[1].gap;
break;
case "sma_vol20":
loopcount[count, 0] = myObjects2[2].numbegin;
loopcount[count, 1] = myObjects2[2].numend;
loopcount[count, 2] = myObjects2[2].gap;
break;
}
count++;
}
for (int f4 = loopcount[0, 0]; f4 <= loopcount[0,1]; f4 += loopcount[0, 2])
for (int f5 = loopcount[1, 0]; f5 <= loopcount[1, 1]; f5 += loopcount[1, 2])
for (int f6 = loopcount[2, 0]; f6 <= loopcount[2, 1]; f6 += loopcount[2, 2])
for (int psyvalue = 30; psyvalue <= 50; psyvalue += 5)
for (int atrdist = 5; atrdist <= 5; atrdist++)
for (int day_atrdist = 5; day_atrdist <= 5; day_atrdist++)
{
try
{
dict.Clear();
dict.Add("--minutefromdate", "2017-01-01");
dict.Add("--dayfromdate", "2016-01-01");
dict.Add("--todate", "2022-01-01");
dict.Add("--sma_day5", f1.ToString());
dict.Add("--sma_day20", f2.ToString());
dict.Add("--sma_day50", f3.ToString());
dict.Add("--lfi", "11");
dict.Add("--sma_vol5", f4.ToString());
dict.Add("--sma_vol10", f5.ToString());
dict.Add("--sma_vol20", f6.ToString());
dict.Add("--day_atrdist", "5");
dict.Add("--atrdist", "5");
dict.Add("--psyvalue", psyvalue.ToString());
if (countC >= 72893)
{
tasks.Add(Task.Factory.StartNew(() => RunBacktrader(dict), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default));
}
// Console.WriteLine("Process ID " + countC++);
/*
string str="";
foreach (KeyValuePair<string, string> kvp in dict)
{
str += kvp.Key + "=" + kvp.Value ;
}
*/
Console.WriteLine("Process ID " + countC++);
tasksArray = tasks.Where(t => t != null).ToArray();
while (tasksArray.Length >= 10)
{
var completedTask = Task.WhenAny(tasks).Result;
tasks.Remove(completedTask);
Console.WriteLine("A task has been completed with result {0}.", completedTask.Id);
}
}
catch (Exception ex)
{
RecordLog(ex.Message);
}
}
}
//Console.WriteLine(string.Join(" ", i));
}
Console.Read();
}
private static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length)
{
if (length == 1) return list.Select(t => new T[] { t });
return GetPermutations(list, length - 1)
.SelectMany(t => list.Where(o => !t.Contains(o)),
(t1, t2) => t1.Concat(new T[] { t2 }));
}
private static void RunBacktrader(Dictionary<string, string> dict)
{
try
{
string paras = "";
foreach (KeyValuePair<string, string> pp in dict)
{
paras += pp.Key + "=" + pp.Value + " ";
}
Console.WriteLine("Tasks count " + processcount++);
string scriptName = scriptpath + " " + paras;
Process p = new Process();
p.StartInfo = new ProcessStartInfo(#pythonpath, #scriptName)
{
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
}
catch (Exception ex)
{
RecordLog("5 " + ex.Message);
}
}
private static void RecordLog(string message)
{
try
{
using (SqlConnection connection = new SqlConnection(connectionstr))
{
SqlCommand sqlcmd = new SqlCommand();
sqlcmd.Parameters.Add(new SqlParameter("message", message));
connection.Open();
sqlcmd.Connection = connection;
sqlcmd.CommandText = "INSERT INTO [dbo].[optmizationLog] (ExecTime, Steps) VALUES (GETDATE(), CAST(#message as varchar(512)) )";
sqlcmd.ExecuteNonQuery();
connection.Close();
}
}
catch (Exception ex)
{
Console.Write("duplicate");
}
}
}
}
I have created a piece of code to create an array of 100 elements which will randomize based on the numbers from a set array. However whenever I enter "y" I am looking the array to delete the last element and add a new random element to the start and move everything in between one to the right to allow for this. However at the moment it is completely changing the array every time I enter "y". Can anyone help with this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
int[] values = { 1, 2, 3, 4, 5, 6 };
int Min = values[0];
int Max = values[5] + 1;
int w = 0 ;
int[] rndValues = new int[100];
Random rndNum = new Random();
Console.WriteLine("Random001 " + w);
for (int i = 0; i < rndValues.Length; i++)
{
rndValues[i] = rndNum.Next(Min, Max);
}
Console.WriteLine("Random " + w);
foreach(var item in rndValues)
{
Console.Write(item.ToString() + " ");
}
if (w==0)
{
Console.WriteLine(Environment.NewLine);
prob(rndValues, Min, Max,w);
Console.WriteLine(Environment.NewLine);
w++;
}
if (w>0)
{
while(true)
{
Console.WriteLine("To change elements in the array press y");
// read input
var s = Console.ReadLine();
if(s == "y")
{
//rndValues[99] = 0;
for(int i = 0; i == rndValues.Length; i++)
{
if (i != rndValues.Length)
{
rndValues[rndValues.Length-i] = rndValues[(rndValues.Length-i)-1];
}
else if (i == rndValues.Length)
{
rndValues[0] = rndNum.Next(Min, Max);
}
}
}
else
{
break;
}
prob(rndValues, Min, Max,w);
}
}
}
public static void prob(int[] rndValues, int Min, int Max, int w )
{
double[] count = new double[rndValues.Length];
//Loop through min to max and count the occurances
for (int i = Min; i <Max; i++)
{
for (int j = 0; j < rndValues.Length; j++)
{
if (rndValues[j] == i)
{
count[i] = count[i] + 1;
}
}
}
//For displaying output only
foreach(var item in rndValues)
{
Console.Write(item.ToString() + " ");
}
Console.WriteLine("W " + w);
for (int i = Min; i < Max; i++)
{
count[i] = (count[i] / rndValues.Length) * 100;
Console.WriteLine("Probability of the number " + i + " is " + count[i]);
}
}
}
}
Thanks.
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
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);
Hey,
I'm trying to read a EAN-13 barcode from my webcam.
I already wrote a class to do that work.
I'm taking a picture from my webcam, trimming it to show ONLY the barcode,
and reading the barcode with the code tables from wikipedia.
For some reason, the barcode gets trimmed, but the output is always "0-1-1-1-1-1-1-1-1-1-1-1-1".
I wonder if i did any stupid mistake or misunderstood something?
I do not want to use ANY third-party programs!
this is my code for now:
public class BarcodeDecoder
{
static string[] ligerade = new string[] { "0100111", "0110011", "0011011", "0100001", "0011101", "0000101", "0010001", "0001001", "0010111" };
static string[] rechtsgerade = new string[ligerade.Length];
static string[] liungerade = new string[ligerade.Length];
static string[] GeradeUG = new string[] { "UUUUUU", "UUGUGG", "UUGGUG", "UUGGGU", "UGUUGG", "UGGUUG", "UGGGUU", "UGUGUG", "UGUGGU", "UGGUGU" };
static int[] links;
static int[] rechts;
static string result;
public static string Decode(Bitmap b)
{
result = "";
Bitmap bb = CutOutOf(b, b.Height / 2);
bb = trimBitmap(bb);
int[] lgs = GetNumberOutOf(bb);
int[][] rr = trimArray(lgs);
links = rr[0];
rechts = rr[1];
FillArrays();
BearbeiteLinks();
BearbeiteRechts();
return result;
}
static void BearbeiteLinks()
{
string GU = "";
string[] zahlen = new string[6];
zahlen[0] = OutOfArray(links, 0, 7);
zahlen[1] = OutOfArray(links, 7, 7);
zahlen[2] = OutOfArray(links, 14, 7);
zahlen[3] = OutOfArray(links, 21, 7);
zahlen[4] = OutOfArray(links, 28, 7);
zahlen[5] = OutOfArray(links, 35, 7);
foreach (string pq in zahlen)
{
bool gerade = ligerade.ToList().IndexOf(pq) > -1;
if (gerade)
{
result += ligerade.ToList().IndexOf(pq).ToString();
GU += "G";
}
else
{
result += liungerade.ToList().IndexOf(pq).ToString();
GU += "U";
}
}
result = GeradeUG.ToList().IndexOf(GU).ToString() + result;
}
static void BearbeiteRechts()
{
string[] zahlen = new string[6];
zahlen[0] = OutOfArray(rechts, 0, 7);
zahlen[1] = OutOfArray(rechts, 7, 7);
zahlen[2] = OutOfArray(rechts, 14, 7);
zahlen[3] = OutOfArray(rechts, 21, 7);
zahlen[4] = OutOfArray(rechts, 28, 7);
zahlen[5] = OutOfArray(rechts, 35, 7);
foreach (string pq in zahlen)
{
result += rechtsgerade.ToList().IndexOf(pq).ToString();
}
}
static string OutOfArray(int[] ar, int startindex, int length)
{
int[] gar = new int[length];
Array.Copy(ar, startindex, gar, 0, length);
StringBuilder bilder = new StringBuilder();
for (int i = 0; i < gar.Length; i++)
{
bilder.Append(gar[i].ToString());
}
return bilder.ToString();
}
static Bitmap trimBitmap(Bitmap b)
{
bool alreadyBlack = false;
int firstblack = 0;
for (int i = 0; i < b.Width; i++)
{
Color gp = b.GetPixel(i, 0);
if ((gp.R + gp.G + gp.B) / 3 < 128)
{
if (!alreadyBlack)
{
alreadyBlack = true;
firstblack = i;
}
}
}
bool alreadyblack = false;
int lastblack = 0;
for (int i = b.Width -1; i > 0; i--)
{
Color gpp = b.GetPixel(i, 0);
if ((gpp.R + gpp.G + gpp.B) / 3 < 128)
{
if (!alreadyblack)
{
alreadyblack = true;
lastblack = i;
}
}
}
Bitmap result = new Bitmap(lastblack - firstblack, 1);
for (int i = firstblack; i < lastblack; i++)
{
Color c = b.GetPixel(i, 0);
result.SetPixel(i - firstblack, 0, c);
}
result.Save("C:\\result.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
return result;
}
static int[][] trimArray(int[] ar)
{
int[][] res = new int[2][];
int[] resl = new int[6 * 7];
int[] resr = new int[6 * 7];
Array.Copy(ar, 2, resl, 0, 6 * 7);
Array.Copy(ar, 2 + 6 * 7 + 5, resr, 0, 6 * 7);
res[0] = resl;
res[1] = resr;
return res;
}
static void FillArrays()
{
for (int i = 0; i < ligerade.Length; i++)
{
rechtsgerade[i] = string.Concat(ligerade[i].Reverse());
}
for (int x = 0; x < liungerade.Length; x++)
{
liungerade[x] = Invert(rechtsgerade[x]);
}
}
static string Invert(string xx)
{
string xs = "";
for (int y = 0; y < xx.Length; y++)
{
int fd = int.Parse(xx[y].ToString());
if (fd == 0)
fd = 1;
else
fd = 0;
xs += fd.ToString();
}
return xs;
}
static Bitmap CutOutOf(Bitmap b, int y)
{
Bitmap res = new Bitmap(b.Width, 1);
for (int i = 0; i < b.Width; i++)
{
Color c = b.GetPixel(i, y);
res.SetPixel(i, 0, c);
}
return res;
}
static int[] GetNumberOutOf(Bitmap bb)
{
List<int> intlst = new List<int>();
float f = (float)bb.Width / 95.0f;
float wd = f / 2.0f;
for (float i = wd; i < bb.Width; i+=f)
{
Color c = bb.GetPixel((int)Math.Round(i,0), 0);
intlst.Add(GetOutOfColor(c));
}
return intlst.ToArray();
}
static int GetOutOfColor(Color c)
{
if (c.A + c.B + c.R > 128 * 3)
{
return 0;
}
return 1;
}
}
Sorry for german names in the code!
I see two problems:
1) You only scan the top most pixel row of your image (see the second parameter of GetPixel). Your barcode is probably in the middle of the image and not at the top.
Color c = bb.GetPixel((int)Math.Round(i,0), 0);
2) Instead of the green component, you take the alpha component to convert the colored pixel into a binary value. Since the alpha component is probably always 255, you always get 0 unless you have a very dark pixel.
if (c.A + c.B + c.R > 128 * 3)