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();
}
Related
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
I have set up a spreadsheet program with a 26 by 26 grid of cell objects. I set up a method which processes a formula entered by the user. The user can enter, for example, =A1+A2 and the method checks the values of cells A1 and A2 and adds them together. For some reason, the value of the second cell is not being assigned to the array.
https://pasteboard.co/IqRO23M.png
The code continues the switch case statement for other operators but that's not important for this problem.
public static void ProcessBasicFormula(Cell selectedCell,Cell[,]
cell,string[] cellsInUse, char operatorInUse)
{
int[] valueOfCell = new int[cellsInUse.Length]; //valueOfCell and
cellInUse have same length
int counter = 0;
double answer = 0.0;
switch(operatorInUse)
{
case ('+'):
for (int i = 0; i < cellsInUse.Length; i++)
{
for (int j = 0; j < cellsInUse.GetLength(0); j++)
{
for (int k = 0; k < cellsInUse.GetLength(0); k++)
{
if (cellsInUse[i] == cell[j, k].CellID)
{
valueOfCell[counter] =Convert.ToInt32(cell[j,k].Text);
counter++;
}
}
}
}
answer = valueOfCell[0] + valueOfCell[1];
break;
I expect the values of the two cells to be added together but instead, I am getting the first value added by 0.
my assumptions are:
the cellsInUse array length is accurate
List item the cell value at index 1 is not zero
the new int[int] will initialize the array to zeros;
int[] valueOfCell = new int[cellsInUse.Length];
cellsInUse is one dimensional array;
string[] cellsInUse
the getLength(0) of one dimensional array is the same as .length
cellsInUse.length == 2 is true;
cellsInUse.GetLength(0) == 2 is true;
so the j and k loops are looping to 2.
I am assuming the first cell value was lucky enough to be in first subset of [2,2] cells.
should the cellsInUse.GetLength(0) be cell.GetLength(0) => j and cell.GetLength(1) => k
There is a 2d grid for example 7(column)x16(row).
A total of 111 cells are obtained with an index from 0 to 111.
Along the perimeter of this grid are 7 numbers and 16 letters.
I want to refer to the index of each individual cell not by their number, but for example using the text field to send commands 1a, 2b, 3c, etc.
I introduced it so that the string element of the array - "numbers[0]" and "letters[0]" will be equal to the original cell of the grid with the number 0.
Then it turns out to associate the elements of the arrays with the grid index it will be necessary to add +1 to the string element "letters[0] -> letters[1]" in the case when the value of the grid row does not change, but the column changes (for example, 1a -> 1b).
And in this case, add +16 to the value of the previous row of the grid (1a -> 2a).
I tried to create two one-dimensional arrays "numbers[]" and "letters[]" with a cycle for, but I had a problem, and how to actually associate the data of this array with the cell index if I know the number of columns and rows of the grid.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GridsNL : MonoBehaviour {
public int indexCellStart;
private int countRow;
private int countColumn;
// Use this for initialization
void Start () {
Grid grid = Grid.instance;
countRow = grid.rowCount;
countColumn = grid.columnCount;
CreateArray();
}
// Update is called once per frame
void Update () {
}
public void CreateArray()
{
int[] numbers = new int[countRow];
for (int countRow = 0; countRow < numbers.Length; countRow++)
{
//Debug.Log(countRow);
}
string[] letters = new string[countColumn]
for (int countColumn = 0; countColumn < letters.Length;
countColumn++)
{
//Debug.Log(countColumn);
}
}
I understand that maybe I need to use some kind of cyclic construction inside an array.
I would either use a multidimensional array like e.g.
string[,] stringArray = new string[rowCount, columnCount];
which you later access e.g.
for(int r = 0; r < rowCount; r++)
{
for(int c = 0; c < columnCount; c++)
{
var certainValue = stringArray[r, c];
...
}
}
Or alternatively if you want a one dimensional array
string[] stringArray = new string[rowCount * columnCount];
And iterate over it like e.g.
for(int r = 0; r < rowCount; r++)
{
for(int c = 0; c < columnCount; c++)
{
var certainValue = stringArray[r * columnCount + c];
...
}
}
Those would not be accessed by something like 2c but it makes little sense in the end and you should stick to those int indexes instead ...
If you really want letters you might want to try e.g.
char someExampleChar = 'e'; // what you get from the InputField
int indexInt = (int) someExampleChar - (int) 'a';
which converts the char value to a 0 based index.
As a simple Extension method like
public static class CharExtensions
{
public static int ToIndex(this char character)
{
return (int) character - (int) 'a';
}
}
Then you can simply use
char someExampleChar = 'f';
int index = someExampleChar.ToIndex();
Typed on smartphone so no warranty but I hope the idea gets clear
This question already has answers here:
List items changes as I add new data... why?
(6 answers)
Closed 6 years ago.
I need to create a dynamically sized list that contains pairs of points for a window's form using C#. The list size will change depending on the data that is loaded.
A simplified version of my approach, to simply convey the problem, is as follows (in the real app, the for-loops will iterate over sizes dependent on loaded data):
int[,] dummyInt = new int[1, 2];
List<int[,]> test = new List<int[,]>();
for (int i = 0; i < 100; i++)
{
dummyInt[0, 0] = i;
for (int j = 0; j < 5; j++)
{
dummyInt[0, 1] = j;
test.Add(dummyInt);
}
}
//Show the values in the list for debugging
foreach (int[,] value in test)
{
MessageBox.Show(value.ToString("G"));
}
Using this approach, all 500 values in the list are [99,4].
What I was expecting/hoping to get was
value 1 [0,0]
value 2 [0,1]
...
value 500 [99,4]
Seems like the list is storing the actual variable, and then changing the value with every iteration of the for loop. How can I store just the value of dummyInt as a new object to the list?
I searched for this, but I'm not sure I know the appropriate vocabulary to nail down the search.
Your List object is storing reference to the dummyInt object. If you want to store different values in List you have to create new int array every time you are adding it to List.
Reference:
https://msdn.microsoft.com/en-gb/library/4d43ts61(v=vs.90).aspx
Firstly, you don't need a 2-dimensional array if you're just storing a pair of coordinates. The first coordinate can go in the first element of a 1-dimensional array, and the second coordinate can go in the second element of the array. Secondly, the Clone method can be used to make a copy of an array object if you want to force a separate copy of the whole array to exist.
int[] dummyInt = new int[2];
List<int[]> test = new List<int[]>();
for (int i = 0; i < 100; i++)
{
dummyInt[0] = i;
for (int j = 0; j < 5; j++)
{
dummyInt[1] = j;
test.Add((int[])dummyInt.Clone());
}
}
foreach (int[] value in test)
{
Console.WriteLine("({0},{1})", value[0], value[1]);
}
And finally, an array might not be the best way to store a pair of coordinates. You might want to use a tuple or make your own structure. If you use a Value type (struct) instead of a Reference type (class), you don't need to clone each one.
struct Pair
{
public int x;
public int y;
}
public class Test
{
public static void Main()
{
Pair dummyInt = new Pair();
List<Pair> test = new List<Pair>();
for (int i = 0; i < 100; i++)
{
dummyInt.x = i;
for (int j = 0; j < 5; j++)
{
dummyInt.y = j;
test.Add(dummyInt);
}
}
foreach (Pair value in test)
{
Console.WriteLine("({0},{1})", value.x, value.y);
}
}
}
Note how the result is different if you change the word struct at the beginning to class.
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 .