i want to save kingarray[x1+1,y1-1],king array[x1+1,y1],etc in an array(ways that king in chess game can go).how can i do it?or if its not possible what do you suggest me to keep the ways that king can go?thanks
int[,] kingarray = new int[8, 8];
for (i = 0; i < 1; i++)
{
return kingarray[x1 + 1, y1];
}
for (i = 1; i > 0; i--)
{
return kingarray[x1 - 1, y1];
}
for (j = 0; j < 1; j++)
{
return kingarray[x1, y1 + 1];
}
for (j = 1; j > 0; j--)
{
return kingarray[x1, y1 - 1];
}
for (i = 0; i < 1; i++)
for (j = 1; j > 0; j--)
{
return kingarray[x1 + 1, y1 - 1];
}
for (i = 1; i > 0; i--)
for (j = 0; j < 1; j++)
{
return kingarray[x1 - 1, y1 + 1];
}
for (i = 0; i < 1; i++)
for (j = 0; j < 1; j++)
{
return kingarray[x1 + 1, y1 + 1];
}
for (i = 1; i > 0; i--)
for (j = 1; j > 0; j--)
{
return kingarray[x1 - 1, y1 - 1];
}
what do you suggest me to keep the ways that king can go?
This may not answer your question directly, and that you have already marked the correct answer. But just to answer the above.
Rather than keeping the all the positions a king can go, I would keep the positions it is allowed to go and calculate the possible routes during run-time.
For any piece(King, Pawn, etc), there are 8 places that it can move. Left, right, up, down, top-left, top-right, bottom-left, bottom-right. Based upon the type of piece, you can control the movement.
For You can create a ChessPiece class. Declare 8 positional flags, bool flags probably, that would define the possible positions that a piece can move.
Declare the number of blocks a piece can skip, for instance directions(; and drive the types from the ChessPiece and allow.
--EDIT--
For instance, following:
//Class that contains the position of the Piece over the Tile
class PiecePosition
{
//Set the bounds an image/vector can move.
public int X, Y;
public PiecePosition(int x, int y) { this.X = x; this.Y = y; }
public PiecePosition(int x, int y, int width, int height) { this.X = x; this.Y = y; }
}
//Base ChessPeice class that shall be used to drive all types of chess pieces.
//Sixteen pieces: one king, one queen, two rooks, two knights, two bishops, and eight pawns
//http://en.wikipedia.org/wiki/Chess
abstract class ChessPiece
{
public object Image;//This is an "optional" object that contains the Picture of the Peice,
//alternatively, it may contain vector of the image that you want
//to draw. Right now this is object is here just for the sake of
//understanding that you can use this object here to Draw() it
//based upon its position.
//Possible movements of the unhindered piece=8
protected const int MaxDirectionsCount = 8;
public enum PieceType { King, Pawn, SomeOtherType }//Types of chess peice.
public enum Moves { Up, Down, Left, Right, TopLeft, Etc }//Possible positions a piece can move
protected PieceType Type; //Contains type of piece
protected Moves MoveableDirections;//Shall contain the allowable directions
public List<PiecePosition> listPositions;//List of possible positions to be calculated during runtime
//Defines a piece can skip
protected int SkippableBlocks;
public abstract void PossiblePositions(PiecePosition CurrentPosition);//Calculates possible positions
public abstract void Draw();//Draws the piece
}
//The King Chess piece
//http://en.wikipedia.org/wiki/King_%28chess%29
class King : ChessPiece
{
//Constructor that sets the type of piece
public King()
{
//Set the directions a King can move.
base.MoveableDirections = Moves.Down | Moves.Left | Moves.Right;
base.Type = PieceType.King;
SkippableBlocks = 1; //Max a king can move is one block in the base.Directions set above.
}
//Calculates possible available positions to move to, during runtime; based upon current position.
public override void PossiblePositions(PiecePosition CurrentPosition)
{
//Calculate position
//Since you know this is king piece, you can calculate the possible positions
//And add that the list of possible positions.
//For instance, a King can move
int X = 0; int Y = 0;
for (int i = 0; i < MaxDirectionsCount; i++)
{
//Calculate directions.
if (base.MoveableDirections == Moves.Down) { X = CurrentPosition.X - 1; Y = CurrentPosition.Y; }
if (base.MoveableDirections == Moves.Up) { X = CurrentPosition.X + 1; Y = CurrentPosition.Y; }
//Rest of the directions go here...
//...Btw, what would you do for cross directions?
//One way could be to pass a Rectangle in the ChessTile(x,y,width,height) constructor
//Add to list of possible directions.
listPositions.Add(new PiecePosition(X, Y));
}
}
public override void Draw()
{
//You can actually draw/redraw using the Image object
//based upon the current/moved position.
}
}
Btw, if you just started writing the code, I would suggest you stop. Look around for Chess class designs first, and see if you want make sense out of Chess Objects. For instance, ChessBoard, Game, Players, Piece, Movements, AllowablePositions, etc.
Take a look at questions related to Chess/Google abit, and see if the questions/answers and your logic is already inline.
Array?
It is rather easy to determine a King's possible movement.
class position { public int x, y }
...
public ArrayList<position> KingPossibleMove(position current)
{
var list = new ArrayList();
if (current.x>0) {
list.add(new position() { x= current.x - 1, y = current.y });
if (current.x<8) {
list.add(new position() { x= current.x + 1, y = current.y });
// The rest follows, try to determine if the move is within bound
// you can also look for if the move will cause immediate checkmate.
return list;
}
int[,][] declares a 1D array containing a 2D array of int. Is that what you want?
And the kingmoves can simply be calculated as:
IEnumerable<Position> ValidKingTargets(Position p)
{
int top=Math.Max(0,y-1);
int left=Math.Max(0,x-1);
int bottom=Math.Min(8,y+2);
int right=Math.Min(8,x+2);
for(int y=top;y<bottom;y++)
for(int x=left;x<right;x++)
if(x!=p.X || y!=p.Y)
yield return new Position(x,y);
}
Related
So basically, I have a list with 2 of each number and I want to randomly assign one of those numbers to each card that gets instantiated. It's for a puzzle memory game where u find the matches.
The game is working fine when I have 2 gridRows and 4 gridCols, but if I change the amount of rows or cols then I get: ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index, which prevents me from expanding the game. I tried adding additional numbers to the current list, but that didn't seem to work and also this way doesn't seem very efficient if I want to have a lot of rows and columns
What I want to do is take a list, then shuffle its contents every time I start a match, and then to loop through the indices in order(contents already shuffled) when I instantiate, that's my logic but couldn't make it work for some reason....
can someone help me expand this and find a better way of storing the index please?
here is the code:
public const int gridRows = 2;
public const int gridCols = 4;
public const float offsetX = 4f;
public const float offsetY = 5f;
public MainCard originalCard;
public Sprite[] images;
private void Start()
{
Vector3 startPos = originalCard.transform.position;
List<int> numbers = new List<int> { 0, 0, 1, 1, 2, 2, 3, 3 };
numbers = Shuffle(numbers);
for (int i = 0; i < gridCols; i++)
{
for (int x = 0; x < gridRows; x++)
{
MainCard card;
if (i == 0 && x == 0)
{
card = originalCard;
}
else
{
card = Instantiate(originalCard) as MainCard;
}
int index = x * gridCols + i;
int id = numbers[index];
card.ChangeSprite(id, images[id]);
float posX = (offsetX * i) + startPos.x;
float posY = (offsetX * x) + startPos.y;
card.transform.position = new Vector3(posX, posY, startPos.z);
}
}
List<T> Shuffle<T>(List<T> cards)
{
for (int i = 0; i < cards.Count; i++)
{
T temp = cards[i];
int randomIndex = Random.Range(i, cards.Count);
cards[i] = cards[randomIndex];
cards[randomIndex] = temp;
}
return cards;
}
}
}
One solution is to cut your project in more parts:
using System.Linq;//to Add
public int gridRows = 2;
public int gridCols = 4;
public List<int> numbers;
public void Start()
{
int[,] cards = new int[gridRows, gridCols];
//just put different numbers not needed to duplicate
//except if you want to increase the probability
// to have lot of same number
numbers = new List<int> { 0, 1, 2, 3 };
InitializeGame(cards);
}
private void InitializeGame(int[,] cards)
{
//1 you could shuffle your number if you want
//numbers = Shuffle(numbers);
//2 you initialize cards to value not used (-1 here)
for (int r = 0; r < gridRows; r++)
{
for (int c = 0; c < gridCols; c++)
{
cards[r, c] = -1;
}
}
// Test if you have filled up all cards
//Is there again one card with the value -1?
while (cards.Cast<int>().Any(x => x == -1))
{
//3 you pick randomnly a number
var numCard = numbers[Random.Range(0, numbers.Count)];
//4 you fill same number to 2 different cards here
var nbcardTofill = 2;
while (nbcardTofill != 0)
{
//you choose randomny card (row and col) which is free (value = -1) not need but add fun
var colRandom = Random.Range(0, gridCols);
var rowRandom = Random.Range(0, gridRows);
if(cards[rowRandom, colRandom] == -1)
{
nbcardTofill--;
cards[rowRandom, colRandom] = numCard;
}
}
}
}
now you have the array cards filled with numbers, you could draw the game now..
so you could change number of cols/rows and the list of numbers as you want...
is just one way to program, but i think ist more readable. i have add lot of randomization to add fun...
Another way is to fill sequentially your cards (2 by 2 with same number) and do a shuffle of all cards at the end...
I'd suggest changing your loop to iterate over the shuffled numbers rather than the expected grid size. If there aren't enough cards, as it were, some will be left out at the "end" of the grid.
You can then use division and remainder to figure out the correct grid X/Y coordinates for a given card index.
for (int i = 0; i < numbers.Length; i++) {
int y = Math.Floor(i / gridCols); // the floor is likely redundant but drives the point home
int x = i % gridCols;
var card = (i == 0 ? originalCard : Instantiate(originalCard) as MainCard);
int id = numbers[i];
card.ChangeSprite(id, images[id]);
float posX = (offsetX * y) + startPos.x;
float posY = (offsetY * x) + startPos.y;
card.transform.position = new Vector3(posX, posY, startPos.z);
}
EDIT: Nevermind, as someone said in a comment Random.Range is exclusive with integers
I don't know at all if this could be causing your problem, but I noticed that in your Shuffle method you have this line:
int randomIndex = Random.Range(i, cards.Count);
In my opinion this could cause an error because the max value in Random.Range is inclusive, so it might be possible that you are generating an unvalid index for some cards.
For example, if you had a list with 5 cards, the maximum index that you would like to generate would be 4, not 5 (which would be the Count).
I would try changing that line to this:
int randomIndex = Random.Range(i, cards.Count-1);
EDIT: I ended up using the FastNoise library found here: https://github.com/Auburns/FastNoise It has everything under the sun which someone might need to generate many different kinds of noise. As the title might suggest its also quite fast!
I'm creating a 2D infinitely, procedural generated world. I load and unload chunks from disc as the player moves. I'm using a cellular automata function to define how local tiles within each chunk are designed but I need noise (Perlin in this case) to define what biome type each chunk will be as new ones are created. I understand how I would translate decimals between 0 and 1 to represent this, my only issue is that the tutorial I followed on creating Perlin noise requires that you pass it a predefined 2d array and returns a noise array of the same size. Because my world grows dynamically I'm a bit confused on how I would use a fixed sized array to designate new chunk types.
Other answers I've seen don't cover exactly how to handle the infinite part of noise generation. My best guess is that I need to somehow generate or expand the noise with each newly created chunk although how I do this stumps me.
Here is some code I translated to C# from here: http://devmag.org.za/2009/04/25/perlin-noise/
admittedly some of the math here I don't fully understand yet, especially the bitwise function!
public class PerlinNoiseGenerator
{
public int OctaveCount { get; set; }
public float Persistence { get; set; }
public PerlinNoiseGenerator(int octaveCount, float persistence)
{
this.OctaveCount = octaveCount;
this.Persistence = persistence;
}
public float[,] GenerateWhiteNoise(int width, int height)
{
float[,] noiseFieldToReturn = new float[width, height];
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
noiseFieldToReturn[i, j] = (float)Game1.Utility.RGenerator.NextDouble() % 1;
}
}
return noiseFieldToReturn;
}
public float[,] SmoothNoiseField(float[,] whiteNoise, int octave)
{
int width = whiteNoise.GetLength(0);
int height = whiteNoise.GetLength(1);
float[,] smoothField = new float[width, height];
int samplePeriod = 1 << octave;
float sampleFrequency = 1.0f / samplePeriod;
for(int i =0; i < width; i++)
{
int samplei0 = (i / samplePeriod) * samplePeriod;
int samplei1 = (samplei0 + samplePeriod) % width;
float horizontalBlend = (i - samplei0) * sampleFrequency;
for(int j =0; j < height; j++)
{
int samplej0 = (j/samplePeriod) * samplePeriod;
int samplej1 = (samplej0 + samplePeriod) % height;
float verticalBlend = (j - samplej0) * sampleFrequency;
float top = LinearInterpolate(whiteNoise[samplei0, samplej0],
whiteNoise[samplei1, samplej0], horizontalBlend);
float bottom = LinearInterpolate(whiteNoise[samplei0, samplej1],
whiteNoise[samplei1, samplej1], horizontalBlend);
smoothField[i, j] = LinearInterpolate(top, bottom, verticalBlend);
}
}
return smoothField;
}
public float[,] GeneratePerlinNoise(float[,] baseNoise, int octaveCount)
{
int width = baseNoise.GetLength(0);
int height = baseNoise.GetLength(1);
float[][,] smoothNoise = new float[octaveCount][,];
float persistance = .5f;
for(int i =0; i < octaveCount;i++)
{
smoothNoise[i] = SmoothNoiseField(baseNoise, i);
}
float[,] perlinNoise = new float[width, height];
float amplitude = 1f;
float totalAmplitude = 0.0f;
for(int octave = octaveCount - 1; octave > 0; octave-- )
{
amplitude *= persistance;
totalAmplitude += amplitude;
for(int i =0; i < width;i++)
{
for(int j =0; j < height; j++)
{
perlinNoise[i, j] += smoothNoise[octave][i, j] * amplitude;
}
}
}
for(int i =0; i < width; i++)
{
for(int j =0; j < height; j++)
{
perlinNoise[i, j] /= totalAmplitude;
}
}
return perlinNoise;
}
public float LinearInterpolate(float a, float b, float alpha)
{
return a * (1 - alpha) + alpha * b;
}
}
This code should compile and produces a FIXED size array of noise
The main thing you want to make sure is that the starting random noise is pseudo random, so you always have a "fixed random value" for a coordinate.
It might be that you'd have to rewrite your random noise generator, using the coordinates as input. I imagine your maps have a random seed number, so you could use this post as a starting point, adding 1 factor:
A pseudo-random number generator based on 2 inputs
For a bit of inspiration for your map making, I wrote this article a while back: https://steemit.com/map/#beeheap/create-a-fantasy-grid-map-in-excel
Added after your comment: the only function you'd need to change is the GenerateWhiteNoise one. I don't speak C#, but this is the general idea:
GenerateWhiteNoise(int x_start_coord, int y_start_coord, int random_seed) {
int default_x_width = 100;
int default_y_heigth = 50;
float[,] noiseFieldToReturn = new float[width, height];
for (in x = x_start_coord; i < default_x_width + x_start_coord; x++)
{
for (in y = y_start_coord; i < default_y_width + y_start_coord; y++)
{
noiseFieldToReturn[i, j] = (float)pseudo_rnd_value(x, y, random_seed);
}
}
return noiseFieldToReturn;
}
That should give you the pseudo random values you need to build your map tiles, the only thing you need is the coordinate of the player (x and y).
I was trying to build a Pathfinding A* code, but keep getting an Array Index error. I have tried tweaking with the x and y, but no luck so far.
Here is the code.
public int columns = 9; //Columns and rows to set up the board
public int rows = 9; //This number are the usable tiles, the complete board is 11 by 11
//With a border of 1 tile
public Node[,] graph;
//Class Node
public class Node
{
public List<Node> neighbours; //List of all the neighbours nodes (4Directions)
public Node()
{
neighbours = new List<Node>();
}
}
//Sets up the outer walls and floor (background) of the game board.
void BoardSetup()
{
for (int x = -1; x < columns + 1; x++)
{
for (int y = -1; y < rows + 1; y++)
{
Edited out Code, don't think has anything to do with my problem.
}
}
}
//Creates the graph to use Pathfinding
void GeneratePathfindingGraph()
{
//Create graph
graph = new Node[columns, rows];
for (int x = -1; x < columns + 1; x++)
{
for (int y = -1; y < rows + 1; y++)
{
graph[x, y] = new Node();
Add the 4 cardinal adjacent tiles
if (x != - 1)
graph[x, y].neighbours.Add(graph[x - 1, y]);
if (x != columns - 1)
graph[x, y].neighbours.Add(graph[x + 1, y]); //Where I am getting the error
if (y != - 1)
graph[x, y].neighbours.Add(graph[x, y - 1]);
if (y != rows - 1)
graph[x, y].neighbours.Add(graph[x, y + 1]);
}
}
}
//SetupScene initializes our level and calls the previous functions to lay out the game board
public void SetupScene(int level)
{
//Creates the outer walls and floor.
BoardSetup();
//Creates the Node map to use Pathfinding
GeneratePathfindingGraph();
}
}
I have edited out most of the code in this class, I don't think it has much to do with the problem.
Can you change all the initialization in the loop like x = -1;to x = 0;
Arrays always start's with a ZERO.
Could someone advise me on a simple way to implement hollow rectangles in C#?
I have been able to make a simple rectangle, but hollow rectangle programs I've looked at either contained or arrays or were pretty convoluted. For instance, the solution on another forum that seems too challenging, and this answer on CodeReview.SE is too difficult to understand.
This is what I've done, which displays a simple (filled) rectangle. How to output a hollow rectangle using if logic if possible?
class Nested_Loops_Hollow_Rectangles
{
public void RunExercise()
{
// how are now supposed to make this hollow?
// columns are side by side, rows is number of top to bottom
// see tut
Console.WriteLine("Welcome to the HollowRectanglePrinter Program.");
Console.WriteLine("How many columns wide should the rectangle be?"); //i.e. 4
int iColMax, iRowMax;
string userChoiceC = Console.ReadLine();
Int32.TryParse(userChoiceC, out iColMax);
Console.WriteLine("How many rows tall should the rectangle be? "); //i.e. 4
string userChoiceR = Console.ReadLine();
Int32.TryParse(userChoiceR, out iRowMax);
Console.WriteLine("Here you go:");
if (iRowMax > 0 || iColMax > 0)
{
for (int iRow = 0; iRow < iRowMax; iRow++)
{
for (int iCol = 0; iCol < iColMax; iCol++)
{
Console.Write("*");
}
Console.WriteLine();
}
}
}
}
The essential part of your application can be reduced to:
private void DrawFillRectangle(int width, int height)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Console.Write("*");
}
Console.WriteLine();
}
}
This, by the way (separating the logic and the input by putting the logic in a dedicated method) is what you should be doing. See Separation of concerns for more information.
The previous method draws a filled rectangle, so how can you draw a hollow one?
Start looking at the output. For instance, for (5, 3), the output is:
*****
*****
*****
and what you want is to have:
*****
* *
*****
How can you do that? Probably by replacing stars by spaces in some cases. Which ones?
Well, look again at the output. The first row is untouched, so the condition where you use spaces instead of stars is limited to rows other than the first one, that is:
private void DrawRectangle(int width, int height)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (y > 0)
{
// Print either a star or a space.
}
else
{
Console.Write("*");
}
}
Console.WriteLine();
}
}
Now you must include the other cases in your condition: the first column, and the last column and row.
In order to combine conditions, you can use && and || operators. The first one means that the condition is true if both operands are true, and the second one means that either the first or the second operand is true.
It might be that your final condition will become too difficult to read. There are two things you can do. The first thing is to use intermediary variables. For instance:
if (a && b && c && d)
{
}
can be refactored into:
var e = a && b;
var f = c && d;
if (e && f)
{
}
if it makes sense to regroup a with b and c with d. A second thing you can do is to put the condition in a separate method, which may improve readability if you find a good name for the method:
private void DrawRectangle(int width, int height)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (this.IsInsideRectangle(x, y))
{
// Print either a star or a space.
}
else
{
Console.Write("*");
}
}
Console.WriteLine();
}
}
private bool IsInsideRectangle(int x, int y)
{
return y > 0 && ...
}
This is hopefully all you need to do the exercise. Depending of your progression in the course, you may also be interested in those aspects:
You may avoid repeating code in an if/else block, so instead of:
if (...)
{
Console.Write(" ");
}
else
{
Console.Write("*");
}
you may end up writing only only Write():
Console.Write(...)
What C# operator can you use for that?
It is a good practice for a method to validate its input before doing its job. If you've already learnt what exceptions are, how can they be used to validate width and height? Why in the current situation it may make sense to not filter negative and zero values (in other words, would the application crash if, for instance, width is equal to -5)?
class emptyRectangle:Shape
{
byte width;
byte height;
public emptyRectangle(byte width,byte height)
{
this.width = width;
this.height = height;
}
public override void area()
{
Console.WriteLine("\n----------");
for (int i = 0; i < height; i++)
{
Console.WriteLine("");
for (int k = 0; k < width; k++)
{
if (i > 0 && k > 0)
{
if (i < height - 1 && k < width - 1)
{
Console.Write(" ");
}
else
Console.Write('*');
}
else
Console.Write("*");
}
}
}
}
Add a single IF statement where you are drawing the character:
if it is the first or last row or the first or last column, write the *
else the space.
For more fun, make a variable sized rectangular "hole" in the rectangle.
static void Main()
{
int width = 0, height = 0;
width = int.Parse(Console.ReadLine());
height = int.Parse(Console.ReadLine());
for (int i = 1; i <= height; i++)
{
for (int j = 1; j <= width; j++)
{
if ((i == 1 || i == height || j == 1 || j == width))
Console.Write("*");
else
Console.Write(" ");
}
Console.WriteLine();
}
Console.ReadKey();
}
I have two arrays mat1 & Mat2.
I want to have new_mat=[ma1,mat2];
I have written a function which works. I wonder if there is an efficient function for very large matrix or How can I do it with Array.CopyTo method.
public static double[,] Concatenate_matrix_byCol(double[,] Mat1, double[,] Mat2)
{
int col1=Mat1.GetLength(1);
int col2 = Mat2.GetLength(1);
int row1=Mat1.GetLength(0);
int row2 = Mat2.GetLength(0);
int i, j, y;
double[,] newMat = new double[row1, col1 + col2];
for (i = 0; i < row1; i++)
{
for (j = 0; j < col1; j++)
{
newMat[i, j] = Mat1[i, j];
}
}
for (i = 0; i < row1; i++)
{
for (y = 0; y < col2; y++)
{
newMat[i, y+col1] = Mat2[i, y];
}
}
return newMat;
}
You could combine your loops into:
for (i = 0; i < row1; i++)
{
for (j = 0; j < col1; j++)
newMat[i, j] = Mat1[i, j];
for (y = 0; y < col2; y++)
newMat[i, y+col1] = Mat2[i, y];
}
And maybe use pointers instead (test performance first!) but a library would properly be the best solution. That way you don't have to do micro-optimizations yourself.
There is a lot of libraries for .Net mentioned in this thread: Matrix Library for .NET
Depending on your performance requirement you could also look into parallel algorithms and you may be inspired by http://innovatian.com/2010/03/parallel-matrix-multiplication-with-the-task-parallel-library-tpl/. Again, a well-build library probably already have parallel algorithms.
When moving Arrays, you should look into Array.CopyTo instead of moving the cells one by one.
Also you could create a class that accepts the 2 matrices, and provides a level of abstraction that makes them look like 1 matrix but just keeps them seperate underneath.
For instance M1 = 20x 30 and M2 = 25 x 30 so you have a class M3 that 'looks like' M1 + M2, a 55 x 30 matrix.
When someone asks for M3[28, 23] this class will know that it should redirect to M2[8, 23] because M1 was only 20 positions wide (28-20=8). That way you don't have to copy the memory, that's expensive. Figuring out how to reroute a request to the right matrix is much cheaper. Depends on how much the matrix accessed afterwards obviously.
edit
This is what I mean:
class Program {
static void Main(string[] args) {
int[,] x = { { 1, 2, 3 }, { 4, 5, 6 } };
int[,] y = { { 7, 8, 9 }, { 10, 11, 12 } };
var xy = new StitchMatrix<int>(x, y);
Console.WriteLine("0,0=" + xy[0, 0]); // 1
Console.WriteLine("1,1=" + xy[1, 1]); // 5
Console.WriteLine("1,2=" + xy[1, 2]); // 6
Console.WriteLine("2,2=" + xy[2, 2]); // 9
Console.WriteLine("3,2=" + xy[3, 2]); // 12
}
}
class StitchMatrix<T> {
private T[][,] _matrices;
private int[] _lengths;
public StitchMatrix(params T[][,] matrices) {
// TODO: check they're all same size
_matrices = matrices;
// call uperbound once for speed
_lengths = _matrices.Select(m => m.GetUpperBound(0)).ToArray();
}
public T this[int x, int y] {
get {
// find the right matrix
int iMatrix = 0;
while (_lengths[iMatrix] < x) {
x -= (_lengths[iMatrix] + 1);
iMatrix++;
}
// return value at cell
return _matrices[iMatrix][x, y];
}
}
}
Regards Gert-Jan