Unity 5 2DArray, Object pooling - c#

Im trying to make a object pooling system for my WaveSpawner.
This is what I got (objectPool is a 2D array):
objectPool = new GameObject[wave.Length,0];
//set columns
for(int i = 0;i< objectPool.Length;i++)
{
objectPool = new GameObject[i,wave[i].numberToSpawn]; //set row for ech column
}
for (int p = 0; p < wave.Length; p++)
{
for(int i = 0;i<wave[p].numberToSpawn;i++)
{
GameObject gbj = Instantiate(wave[p].spawnObject);
gbj.transform.position = RandomizePositions();
gbj.SetActive(false);
objectPool[p,i]= gbj; //fill 2D array
}
}
Thats the Error I got;
Array index is out of range.

objectPool = new GameObject[wave.Length,0];
You're creating the array with a size of 0 in the second dimension.

objectPool = new GameObject[wave.Length,0];
Second dimension has size 0
for(int i = 0;i< objectPool.Length;i++)
Length return the size of all dimension, use array.GetLength();
You should read how to use 2d dimension array
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/multidimensional-arrays

Related

Getting a 1D array from a 3D array C#

I have a 8x8x3 array with some values. What I want to do is make a list of just the 1D arrays.
What I've got so far:
int[] packIt(int[,,] data, int factor) {
List<int[]> toReturn = new List<int[]>();
int[] test = data[0, 0];
So unless I'm missing something, I make a list of one dimensional arrays and try to fit in the one dimensional array at data[0, 0] (the test is just a placeholder so far). The error I'm getting is "Wrong number of indices", however if I follow the data[0,0,0] (which gives no error) I'll just get the 1 value at the location. I could do it manually, but am just wondering if there is an implementation for the functionality that I'm trying to do, as I will be using it a lot. Thanks a bunch.
You don't need to do anything specific to turn a 3D array into a 1D one; you can just enumerate it:
foreach(var x in multiDim)
...
This will print 1 to 8:
var x = new int[2,2,2];
x[0,0,0] = 1;
x[0,0,1] = 2;
x[0,1,0] = 3;
x[0,1,1] = 4;
x[1,0,0] = 5;
x[1,0,1] = 6;
x[1,1,0] = 7;
x[1,1,1] = 8;
foreach(int i in x)
Console.WriteLine(i);
To this end you can just straight enumerate your array in chunks of whatever:
var out = new List<int[]>();
var arr = new int[chunkSize];
out.Add(arr);
var idx = 0;
foreach(var x in miltiDimArray){
if(idx == chunkSize){
out.Add(arr = new int[chunkSize]);
idx = 0;
}
arr[idx++] = i;
}
Note that I don't try to make the ticks array smaller if the chunk size doesn't divide into the number of elements. idx will have a residual value you can use to work out what to resize the last array by if that is important

Storing arrays withing arrays in C#

I'm working on a project right now that requires me to work with and store millions of different doubles. So I figure the most effective way to store all of these values would be in sets of arrays within arrays. but i have no idea how to do this. Plus i have to feed values into the lower level arrays and don't yet know an effective way of doing this.
The below is an attempt at explaining what I'm going for (This is not code, but the website thought it was):
L01 = [1,2,3]
L02 = [3,2,1]
L03 = [2,3,1]
L04 = [1,3,2]
L11 = [L01,L02]
L12 = [L03,L04]
L2 = [L11,L12]
So far I have only come up with this, and you should see why it doesn't work. I'm still pretty new to programming so please explain what I should be doing:
//Stores the weight values attached to an individual neuron
public double[] NeuronWeights = new double[321];
//Stores the NeuronWeights[] for an individual layer with incoming weights
public double[][] LayerWeight = new double[321][];
//Stores all of the LayerWeight[] in the network
public double[][][] TotalWeights = new double[11][][];
public void InitializWeights()
{
for (int i = 0; i < TotalWeights.Length; i++)
{
for(int j = 0; j < LayerWeight.Length; j++)
{
for(int k = 0; k < NeuronWeights.Length; k++)
{
Random r = new Random();
//Creating randome values to fill first level
if (r.Next(0, 2) > 0)
{
NeuronWeights[k] = r.NextDouble() * 2 - 1;
}
else NeuronWeights[k] = 0.0;
}
LayerWeight[j][] = NeuronWeights[];
}
TotalWeights[i][][] = LayerWeight[][];
}
}
}
To add more detail; I'm trying to generate and store 321 doubles ,within the range of (-1, 1), 321 time per "layer". Then do that for all 11 "layers". this information then needs to be called on to assign values for 321 other doubles, 11 times.
Multi-dimensional arrays are not the same as arrays of arrays. Try using List<> instead:
var L01 = new List<int> { 1,2,3 };
var L02 = new List<int> { 3,2,1 };
var L03 = new List<int> { 2,3,1 };
var L04 = new List<int> { 1,3,2 };
var L11 = new List<List<int>> { L01,L02 };
var L12 = new List<List<int>> { L03,L04 };
var L2 = new List<List<List<int>>> { L11,L12 };
But depending on what you are trying to accomplish, maybe you don't need to nest your Lists like that.
It looks like you are trying to create a structure where there are 11 layers, each with 321 neuron weights? That doesn't seem to make sense with your initial goal of storing and working with millions of doubles.
If you simply wanted to store a variable number of layers, each with a variable number of recorded weights, you'd set up something like this:
List<List<double>> weightData = new List<List<double>>();
You can think of a List as a variable-sized array that is expandable as you are going along in your process. So for each Layer, you'd
List<double> currentLayer = new List<double>();
weightData.add(currentLayer);
Then for each weight you wanted to add to the layer you'd do something like:
double neuronWeight = 17.0;
currentLayer.add(neuronWeight);
at the end of the day, weightData will have all your layers and weights within the layers. If you plan to manipulate the data after loading it, you will need to come up with a scheme to reference the various layers and weights, but I'm not sure what your use case for that is.
Good luck!
What about something like this, which uses one multi-dimensional array?
int totalWeightLength = 11;
int layerWeightLength = 321;
int neuronWeights = 321;
double[,,] TotalWeights = new double[totalWeightLength, layerWeightLength, neuronWeights];
void InitializWeights()
{
for (int i = 0; i < totalWeightLength; i++)
{
for (int j = 0; j < layerWeightLength; j++)
{
for (int k = 0; k < neuronWeights; k++)
{
Random r = new Random();
//Creating randome values to fill first level
if (r.Next(0, 2) > 0)
{
TotalWeights[i,j,k] = r.NextDouble() * 2 - 1;
}
else TotalWeights[i,j,k] = 0.0;
}
}
}
}
InitializWeights();
Console.WriteLine(TotalWeights[1,34,23]);
Console.WriteLine(TotalWeights[2,84,123]);
Console.WriteLine(TotalWeights[3,39,24]);
Console.WriteLine(TotalWeights[4,27,36]);

(C#) How to fill a 2D array with 2 different numbers evenly, but randomly?

For a randomized tic-tac-toe game simulator, I need to utilize a 2D array to simulate a round between 2 players. To fill the array, I've been using a simple randomizer to generate a random number between 0 and 1.
//create 2D array
const int ROWS = 3;
const int COLS = 3;
int[,] tictactoeArray = new int[ROWS, COLS];
//create random variable
Random rand = new Random();
//method to fill array with random values between 0 and 1.
private void RandomizeArray(ref int[,] iArray)
{
for (int row = 0; row < ROWS; row++)
{
for (int col = 0; col < COLS; col++)
{
tictactoeArray[row, col] = rand.Next(2);
}
}
}
But when I use a random number generator like this, I occasionally end up with an impossible combination of values in relation to tic-tac-toe. As in the value 1 will occur 6 or more times, and make the game unfair for the other "player". I've done extensive searching, but haven't found a way to (more or less) evenly distribute the 2 values. Any suggestions?
You need to simulate the turns of player. instead of randomly generating 1 or 2, you can follow the below algorithm only assume
0. initialize all 9 positions with 0 on tic-tac-toe board
1. select a number between 0 to 8 randomly. ( which denotes one of 9 positions)
2. put 1 in that position
3. select another number between 0 to 8 randomly ( if it collides with number previously selected pull other random number.
4. put 2 in that position.
5. repeat till all the 9 positions are filled.
Approach 2 ..
create a Linked list of 9 numbers (from 1 to 9).
draw a number (name it x) between 1 to size of the Set ( which will be 9 for first draw)
read the value at the position 'x' and put 1 in that position
remove the element at position x
draw another number x ( between 1 to 8 this time ) and put 2 in that position.
remove the element at position x.
keep doing till linked list is empty.
It seems simpler just to pre-create the x's and o's in a 1 dimensional array and then randomly shuffle them like so
//Both X and O always get at least 4 moves
List<int> common = new List<int> { 0, 0, 0, 0, 1, 1, 1, 1 };
//Either X or O gets a 5th move, make this equally likely
Random rand = new Random();
common.Add(rand.Next(0, 2));
//Randomly shuffle the X's and O's, this creates a completed tic tac toe board
//This can have more than one winner since we aren't stopping when someone wins
//as would normally be done
var randomBoard = common.OrderBy(x => rand.Next()).ToArray();
//Convert to a 2 dimensional array if desired
int[,] twoDRandomBoard = new int[3, 3];
for (int i = 0; i < randomBoard.Length; i++)
twoDRandomBoard[i / 3, i%3] = randomBoard[i];
You will end up with some boards having two "winners", but this is the way it has to be if you assume the entire board is full which is what you are showing in your question. If you want to stop once someone wins then that will be different, but this will work for a random complete board.
The literal answer to the question title would be something like this:
var random = new Random();
var randomValues = new[] { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 } // enough values to fill board
.Select(x => new { Weight = random.Next(), Value = x }) // add random weight
.OrderBy(x => x.Weight) // order by weight to create random sort
.Take(9) // only need 9 of the 10 values
.ToList();
var ticTacToeBoard = new int[3, 3];
var index = 0;
for (int row = 0; row < 3; row++) // fill the two-dimensional array
{
for (int column = 0; column < 3; column++)
{
ticTacToeBoard[row, column] = randomValues[index].Value;
index++;
}
}
Most of the time, this "random without replacement" technique will result in a possible ending game board, however, you'll occasionally get a game board with 3 zeroes and 3 ones in a row, which would not be valid. To solve that, you could put the above code in a loop and only exit the loop in the case of a valid game board.
That said, I agree that #meetthakkar's approach to actually simulate a game would more sense for this particular problem.
Okay, I might be a little confused but it doesn't make sense to have a tic-tac-toe board represented with 1 or 0 being populated from that start, maybe 1 or 2.
Would recommend doing the following :
private static ThreadLocal<Random> rand = new ThreadLocal<Random>(()=>new Random());
const int PLAYER_ONE = 1;
const int PLAYER_TWO = 2;
//color decided by who goes first in tic-tac-toe?
private static int playingColor;
private static void PlayRound(int[][] board)
{
var playableCoords = new List<Tuple<int,int>>();
for(int x=0;x<board.Length;x++)
for(int y=0;y<board[x].Length;y++)
if(board[x][y] == 0)
playableCoords.Add(Tuple.Create(x,y));
//check for a terminal board state before you do this method
if(!playableCoords.Any()) return;
var randm = rand.Value;
var vl = playableCoords[ randm.Next(playableCoords.Count - 1) ];
board[vl.Item1][vl.Item2] = playingColor ;
}
There are more efficient ways to do this, if you were dealing with a board with a lot of possible combinations then I would suggest keeping a record of available spots and taking from there, but for a 3x3 game don't see the need to do that.
If you want to do this until it is full just do this :
var board = new int[3][3];
for(int i=0;i<9;i++)
{
playingColor = (i%1)+1;
PlayRound(board);
}
Doesn't really make sense to me but that is how you would simulate a game.
void RandomizeArray(ref int[,] iArray)
{
for (int row = 0; row < ROWS; row++)
{
for (int col = 0; col < COLS; col++)
{
Random rand = new Random();
tictactoeArray[row, col] = rand.Next(2);
}
}
}
please put Random rand = new Random() into the funcion body.
Maybe better every times it make a new rand .

Create specific multidimensional array

I have an somewhat basic question regarding multidimensional arrays in C#.
Currently I have the following array:
float[] matrix = new float[16];
I need to create instead a 2D array with each line containing the previously mentioned 16 float numbers. Also, the number of lines in the 2D array is not known at the start of the program (i.e. it will be based on a variable).
How can I create such an array using an efficient data structure?
You could do something like this:
const Int32 arraySize = 16;
var list = new List<float[]>();
Which gives you an empty list containing zero elements (arrays) to start. As you need to add new arrays you would write this:
var array = new float[arraySize];
// do stuff to the array
And then add it to the list:
list.Add(array);
To store 16 float numbers, you could use a 4x4 matrix (which is a 4x4 2-dimensional array). For more details, check out this documentation.
// init the array
float[,] matrix = new float[4,4];
// loop through the array
for(int col = 0; col < matrix.GetLength(0); col++)
for(int row = 0; row < matrix.GetLength(1); row++)
Console.WriteLine(matrix[col, row]);
You can use multidimentional array syntax
float[,] arr2D = new float[12,12];
Alternatively, you could use a loop
float[][] floats = new float[12][];
for(int i=0; i< 12; i++)
{
floats[i] = new float[12];
}

C# Insert Array Values via for loop

Hello Everyone
What I am trying to do is call the "FillDeck" method to fill the "deck []" with 52 array elements. The for loop is used to add the elements - for testing purposes it is just adding the y+x values from the for loop.
What I did was use the variable "placement" to indicate my index position then increment the placement variable so for each loop iteration the index is increased thus adding an array element to that particular index. However, I get the IndexOutOfRangeException which is what I trying to figure out.
To note: I CANNOT automatically use predetermined values for the array, I must call a method which purpose is to add the values to the array. Since it is a card deck having a nested for loop to determine the rank / suit would be a good way to approach this.
Thanks =)
static void Main(string[] args)
{
int [] deck = {};
FillDeck(deck); // Error Here
}
public static void FillDeck(int[] deck)
{
int placement = 0;
// 0 = Ace , 12 = King : 0 = Hearts, 1 = Diamonds, 2 = Clubs, 3 = Spades
for (int x = 0; x < 13; x++)
for (int y = 0; x < 4; ++y)
{
deck[placement] = x + y;// Error here
++placement;
}
}
int [] deck = {}
This creates an array of size 0.
You can't put anything in it.
You need to write new int[52] (or other appropriate number) to create an array that can actually hold things.
Alternatively, you can create a List<T>, which can expand to any (reasonable) size by calling the Add() method.
Of course error there, array inited size is 0 means no element you can store in it.
hope code below can help you:
public static int[] FillDeck()
{
var deck = new List<int>();
// 0 = Ace , 12 = King : 0 = Hearts, 1 = Diamonds, 2 = Clubs, 3 = Spades
for (int x = 0; x < 13; x++)
for (int y = 0; x < 4; ++y)
{
deck.Add(x + y);
}
return deck.ToArray();
}

Categories

Resources