Reputation: 380
I've got a 2D array of int's in a console c# code (7X3 'cells'). The moment I create it, it is initialized with zeros.
I've got to change the value of only five 'cells' into 1, without changing the value of other 'cells'. I know it is a basic thing, but, as an absolute rookie in C#, I can't get it to work, no matter what cell I use. Can you help me?
Thanks in advance.
(Note: As I am a frequent user/contributer, I know it looks like a classic "Do my homework" question and I apologize, but as I'm really stuck on this weenie part (and the rest of my project is OK), I'd appreciate the help).
Upvotes: 2
Views: 618
Reputation: 6451
Here are two ways of solving this issue, the first one; called BruteForceRandomImplementation
is easy to implement and understand but quite slow once you attempt to mark a very large number of locations with 1s due to it's brute-force like usage of Random
till it fills enough locations.
/// <summary>
/// This method uses a random based algorithm to create a two-dimensional array of [height, width]
/// with exactly locationsToFind locations set to 1.
/// </summary>
/// <param name="height"></param>
/// <param name="width"></param>
/// <param name="locationsToFind"></param>
/// <returns></returns>
public int[,] BruteForceRandomImplementation(int height, int width, int locationsToFind)
{
var random = new Random();
locationsToFind = LimitLocationsToFindToMaxLocations(height, width, locationsToFind);
// Create our two-dimensional array.
var map = new int[height, width];
int locationsFound = 0;
// Randomly set positons to 1 untill we have set locationsToFind locations to 1.
while (locationsFound < locationsToFind)
{
// Get a random Y location - limit the max value to our height - 1.
var randomY = random.Next(height);
// Get a random X location - limit the max value to our width - 1.
var randomX = random.Next(width);
// Find another random location if this location is already set to 1.
if (map[randomY, randomX] == 1)
continue;
// Otherwise set our location to 1 and increment the number of locations we've found.
map[randomY, randomX] = 1;
locationsFound += 1;
}
return map;
}
With the following helper method to keep our locationsToFind
range sane:
/// <summary>
/// Limits the locationsToFind variable to the maximum available locations. This avoids attempting to
/// mark more locations than are available for our width and height.
/// </summary>
/// <param name="height"></param>
/// <param name="width"></param>
/// <param name="locationsToFind"></param>
/// <returns></returns>
public int LimitLocationsToFindToMaxLocations(int height, int width, int locationsToFind)
{
return Math.Min(locationsToFind, height * width);
}
My second implementation called ShuffleImplementation
is a lot faster when you are marking large numbers of unique locations. It creates a one-dimensional array, fills this with enough 1s to satisify your needs then shuffles this array using the Fisher-Yates shuffle to finally proceed to expand this one-dimensional array into a two-dimensional one:
/// <summary>
/// This method uses a shuffle based algorithm to create a two-dimensional array of [height, width]
/// with exactly locationsToFind locations set to 1.
/// </summary>
/// <param name="height"></param>
/// <param name="width"></param>
/// <param name="locationsToFind"></param>
/// <returns></returns>
public int[,] ShuffleImplementation(int height, int width, int locationsToFind)
{
locationsToFind = LimitLocationsToFindToMaxLocations(height, width, locationsToFind);
// Create a 1 dimensional array large enough to contain all our values.
var array = new int[height * width];
// Set locationToFind locations to 1.
for (int location = 0; location < locationsToFind; location++)
array[location] = 1;
// Shuffle our array.
Shuffle(array);
// Now let's create our two-dimensional array.
var map = new int[height, width];
int index = 0;
// Expand our one-dimensional array into a two-dimensional one.
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
map[y, x] = array[index];
index++;
}
}
return map;
}
/// <summary>
/// Shuffles a one-dimensional array using the Fisher-Yates shuffle.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="arr"></param>
public static void Shuffle<T>(T[] array)
{
var random = new Random();
for (int i = array.Length - 1; i > 0; i--)
{
int n = random.Next(i + 1);
Swap(ref array[i], ref array[n]);
}
}
/// <summary>
/// Swaps two values around.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="valueA"></param>
/// <param name="valueB"></param>
public static void Swap<T>(ref T valueA, ref T valueB)
{
T tempValue = valueA;
valueA = valueB;
valueB = tempValue;
}
Usage:
var map = BruteForceRandomImplementation(7, 3, 5);
Or:
var map = ShuffleImplementation(7, 3, 5);
Depending on which one you want to use. For a good example of the performance difference between the two, try:
int width = 1000;
int height = 1000;
int locationsToFind = (width * height) - 1;
var stopwatch = new Stopwatch();
stopwatch.Start();
BruteForceRandomImplementation(height, width, locationsToFind);
stopwatch.Stop();
Console.WriteLine(string.Format("BruteForceRandomImplementation took {0}ms", stopwatch.ElapsedMilliseconds));
stopwatch.Restart();
ShuffleImplementation(height, width, locationsToFind);
stopwatch.Stop();
Console.WriteLine(string.Format("ShuffleImplementation took {0}ms", stopwatch.ElapsedMilliseconds));
On my laptop BruteForceRandomImplementation took 1205ms and ShuffleImplementation took 67ms or nearly 18x faster.
Upvotes: 8
Reputation: 107536
So you've defined a multi-dimensional array (basically a matrix):
int[,] cells = new int[7,3];
And then you initialize all of the values to 0.
To change a value, you should be able to do it like this, for example:
cells[3,2] = 1;
Is that what you've tried? Are you receiving any exceptions or warnings?
If you're using jagged arrays (arrays of arrays), then it might be like:
int[][] cells = new int[7][3];
And then you can set values:
cells[3][2] = 1;
Upvotes: 3
Reputation: 36082
var array = new int[7,3];
array[5,2] = 1;
array[3,2] = 1;
Keep in mind that the array indices are zero-based, so the valid range of int[7,3] is [0..6,0..2]
Upvotes: 1