First I would like to say that I am aware of different topics on true Randomness with seeds and how new Random() is created depending on Environment.TickCount.
Despite all that I couldn't figure out what my problem is.
I'm trying to create a population of 100 graphs for use in Graph Coloring Genetic Algorithm.
Every single population consists of set number of edges and set number of nodes. Every node has an index number and a random initial color.
That initial color is what I want to random. The colors are ints between 1 and 10.
But every single population looks the same, same nodes got same colors.
I probably might have missed something simple but I just cannot figure it out.
Any help would be appreciated.
CreatePopulation.cs
class CreatePopulation
{
private static Solution CreateRandomSolution(Graph graph, int colorsCount)
{
Solution solution = new Solution(graph, colorsCount);
for (int node = 0; node < graph.Nodes.Count; node++)
{
solution.assignColor(node, Program.RandomNumber(1, 10));
}
return solution;
}
public static List<Solution> CreateRandomPopulation(Graph graph, int populationSize)
{
List<Solution> list = new List<Solution>();
for (int i = 0; i < populationSize; i++)
{
list.Add(CreateRandomSolution(graph, 10));
}
return list;
}
}
Solution.cs holding future implementation of fitness methods and other methods needed for algorithm
class Solution
{
private int colorsCount;
private List<Vertex> edges;
private List<Node> nodes;
private Solution(List<Vertex> edges, List<Node> nodes, int colorsCount)
{
this.colorsCount = colorsCount;
this.edges = edges;
this.nodes = nodes;
}
public Solution(Graph graph, int colorsCount)
{
edges = graph.Vertices;
this.colorsCount = colorsCount;
this.nodes = graph.Nodes;
}
public void assignColor(int index, int color)
{
nodes[index].color = color;
}
}
Program.cs with main function
class Program
{
public static readonly Random Random = new Random();
private static double MutationRate = 0.05;
private static double CrossoverRate = 0.7;
private static int Colors = 10;
private static int GenerationCount = 100;
private static int PopulationSize = 100;
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock (syncLock)
{
return Random.Next(min, max);
}
}
static void Main(string[] args)
{
var graph = new Graph(#"C:\Users\Pawel\Desktop\lab1\GraphColoring-branch\bin\Debug\geom20.col");
var initPopulation = CreatePopulation.CreateRandomPopulation(graph, PopulationSize);
Console.ReadLine();
}
}
Node.cs
namespace Graph
{
class Node
{
public int number { get; set; }
public int color { get; set; }
public Node(int number)
{
this.number = number;
}
public Node() { }
}
}
Update
Changed the way I create a new List in Solution.cs but would like to know if it can be done in a nicer way.
public Solution(Graph graph, int colorsCount)
{
this.edges = graph.Vertices;
this.colorsCount = colorsCount;
this.nodes = new List<Node>(graph.Nodes.Count);
for (int i = 0; i < graph.Nodes.Count; i++)
{
this.nodes.Add(new Node{color = graph.Nodes[i].color, number = graph.Nodes[i].number});
}
}
The problem is every single one of your Solution objects are working from the same instance of List<Vertex> and List<Node>. So Random is working correctly, the real problem is you are overwriting the values for the previous solutions when generate the next solution.
The only constructor I see you use is
Solution solution = new Solution(graph, colorsCount);
In there you do
public Solution(Graph graph, int colorsCount)
{
edges = graph.Vertices;
this.colorsCount = colorsCount;
this.nodes = graph.Nodes;
}
This is just copying the reference of graph.Vertices and graph.Nodes, if any Solution modifies one of the items in the collections all Solutions get modified.
To fix this you need to make a deep copy of those two lists. You did not show what a Vertex or Node was, however if they are classes just doing
public Solution(Graph graph, int colorsCount)
{
edges = graph.Vertices.ToList();
this.colorsCount = colorsCount;
this.nodes = graph.Nodes.ToList();
}
will not be enough because that will only create a shallow copy of the list, your call to nodes[index].color = color; will still modify the nodes in all of the other graphs because although the lists are now separate references the elements in the list are still shared across Solution objects. You need something similar to
class Solution
{
private int colorsCount;
private List<Vertex> edges;
private List<Node> nodes;
private Solution(List<Vertex> edges, List<Node> nodes, int colorsCount)
{
this.colorsCount = colorsCount;
this.edges = edges;
this.nodes = nodes.Select(old => old.Clone()).ToList();
}
public Solution(Graph graph, int colorsCount)
{
edges = graph.Vertices;
this.colorsCount = colorsCount;
this.nodes = graph.Nodes.Select(old => old.Clone()).ToList();
}
public void assignColor(int index, int color)
{
nodes[index].color = color;
}
}
class Node
{
public int number { get; set; }
public int color { get; set; }
public Node(int number)
{
this.number = number;
}
public Node() { }
public Node Clone()
{
var newNode = new Node();
newNode.number = this.number;
newNode.color = this.color;
return newNode;
}
}
Related
I am looking to randomly generate 3 items using a loot table. The loot table currently works as expected, it will randomly generate an item based on the item's rarity. However, I don't want there to be duplicates of the same item. How can I set this up? This script is currently attached to 3 separate GameObject item pedestals.
using System.Collections.Generic;
using UnityEngine;
public class ShopItemSpawner : MonoBehaviour
{
[System.Serializable]
public class DropItem
{
public string name;
public GameObject item;
public int dropRarity;
}
public List<DropItem> ShopItemPool = new List<DropItem>();
private void Start()
{
int itemWeight = 0;
for (int i = 0; i < ShopItemPool.Count; i++)
{
itemWeight += ShopItemPool[i].dropRarity;
}
int randomValue = Random.Range(0, itemWeight);
for (int j = 0; j < ShopItemPool.Count; j++)
{
if (randomValue <= ShopItemPool[j].dropRarity)
{
Instantiate(ShopItemPool[j].item, transform.position, Quaternion.identity);
return;
}
randomValue -= ShopItemPool[j].dropRarity;
}
}
}
You could clone the ShopItemPool list and with each item rolled you remove that item from the list. You then need to go all over again by recalculating the total weight.
I find it useful to have a general purpose class for randomizing items with weights, it allows you do this this:
var randomizer = new WeightRandomizer<DropItem>();
foreach (var shopItem in ShopItemPool) {
randomizer.Add(shopItem, shopItem.dropRarity);
}
randomizer.Roll(); // Get a random element based on weight.
randomizer.Take(); // Get a random element based on weight and remove it from the randomizer.
General Purpose Weight Randomizer:
public class WeightRandomizer<T> {
[Serializable]
public class WeightedElement<T> {
public T value;
public int weight;
public WeightedElement (T value, int weight) {
this.value = value;
this.weight = weight;
}
}
private readonly List<WeightedElement<T>> elements = new();
public void Add (T value, int weight) => elements.Add(new WeightedElement<T>(value, weight));
public void AddRange (IEnumerable<WeightedElement<T>> weightedElements) => elements.AddRange(weightedElements);
public int TotalWeight() => elements.Sum(x => x.weight);
public T Roll() => Pick(false);
public T Take() => Pick(true);
private T Pick (bool remove) {
if (elements.Count == 0) {
Debug.LogWarning($"{nameof(WeightRandomizer<T>)} is missing elements.");
return default(T);
}
var roll = Random.Range(0, TotalWeight());
var selectedIndex = elements.Count - 1;
var selected = elements[selectedIndex].value;
for (var i = 0; i < elements.Count; i++) {
var element = elements[i];
// Found an element with a low enough value.
if (roll < element.weight) {
selected = element.value;
selectedIndex = i;
break;
}
// Keep searching for an element with a lower value.
roll -= element.weight;
}
// Sometimes we want to take and remove the element from the pool.
if (remove) elements.RemoveAt(selectedIndex);
return selected;
}
}
I want to be able to count multiple entries in an already sorted array. In previous attempts, I've tried to use a list like this.
public static List<int> duplicate = new List<int>();
However, it wouldn't count properly and kept printing the same index number. I'm pretty much stumped on what to do at this point any help would be appreciated.
class binarysearch
{
public static int lowestIndex = 0;
public static int highestIndex;
public static int middleIndex = 0;
public static int indexValue = -1;
public static int binarySearch(double[] data, double target)
{
int highestIndex = data.Length - 1;
while (lowestIndex < highestIndex)
{
middleIndex = lowestIndex + (highestIndex - lowestIndex) / 2;
if (data[middleIndex] == target)
{
indexValue = middleIndex;
highestIndex = middleIndex;
}
else if (data[middleIndex] > target)
{
highestIndex = middleIndex;
}
else
{
lowestIndex = middleIndex + 1;
}
}
return indexValue;
}
}
edit
public static List<int> duplicate = new List<int>();
is declared earlier in the code in
class dataset
{
public static List<int> duplicate = new List<int>();
}
then printed later in the main method
foreach (object dupes in dataset.duplicate)
{
Console.WriteLine(dupes);
}
I'm looking for an implementation of a three dimensional circular buffer in C# .NET that allows me to extract slices of the buffer.
I tried the multidimensional array but it doesn't allow me to get a specific slice of the buffer.
I also tried to implement a version using jagged array, but i have find some problems in understanding how to initialzie the matrix, and also in slice extraction.
Thanks for the help.
[EDIT 1]
The buffer will be used to store data from reltime sensors, it will be fixed in width height and the depth (time which be the circular part) will be defined by the user.
The slices i need will be a fixed size matrix (width and heigh with the data of a given time).
[EDIT 2]
The only implementation that i could implement that works. With the jagged array i'm still stuck at the declaration (i find it chaotic)
public class CircularBufferMatrix<T>
{
private readonly T[,,] _buffer;
public CircularBufferMatrix(int width, int height, int depth)
{
Width = width;
Height = height;
Depth = depth;
_buffer = new T[width, height, depth];
}
public T this[int x, int y, int z]
{
set { _buffer[x, y, z%Depth] = value; }
get { return _buffer[x, y, z%Depth]; }
}
#region Getters
public int Width { get; }
public int Height { get; }
public int Depth { get; }
#endregion
}
I would split these in two classes. You want something like a CircularBuffer class, which handles the reading and writing. The other could be an implementation of the 2D array you want to store. The reason of splitting these, is because you want to Read/write frames separately.
For example:
Circular buffer implementation:
public class CircularBuffer<T>
{
private T[] _buffer;
private int IncRollover(int value)
{
value++;
if (value >= _buffer.Length)
value = 0;
return value;
}
public CircularBuffer(int count)
{
_buffer = new T[count];
}
public bool Write(T element)
{
// if the writeindex (after increasing) equals the readindex, the buffer is full
var newWriteIndex = IncRollover(WriteIndex);
if (newWriteIndex == ReadIndex)
return false;
_buffer[WriteIndex] = element;
WriteIndex = newWriteIndex;
return true;
}
public bool TryRead(out T element)
{
if (ReadIndex == WriteIndex)
{
element = default(T);
return false;
}
element = _buffer[ReadIndex];
ReadIndex = IncRollover(ReadIndex);
return true;
}
public IEnumerable<T> ReadAll()
{
T element;
while (TryRead(out element))
yield return element;
}
public int ReadIndex { get; private set; }
public int WriteIndex { get; private set; }
}
This will take care of reading and writing induvidual 'frames'/slices. You can expand this class if you like to read on Index.
note: The write will return false if the buffer is full
This could be an implementation of the 2d buffers stored within the Circular buffer:
public class MyWhateverBuffer<T>
{
private CircularBuffer<T[,]> _buffer;
public int Width { get; private set; }
public int Height { get; private set; }
public int Depth { get; private set; }
public MyWhateverBuffer(int width, int height, int depth)
{
Width = width;
Height = height;
Depth = depth;
_buffer = new CircularBuffer<T[,]>(depth);
}
public T[,] New()
{
return new T[Width, Height];
}
public bool Add(T[,] buffer)
{
return _buffer.Write(buffer);
}
public bool TryRead(out T[,] buffer)
{
return _buffer.TryRead(out buffer);
}
public IEnumerable<T[,]> ReadAll()
{
return _buffer.ReadAll();
}
}
This class can be used like:
MyWhateverBuffer<double> myBuffer = new MyWhateverBuffer<double>(100, 100, 100);
var oneSlice = myBuffer.New();
oneSlice[10, 10] = 3.5;
oneSlice[50, 10] = 23.5;
oneSlice[10, 20] = 43.5;
myBuffer.Add(oneSlice);
var anotherSlice = myBuffer.New();
anotherSlice[10, 10] = 13.5;
anotherSlice[50, 10] = 23.5;
anotherSlice[10, 20] = 43.5;
var result = myBuffer.Add(anotherSlice);
if(!result)
{
// the buffer was full..
}
// Read the results from the buffer.
foreach(var slice in myBuffer.ReadAll())
{
Trace.WriteLine(slice[10, 10]);
}
You should always check if the buffer could be added. You don't want to lose info.
Side note:
The most profit gains with a Circular buffer is declaring the elements ones. Like big arrays will be reused every time.
If I understand your requirements correctly, you want a circular buffer consisting of items that are two dimensional arrays of data and the data from one item is never repeated in other items. C# doesn't have a cicular buffer type but you can always create one yourself:-
public class CircularBuffer <T> // make it generic
{
public class Iterator
{
public void MoveForward ();
public void MoveBackward ();
public T Item { get { } };
CicrcularBuffer <T> m_container;
LinkedListNode <T> m_current_item;
}
public void Add (T item);
public Iterator GetIterator ();
LinkedList<T> m_data;
}
Then create a class to contain your data:-
public class SensorData
{
// contains the two dimension data
}
And use it like:-
var buffer = new CircularBuffer <SensorData> ();
var iterator = buffer.GetIterator ();
var item = iterator.Item;
iterator.MoveForward ();
Obviously, there's a lot to be filled in but it should get you started.
class Knight
{
public static readonly double LegalDistance = Math.Sqrt(5);
public Stack<Field> Steps { get; set; }
private static readonly List<Field> board = Board.GameBoard;
private static List<Field> fields;
private static readonly Random random = new Random();
private static readonly object synLock = new object();
public Knight(Field initial)
{
Steps = new Stack<Field>();
Steps.Push(initial);
}
public void Move()
{
Field destination = Choose();
if (destination == null)
{
return;
}
Console.WriteLine("Moving from " + GetPosition().GetFieldName() + " to " + destination.GetFieldName());
Steps.Push(destination);
}
public Field Back()
{
Field from = Steps.Pop();
Console.WriteLine("Moving back from " + from.GetFieldName() + " to " + GetPosition().GetFieldName());
return from;
}
public Field Choose()
{
List<Field> legalMoves = Behaviour();
legalMoves.RemoveAll(field => Steps.Contains(field, new FieldValueComparer()));
if (legalMoves.Count == 0)
{
return null;
}
Field theChoosenOne;
int index;
lock (synLock)
{
index = random.Next(0, legalMoves.Count);
}
theChoosenOne = legalMoves.ElementAt(index);
return theChoosenOne;
}
private List<Field> Behaviour()
{
fields = new List<Field>();
fields.AddRange(board);
for (int i = fields.Count - 1; i >= 0; i--)
{
double actualDistance = fields[i].GetDistance(GetPosition());
if (!actualDistance.Equals(LegalDistance))
{
fields.Remove(fields[i]);
}
}
return fields;
}
public List<Field> GetSteps()
{
return Steps.ToList();
}
public Field GetPosition()
{
return Steps.Peek();
}
}
So this is how I'd do the stuff. The problem is, I am missing some key functionality, because on low given stepcount it backtracks to the start, on high stepcount, it causes StackOverFlow.
Here are some other functions to let you understand what I want to do:
Calculating distance:
public double GetDistance(Field other)
{
return Math.Sqrt(Math.Pow(other.X - X, 2) + Math.Pow(other.Y - Y, 2));
}
Finding the path:
class PathFinder
{
public static void FindPath(Knight knight)
{
if (knight.Steps.Count != 20)
{
knight.Move();
FindPath(knight);
knight.Back();
}
}
}
Your path search is essentially random walk. On large board, this may take a while anyway.
Now about StackOverflow: notice that you don't push anything on Move() when there are no places to go. So, on recursive call to FindPath() there still will be the same knight.Steps.Count, the same position, the same null return on Choose()... and so on, until you're out of stack space.
Obvious fix would be to add bool return value to Move() indicating if there was any move. Unless there is actual reason behind using random moves, more deterministic search algorithm is recommended.
I'm stuck one an exercise which is very important to understand for my soon come final exam, in a basic C# course.
I have an issue that I can't describe in words. So I'll show you with code and perhaps then you might help me.
I've been stuck on this, not being able to solve it, for a long time. Cuz of that, I don't want any copy paste code. I want to understand it. So please enlighten me where I've failed.
Explanation what I want to do.
I want to create a dart game 501. So first I add players, they throw their darts, you get the score after each turn announced, then when one player reach 501 points, the game announce the winner and all of his throws.
My idea of approaching the problem is to have an add player loop, which terminates (I got this fixed already).
Once you done creating the players(list elements), then you'll execute the methods with a foreach loop running all the players in the player list, executing the objects one at a time and finally Here is my real problem: storing all their scores in another list.
Here we go with the code
The list.
private List<Player> players = new List<Player>(); //This list is fine
Here is the loop.
foreach (Player dartThrows in players) //My loop
{
dartThrows.DoThrow();
dartThrows.GetScore();
}
SubClass1(named Player)
public List<Darts> dartList = new List<Darts>(); //<--HERE IS THE PROBLEM
Just some random constructors and methods.
The throw method. It's not an issue but I typed it down to give you an idea
public void DoThrow()
{
var tries = 3;
for (int i = 0; i < tries; i++)
{
//No problems here just int read-user input data
}
AddDarts(int a, int b, intc)
}
Here lies all my problems, it would make my life so much easier if this could get solved.
public void AddDarts(Darts toDartList)
{
dartList.Add(toDartList);
}
SubClass2 (Darts)
Here are my constructors
private int dartOne;
private int dartOne;
private int dartOne;
Here is my method
public Darts(int DartOne, int DartTwo, int DartThree)
{
dartOne = DartOne;
dartTwo = DartTwo;
dartThree = DartThree;
}
Best regards Marcus Johansson
Here is my full program
class Program
{
static void Main(string[] args)
{
Game game = new Game();
game.PlayGame();
}
}
class Game
{
private List<Player> players = new List<Player>();
private List<Player> computers = new List<Player>();
public void AddPlayer(string newPlayers)
{
players.Add(new Player(newPlayers));
}
public void AddComputer(string newComputer)
{
computers.Add(new Player(newComputer));
}
static string UpperCaseFirst(string s)
{
if (string.IsNullOrEmpty(s))
{
return string.Empty;
}
return char.ToUpper(s[0]) + s.Substring(1);
}
public void PlayGame()
{
bool noWinner = false;
bool stopLoop = false;
Console.WriteLine("<<<WELCOME TO DART 501>>>");
Console.WriteLine("\nPress [S] to start game!");
Console.Beep();
Console.ReadLine();
Console.Clear();
do
{
Console.WriteLine("Enter name of players and type [D]ator for adding NPC\nType [S]top to start the game");
string addPlayer = Console.ReadLine();
string FirstUpperLetter = UpperCaseFirst(addPlayer);
if (FirstUpperLetter == "Stop" || FirstUpperLetter == "S")
{
stopLoop = true;
}
if (FirstUpperLetter == "D" || FirstUpperLetter == "Dator")
{
string computer = FirstUpperLetter;
AddComputer(computer);
}
else
{
AddPlayer(FirstUpperLetter);
}
} while (stopLoop == false) ;
players.RemoveAt(players.Count - 1);
do
{
Console.Clear();
foreach (Player arrowThrows in players)
{
noWinner = true;
Console.WriteLine("\n~~~Starting Round~~~~");
arrowThrows.DoThrow();
Console.WriteLine("This round you got {0}", arrowThrows.CalculatePoints());
if (arrowThrows.Score > 501)
{
Console.Clear();
Console.WriteLine("<<<WE HAVE A WINNER>>>");
System.Threading.Thread.Sleep(500);
Console.WriteLine("...The winner is: ");
System.Threading.Thread.Sleep(1000);
Console.WriteLine("{0} He made these epic throws: ", arrowThrows.Name);
foreach(Arrows finalResult in arrowThrows.arrowList)
{
Console.WriteLine(finalResult);
Console.ReadLine();
}
noWinner = false;
}
}
foreach (Player computerThrows in computers)
{
computerThrows.RandomThrow();
System.Threading.Thread.Sleep(500);
}
}while(noWinner == true);
}
}
class Player
{
public List<Arrows> arrowList = new List<Arrows>();
public List<int> ScoreBoard = new List<int>();
public Player() { }
public int Score { get; set; }
public Player(int score)
{
Score = score;
}
public string Name { get; set; }
public Player(string name)
{
Name = name;
}
public int RoundScore { get; set; }
public void RandomThrow()
{
Random rndComp = new Random();
Console.WriteLine("...Loading Npc_throw.exe");
System.Threading.Thread.Sleep(300);
int random1 = rndComp.Next(0, 60);
System.Threading.Thread.Sleep(300);
int random2 = rndComp.Next(0, 60);
System.Threading.Thread.Sleep(300);
int random3 = rndComp.Next(0, 60);
Console.WriteLine("Random computer got this random score {0}", random1 + random2 + random3);
arrowList.Add(new Arrows(random1, random2, random3));
}
public void DoThrow()
{
Console.WriteLine("###{0} make your throws###", Name);
var tries = 3;
for (int i = 0; i < tries; i++)
{
Console.WriteLine("\nEnter score for {0} arrow", i + 1);
string arrowScore = Console.ReadLine();
int addScore = int.Parse(arrowScore);
while(-1 > addScore || 61 < addScore)
{
Console.WriteLine("\nInvalid score! Enter a score between 0-60/n<<<You may type [R]andom or [R] for a random score>>>");
arrowScore = Console.ReadLine().ToUpper();
if (arrowScore == "R" || arrowScore == "RANDOM")
{
Random rnd = new Random();
addScore = rnd.Next(0, 60);
goto start;
}
else
{
addScore = int.Parse(arrowScore);
}
}
start:
ScoreBoard.Add(addScore);
}
ScoreBoard.ToArray();
arrowList.Add(new Arrows(ScoreBoard[0],ScoreBoard[1], ScoreBoard[2]));
}
public int CalculatePoints()
{
Score = ScoreBoard.Sum();
return Score;
}
public void AddArrows(Arrows toArrowList)
{
toArrowList.ToString();
arrowList.Add(new Arrows(ScoreBoard[0], ScoreBoard[1], ScoreBoard[2]));
}
}
class Arrows
{
private int arrowOne;
private int arrowTwo;
private int arrowThree;
public int score { get; set; }
public Arrows(int ArrowOne, int ArrowTwo, int ArrowThree)
{
arrowOne = ArrowOne;
arrowTwo = ArrowTwo;
arrowThree = ArrowThree;
}
public int GetScore()
{
return arrowOne + arrowTwo + arrowThree;
}
public override string ToString()
{
return string.Format("{0}-1:st arrow: {1}-2:nd arrow: {2}- 3:rd arrow: {3}", GetScore(), arrowOne, arrowTwo, arrowThree);
}
}
}
The problem with your approach, is your utilizing a List. This collection has no unique information, simply a grouping of data. Which would have me recommend either a Tuple, Dictionary, KeyValuePair, or a clean Data Model.
Without the requirements are approaches may not be viable. Your issue stems from persistence related issues. Your multiple inheritance title is also incorrect, C# only allows a single class to be inherited.
What I would potentially do would be:
public class Player
{
public string Name { get; set; }
public string Throw { get; set; }
public string Points { get; set; }
}
What this does, is incredibly beneficial. The above class represents a specific Model. When your method is called for a throw you apply said results. Then when you calculate the score you iterate through the List<Player> for a specific person or all and display the output.
I'm not going to write your application, but think of it like this:
Player Registers
Player Turn
Player Throws
Play Scored
Store Player Result
Repeat Steps two through five, three times.
Display Output: Player, Throw, Score, and Total Score
By utilizing that model, you hold the relative information for your outcome. This conceptual notion is important for Object Oriented Programming.
You can use a Dictionary to save scores for each player
Dictionary<Player, List<int>> playerScores = new Dictionary<Player, List<int>>();
playerScores.Add(player1, new List<int>()); //init dictionary with a new player
playerScores[player1].Add(number); //add a value to the list associated with the player
So each player has a list of scores.