So I got this base class
abstract class Item
{
private int x, y, ataque, defesa, saude, raridade;
private char appearance;
private bool pickedUp;
private readonly Random rng = new Random();
public Item(Map argMap, int argAtaque, int argDefesa, int argSaude, int argRaridade, char argAppearance)
{
bool empty = false;
while (!empty)
{
x = rng.Next(1, argMap.ReLengthX() - 1);
y = rng.Next(1, argMap.ReLengthY() - 1);
if (!argMap.CheckTile(y, x)) empty = true;
}
pickedUp = false;
ataque = argAtaque;
defesa = argDefesa;
saude = argSaude;
raridade = argRaridade;
appearance = argAppearance;
}
}
And I got this derived class
class Armadura : Item
{
public Armadura(Map argMap, int ataque, int defesa, int saude, int raridade, char appearance) : base(argMap, ataque, defesa, saude, raridade, appearance)
{
ataque = -1;
defesa = 2;
saude = 0;
raridade = ReRNG().Next(Convert.ToInt32(Math.Round(argMap.ReLengthY() * 0.02)), Convert.ToInt32(Math.Round(argMap.ReLengthY() * 0.04)));
appearance = ' ';
}
}
So my question is, how do I get to set the values on :base, using the values that I set on the derived constructor (for example, set the base argAtaque with ataquewwww, therefore, argAtaque being equal to '-1')?
I tried this using a few ways but I didn't get this to work in any way.
I thank you in advance!
The : base() syntax will work for constants and parameters, but not for more complex expressions with side-effects (as you found).
You'll be needing a initialization method on the base class.
abstract class Item
{
...
// If you use this constructor, call Setup() afterwards.
public Item() {}
// Constructor including a call to Setup()
public Item(Map argMap, int argAtaque, int argDefesa, int argSaude, int argRaridade, char argAppearance)
{
Setup(argMap, argAtaque, argDefesa, argSaude, argRaridade, argAppearance);
}
// Sets private variables for this Item
protected void Setup(Map argMap, int argAtaque, int argDefesa, int argSaude, int argRaridade, char argAppearance)
{
bool empty = false;
while (!empty)
{
x = rng.Next(1, argMap.ReLengthX() - 1);
y = rng.Next(1, argMap.ReLengthY() - 1);
if (!argMap.CheckTile(y, x)) empty = true;
}
pickedUp = false;
ataque = argAtaque;
defesa = argDefesa;
saude = argSaude;
raridade = argRaridade;
appearance = argAppearance;
}
}
Now you can setup the base class with the calculated values:
class Armadura : Item
{
public Armadura(Map argMap)
{
int ataque = -1;
int defesa = 2;
int saude = 0;
int raridade = ReRNG().Next(Convert.ToInt32(Math.Round(argMap.ReLengthY() * 0.02)), Convert.ToInt32(Math.Round(argMap.ReLengthY() * 0.04)));
char appearance = ' ';
Setup(argMap, ataque, defesa, saude, raridade, appearance);
}
All you have to do is set ataque in the child constructor, as it will override what ataque is being set to in your base class. The base constructor is called first, then the child constructor.
For this to work, you will need to make your private variables protected in the base class. This will make them private in the child class.
Related
If I call the default constructor "Creature" in main and then try to call the method "Generate Creator" the loop never runs. If I did a normal for loop it throws out of bounds errors even knowing the default constructor sets the length of the array. It is probably a dumb error I am not seeing. (this isnt all of the code)
class Creature
{
static int geneLength;
byte[] Chromosome = new byte[geneLength];
int fitness;
string geneString;
Random rn = new Random();
public Creature()
{
geneLength = 36;
fitness = 0;
}
public void GenerateCreature()
{
foreach(byte g in Chromosome)
{
Chromosome[g] = (byte)rn.Next(0, 2);
geneString += Chromosome[g].ToString();
}
}
}
Main:
namespace Creature_Generator
{
class Program
{
static void Main(string[] args)
{
Creature c = new Creature();
c.GenerateCreature();
Console.WriteLine(c.getGeneString);
}
}
}
foreach(byte g in Chromosome)
{
Chromosome[g] = (byte)rn.Next(0, 2); // 'g' is not an index
geneString += Chromosome[g].ToString(); // 'g' is not an index
}
while you are using foreach (byte g in Chromosome), I believe it is not a proper way to use code like Chromosome[g] which g is suppose a value not an index
try
StringBuilder geneString = new StringBuilder();
public Creature()
{
geneLength = 36;
this.Chromosome = new byte[geneLength];
fitness = 0;
}
for (int i = 0; i < this.Chromosome.Length; i++)
{
byte g = this.Chromosome[i]; // this line is useless
this.Chromosome[i] = (byte)rn.Next(0, 2);
geneString.Append(this.Chromosome[i].ToString());
}
Plus, if you are hard-coding geneLength = 36 in the constructor, consider use public int geneString { get; private set;} instead of static int geneLength; or
static int _geneLength = 36;
public int geneLength { get; private set; }
public Creature() { this.geneLength = _geneLength; }
public Creature(int geneLength) { this.geneLength = geneLength; }
Edit 1 -
According to #moreON advice, string geneString is modified from class string to StringBuilder, read more on https://msdn.microsoft.com/en-us/library/system.text.stringbuilder(v=vs.110).aspx
Other than your issue attempting to use the results of foreach to index an array, as others have mentioned, you're also ignoring the order in which initialisers and constructors are executed.
If we ignore inheritance (because you have none that is interesting here). Initializers are run before constructors.
This means that you are creating the array Chromosome before assigning 36 to geneLength. This means that geneLength was still default(int), which is 0, so you created an array with length 0.
For more on c# constructors see Jon Skeet's excellent page: http://jonskeet.uk/csharp/constructors.html
geneLength should probably also not be static, but that's a different discussion.
If you want geneLength to be a static field then you need to initialize it with a static constructor. Otherwise the value of geneLength is still 0 at the moment you instantiate the class.
Write your code like this instead:
class Creature
{
static int geneLength;
byte[] Chromosome = new byte[geneLength];
int fitness;
string geneString;
Random rn = new Random();
static Creature()
{
geneLength = 36;
}
public Creature()
{
fitness = 0;
}
public void GenerateCreature()
{
foreach (byte g in Chromosome)
{
Chromosome[g] = (byte)rn.Next(0, 2);
geneString += Chromosome[g].ToString();
}
}
}
Having trouble with 'System.AccessViolationException' while developing a WindowsPhone8 app and don't know how to deal with it. Here is GitHub repo.
Exception appears when app tries to access (assign value 5) int field of an object ("value") of a class ("SudokuCell") in a class ("SudokuSection") in a class ("SudokuField").
testSudokuField.AddValueToSingleCell(5, new Tuple<int, int>(i, j)); // class MainPage
public class SudokuField
{
public SudokuSection[,] Sections;
public SudokuHorizontal[] Horizontals;
public SudokuVertical[] Verticals;
public bool solved;
public void AddValueToSingleCell(int value, Tuple<int, int> coords) // Item1 - horizontal, Item2 - vertical
{
var temp = InterpretCoordsForSection(coords);
this.Sections[temp.Item1 - 1, temp.Item2 - 1].ChangeCellValue(value, temp.Item3, temp.Item4);
this.Horizontals[coords.Item1 - 1].cells[coords.Item2 - 1].value = value;
this.Verticals[coords.Item2 - 1].cells[coords.Item1 - 1].value = value;
}
public class SudokuSection
{
public SudokuCell[,] cells;
// --------- Constructors
public SudokuSection()
{
this.cells = new SudokuCell[3, 3];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
this.cells[i, j] = new SudokuCell();
}
public void ChangeCellValue(int value, int x, int y)
{
this.cells[x-1, y-1].ChangeValue(value);
}
}
public class SudokuCell
{
public int value; // Exect value of a cell
public SortedSet<int> acceptableValues; // A of acceptable values of a single cell
// --------- Constructors
public SudokuCell() // Empty constructor
{
this.acceptableValues = new SortedSet<int>();
}
public SudokuCell(int value) // Constructor for a cell with an exect value
{
this.value = value;
}
// --------- Methods
public void ChangeValue(int value)
{
this.value = value;
}
}
I tried to explain the issue maximally understandable. Will be grateful if you just point me to a solution.
Exception http://cs609829.vk.me/u33859447/docs/890ffbe19d74/question1.png?extra=UlBQBDfFTVi4oKt83aRDNfDrQcjh6AeNYv0aUQ1MmwDHWILYUR3EXmP82OylatDnm0BiT5wZBKYvqEcmQfLqLZX6bpJ7aCo
Absolutely stupid mistake: testSudokuField = new SudokuField();
I'm trying to make a few simple classes for my program and I'm being stumped by the inconsistent accessibility on field types error for my Tile[,] class 'theGrid' object. I've had a look at a few of the other solutions and set everything to public as I can see but I'm still stuck as to what to do with this.
Could you tell me how to fix this?
public class Level
{
public Tile[,] theGrid;
public Tile[,] TheGrid
{
get { return theGrid; }
set { theGrid = value;}
}
public static Tile[,] BuildGrid(int sizeX, int sizeY)
{
Tile earth = new Tile("Earth", "Bare Earth. Easily traversable.", ' ', true);
//this.createTerrain();
for (int y = 0; y < sizeY; y++)
{
for (int x = 0; x < sizeX; x++)
{
theGrid[x, y] = earth;
}
}
return theGrid;
}
And here's a shortened version of the tile class:
public class Tile
{
//all properties were set to public
public Tile()
{
mineable = false;
symbol = ' ';
traversable = true;
resources = new List<Resource>();
customRules = new List<Rule>();
name = "default tile";
description = "A blank tile";
area = "";
}
public Tile(string tName, string tDescription, char tSymbol, bool tTraversable)
{
resources = new List<Resource>();
customRules = new List<Rule>();
area = "";
symbol = tSymbol;
this.traversable = tTraversable;
this.name = tName;
this.description = tDescription;
mineable = false;
}
public void setArea(string area)
{
this.area = area;
}
}
I'd appreciate any help you could give me with this one.
Static methods can only access static members.
You need to create new array of tiles
public static Tile[,] BuildGrid(int sizeX, int sizeY)
{
Tile[,] theGrid = new Tile[sizeX, sizeY];
.... the rest of the code is the same
}
The exact error message indicates that the accessibility of Tile is less than public.
But in you listing of Tile it is public.
Possible causes
one of the other types, Resource or Rule is declared internal (ie without public)
you have another Tile class
the posted code for public class Tile is incorrect.
the error message is quoted incorrectly
class SomeClass
{
private struct PhraseInfo
{
public int Start;
public int Length;
}
...
private void SomeMethod(...)
{
List<PhraseInfo> posesBracket = new List<PhraseInfo>();
posesBracket.Add(new PhraseInfo());
posesBracket[0].Start = 10;
}
of cause, posesBracket[0].start=10; occur compiler error CS1612 : "Cannot modify the return value of 'expression' because it is not a variable"
how can i modify a value in list?
The problem is that PhraseInfo is a value type, so the this[] method will return a value, not a reference, to solve it, do this:
PhraseInfo pi = posesBracket[0];
pi.Start = 10;
posesBracket[0] = pi;
var temp = posesBracket[0];
temp.Start = 10;
posesBracket[0] = temp;
You cannot have a struct defined as a method. And as they say, you need the reference to change values. So it goes like this:
class SomeClass
{
private struct PhraseInfo
{
public int Start;
public int Length;
}
private void somemethod()
{
List<PhraseInfo> posesBracket = new List<PhraseInfo>();
posesBracket.Add(new PhraseInfo());
PhraseInfo pi = posesBracket[0];
pi.Start = 10;
posesBracket[0] = pi;
}
}
I have many constants I need to move around in one of my classes but I'm not allowed to use member variables. What are some options?
Here's my initial try:
private void MyConstants(out int textSize, out int paddingValue, out int borderType, ...)
{
//Set them here
}
private Method1()
{
int textSize = 0;
int paddingValue = 0;
int borderValue = 0;
....
MyConstants(out textSize, out paddingValue, out borderValue)
}
private Method2()
{
int textSize = 0;
int paddingValue = 0;
int borderValue = 0;
....
MyConstants(out textSize, out paddingValue, out borderValue)
}
//Many more methods...Just seems to repetitive.
Use Private Class or Struct.
private class Variables {
public int textSize;
public int paddingValue;
public int borderValue;
}
private Variables MyConstants{
get{ return new Variables(){textSize=1, paddingValue=2, borderValue=3};}
}
If you need to initialize in constructor try using readonly instead on const.
Edit 1:
You can create a class that holds a private Dictionary:like key and value.
put a "object LoadConstant(string)" method in it that will withdraw the data.
public static class ConstantManager {
private static Hashtable _consts = new Hashtable();
private static const keyName = "Name 1";
public static void ConstantManager()
{
_consts[keyName] = ...;
}
public static Hashtable GetConstants()
{
var _copy = new Hashtable(_consts);
return _copy;
}
}
public OtherClass{
public void Method()
{
var consts = ConstantManager.GetConstants();
var a = consts[ConstantManager.keyName];
}
}