I'm trying to figure out if I can find any exist chart in winforms C# application.
I have several integer inputs a, b, c... and at the end of processing I got results with wide range of values like 12, 342, 445879 etc.
On chart I want to see only hierarchy from higher size to lower without equivalent scale distance between higher and lower line ends. Just stairway by downward curve for each input.
So two things is needed, if some kind of such chart tool is already exist, is a sorting of sequence from higher to lower with names attached to the lines and non-scaled value display in the ratio between each other.
For example I have inputs:
int a = 12989;
int b = 324;
int c = 23;
int d = 12;
int e = 3;
and second process results:
int a = 4;
int b = 25;
int c = 1;
int d = 4;
int e = 14;
I have tried to use different graphs in list of VS,
private void Size(int a, int b)
{
this.chart1.Series["Series1"].Points.AddXY("a1", a);
this.chart1.Series["Series1"].Points.AddXY("a2", b);
}
but seems like I need different thing.
Here is desired results:
Yes, this is possible.
For x-values there is in fact a Series property IsXValueIndexed to enforce an unscaled display. There is no such thing for the y-values, though.
(The reason is probably that unscaled y-values are not really useful, as they will arguably mislead the user about the data..(..which may or may not be true of x-values; x-values containing, say, zip codes or other IDs should be displayed unscaled!))
To workaround you need to set the x and y-values to a count value and set the Labels of each DataPoint explicitly to the actual values you have.
Example:
// create an odered list of data:
List<double> data = new List<double>();
for (int i = 0; i < 12; i++) data.Add(rnd.Next(100) * rnd.Next(i * 5));
data = data.OrderByDescending(x => x).ToList();
// now add with dummy x and y-values:
Series s = chart1.Series[0];
for (int i = 0; i < data.Count; i++)
{
int p = s.Points.AddXY(i, data.Count - i); // dummy values
DataPoint dp = s.Points[p];
dp.Label = data[i] +""; // real value, formatted
dp.Tag= data[i]; // real value
}
To get rid of the axes, which can't show ay meanigful values, disable them:
chart1.ChartAreas[0].AxisX.Enabled = AxisEnabled.False;
chart1.ChartAreas[0].AxisY.Enabled = AxisEnabled.False;
More styling:
s.SetCustomProperty("PixelPointWidth","15");
s.Color = Color.DarkSlateGray;
Note the as the y-values are really just dummies, if you need to access them, you will have to use the Labels and convert them from string to number type. Also note that if they are double or floats those strings will either be terribly long or formatted to a short string. To preserve the actual values you can store these additionally in the Tag field of each DataPoint..
Related
I'm new to c#. I have a task to make a type of minesweeper, but which immediately opens a solution.
static void Main(string[] args)
{
Console.Write("Enter the width of the field: ");
int q = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the length of the field: ");
int w = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the number of bombs: ");
int c = Convert.ToInt32(Console.ReadLine());
Random rand = new Random();
var charArray = new char[q, w];
var intArray = new int[q, w];
for (int i = 0; i < q; i++)
{
for (int j = 0; j < w; j++)
{
intArray[i, j] = rand.Next(2);
charArray[i, j] = intArray[i, j] == 0 ? '_' : '*';
Console.Write(charArray[i, j]);
}
Console.WriteLine();
}
}
}
}
Two arrays should be output. Everything should be closed on the first one, that is, there should be only the characters: _ and *
0 - these are places without mines, I replaced them with a symbol _
1 - these are places with mines, I replaced them with an asterisk symbol, but they do not accept the number of mines entered by the user. And it is necessary that there are as many "*" characters as there are mines.
And in the second array there should be an already open solution of the game. That is, the cells next to which there are mines should take a number meaning the number of mines next to this cell.
Please help me..
Compiling the current code
Random random = new Random();
while(c > 0)
{
var rq = random.Next(q);
var rw = random.Next(w);
if(intArray[rq,rw] == 0)
{
intArray[rq, rw] = 1;
c--;
}
}
I would suggest dividing the problem in smaller manageable chunks. For instance, you can place the bombs in a initial step, and on a second step build the solution. You can build the solution at the same time you place the bombs, although for clarity you can do it after.
Naming of variables is also important. If you prefer using single letter variable names, I believe that's fine for the problem limits, however I would use meaningful letters easier to remember. eg: W and H for the width and height of the board, and B for the total number of bombs.
The first part of the problem then can be described as placing B bombs in a WxH board. So instead of having nested for statements that enumerate WxH times, it's better to have a while loop that repeats the bomb placing logic as long as you have remaining bombs.
Once you generate a new random location on the board, you have to check you haven't placed a bomb there already. You can have an auxiliary function HasBomb that checks that:
bool HasBomb(char[,] charArray, int x, int y)
{
return charArray[x,y] == '*';
}
I'll leave error checking out, this function being private can rely on the caller sending valid coordinates.
Then the bomb placing procedure can be something like:
int remainingBombs = B;
while (remainingBombs > 0)
{
int x = rand.Next(W);
int y = rand.Next(H);
if (!HasBomb(charArray, x, y)
{
charArray[x,y] = '*';
remainingBombs--;
}
}
At this point you may figure out another concern. If the number B of bombs to place is larger than the available positions on the board WxH, then you wont be able to place the bombs on the board. You'll have to check for that restriction when requesting the values for W, H and B.
Then in order to create the array with the number of bombs next to each position, you'll need some way to check for all the neighbouring positions to a given one. If the position is in the middle of the board it has 8 neighbour positions, if it's on an edge it has 5, and if it's on a corner it has 3. Having a helper function return all the valid neighbour positions can be handy.
IEnumerable<(int X, int Y)> NeighbourPositions(int x, int y, int W, int H)
{
bool leftEdge = x == 0;
bool topEdge = y == 0;
bool rightEdge = x == W - 1;
bool bottomEdge = y == H - 1;
if (!leftEdge && !topEdge)
yield return (x-1, y-1);
if (!topEdge)
yield return (x, y-1);
if (!rightEdge && !topEdge)
yield return (x+1, y-1);
if (!leftEdge)
yield return (x-1, y);
if (!rightEdge)
yield return (x+1, y);
if (!leftEdge && !bottomEdge)
yield return (x-1, y+1);
if (!bottomEdge)
yield return (x, y+1);
if (!rightEdge && !bottomEdge)
yield return (x+1, y+1)
}
This function uses Iterators and touples. If you feel those concepts are too complex as you said are new to C#, you can make the function return a list with coordinates instead.
Now the only thing left is to iterate over the whole intArray and increment the value on each position for each neighbour bomb you find.
for (int x = 0; x < W; x++)
{
for (int y = 0; y < H; y++)
{
foreach (var n in NeighbourPositions(x, y, W, H))
{
if (HasBomb(charArray, n.X, n.Y))
intArray[x,y]++;
}
}
}
The answers here are mostly about generating random x and random y put in loop and trying to put the mine into empty cells. It is ok solution, but if you think of it, it is not that sufficient. Every time you try to find a new random cell, there is chance that cell is already a mine. This is pretty much alright, if you don't put too many mines into your field, but if you put some greater number of mines, this event can occur quite often. This means that the loop might take longer than usually. Or, theoretically, if you wanted to put 999 mines into 1000 cell field, it would be really hard for the loop to fill all the necessary cells, especially for the last mine. Now, I am not saying that the solutions here are bad, I think, it's really alright solution for many people. But if someone wanted a little bit efficient solution, I have tried to crate it.
Solution
In this solution, you iterate each cell and try to calculate a probability of the mine to be placed there. I have come up with this easy formula, which calculates the probability:
Every time you try to place a mine into one cell, you calculate this formula and compare it to random generated number.
bool isMine = random.NextDouble() < calcProbability();
So I'm having some trouble with a C# program that is meant to sum the 8 highness value from a list.
The program works by declaring a variable currenthigh, which stores a value from the gradelist. It then compares itself to the value abshigh to see if it is greater than the established highest value. If it is, it sets currenthigh as the new highest value.
Once the loop has run through the list and confirmed the highest value, it adds it to the uppertotal variable and uses the ejector variable to remove it from the list. The program then iterates, this time without the previous highest value. It iterates 8 times so that in the end the top 8 values are added to uppertotal.
Trouble is, the highest variable remains in the list, despite the code having instructions to delete it, so it just adds the highest value to itself 8 times.
int currenthigh = 0;
int abshigh = 0;
int ejector = 0;
int uppertotal = 0;
for (int g = 0; g < 8; g++)
{
for (int z = 0; z < gradelist.Count; z++)
{
Console.WriteLine("PASS STARTED");
currenthigh = Convert.ToInt32((gradelist[z]));
Console.WriteLine("currenthigh" + currenthigh);
if (currenthigh > abshigh)
{
abshigh = currenthigh;
ejector = z;
}
}
Console.WriteLine("ejector" + ejector);
uppertotal = uppertotal + currenthigh;
gradelist.RemoveAt(ejector);
Console.WriteLine("PASS COMPLETE");
Console.WriteLine("RESETING");
}
Note - gradelist is a list of integers containing at least 12 items at all time.
This happens because you do not remove the highest value from gradelist. Pay attention, you put Z in ejector, but Z is an index in gradelist and when you try to remove it, you remove nothing because there is no Z in gradelist as a member! Instead of
gradelist.RemoveAt(ejector);
you should do this:
gradelist.RemoveAt(gradelist[ejector]);
But I'd recommend you completely different approach. If you just want to get your uppertotal which is the sum of top 8 members in gradlist, use this simple trick:
uppertotal += gradelist.OrderByDescending(p => p).Take(8).Sum();
Your code is extremely big for the relatively simple task.
You can select the top X of a list as follows:
top_list = gradelist.OrderByDescending(i => i).Take(X)
When working with lists/collections System.Linq is your friend
I am stuck with this two dimension array with Unity framework coding with c#. I am trying to create a Checker game with an Intelligent agent. So I trying to get all the pieces and passing to the Alpha Beta algorithm and get the maximum amount of Opponent side. But in order to do that I have to check each piece on my board. I am using 8by8 board on my game. So I used
Piece[,] pieces = new Pieces[8,8];
code in order to store the pieces. Now I want to change one piece and retrieve the pieces.
I tried in several ways and experimented, But I could not found any to take this array and change one generic object and retrieve the list with the changes.
Please help me to solve this. Thanks in advance.
I written down here about what I experimented. Any suggestions about this matter or did I do something wrong?....
internal static void TryMoveInImaginaryWay(Piece[,] piece)
{
int x = 0;
int y =2;
int x1 = 1;
int y1 = 3;
Moves move = new Moves();
move.X = x;
move.Y = y;
move.X1 = x1;
move.Y1 = y1;
// Copping the pieces state
Piece p = piece[x, y];
//I am creating a list with those pieces
List<Piece> temppiecelist = new List<Piece>();
foreach (Piece pi in piece)
{
if (pi == p)
{
piece[x1, y1] = p;
temppiecelist.Add(null);
}
else
{
temppiecelist.Add(pi);
}
}
Piece[,] piek = temppiecelist; // can't convert it says Cannot Implicitly convert type "System.Collection.Generic.List<Piece>' to Piece[*,*]'"
// I know i can't convert like this, but any ideas.
//Piece[,] piek = new Piece[8, 8];
I am asking about , Is there any way to change above Piece[,] array list values. And I want the same format as output.
It looks like what you are trying to do is make a copy of the board and then make a move on that board.
Why on you would get a List involved I cannot figure out; what led you to believe that a List was the right solution? I am interested to know; by learning why people come to bad conclusions about program writing, I can help them write better programs.
To make a mutated copy of the board, just copy the board and mutate the copy:
internal static void TryMoveInImaginaryWay(Piece[,] original)
{
int x0 = 0;
int y0 = 2;
int x1 = 1;
int y1 = 3;
Piece[,] copy = (Piece[,])original.Clone();
copy[x1,y1] = copy[x0,y0];
copy[x0,y0] = null;
And you're done.
I apologize if this question is too vague because I haven't actually built out any code yet, but my question is about how to code (perhaps in C# in a Unity3d script, but really just generically) the dynamically changing unit depth/width in total war games.
In TW games, you can click and drag to change a unit from an nx2 formation to 2xn formation and anything in between. Here's a video (watch from 15 seconds in to 30 seconds in):
https://www.youtube.com/watch?v=3aGRzy_PzJQ
I'm curious, generically speaking, about the code that would permit someone to on the fly exchange the elements of an array like that. I'm assuming here that the units in the formation are elements in an array
so, you might start with an array like this:
int[,] array = new int[2, 20];
and end up with an array like this:
int[,] array = int[20, 2];
but in between you create the closest approximations, with the last row in some cases being unfilled, and then the elements of that last row would have to center visually until the column width was such that the number of elements in all the rows are equal again.
It kind of reminds me of that common intro to programming problem that requires you to write to the console a pyramid made of *'s all stacked up and adding one element per row with spaces in between, but a lot more complicated.
Most of the lower-tech formation tactics games out there, like Scourge of War just let you choose either Line Formation (2 rows deep) or column formation (2 columns wide), without any in between options, which was perhaps an intentional design choice, but it makes unit movement so awkward that I had to assume they did it out of technical limitations, so maybe this is a hard problem.
I wrote some code to clarify the question a bit. The method form() takes parameters for the number of units in the formation and the width of the formation, without using an array, and just prints out the formation to the console with any extra men put in the last row and centered:
x = number of men
y = width formation
r = number of rows, or depth (calculated from x and y)
L = leftover men in last row if y does not divide evenly into x
Space = number spaces used to center last row
form() = method called from the class Formation
I figured it should take the depth and number of men because the number of men is set (until some die but that's not being simulated here) and the player would normally spread out the men to the desired width, and so the number of rows, and number of men in those rows, including the last row, and the centering of that last row, should be taken care of by the program. At least that's one way to do that.
namespace ConsoleApplication6
{
class Formation
{
public int x;
public int y;
public Formation(int x, int y)
{
this.x = x;
this.y = y;
}
public void form()
{
int r = x / y;
int Left = x % y;
int Space = (y - Left)/2;
for (int i = 0; i < r;i++)
{
for (int j = 0; j < y; j++)
{
Console.Write("A");
}
Console.WriteLine();
if (i == r - 1)
{
for (int m = 0; m < Space; m++)
{
Console.Write(" ");
}
for (int k = 0; k < Left; k++)
{
Console.Write("A");
}
}
}
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("enter the number of men: ");
int a = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("enter the formation width: ");
int b = Convert.ToInt32(Console.ReadLine());
Formation testudo = new Formation(a,b);
testudo.form();
Console.ReadKey();
}
}
}
So, I think what I'm trying to do to improve this is have the above code run repeatedly in real time as the user inputs a different desired width (y changes) and men die (x changes)
But, if it were actually to be implemented in a game I think it would have to be an array, so I guess the array could take the x parameter as its max index number and then i would do a kind of for loop like for(x in array) or whatever print x instead of just console logging the letter A over and over
I've learned C++ and am currently taking C#. Just to clarify, I am providing all the instructions but if I can get help with parts (b) and (c) I think I can do the rest.
This is my assignment:
Matrix is a 2 dimensional array of row size r and column size c. There are specific rules of adding or subtracting matrices A and B (of same row size m and column size n). The product of matrix A of dimension m by n (m is the row size or row dimension, n is the column dimension) and another matrix B of dimension p by q is meaningful only if p = n and in this case AB is a matrix of dimension m by q.
(a) Define class Matrix with at least private variables depending on row size, column size etc.
(b) Provide constructor when row size and column size are specified. You will set all the arguments to 0.0.
(c) Provide method to set the entries of a matrix
(d) Provide Add method of matrices
(e) Provide Subtract method.
(f) Provide scalar multiplication which will multiply all the elements of matrix A by the value x.
(g) Provide multiplication method mul so that A.mul(B) is equal to AB if A’s column dimension c is equal to B’s row dimension. Generate error message if the product AB is meaningless.
{
{
private int r=10;//row size
private int c=10;//column size
int[,] array=new int [10,10];
public Matrix()
{
for (int i = 0; i < this.r; i++)
{
for (int j = 0; j < this.c; j++)
{
}
}
}
public Matrix(int rowSize, int columnSize)
{
this.r = rowSize;
this.c = columnSize;
}
public void SetMatrix()
{
for (int i=0; i<this.r; i++)
{
for(int j=0; j<this.c; j++)
{
}
}
}
}
}
Without a finite size, I'm not sure how to proceed with creating the array (the 10,10 was just so the compiler would stop complaining). Secondly, when that's established, I'm not sure on how to fill in the array (most likely from the console). Hopefully my question doesn't sound too much like I'm asking for someone to do my homework for me. XD
First - you don't need a loop to initialize your matrix. Just declaring an int[r,c] will give you a 2d array filled with zeros. Your description doesn't say a zero argument constructor is required, so I wouldn't provide one, it's not clear how it should behave anyway. So just create one constructor like this:
public Matrix(int rows, int cols)
{
r = rows;
c = cols;
array = new int[r,c]; // Note: this will be filled with zeros!
}
For setting entries you can just provide a method like this:
public void SetCell(int row, int col, int val)
{
array[row,col] = val;
}
Or you could even do something like this using an indexer:
public int this[int row, int col]
{
get { return array[row,col]; }
set { array[row,col] = value; } // You didn't ask for a setter, but I assume you'll need one
}
if I can get help with parts (b) and (c) I think I can do the rest.
Ok, good luck then
EDIT:
So to clarify, when you declare an array of int it will be initially filled with zeros. This is in contrast to c++ where it would be a random block of memory that will be filled with random junk and you would need to set to zero. The use of unassigned variables is one of the "problems" with c++ that c# aimed to fix. For example, if you run this code:
int[] arr = new int[10];
Console.WriteLine(string.Join(",",arr));
It will write 0,0,0,0,0,0,0,0,0,0 every single time.
For more info read here. In particular, this part:
Note If you do not initialize an array at the time of declaration, the array members are automatically initialized to the default initial value for the array type. Also, if you declare the array as a field of a type, it will be set to the default value null when you instantiate the type.
But note, if you do this:
int a;
Console.WriteLine(a);
You will actually get a compile time error complaining about the usage of an unassigned variable.