I'm working on building a little game, and I'm having an issue with reading a level map from a .txt file, converting it to a 2D array of characters, then converting any non blank character to an object of one type or another. I think converting to the 2D array is fine, but it looks like there's a null reference exception in one of two for loops traversing the array when converting to objects. Here's the code:
public void buildLevel()
{
List<Tangible> objects = new List<Tangible>(0);
for (int i = 0; i < map.GetLength(1); i++)
{
for (int j = 0; j < map.GetLength(0); j++)
{
if (map[j, i] == 'O')
{
objects.Add(new Ball((50 * j), (50 * i)));
}
if (map[j, i] == 'X')
{
objects.Add(new Block((50 * j), (50 * i), 50, 50));
}
}
}
allObjects = objects;
}
Any idea what might be happening here? I really appreciate it.
EDIT: here's the code for reading the file into a 2D array:
public void setMap(String mapFile)
{
try
{
List<String> lines = new List<String>();
using (StreamReader sr = new StreamReader("maps\\testLevel.txt"))
{
String currentLine;
while ((currentLine = sr.ReadLine()) != null)
{
lines.Add(currentLine);
}
}
map = new char[lines[0].Length, lines.Count];
for (int i = 0; i < lines.Count; i++)
{
for (int j = 0; j < lines[0].Length; j++)
{
map[j, i] = lines[i][j];
}
}
}
catch (DirectoryNotFoundException e)
{
Console.Error.WriteLine(e);
}
}
Related
Long time lurker on this website, because I always find my answer without having to post... I cannot tell what I'm doing in this case... does someone mind to take a look and help with what I am missing?
I downloaded a linear algebra class library (CSML) that I am trying to use. I'm trying to store individual values to a Matrix class. I get the error: Cannot implicitly convert type 'double' to 'CSML.Complex'.
I've tried many different ways to initiate the Matrix and add the array:
Matrix A = new Matrix(B);
Matrix A = new Matrix(double[,] B);
I have even tried to use a for loop to add the values individually:
Matrix A = new Matrix(new double[TotalARows,TotalACols]);
for (int i = 0; i < TotalARows; i++) {
for (int j = 0; j < TotalACols; j++) {
A[i,j] = B[i,j];
}
}
Here is the code in the DLL for the creation of the Matrix Class with double[,] input
public Matrix(double[,] values)
{
if (values == null)
{
Values = new ArrayList();
columnCount = 0;
rowCount = 0;
}
rowCount = (int)values.GetLongLength(0);
columnCount = (int)values.GetLongLength(1);
Values = new ArrayList(rowCount);
for (int i = 0; i < rowCount; i++)
{
Values.Add(new ArrayList(columnCount));
for (int j = 0; j < columnCount; j++)
{
((ArrayList)Values[i]).Add(new Complex(values[i, j]));
}
}
}
Here is the 'get' 'set' of Class Complex.
public virtual Complex this[int i, int j]
{
set
{
if (i <= 0 || j <= 0)
throw new ArgumentOutOfRangeException("Indices must be real positive.");
if (i > rowCount)
{
// dynamically add i-Rows new rows...
for (int k = 0; k < i - rowCount; k++)
{
this.Values.Add(new ArrayList(columnCount));
// ...with Cols columns
for (int t = 0; t < columnCount; t++)
{
((ArrayList)Values[rowCount + k]).Add(Complex.Zero);
}
}
rowCount = i; // ha!
}
if (j > columnCount)
{
// dynamically add j-Cols columns to each row
for (int k = 0; k < rowCount; k++)
{
for (int t = 0; t < j - columnCount; t++)
{
((ArrayList)Values[k]).Add(Complex.Zero);
}
}
columnCount = j;
}
((ArrayList)Values[i - 1])[j - 1] = value;
//this.Values[i - 1, j - 1] = value;
}
get
{
if (i > 0 && i <= rowCount && j > 0 && j <= columnCount)
{
return (Complex)(((ArrayList)Values[i - 1])[j - 1]);
}
else
throw new ArgumentOutOfRangeException("Indices must not exceed size of matrix.");
}
}```
The Complex class doesn't contain an implicit conversion from double. If you want to get an instance of Complex, you need to call new Complex(_your_double_here_). You can initialize a matrix with a double array, and it will perform the conversion for you in the constructor:
var array = new double[,] {
{1,1,1,1},
{1,2,3,4},
{4,3,2,1}
};
var matrix = new Matrix(array);
// Complex has a constructor which a single 'real' value as a double
matrix[1, 2] = new Complex(3);
// It also has a constructor which a 'real' value and an 'imaginary' value
matrix[1, 2] = new Complex(3, 4);
But again, this library hasn't been updated since 2007 and will teach you some bad and obsolete practices. Have a look at Math.Net, it is up to date and has great documentation
I want to remove a specific object from an array, put it in a smaller array without getting out of range. This is what I've tried but it won't work.
Skateboard[] newSkateboard = new Skateboard[_skateboards.Length - 1];
for (int i = 0; i < _skateboards.Length; i++)
{
if (skateboard.Code != _skateboards[i].Code)
{
newSkateboard[i] = _skateboards[i];
}
}
Sure.
var j = 0;
for (int i = 0; i < _skateboards.Length; i++)
{
if (skateboard.Code != _skateboards[i].Code)
{
newSkateboard[j] = _skateboards[i];
j = j + 1;
}
}
How can I properly do so that a check is performed for each string?
My code looks like :
string[,] screeny_baza = new string[300, 300];
for (int i = 0; i < 299; i++)
{
try
{
string nazwa_screna_pokolei = screeny_baza[0,i]
}
catch { };
}
As i see i want to do just it one by one. Is it possible to do it faster omitting values that do not exist or have not been declared? They are just null i think.
I have dimension that looks like to 300/300 .
X0 X1 X2
Y0 00 10 20
Y1 01 11 21
Y2 02 12 22
And want to save just string to each of dimesnion for example
string [00] = "bird";
string [01] = "bird2";
and later need to get this values in loop ( omitting values that do not exist or have not been declared)
Thanks for help.
I don't know about foreach loops on multi dimensional arrays but you can always do this:
string[,] screeny_baza = new string[300, 300];
for (int x = 0; x < screeny_baza.GetLength(0); x++)
{
for (int y = 0; y < screeny_baza.GetLength(1); y++)
{
try
{
string nazwa_screna_pokolei = string.empty;
if (screeny_baza[x, y] != null)
nazwa_screna_pokolei = screeny_baza[x, y];
}
catch { };
}
}
You can foreach on a 2d array. You can even LinQ Where to filter it.
var table = new string[20, 20];
table[0, 0] = "Foo";
table[0, 1] = "Bar";
foreach (var value in table.Cast<string>().Where(x =>!string.IsNullOrEmpty(x))) {
Console.WriteLine(value);
}
Actually your try-catch block will not raise any exception because when you construct the array:
string[,] screeny_baza = new string[300, 300];
you can always index it as long as the indexes are in range; so the statement:
string nazwa_screna_pokolei = screeny_baza[0,i];
will execute without error. Just nazwa_screna_pokolei will be null;
Also if speed is concerned, a nested for-loop is much faster than LinQ. at least for this simple check. for example:
var list = screeny_baza.Cast<string>().Where(x => !string.IsNullOrEmpty(x)).ToList();
will take about 10 milliseconds, but
for (int i = 0; i < 300; i++)
{
for (int j = 0; j < 300; j++)
{
if (string.IsNullOrEmpty(screeny_baza[i,j]))
{
continue;
}
list.Add(screeny_baza[i, j]);
}
}
will take only 1 millisecond.
For storing you would use row and column indices like:
screeny_baza[0,0] = "bird";
screeny_baza[0,1] = "bird";
For looping the values you use GetLength (though you know the dimensions as constant, this is a more flexible way):
for (int row = 0; row < screeny_baza.GetLength(0); row++) {
for (int col = 0; col < screeny_baza.GetLength(1); col++) {
if (!string.IsNullOrEmpty(screeny_baza[row,col])) // if there is a value
Console.WriteLine($"Value at {row},{col} is {screeny_baza[row,col]}");
}
}
My simple helper for such cases
private static void forEachCell(int size, Action<int, int> action)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
action(j, i);
}
}
}
It can be modified to use different sizes.
Usage example:
double totalProbability = 0;
forEachCell(chessboardSize, (row, col) =>
totalProbability += boardSnapshots[movesAmount][row, col]);
return totalProbability;
I was trying to put loop through and put CSV to 2D array.
My app crashes due to var tokens = sr.ReadLine().Split(','); It throws a NullPointerException. How can I fix this?
Below is my whole method named csvToArray:
public string[,] csvToArray (string filePath)
{
int col = colCount(filePath);
int row = rowCount(filePath);
string line;
string[,] data = new string[col, row];
using (StreamReader sr = new StreamReader(filePath))
{
for (int i = 0; i < col; i++)
{
var tokens = sr.ReadLine().Split(',');
for (int j = 0; j < row; j++)
{
data[i, j] = tokens[j];
}
}
}
return data;
}
What does not make sense is that it finished the whole loop. The variables below the exception have the values that they were supposed to have.
You have to use first for loop for row and then inner loop for column.
public static string[,] csvToArray(string filePath)
{
int col = colCount(filePath);
int row = rowCount(filePath);
string line;
string[,] data = new string[row, col];
using (StreamReader sr = new StreamReader(filePath))
{
for (int i = 0; i < row; i++)
{
var tokens = sr.ReadLine().Split(',');
for (int j = 0; j < col; j++)
{
data[i, j] = tokens[j];
}
}
}
return data;
}
In your code you are doing null.Split(), that is why it giving you exception.
If you want to insert 0 in each cell for a blank row, then you can implement the following code.
for (int i = 0; i < row; i++)
{
string content = sr.ReadLine();
if (!string.IsNullOrEmpty(content))
{
var tokens = content.Split(',');
for (int j = 0; j < col; j++)
{
data[i, j] = tokens[j];
}
}
else
{
for (int j = 0; j < col; j++)
{
data[i, j] = "0";
}
}
}
Lets first analyse errors in your example.
1) Why do you event need to know length of row and columns in the beggining? It is overhead.
2) Row and columns in your loop is invalid.
3) This exception throws in your example because your reached EOF.
So, here is better way to read csv to 2D matrix:
public int[][] csvToArray (string filePath)
{
string line = null;
var result = new List<int[]>();
using (var sr = new StreamReader(filePath))
{
while((line = sr.ReadLine()) != null)
{
if(string.IsNullOrWhiteSpace(line)) continue;
result.Add(sr.Split(',').Select(x=> string.IsNullOrWhiteSpace(x) ? 0 : int.Parse(x)).ToArray());
}
}
return result.ToArray();
}
Then you can just check your matrix for consistency.
At least, this way you won't open your file three times and protected from counting errors.
So I have built my own (toy) encryption algorithm using matrices. The program is supposed to encrypt the plaintext with the key and then ask you the key and print out the decrypted plaintext. Everything is ok until the point when the C# program generates the 'key matrix' from the key to decrypt the cipher. Note that the first time that it generates the 'key matrix' from the key it is ok but the second time it freezes. Here is the code.
using System;
namespace MatrixEncryption
{
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine("Enter a relatively short piece of text:");
string txt = Console.ReadLine();
txt += "L";
Console.WriteLine("Enter an encryption key:");
string ekey = Console.ReadLine();
int times = 0;
while(true)
{
if(txt.Length + 1 < (Math.Pow((double)ekey.Length,(double)times))) break;
times++;
}
times++;
Console.WriteLine(times);
Matrix keym = new Matrix(ekey.Length^times, ekey.Length^times);
string res = ekey;
for(int i = 0; i<times - 1; i++)
{
res = GetCharRep(GenMatrix(res));
}
keym = GenMatrix(res);
Console.WriteLine(keym.cols + ":" + keym.rows);
Matrix passm = new Matrix(keym.rows, keym.cols);
int unicnt = 0;
Random a = new Random();
for(int i = 0; i<(keym.rows); i++)
{
for(int j = 0; j<(keym.cols); j++)
{
if(unicnt == 0)
{
passm[i, j] = (byte)txt.Length;
unicnt++;
continue;
}
if(unicnt < txt.Length)
{
passm[i, j] = (byte)txt[unicnt - 1];
}
else
{
int aa = a.Next();
passm[i, j] = (byte)(aa % byte.MaxValue);
}
unicnt++;
}
}
Matrix cipherm = new Matrix(keym.rows, keym.cols);
Matrix TwoMatrix = new Matrix(cipherm.rows, cipherm.cols);
for(int i = 0; i<TwoMatrix.rows; i++)
{
for(int j = 0; j<TwoMatrix.cols; j++)
{
TwoMatrix[i, j] = 2;
}
}
cipherm = NotMul(passm + TwoMatrix, keym + TwoMatrix);
Console.WriteLine("Enciphered text : " + GetCharRep(cipherm));
Console.WriteLine("Enter key now to check if decryptable cipher : ");
string keyy = Console.ReadLine();
int timesx = cipherm.cols;
double aaa = (double)timesx;
double bbb = (double)keyy.Length;
timesx = (int)Math.Log(aaa, bbb);
Matrix keymx = new Matrix(timesx, timesx);
string resss = keyy;
for(int i = 0; i<timesx; i++)
{
resss = GetCharRep(GenMatrix(resss));
}
keymx = GenMatrix(resss);
if(keymx != keym)
{
Console.WriteLine("STUPID COMPUTER xD");
Console.WriteLine(cipherm.cols.ToString() + ":" + cipherm.rows.ToString());
}
Matrix ress = new Matrix(keymx.rows, keymx.cols);
keymx = keymx + TwoMatrix;
ress = NotDiv(cipherm, keymx);
ress = ress - TwoMatrix;
Console.WriteLine(GetCharRep(ress).Substring(0, (int)(ress[0, 0])));
}
public static Matrix NotMul(Matrix m1, Matrix m2)
{
Matrix result = Matrix.ZeroMatrix(m1.cols, m1.rows);
for(int i = 0; i<m1.rows; i++)
{
for(int j = 0; j<m2.cols; j++)
{
result[i, j] = (m1[i, j] * m2[i, j]);
}
}
return result;
}
public static Matrix NotDiv(Matrix m1, Matrix m2)
{
Matrix result = Matrix.ZeroMatrix(m1.cols, m1.rows);
for(int i = 0; i<m1.rows; i++)
{
for(int j = 0; j<m2.cols; j++)
{
result[i, j] = m1[i, j] * (1/m2[i, j]);
}
}
return result;
}
public static Matrix GenMatrix(string key)
{
Matrix ret = new Matrix(key.Length, key.Length);
for(int i = 0; i<key.Length; i++)
{
for(int j = 0; j<key.Length; j++)
{
ret[i, j] = (byte)(Math.Pow((double)key[i], (double)key[j]) % byte.MaxValue);
}
}
return ret;
}
public static string GetCharRep(Matrix INM)
{
string ret = "";
for(int i = 0; i<INM.rows; i++)
{
for(int j = 0; j<INM.cols; j++)
{
ret += (char)((byte)INM[i, j] % byte.MaxValue);
}
}
return ret;
}
}
}
For a little bit of explanation:
1. The matrix class is burrowed from the internet and is too large to be put here.
2. Explaining the encryption algorithm:
Shortly all that happens is that the code generates two matrices, one from the plaintext and one from the key (you can guess how exactly it is generated by the code).
Then it multiplies each element of the key and the plaintext (NOT MATRIX MULITIPLICATION JUST EACH ELEMENT) the algorithm also involves random numbers e.t.c. But the problem I believe here is that the process of turning the key into the 'key matrix' is not repeated correctly the second time. Anyway I don't know a good solution so please help.
Ok, so I solved the first part, It isn't freezing any more I just changed the
for(int i = 0; i<times - 1; i++)
{
res = GetCharRep(GenMatrix(res));
}
to
for(int i = 0; i<times - 2; i++)
{
res = GetCharRep(GenMatrix(res));
}
But this time the dimensions of the ress matrix and the TwoMatrix Matrix don't match.