I'm making a game about genetics, and I stumble into a little "problem". (it's more of a question in fact)
I have a DNA class with a lot of variables that stores the infos about each "creature" in the game.
public class DNA {
float size;
float speed;
float drag;
float eyeSize;
int numberOfEyes;
float color_r;
[...]
}
Now let's imagine I want to average two DNAs.
I could do:
DNA AverageDNAs (DNA dna1, DNA dna2) {
DNA newDNA = new DNA ();
newDNA.size = (dna1.size+dna2.size)/2f;
newDNA.speed = (dna1.speed+dna2.speed)/2f;
[...]
}
But it seems pretty long, and every time I'm going to do some calculation, I'll need to rewrite every variable one by one.
So I made a function that stores all the variables (normalized between 0 and 1) into a list
public class DNA {
public float size;
public float speed;
[...]
private List<float> tempList;
public List<float> ToList() {
if (tempList == null) {
tempList = new List<float>();
toReturn.Add (size/sizemax);
toReturn.Add (speed/speedmax);
[...]
}
return tempList
}
public static ADN fromList(List<float> list) {
ADN toReturn = new ADN();
toReturn.size = list[0]*sizemax;
[...]
}
}
Now, I can do:
DNA AverageDNAs (DNA dna1, DNA dna2) {
List<float> dnaList1 = dna1.ToList();
List<float> dnaList2 = dna2.ToList();
List<float> newDNA = new List<float>();
for (int i = 0; i<dnaList1.Count; i++) {
newDNA.Add ((dnaList1[i]+dnaList2[i])/2f);
}
return DNA.fromList(newDNA);
}
It's easier to implement new functions and calculations, but it's pretty heavy (partly due to Lists creation), and not very pretty (I guess ?).
I would not prefer using just a List<float>
for the sake of readability.
I wanted to know if there's a better way to handle that kind of situations?
(Please pardon my poor english, as I'm not a native speaker)
If you're always applying the same operation to all, you could use a parameter to specify the operation to be performed:
public DNA Cross(DNA dna1, DNA dna2, Func<float, float, float> operation)
{
var newDNA = new DNA();
newDNA.size = operation(dna1.size, dna2.size);
newDNA.speed = operation(dna1.speed, dna1.speed);
// And all the rest
}
This allows you to reuse this method for a wide range of different operations - as long as they always operate on the same amount of fields:
// Average
(d1, d2) => (d1 + d2) / 2f
// Sum
(d1, d2) => d1 + d2
// Random
(d1, d2) => RandomBool() ? d1 : d2
etc.
If you do want to apply the operation more selectively, you could also expand the Cross
method to take an enum specifying which fields exactly you want to update. And of course, you might want to add another Func
(or Action
, depending on how comfortable you are with mutating arguments) to update the rest in any way you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With