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.
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();
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..
I am trying to create an audio visualizer in the Unity game engine using C#.
I am also using the FMOD plugin which has functions for retrieving the audio spectrum of a playing sound (aka the volume of a sound across a range of frequencies).
FMOD returns this data as a struct containing a jagged array, with the first array being the audio channel (0 = left, 1 = right), and the second array being the volumes for each frequency range, being a float value between 0 and 1.
I need to copy the values in these arrays into my own arrays, for the purposes of altering and displaying the data. I am currently using a for-loop to iterate through the array and assign the values from the left and right channels to new arrays, as well as another array that finds the average volume:
private int SAMPLE_SIZE = 512;
private float[] spectrumLeft;
private float[] spectrumRight;
public float[] spectrumTotal;
void Start () {
spectrumLeft = new float[SAMPLE_SIZE];
spectrumRight = new float[SAMPLE_SIZE];
spectrumTotal = new float[SAMPLE_SIZE];
}
void Update () {
System.IntPtr data;
uint length;
result = spectrumFilter.getParameterData ((int)FMOD.DSP_FFT.SPECTRUMDATA, out data, out length);
FMOD.DSP_PARAMETER_FFT spectrumBuffer = new FMOD.DSP_PARAMETER_FFT ();
spectrumBuffer = (FMOD.DSP_PARAMETER_FFT) Marshal.PtrToStructure(data,typeof (FMOD.DSP_PARAMETER_FFT));
for (int i = 0; i < SAMPLE_SIZE; i++) {
spectrumLeft[i] = spectrumBuffer.spectrum[0][i];
spectrumRight[i] = spectrumBuffer.spectrum[1][i];
spectrumTotal[i] = (spectrumLeft[i] + spectrumRight[i]) / 2f;
}
}
THE PROBLEM: The code running in the for-loop above is incredibly slow (It maxes out my CPU core and causes the program to run slowly, when I comment out the contents of the loop the CPU usage is below 1%).
Since FMOD returns the data as a struct in this format I cannot change how I retrieve the data.
Is there a better/faster way of retrieving values from a struct?
Note that I am relatively new to C# and I may be missing something obvious
Ok, very simple fix I overlooked:
private int SAMPLE_SIZE = 512;
private float[][] spectrum;
public float[] spectrumTotal;
void Start () {
spectrum = new float[2][];
spectrum[0] = new float[SAMPLE_SIZE];
spectrum[1] = new float[SAMPLE_SIZE];
spectrumTotal = new float[SAMPLE_SIZE];
}
void Update () {
System.IntPtr data;
uint length;
result = spectrumFilter.getParameterData ((int)FMOD.DSP_FFT.SPECTRUMDATA, out data, out length);
FMOD.DSP_PARAMETER_FFT spectrumBuffer = new FMOD.DSP_PARAMETER_FFT ();
spectrumBuffer = (FMOD.DSP_PARAMETER_FFT) Marshal.PtrToStructure(data,typeof (FMOD.DSP_PARAMETER_FFT));
spectrum = spectrumBuffer.spectrum;
for (int i = 0; i < SAMPLE_SIZE; i++) {
spectrumTotal[i] = (spectrum[0][i] + spectrum[1][i]) / 2f;
}
}
Rather than iterating through the entire array and assigning each value one by one, I simply declared my own jagged array with the same size as the one in the struct and copied it all over in one go. Then I can loop through them and find the average volume.
I am however still interested in why it takes so much longer to get a value from an array in a struct, compared to just another local array. Will do some more research.
Silly mistake now that I see it but thanks, was amazed at how quickly people posted helpful responses.
Background -
I am new to programming in C# and am trying to code a custom indicator. On a trading platform that uses C#. A histogram with
positive Y axis = reqAskArraySum
negative Y axis = reqBidArraySum
The inbuilt compiler shows no errors. However the desired results do not seem to show up.
I know/it is possible there are some platform specific initialization problems i.e. code that I have not entered yet correctly.
Question -
The question here is with regards to the code posted below , which is a part of the whole code.
I would like to know whether the posted code satisfies the below objectives.
The objective here is to get a 'number' using a method.
Then only accept selected 'numbers' into an array. The selection/filtration is done by an 'If' statement
Any help and pointers would be highly appreciated.
int i=0;
double iAskSize = GetLevel2Size(ASK,0); //GetLevel2Size(ASK,0) is the method that helps me to retrieve the ASK side 'numbers'//
double iBidSize = GetLevel2Size(BID,0); //GetLevel2Size(BID,0) is the method that helps me to retrieve the BID side 'numbers' //
if(iAskSize>=AskTH_value) //the number should be >= user defined AskTH_value, this is the filtration of the Ask Side 'numbers'//
I am trying to get the filtered iAskSize 'numbers' into the array
reqAskSize, I believe there is a problem here. However I am not sure
{
double[] reqAskSize = new double[1000];
double reqAskArraySum = 0;
for(i=0;i<reqAskSize.Length;i++)
{
reqAskArraySum = reqAskArraySum + reqAskSize[i];
}
SetValue(0,reqAskArraySum);
}
if(iBidSize>=BidTH_value) **//the number should be >= user defined BidTH_value,this is the filtration of the Bid Side 'numbers'//**
I am trying to get the filtered iBidSize 'numbers' into the array
reqBidSize, I believe there is a problem here. However I am not sure
{
double[] reqBidSize = new double[1000];
double reqBidArraySum = 0;
for(i=0;i<reqBidSize.Length;i++)
{
reqBidArraySum = reqBidArraySum + reqBidSize[i];
}
SetValue(1,-reqBidArraySum);
}
If you are trying to add selected numbers into an array, once a number has been selected (through a conditional like if/else), the number should be set in the array.
For example
int[] array = new int[6];
for(int val = 0; val < 6; val++)
{
if(array[val] > 0)
array[val] = 6;
}
Also to obtain a numeral, a return statement makes clear if anything is got.
You should try and see where a return statement may belong within your code.
Basically I have x amount of matrices I need to establish of y by y size. I was hoping to name the matrices: matrixnumber1 matrixnumber2..matrixnumbern
I cannot use an array as its matrices I have to form.
Is it possible to use a string to name a string (or a matrix in this case)?
Thank you in advance for any help on this!
for (int i = 1; i <= numberofmatricesrequired; i++)
{
string number = Convert.ToString(i);
Matrix (matrixnumber+number) = new Matrix(matrixsize, matrixsize);
}
You can achieve a similar effect by creating an array of Matrices and storing each Matrix in there.
For example:
Matrix[] matrices = new Matrix[numberofmatricesrequired];
for (int i = 0; i < numberofmatricesrequired; i++)
{
matrices[i] = new Matrix(matrixsize, matrixsize);
}
This will store a bunch of uniques matrices in the array.
If you really want to you could create a Dictionary<String, Matrix> to hold the matrices you create. The string is the name - created however you like.
You can then retrieve the matrix by using dict["matrix1"] (or whatever you've called it).
However an array if you have a predetermined number would be far simpler and you can refer to which ever you want via it's index:
Matrix theOne = matrix[index];
If you have a variable number a List<Matrix> would be simpler and if you always added to the end you could still refer to individual ones by its index.
I'm curious why you cannot use an array or a List, as it seems like either of those are exactly what you need.
Matrix[] matrices = new Matrix[numberofmatricesrequired];
for (int i = 0; i < matrices.Length; i++)
{
matrices[i] = new Matrix(matrixsize, matrixsize);
}
If you really want to use a string, then you could use a Dictionary<string, Matrix>, but given your naming scheme it seems like an index-based mechanism (ie. array or List) is better suited. Nonetheless, in the spirit of being comprehensive...
Dictionary<string, Matrix> matrices = new Dictionary<string, Matrix>();
for (int i = 1; i <= numberofmatricesrequired; i++)
{
matrices.Add("Matrix" + i.ToString(), new Matrix(matrixsize, matrixsize));
}