i'm trying to convert a string from file to 2d array. Is it possible to make the array dynamic? And how can i return the array, so i can work with it? I'm really confused.
public interface IMazeLoader
{
Maze LoadMaze(string src);
}
class MazeLoader : IMazeLoader
{
public Maze LoadMaze(string filepath)
{
var width = 5;
var height = 5;
var map = new char[width, height];
var file = new StreamReader(filepath);
string line;
var lineCount = 0;
while ((line = file.ReadLine()) != null)
{
if (lineCount < height)
{
for (int i = 0; i < width && i < line.Length; i++)
{
map[i, lineCount] = line[i];
}
}
lineCount++;
}
file.Close();
return;
}
}
Here is my Maze class :
public class Maze
{
public static readonly char CHAR_WALL = '#';
public static readonly char CHAR_START = 'S';
public static readonly char CHAR_FINISH = 'F';
public int Width { get; internal set; }
public int Height { get; internal set; }
public int StartX { get; private set;}
public int StartY { get; private set; }
public int StartAngle { get; private set; }
private char[,] _plan;
public char[,] Plan { get { return _plan; } }
public Maze(char[,] plan)
{
}
Thanks for any reply, happy Eastern btw. :)
Something like this should allow you to load any rectangular dimension map:
public class MazeLoader : IMazeLoader
{
public Maze LoadMaze(string filepath)
{
char[][] loaded =
File
.ReadLines(filepath)
.Select(x => x.ToCharArray())
.ToArray();
int[] widths =
loaded
.Select(x => x.Length)
.Distinct()
.ToArray();
if (widths.Length != 1)
{
throw new InvalidDataException("Map Data Not Rectangular");
}
else
{
var width = widths[0];
var height = loaded.Length;
var map = new char[height, width];
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
map[i, j] = loaded[i][j];
return new Maze(map);
}
}
}
Now I tested this on this input:
aaaa
aaaa
bbbb
bbbb
bbbb
And got this map:
Please note that the file orientation and the map orientation are the same. I had to flip around how you were building our your map to get that to work.
Here's my alterations to Maze itself:
public class Maze
{
public int Width => this.Plan.GetUpperBound(1) - this.Plan.GetLowerBound(1) + 1;
public int Height => this.Plan.GetUpperBound(0) - this.Plan.GetLowerBound(0) + 1;
public char[,] Plan { get; private set; }
public Maze(char[,] plan)
{
this.Plan = plan;
}
}
Related
I want to read data from a file or an analog digital converter (ADC) and convert the data with the help of the dynamicdata library. Suppose I read blocks of 2d matrices of ushort numbers from this file or ADC.
In the example below I add a 2d matrix to the FileNode class and that is converted to an IObservableList<double[]> list. Now I want to connect this to the Data property of the SampledSignal class which is of type IObservableList<double>. Does anyone have any idea how I should do this?
public class SampledSignal
{
public SampledSignal(IObservableList<double> data, double sr)
{
Data = data;
Samplerate = sr;
}
public IObservableList<double> Data { get; private set; }
public double Samplerate { get; }
}
public class FileNode : ReactiveObject
{
readonly IObservable<IEnumerable<ushort[]>> _currentDataObsv;
const int _signalCount = 4;
readonly private SampledSignal[] _sampledSignals;
public FileNode()
{
_sampledSignals = Enumerable.Range(0, _signalCount)
.Select(s => new SampledSignal(null, 200)).ToArray();
CurrentData = Enumerable.Empty<ushort[]>();
_currentDataObsv = this.WhenAnyValue(x => x.CurrentData);
IObservableList<double[]> dblArList = _currentDataObsv
.ToObservableChangeSet()
.TransformMany(d => ToEnumerable(d))
.AsObservableList();
// The lines below are just some code to give an idea of what I want
for (int i = 0; i < _signalCount; i++)
{
// maybe here an observablelist should be created?
// IObservableList<double> data = ??
// _sampledSignals[i] = new SampledSignal(data, 200);
}
OutSignals=_sampledSignals;
}
public IEnumerable<double[]> ToEnumerable(ushort[] array)
{
double offset = 0;
double amp = 4;
int len = array.Length;
int cnt = 0;
double[] x = new double[len];
for (int i = 0; i < len; i++)
{
x[i] = Convert.ToDouble(array[i] - short.MaxValue) / ushort.MaxValue * amp + offset;
}
cnt++;
yield return x;
}
[Reactive] public IEnumerable<ushort[]> CurrentData { get; set; }
// maybe this property can also be an IObservableList<SampledSignal> OutSignals
public IEnumerable<SampledSignal> OutSignals { get; private set; }
}
[Fact]
public void Test_SampledData()
{
int signalcount = 20;
IEnumerable<ushort[]> array = Enumerable.Range(0, 4)
.Select(j =>
{
var x = new ushort[signalcount];
for (int i = 0; i < x.Length; i++)
{
x[i] = Convert.ToUInt16(short.MaxValue+(i+j)*4);
}
return x;
});
var filenode = new FileNode();
filenode.CurrentData = array;
// do some testing below
SampledSignal signal = filenode.OutSignals.First();
signal.Should().NotBeNull();
signal.Data.Count.Should().Be(signalcount);
}
I have created a solution that works but I don't like it very much because I have to create a SourceList class in the SampledData class.
I was hoping for a solution were I directly could set the IObservable<double> Data property of the SampledData class.
// The SampledSignal class now looks like this.
public class SampledSignal
{
private readonly ISourceList<double> _sourceList = new SourceList<double>();
public SampledSignal(IObservableList<double> data, double sr)
{
Data = _sourceList;
Samplerate = sr;
}
public ISourceList<double> Data { get; private set; }
public double Samplerate { get; }
}
// The FileNode constructor now looks like this
public FileNode()
{
_sampledSignals = Enumerable.Range(0, _signalCount)
.Select(s => new SampledSignal(null, 200)).ToArray();
CurrentData = Enumerable.Empty<ushort[]>();
_currentDataObsv = this.WhenAnyValue(x => x.CurrentData);
IObservableList<double[]> dblArList = _currentDataObsv
.ToObservableChangeSet()
.TransformMany(d => ToEnumerable(d))
.AsObservableList();
dblArList.Connect().ToCollection()
.Subscribe(sigs =>
{
int cnt = 0;
foreach (var sig in sigs)
{
var regdata = _sampledSignals[cnt++];
regdata.Data.Edit(innerlist =>
{
innerlist.Clear();
innerlist.AddRange(sig);
});
}
});
OutSignals=_sampledSignals;
}
i'm trying to store objects in array, but i recive error - System.ArrayTypeMismatchException: 'Attempted to access an element as a type incompatible with the array.' I was looking for answer but still can't figure it out. It seemed to me that if i use arrays of object type i can update array with any type of data...
my code:
{//cass.cs
public class Map
{
private int Rows { get; set; }
private int Cols { get; set; }
private string[,] Grid { get; set; }
private Object[,] BoardTiles { get; set; }
public Map(int rows, int cols)
{
this.Rows = rows;
this.Cols = cols;
this.BoardTiles = new string[rows, cols];
}
public void printBoard(int playerPositionRowIndex, int playerPositionColumnIndex)
{
Floor floor = new Floor("floor", 1);
for (int r = 0; r < Rows; r++)
{
for (int c = 0; c < Cols; c++)
{
if (r == playerPositionRowIndex && c == playerPositionColumnIndex)
{
BoardTiles[r, c] = floor; //this place will be changed
Console.Write("#");
}
else
{
BoardTiles[r, c] = floor;
Console.Write("*");
}
}
Console.WriteLine();
}
}
}
{//floor.cs
public class Floor
{
private string Type { get; set; }
private int Num{ get; set; }
public Floor(string type, int num)
{
this.Type = type;
this.Num = num;
}
}
}
Map map = new Map(5, 10);
map.printBoard(4, 3);
I have an assignment to save and load a Minesweeper board. I'm having issues saving the board matrix. These are my Minesweeper properties:
[XmlIgnore]
public Tile[,] Grid { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public int NumberOfMines { get; set; }
Tile properties:
public int X { get; set; }
public int Y { get; set; }
public int NeighbourMines { get; set; }
public bool IsMine { get; set; }
public bool IsRevealed { get; set; }
public bool IsFlagged { get; set; }
I tried something like this:
public List<Tile> ListFromMatrix
{
get
{
List<Tile> temp = new List<Tile>(Height * Width);
for (int i = 0; i < Height; i++)
for (int j = 0; j < Width; j++)
temp.Add(Grid[i, j]);
return temp;
}
set
{
//Grid = new Tile[Height, Width];
int it = 0;
for (int i = 0; i < Height; i++)
for (int j = 0; j < Width; j++)
Grid[i, j] = value[it++];
}
}
Saving into the file works fine, but loading from it causes an exception. And I really don't know how to debug it since the exception is thrown at:
//this.Game is the Minesweeper reference in the main form
this.Game = (Game)xs.Deserialize(fileStream);
Any help is appreciated!
EDIT: This is the exception
System.InvalidOperationException: 'There is an error in XML document (7, 4).
Inner Exception 1: NullReferenceException: Object reference not set to an instance of an object.
EDIT2: Save code
SaveFileDialog sfd = new SaveFileDialog();
if (sfd.ShowDialog() == DialogResult.OK)
{
using (FileStream fs = new FileStream(sfd.FileName, FileMode.Create))
{
XmlSerializer xs = new XmlSerializer(typeof(Game));
xs.Serialize(fs, this.Game);
}
}
EDIT3: Here are the xml contents https://pastebin.com/0vkxQC5A
EDIT4: Thank you for trying but nothing works with this so I will just rewrite the code to use a list instead of the matrix.
You might try changing your set like so:
set
{
var height = value.Max(t=>t.Y);
var width = value.Max(t=>t.X);
Grid = new Tile[height, width];
foreach(var tile in value)
{
Grid[tile.Y,tile.X]=tile;
}
}
You probably don't want to use the height and width properties from the game object, because then you would need to assume those get set prior to this property. Might as well just calculate them yourself. And while you are at it, might as well just change get as well, and then throw away Height/Width, or change them to actually pull the current width/height of the Grid:
get
{
var temp = new List<Tile>(Grid.Length);
for (int i = 0; i < Grid.GetLength(0); i++)
for (int j = 0; j < Grid.GetLength(1); j++)
temp.Add(Grid[i, j]);
return temp;
}
It appears the error is in deserializing your property ListFromMatrix.
public List<Tile> ListFromMatrix {get; set;}
// when it comes time to serialize
ListFromMatrix = CreateList();
using (FileStream fs = new FileStream(sfd.FileName, FileMode.Create))
{
XmlSerializer xs = new XmlSerializer(typeof(Game));
xs.Serialize(fs, this.Game);
}
private List<Tile> CreateList()
{
var temp = new List<Tile>(Height * Width);
for (int i = 0; i < Height; i++)
for (int j = 0; j < Width; j++)
temp.Add(Grid[i, j]);
return temp;
}
I want to make game, like Tribal Wars, but in console and single player. I have Village class and there I have to make something, which contains building level and according to level is production of the building. I tried to do it with multidimension array, like building[level, production] but it haven't worked.
This is full code from class Village (Primary class is Program)
class Village
{
/*
private int mainBuild = 0;
private double[] mainBuildCost = new double[20];
private int woodCutter = 0;
private double[] woodCutterCost = new double[20];
private double[] woodCutterProd = new double[20];*/
public double[,] woodCutter = new double[20, 1];
private int wood = 50;
public Village()
{
woodCutter[0, 0] = 5;
for (int lvl = 1; lvl < woodCutter.GetLength(0); lvl++)
{
for (int prod = 1; prod <= woodCutter.GetLength(1); prod++)
{
woodCutter[lvl, 0] = Math.Round(woodCutter[lvl-1, prod-1])*1.3;
}
woodCutter[lvl, 0] = lvl;
Console.Write(woodCutter);
}
}
}
And yes, it's really but and doesn't work, but i have no idea, how do I make my plan.
I would do it differently. Your production here can be represented as a formula.
Here's a little example:
class Village
{
public double CurrentWood { get; private set; }
public int WoodLevel { get; private set; }
public double WoodProduction { get { return WoodLevel * 1.3; } } // Change the formula to your own
public void Update()
{
// Update all your resources in here
CurrentWood += Production;
}
}
I have to build some logic to write some sort of scoreboard. The idea is this:
There are many stages:
1st stage you have 2 numbers. 7 and 3=10
2nd stage you have another 2 numbers. 5 and 1 =6
After the loop has finished, the wanted result should be:
Stage 1 total score=15 (total 1st Stage + firstTry of secondStage)
Stage 2 total score=21 (total 1st Stage + (firstTry + SecondTry of SecondStage)
What's wrong with my loop? I dont seem to get the wanted resoult.
private void Calculate(Player player)
{
for (int i = 0; i < player.Game.Stages.Length; i++)
{
int firstThrow = player.Game.Stages[i].FirstTry;
int secondThrow = player.Game.Stages[i].SecondTry;
int sumFirstAndSecond = firstThrow + secondThrow;
//If firstTry + SecondTry==10 is spare
if ((sumFirstAndSecond == 10) && (firstThrow != 10) && i != player.Game.Stages.Length- 1)
{
int stageScore= player.Game.Stages[i].TotalScore +
player.Game.Stages[i + 1].FirstTry;
player.Game.Stages[i].TotalScore = stageScore;
}
}
}
public class Stage
{
public int FirstTry { get; set; }
public int SecondTry { get; set; }
public int TotalScore { get; set; }
}
public class Player
{
public Player(string name)
{
Name = name;
Game = new Game(name);
}
public Game Game { get; set; }
public string Name { get; set; }
}
public class Game
{
public Game(string playerName)
{
PlayerName = playerName;
Stages = new Stage[10];
for (int i = 0; i < Stages.Length; i++)
{
Stages[i] = new Stage();
}
}
public Stage[] Stages { get; internal set; }
public string PlayerName { get; set; }
}
Change this:
private void Calculate(Player player)
{
for (int i = 0; i < player.Game.Stages.Length; i++)
{
int firstThrow = player.Game.Stages[i].FirstTry;
int secondThrow = player.Game.Stages[i].SecondTry;
int sumFirstAndSecond = firstThrow + secondThrow;
if ((sumFirstAndSecond == 10) && (firstThrow != 10) && i != player.Game.Stages.Length- 1)
{
int stageScore= player.Game.Stages[i].TotalScore + player.Game.Stages[i + 1].FirstTry;
player.Game.Stages[i].TotalScore = sumFirstAndSecond + stageScore;
}
else if (i > 0) player.Game.Stages[i].TotalScore = player.Game.Stages[i - 1].TotalScore + sumFirstAndSecond;
}
}
Bowling?
Try this, and do not forget to add misses (as 0).
Should work for both running and final scoring.
// All balls, including misses (0)!
public readonly IList<int> _balls = new List<int>();
private int _currentBall;
public int CalculateTotalScore()
{
int score = 0;
_currentBall = 0;
for (var frame = 0; frame < 10; frame++)
{
if (_currentBall >= _balls.Count)
break;
if (_balls[_currentBall] == 10)
{
// Strrrike!
score += AggregateScoreFromCurrentBall(3);
_currentBall++;
}
else if (AggregateScoreFromCurrentBall(2) == 10)
{
// Spare
score += AggregateScoreFromCurrentBall(3);
_currentBall += 2;
}
else
{
score += AggregateScoreFromCurrentBall(2);
_currentBall += 2;
}
}
return score;
}
private int AggregateScoreFromCurrentBall(int numberOfBallsToSum)
{
var sum = 0;
for (var i = 0; i < numberOfBallsToSum; i++)
if (_currentBall + i < _balls.Count)
sum += _balls[_currentBall + i];
return sum;
}