Loop not running when its method to run it is called - c#

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();
}
}
}

Related

C# Error: "A namespace cannot directly contain members such as fields or methods"

A method receiving 2 numbers and I need to return the numbers of common digits for them. For example, the numbers 2201 and 3021 returns 3 because these numbers have 3 common digits: 0, 1, and 2.
I get this error and don't understand it: A namespace cannot directly contain members such as fields or methods
Here is the code:
public static int AlphaRomeo(int a, int b)
{
int count = 0;
while (a > 0)
{
int tempa = a % 10;
a = a / 10;
int tempb = b % 10;
b = b / 10;
if (tempa == tempb)
count++;
}
return count;
}
Might be easier to avoid the mathematics:
private static string _digits = "0123456789";
public static int AlphaRomeo(int a, int b)
{
string aStr = a.ToString();
string bStr = b.ToString();
int common = 0;
for (int i = 0; i < _digits.Length; i++)
{
if (aStr.Contains(_digits[i]) && bStr.Contains(_digits[i]))
common++;
}
return common;
}
Consider this example, you don't have a class in your code:
using System; // Imports
namespace LearnClasses // Namespace
{
class Program //class
{
static void Main(string[] args) // Method 1
{
Console.WriteLine( AlphaRomeo(2201, 3021));
}
public static int AlphaRomeo(int a, int b) // Method 2
{
int count = 0;
// Your code
return count;
}
}
}

Constructor does not pass initial array values to the method

I would like an explanation what I'm doing wrong. I paste two block of codes; one is working another is not working. The first code works becasue the initial values are passed into the method "MyGreatMethod" I can see them:
public class Something
{
private int [] MyArray = new int [3];
public Something()
{
MyArray[0] = 100;
MyArray[1] = 200;
MyArray[2] = 300;
}
public void MyGreatMethod()
{
Console.WriteLine(MyArray[0] / 3);
Console.WriteLine(MyArray[1] / 3);
Console.WriteLine(MyArray[2] / 3);
}
}
but if I place values into "MyArray" this way(see below), the method "MyGreatMethod" gets NULLs from constructor, what I do wrong? Please help..
public class Something
{
private int [] MyArray = new int [3];
public Something()
{
int[] MyArray = {100,200,300};
}
public void MyGreatMethod()
{
Console.WriteLine(MyArray[0] / 3);
Console.WriteLine(MyArray[1] / 3);
Console.WriteLine(MyArray[2] / 3);
}
}
It is null because you haven't assigned the values to MyArray. Instead, you have created a new array and assigned it to a local variable with the same name.
You should remove the int[] from the constructor:
public class Something
{
private int [] MyArray = new int [3];
public Something()
{
MyArray = {100,200,300};
}
public void MyGreatMethod()
{
Console.WriteLine(MyArray[0] / 3);
Console.WriteLine(MyArray[1] / 3);
Console.WriteLine(MyArray[2] / 3);
}
}
You need to use new keyword when you want to set values for a specific array after the declaration:
public class Something
{
private int[] MyArray;
public Something()
{
MyArray = new int[3] { 100, 200, 300 };
}
public void MyGreatMethod()
{
Console.WriteLine(MyArray[0] / 3);
Console.WriteLine(MyArray[1] / 3);
Console.WriteLine(MyArray[2] / 3);
}
}

Rolling a dice with custom amount of faces

So i am creating a dice using a public class called die. this class has 2 constructors and 3 other methods. When i call class within the main program, it will not print the desired (random) result.
Firstly i am trying to print out a random number between 1-6 based on the default values. Once i figure this out, i would eventually like to specify a number of sides for and print out a number between 1 and this specific number.
/// Represents one die (singular of dice) with faces showing values between
/// 1 and the number of faces on the die.
public class Die
{
private int numFaces, faceValue;
public Die() => (numFaces, faceValue) = (6, 1);
public Die(int faces)
{
numFaces = faces;
if (numFaces < 3)
numFaces = 6;
faceValue = 1;
}
public void RollDie()
{
//for (int ctr = 0; ctr <= numFaces; ctr++)
var rnd = new Random();
for (int ctr = 1; ctr <= 20; ctr++)
faceValue = rnd.Next(1, numFaces + 1);
}
public int GetFaceValue() => faceValue;
public int GetNumFaces() => numFaces;
}
public class Program
{
public static void Main()
{
var myDie = new Die(1);
for (int i =0; i < 20; i++)
{
myDie.RollDie();
Console.WriteLine(myDie.GetFaceValue());
}
}
}
Since Random is time seeded when the parameterless constructor is used, this can have the very negative consequence of duplicating results.
Excerpt from the API documentation:
However, because the clock has finite resolution, using the
parameterless constructor to create different Random objects in close
succession creates random number generators that produce identical
sequences of random numbers.
...
On most Windows systems, Random objects created within 15 milliseconds of one another are likely to have identical seed values.
This is a safer approach in regards to getting random numbers when creating and rolling multiple dice:
public class Die
{
static int seed = Environment.TickCount;
static readonly ThreadLocal<Random> DieRandom = new ThreadLocal<Random>(()
=> new Random(Interlocked.Increment(ref seed)));
public int FaceCount { get; }
public int Value { get; private set; }
public Die() : this(6) // default to 6 faces
{
}
public Die(int faceCount)
{
if (faceCount < 3) // validate input
throw new ArgumentOutOfRangeException(nameof(faceCount));
this.FaceCount = faceCount;
}
public int Roll()
{
Value = DieRandom.Next(1, FaceCount + 1);
return Value;
}
}
Edit: updated the Random with thread safety as suggested here.

How to set base class the values in the derived constructor

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.

Get; Set; Variables

I'm setting up multiple methods and wondering how to continue to pass one variable (The "top" variable) to different methods.
Main method:
public static void Main(string[] args)
{
int[] anArray = new int[5];
int top = -1;
PushPeek(anArray);
then I need to pass top to:
public static void PushPeek(int[] ar)
{
if (ar[ar.Length -1] == ar.Length -1)
{
//do nothing
}
else
{
top = top + 1;
Console.WriteLine(ar[top]);
}
}\
I know it involves something with get; set; but I don't know how, any help?
Pass it by reference:
public static void PushPeek(int[] ar, ref int top)
{
...
}
int[] anArray = new int[5];
int top = -1;
PushPeek(anArray, ref top);
All about properties: http://msdn.microsoft.com/en-us/library/aa288470(v=vs.71).aspx
Auto-implemented properties are awesome! http://msdn.microsoft.com/en-us/library/bb384054.aspx

Categories

Resources