I know that they are used to store data, but I have a difficult time understanding exactly how to use them in a program.
In addition, I found this site with a tetris clone tutorial (the actual tutorial is missing). It uses arrays, but I can't really make sense of how it works.
Here's an example of the code -
public int[, ,] TShape = new int[4, 4, 2]
{
{{1, 0}, {0, 1}, {1, 1}, {2, 1}},
{{1, 0}, {0, 1}, {1, 1}, {1, 2}},
{{0, 0}, {1, 0}, {2, 0}, {1, 1}},
{{0, 0}, {0, 1}, {1, 1}, {0, 2}}};
Could it be that I'm looking too hard into this, or perhaps there's something I'm not grasping about it?
It would be clearer if formatted this way:
public int[, ,] TShape = new int[4, 4, 2]
{
{ {1, 0}, // <- this is int[2]
{0, 1},
{1, 1},
{2, 1} }, // <- the last four lines are an int[4,2]
{ {1, 0},
{0, 1},
{1, 1},
{1, 2} }, // <- another int[4,2]
{ {0, 0},
{1, 0},
{2, 0},
{1, 1} }, // <- third int[4,2]
{ {0, 0},
{0, 1},
{1, 1},
{0, 2} } // <- fourth and last int[4,2]
}; // <- The whole thing is int[4, 4, 2]
"Well I've been having a hard time
understanding how to use arrays. I
know they are used for storing data,
but I have yet to find any resource
that gives a clearer explanation than
that."
I'll try to give you an analogy: array is to programming like a file cabinet is to an office. The only difference is that a file cabinet is restricted to what it can hold: i.e. files... the only restriction for arrays is that it must hold items of the same type, but the actual type of the item can be nearly anything. Arrays can not only hold data, but objects, other arrays, other containers, etc.
So what can you do with an array in programming? Well a LOT of stuff! Let's look at several examples:
Financial: an array can hold the stock prices for today.
Gaming: an array can hold the 3D models that are used on a level.
Military: an array can hold all of the targets identified by a targeting system.
etc...
The main purpose of arrays is to contain various things and allow us to iterate over them. For example:
// Financial
int[] stockPrices = new int[4]{ 15, 14, 18, 16 }; // contains four prices
foreach( int price in stockPrices )
{
MakeTransaction(price);// calls a function that makes a transaction at the price: e.g. buy/sell
}
// Gaming
3DModel[] gameModels = new 3DModel[4]{ new Tank(), new Truck(), new Soldier(), new Building()}; // contains 3D models
foreach( 3DModel model in gameModels )
{
model.Draw();// calls a function of each 3DModel that draws the model on the screen
}
// Military
Target[] targets = new Target[4]{ new Tank(), new Helicopter(), new APC(), new Truck()}; // contains targets
foreach( Target target in targets )
{
Attack(target);// calls an attack function which initiates an attack on each target
}
The possibilities are endless! Arrays are a subset of containers and containers are an integral part of programming. Does that help?
Straight from the horse's mouth: http://msdn.microsoft.com/en-us/library/system.array.aspx
Those details will come in handy after you have gone through online tutorials such as this http://www.functionx.com/csharp/Lesson21.htm
Imagine you have 10 boxes. Now you want to clearly tell someone which box you are talking about. So you assign numbers to them, from 0 to 9. What you have now is an array of boxes, defined as:
box[ 10 ]
The number in the brackets tells you, how many of them are there. By default they are numbered from 0 to 9 (some languages allow to change this, but lets skip that for now). So if you are talking about the fifth box, its box[ 4 ] (since we index from 0!). Now imagine you open the box and see that there are five balls in it. This defines an array:
box[ 10 ][ 5 ]
A two dimensional array. How do you tell your friend which ball do you want to talk about? Again, you number them, this time from 0 to 4. How do you specify say the third ball in the seventh box? Simple: box[ 6 ][ 2 ]. And so on. Hope that helps.
In your question, you're stating the Tetris game which uses an array. That is a good use of arrays in whatever language you're using.
You have to see the Tetris play yard as the array. Let's say this play yard is a 20 spaces on the X axis, and 100 spaces on the Y axis. What tells you whether you have a piece on a space, is when you have the integer value 1, and you get an integer value of 0 for empty spaces. We then get:
var tetrisPlayYard = new int[20][100];
You now have to initialize each positions of the board to 0 in order to mark them as empty spaces, so no pieces have ever been placed already.
for(int xAxisIndex = 0; xAxisIndex < tetrisPlayYard.GetLength(0); ++xAxisIndex )
for (int yAxisIndex = 0; yAxisIndex < tetrisPlayYard.GetLength(1); ++ yAxisIndex)
tetrisPlayYard[xAxisIndex][yAxisIndex] = 0;
We now know that no pieces is on board as each array's positions are set to 0.
Then, when we place, let's say a four spaces straight line horizontally at the bottom-right of the board, we would then have to address 4 spaces, and set their values to 1 to indicate there is a piece on these spaces.
tetrisPlayYard[19][99] = 1;
tetrisPlayYard[18][99] = 1;
tetrisPlayYard[17][99] = 1;
tetrisPlayYard[16][99] = 1;
This tells that you have a four spaces straight line. Your algorithm should work around this logic to display the bars, the cubes, etc. while playing the game.
In conclusion, use arrays whenever a finite space is known, and that you know that it won't be required to resize it dynamically. Otherwise, a Collection should be used.
Related
I want to sort two-dimensional array. Instead of ordering for the first dimension I want to order the inner dimension.
For example if initial array is like this:
{{4, 1, 3},
{6, 5, 2},
{0, 9, 8}}
Then if we sort array by first row, result will be:
{{1, 3, 4},
{5, 2, 6},
{9, 8, 0}}
I managed doing this by transposing the array, ordering and transposing again. But is there a better way to do it?
Hmmmm this is a bit of an odd one and I actually misunderstood it at first. There are ways to do this but none of them that I can think of are really nice. Personally I think I would so something like
public class Matrix
{
private List<RowGroup> _groups;
public Matrix(List<List<int>> matrix)
{
//Removed for simplicity
}
public void SortMaxtrixByRow(int rowNumber)
{
this._groups.Sort((r1, r2) =>
{
return r1.Col[rowNumber].CompareTo(r2.Col[rowNumber]);
});
}
public class RowGroup
{
public List<int> Col;
public RowGroup(List<int> col)
{
Col = col;
}
}
}
This is doing something similar to your transposing. The main benefit would be that its an object so if you had to do multiple sorts on the same set it wouldn't need to re-transpose it over and over again.
Other than this you could copy the desired array and sort it then compare each value to the original to see how it moved and move the other rows accordingly but that is only assuming that you are using unique values in each row, writing your own sorting algorithm so you could be sure which index, or are okay with there being multiple "correct" answers.
What is the difference between these two:
string[,] array1;
and
string[][] array2;
Could someone please explain me about these two in terms of applications and functionality, memory management etc... how do you called them, which one is better to use? how to initialize them?
array1 is called a reference to a multidimensional array; array2 is a reference to a jagged array.
The first one is designed to store rectangular data which is not sparse and the number of elements in the dimensions are almost the same. You can initialize it like:
// Two-dimensional array.
int[,] array1= new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
In the latter case which is also called array of array the elements can be of different dimensions and sizes. Some times it is memory optimized to store sparse 2d data in the RAM. You can initialize it like:
int[][] array2= new int[][]
{
new int[] { 1, 3, 5, 7, 9 },
new int[] { 0, 2, 4, 6 },
new int[] { 11, 22 }
};
Absolutely the usage is depends on you requirements and purposes. You can review these 1, 2.
Let's say I have the following nested array:
[
[1, 2, 3],
[4, 7, 9, 13],
[1, 2],
[2, 3]
[12, 15, 16]
]
I only need the arrays with the most occurrences of the same numbers. In the above example this would be:
[
[1, 2, 3],
[4, 7, 9, 13],
[12, 15, 16]
]
How can I do this efficiently with C#?
EDIT
Indeed my question is really confusing. What I wanted to ask is: How can I eliminate sub-arrays if some bigger sub-array already contains all the elements of a smaller sub-array.
My current implementation of the problem is the following:
var allItems = new List<List<int>>{
new List<int>{1, 2, 3},
new List<int>{4, 7, 9, 13},
new List<int>{1, 2},
new List<int>{2, 3},
new List<int>{12, 15, 16}
};
var itemsToEliminate = new List<List<int>>();
for(var i = 0; i < allItems.ToList().Count; i++){
var current = allItems[i];
var itemsToVerify = allItems.Where(item => item != current).ToList();
foreach(var item in itemsToVerify){
bool containsSameNumbers = item.Intersect(current).Any();
if(containsSameNumbers && item.Count > current.Count){
itemsToEliminate.Add(current);
}
}
}
allItems.RemoveAll(item => itemsToEliminate.Contains(item));
foreach(var item in allItems){
Console.WriteLine(string.Join(", ", item));
}
This does work, but the nested loops for(var i = 0; i < allItems.ToList().Count; i++) and foreach(var item in itemsToVerify) gives it a bad performance. Especially if you know that the allItems array can contain about 10000000 rows.
I would remember the items that are already in the list.
First sort your lists by decreasing length, then check for each item if it's already present.
Given your algorithm, the array is not added if even a single integer is in the list already of known integers already.
Therefore I would use the following algorithm:
List<List<int>> allItems = new List<List<int>>{
new List<int>{1, 2, 3},
new List<int>{4, 7, 9, 13},
new List<int>{1, 2},
new List<int>{2, 3},
new List<int>{12, 15, 16}
};
allItems = allItems.OrderByDescending(x => x.Count()).ToList(); // order by length, decreasing order
List<List<int>> result = new List<List<int>>();
SortedSet<int> knownItems = new SortedSet<int>(); // keep track of numbers, so you don't have to loop arrays
// https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.sortedset-1?view=netframework-4.7.2
foreach (List<int> l in allItems)
{
// bool allUnique = true;
foreach (int elem in l)
{
if (knownItems.Contains(elem))
{
// allUnique = false;
break;
}
else
{
// OK, because duplicates not allowed in single list
// and because how the data is constrained (I still have my doubts about how the data is allowed to look and what special cases may pop up that ruin this, so use with care)
// this WILL cause problems if a list starts with any number which has not yet been provided appears before the first match that would cause the list to be discarded.
knownItems.Add(elem);
}
}
// see comment above near knownItems.Add()
/*
if (allUnique)
{
result.Add(l);
foreach (int elem in l)
{
knownItems.Add(elem);
}
}
*/
}
// output
foreach(List<int> item in result){
Console.WriteLine(string.Join(", ", item));
}
Instead of looping over your original array twice nestedly (O(n^2)), you only do it once (O(n)) and do a search in known numbers (binary search tree lookup: O(n*log2(n))).
Instead of removing from the array, you add to a new one. This uses more memory for the new array. The reordering is done because it is more likely that any subsequent array contains numbers already processed. However sorting a large amount of lists may be slower than the benefit you gain if you have many small lists. If you have even a few long ones, this may pay off.
Sorting your list of lists by the length is valid because
what is to happen if a list has items from different lists? say instead of new List{2, 3} it was new List{2, 4}?
That unexpected behavior. You can see the ints as an id of a person. Each group of ints forms, for example, a family. If the algorithm creates [2, 4], then we are creating, for example, an extramarital relationship. Which is not desirable.
From this I gather the arrays will contain subsets of at most only one other array or be unique. Therefore the Order is irrelevant.
This also assumes that at least one such array would contain all elements of such subsets (and therefore be the longest one and come first.)
The sorting could be removed if it were not so, and should probably be removed if in doubt.
For example:
{1, 2, 3, 4, 5} - contains all elements that future arrays will have subsets of
{1, 4, 5} - must contain no element that {1,2,3,4,5} does not contain
{1, 2, 6} - illegal in this case
{7, 8 ,9} - OK
{8, 9} - OK (will be ignored)
{7, 9} - OK (will be ignored, is only subset in {7,8,9})
{1, 7} - - illegal, but would be legal if {1,2,3,4,5,7,8,9} was in this list. because it is longer it would've been earlier, making this valid to ignore.
This is such a simple question, but I cannot find the answer.
What I am looking for is the lightweight way of enumerating through a list of integers without having to define a new array or list or something. The code shown below represents what I want to do, but it doesn't work.
var x = from z in [] {1, 19, 64, 128, 132}
select new {z, "asdffdghdfgh" };
The bit I need help with, without creating something horrible or another variable, is the {1, 19, .... } inline
Thanks
John
In order to do so you must still instantiate an array. This still allocates the object but you just don't have any reference to it after the query is executed.
// See addition of `new int[]`
var x = from z in new int[] { 1, 19, 64, 128, 132 }
select new { z, x = "someText" };
If you were creating a string[] then you wouldn't have to specify the string word before the [] but you would still have to write new [] {...}
I am currently making a Minesweeper clone.
I made an algorithm that, when clicked on a tile with 0 surrounding mines, reveals all neighbors with 0 surrounding mines then all neighbors of them with 0 surrounding mines... (recursion).
This result only needs one click:
It works like it should but it is too slow. The original Minesweeper reveals these tiles instantly, but in my case, they have a little delay between the reveals.
I wrote this code:
private void RevealNeighbor(int x, int y) {
foreach(var neighbor in _neighbors) {
try {
Tile tile = _tiles[x + neighbor[0], y + neighbor[1]];
if(tile.TileType == TileType.Empty && tile.Hidden) {
tile.Reveal();
if(tile.Number == 0) {
RevealNeighbor(x + neighbor[0], y + neighbor[1]);
}
}
}
catch(IndexOutOfRangeException) {
}
}
}
_neighbors is an array of arrays, that has the 8 position offsets for the neighbors:
private readonly int[][] _neighbors = new[] {
new[] {-1, -1},
new[] {0, -1},
new[] {1, -1},
new[] {1, 0},
new[] {1, 1},
new[] {0, 1},
new[] {-1, 1},
new[] {-1, 0}
};
How can I make it faster?
Use the SuspendLayout method, to draw only when needed:
*false is a default for the designer, find out what it means
this.SuspendLayout();
... logic
this.ResumeLayout(false);
ALSO - avoid abusing the Exceptions mechanism, it is not efficient and bad practice
instead use a wall (extra tile on the end of the matrix indicating.. well.. a wall).
I'm guessing RevealNeighbor actually redraws the Board. Instead, you should compute what is going to be revealed and only then redraw the Board.