Random.Range is picking two gameobjects instead of one - c#

I have created code for a question generator but every now and then my random.range is picking two of my gameobjects(out of 20). The code should work but something is causing it to pick two. Is it a bug with unity or the code itself? I have created a list and then when the number is picked it should the delete it from the list preventing any number duplication's(same question asked twice).
public GameObject Question1, Question2, Question3, Question4, Question5, Question6, Question7, Question8, Question9, Question10, Question11, Question12, Question13, Question14, Question15, Question16, Question17, Question18, Question19, Question20;
public GameObject VerdictGood, VerdictBad;
public GameObject box_QA;
public courtDialogue _courtDialogue;
List<int> list = new List<int>();
private int i, index, calculate, maxquestions;
public bool neverdone;
public void Start()
{
box_QA.SetActive(false);
calculate = 0;
for (int n = 1; n < 21; n++)
{
list.Add(n);
}
}
void Update()
{
DeleteQuestions();
}
public void CheckQuestion()
{
index = Random.Range(0, list.Count - 1);
i = list[index];
Debug.Log(i);
list.RemoveAt(index);
}
public void WhatQuestion()
{
CheckQuestion();
if (i == 1)
{
Question1.SetActive(true);
Question2.SetActive(false);
Question3.SetActive(false);
Question4.SetActive(false);
Question5.SetActive(false);
Question6.SetActive(false);
Question7.SetActive(false);
Question8.SetActive(false);
Question9.SetActive(false);
Question10.SetActive(false);
Question11.SetActive(false);
Question12.SetActive(false);
Question13.SetActive(false);
Question14.SetActive(false);
Question15.SetActive(false);
Question16.SetActive(false);
Question17.SetActive(false);
Question18.SetActive(false);
Question19.SetActive(false);
Question20.SetActive(false);
}
}
void DeleteQuestions()
{
if (maxquestions == 10)
{
StopCoroutine("CheckQuestion");
StopCoroutine("WhatQuestion");
Destroy(Question1);
Destroy(Question2);
Destroy(Question3);
Destroy(Question4);
Destroy(Question5);
Destroy(Question6);
Destroy(Question7);
Destroy(Question8);
Destroy(Question9);
Destroy(Question10);
Destroy(Question11);
Destroy(Question12);
Destroy(Question13);
Destroy(Question14);
Destroy(Question15);
Destroy(Question16);
Destroy(Question17);
Destroy(Question18);
Destroy(Question19);
Destroy(Question20);
if (calculate > 7)
{
JudgeImage.GetComponent<Image>().color = new Color32(6, 255, 0, 255);
VerdictGood.SetActive(true);
Debug.Log("Not Quilty");
}
else
{
JudgeImage.GetComponent<Image>().color = new Color32(255, 0, 0, 255);
VerdictBad.SetActive(true);
Debug.Log("Not Quilty");
}
}
}
Console Output
public GameObject judgeFace;
public GameObject prosecutorFace;
public GameObject clientFace;
public GameObject courtQuestions;
public GameObject healthBar;
public int courtIntroCount; //This variable keeps track of whose line is next in the court dialogue scene.
public GameObject fullTextBox;
public Text nameText;
public Text mainText;
public float delay = 0.1f;
public string fullText;
private string currentText = "";
public GameManager2 _gameManager2;
// Use this for initialization
void Start ()
{
// courtQuestions.SetActive(false);
fullTextBox.SetActive(false);
healthBar.SetActive(false);
Invoke("CourtIntro1", 3);
}
IEnumerator ShowText()
{
for (int i = 0; i < fullText.Length; i++)
{
currentText = fullText.Substring(0, i);
mainText.GetComponent<Text>().text = currentText;
yield return new WaitForSeconds(delay);
}
}
// Update is called once per frame
public void CourtButtons()
{
if (courtIntroCount == 1)
CourtIntro2();
else if (courtIntroCount == 2)
CourtIntro3();
else if(courtIntroCount == 3)
CourtIntro4();
else if(courtIntroCount == 4)
CourtIntro5();
else if (courtIntroCount == 5)
CourtIntroEND();
// This needs to have a way of checking which question has been disabled after the answer has been selected
}
// COURT DIALOGUE _ INTRO SEQUENCE
public void CourtIntro1()
{
courtIntroCount = 1;
fullTextBox.SetActive(true);
judgeFace.SetActive(true);
nameText.text = "Judge";
StartCoroutine(ShowText());
currentText = "Court is now in-session. All rise.";
}
public void CourtIntro2()
{
courtIntroCount = 2;
fullTextBox.SetActive(true);
nameText.text = "Judge";
StartCoroutine(ShowText());
fullText = "Now, you, lawyer. Do you solemnly and sincerely and truly declare and affirm that the evidence you shall give shall be the truth, the whole truth and nothing but the truth?.";
}
public void CourtIntro3()
{
courtIntroCount = 3;
fullTextBox.SetActive(true);
nameText.text = "Judge";
StartCoroutine(ShowText());
fullText = "... Very good. Now, the prosecution would like to begin by asking the defence a number of questions..";
}
public void CourtIntro4()
{
courtIntroCount = 4;
fullTextBox.SetActive(true);
judgeFace.SetActive(false);
prosecutorFace.SetActive(true);
nameText.text = "Prosecutor";
StartCoroutine(ShowText());
fullText = "I would, Your Honour. I hope the defence will be able to answer them accurately and appropriately for you and the jury..";
}
public void CourtIntro5()
{
courtIntroCount = 5;
fullTextBox.SetActive(true);
prosecutorFace.SetActive(false);
clientFace.SetActive(true);
nameText.text = "Ellen";
StartCoroutine(ShowText());
fullText = "This is it! You'll need to convince the judge and jury that I'm not guilty. Best of luck!.";
}
public void CourtIntroEND()
{
courtIntroCount = 10;
clientFace.SetActive(false);
fullTextBox.SetActive(false);
//courtQuestions.SetActive(true);
healthBar.SetActive(true);
_gameManager2.box_QA.SetActive(true);
_gameManager2.WhatQuestion();
}

It would be nice to have more information about how this is structured, but based on what I see here, it looks like your WhatQuestion() method needs to know what the variable 'i' is. This is usually done by creating methods that accept parameters and return values. For this example, it looks like your CheckQuestion() method should return a value of 'i':
public int CheckQuestion()
{
//do some stuff
return i;
}
Then, your WhatQuestion() method should call CheckQuestion() to get 'i':
public void WhatQuestion()
{
i = CheckQuestion();
if (i == 1)
{
//Do your stuff
}
}
You may also need a way to de-activate all of the other questions so that only one is activated at a time. Something like
foreach (var question in QuestionList)
{
question.SetActive(false);
}
Then, to activate the one question:
QuestionList[i].SetActive(true);
Hope this info helps, it's my best guess with what's presented here.

Related

how to scramble words in sentence using C# and put in into array

i need help for fix my code from the lesson i get, i try to create simple script for scramble words in sentences like "the house is broken" became "broken the is house"..my code work as well but it scramble only by one word, like "THE" became "H.T.E",
i try to use string.split method but i dont understand where i must change the code was into array.
here my code and the result is
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
[System.Serializable]
public class Word
{
public string word;
[Header("biarkan kosong untuk acak otomatis")]
public string desiredRandom;
public string GetString()
{
if (!string.IsNullOrEmpty(desiredRandom))
{
return desiredRandom;
}
string result = word;
// **I'm try to split string here where i try to input that into array**
string[] array = result.Split(' ');
foreach (string token in array)
{
Debug.Log((token).ToString());
word = token;
}
result = "";
List<char> characters = new List<char>(word.ToCharArray());
while (characters.Count > 0)
{
int indexChar = Random.Range(0, characters.Count - 1);
result += characters[indexChar];
characters.RemoveAt(indexChar);
}
return result;
}
}
public class WordScramble : MonoBehaviour
{
public Word[] words;
[Header("UI Reference")]
public CharObject prefab;
public Transform container;
public float space;
public float lerpSpeed = 5;
List<CharObject> charObjects = new List<CharObject>();
CharObject firstSelected;
public int currentWord;
public static WordScramble main;
void Awake()
{
main = this;
}
// Use this for initialization
void Start()
{
ShowScramble(currentWord);
}
// Update is called once per frame
void Update()
{
RepositionObject();
}
void RepositionObject()
{
if (charObjects.Count == 0)
{
return;
}
float center = (charObjects.Count - 1) / 2;
for (int i = 0; i < charObjects.Count; i++)
{
charObjects[i].rectTransform.anchoredPosition
= Vector2.Lerp(charObjects[i].rectTransform.anchoredPosition,
new Vector2((i - center) * space, 0), lerpSpeed * Time.deltaTime);
charObjects[i].index = i;
}
}
public void ShowScramble()
{
ShowScramble(Random.Range(0, words.Length - 1));
}
public void ShowScramble(int index)
{
charObjects.Clear();
foreach (Transform child in container)
{
Destroy(child.gameObject);
}
if (index > words.Length - 1)
{
Debug.LogError("index out of range between 0-" + (words.Length - 1).ToString());
return;
}
// string result = huruf ;
// foreach (string words is word());
char[] chars = words[index].GetString().ToCharArray();
foreach (char c in chars)
{
CharObject clone = Instantiate(prefab.gameObject).GetComponent<CharObject>();
clone.transform.SetParent(container);
charObjects.Add(clone.Init(c));
}
currentWord = index;
}
public void Swap(int indexA, int indexB)
{
CharObject tmpA = charObjects[indexA];
charObjects[indexA] = charObjects[indexB];
charObjects[indexB] = tmpA;
charObjects[indexA].transform.SetAsLastSibling();
charObjects[indexB].transform.SetAsLastSibling();
CheckWord();
}
public void Select(CharObject charObject)
{
if (firstSelected)
{
Swap(firstSelected.index, charObject.index);
// unselect
//firstSelected = null;
firstSelected.Select();
charObject.Select();
}
else
{
firstSelected = charObject;
}
}
public void UnSelect()
{
firstSelected = null;
}
public void CheckWord()
{
StartCoroutine(CoCheckWord());
}
IEnumerator CoCheckWord()
{
yield return new WaitForSeconds(0.5f);
string word = "";
foreach (CharObject charObject in charObjects)
{
word += charObject.character;
}
if (word == words[currentWord].word)
{
currentWord++;
ShowScramble(currentWord);
}
}
}
this for a result
maybe i can get help for this problem, i'm still learn for C#, i'm sorry if my code is mess up
Your code is assigning the splits in a loop to the word variable over and over, overwriting word at each time. Then you are splitting word into its chars and try to shuffle them. You should instead shuffle the array of splits.
Example using LINQ:
public static string[] ScrambleSentence(string sentence)
{
var random = new Random();
return sentence.Split(' ').OrderBy(x => random.Next()).ToArray();
}
Here is a simple way to randomize word positions in a text
var rd = new Random();
string[] words = text.Split(' ').OrderBy(w => rd.Next()).ToArray();
// If you want a simple string instead of an array of words
string rdText = string.Join(" ", words);

Prevent System.StackOverflowException when recursively calling a method

I am new to c# (or coding in general) and I guess this question is really stupid and confusing (I know I'm doing it a hard way) but please help me.
I'm trying to make a minesweeper with form app. I made a 10 x 10 of buttons and if you click it, number of mines around it will be revealed. If a mine is there "F" (the first letter of "False") will appear.
There's a constructor that contains the button, x and y position, list of surrounding blocks, number of mines around it, and a boolean that indicates if there's a mine or not.
What I tried to do was to make the 8 surrounding blocks (from the list) cleared when the player clicked a block with no mine around it and if the block surrounding that block also doesn't have any mine around it, these blocks that surrounding that block will also be cleared. The method uses foreach to reveal and check the number of mines around that block. If there's no mines, same method will be applied to that block (calling the method recursively). The problem is that I keep getting System.StackOverflowException.
I somehow understand why it's happening but I just can't come up with the other way.
//scroll to the bottom for the method with the problem
private void Form1_Load(object sender, EventArgs e)
{
Random random = new Random();
Button[,] buttons = new Button[10, 10]
{
{ r0c0, r0c1, r0c2, r0c3, r0c4, r0c5, r0c6, r0c7, r0c8, r0c9 },
{ r1c0, r1c1, r1c2, r1c3, r1c4, r1c5, r1c6, r1c7, r1c8, r1c9 },
{ r2c0, r2c1, r2c2, r2c3, r2c4, r2c5, r2c6, r2c7, r2c8, r2c9 },
{ r3c0, r3c1, r3c2, r3c3, r3c4, r3c5, r3c6, r3c7, r3c8, r3c9 },
{ r4c0, r4c1, r4c2, r4c3, r4c4, r4c5, r4c6, r4c7, r4c8, r4c9 },
{ r5c0, r5c1, r5c2, r5c3, r5c4, r5c5, r5c6, r5c7, r5c8, r5c9 },
{ r6c0, r6c1, r6c2, r6c3, r6c4, r6c5, r6c6, r6c7, r6c8, r6c9 },
{ r7c0, r7c1, r7c2, r7c3, r7c4, r7c5, r7c6, r7c7, r7c8, r7c9 },
{ r8c0, r8c1, r8c2, r8c3, r8c4, r8c5, r8c6, r8c7, r8c8, r8c9 },
{ r9c0, r9c1, r9c2, r9c3, r9c4, r9c5, r9c6, r9c7, r9c8, r9c9 }
};
Square[,] squares = new Square[10, 10];
for (int i = 0, ii = 0, iii = 0; i < 100; i++, ii++)
{
if (ii == 10)
{
ii = 0;
iii++;
}
squares[ii, iii] = new Square(i, buttons[ii, iii], ii, iii, 0, true);
}
List<int> randoms = new List<int>();
for (int i = 0; i < 10; i++)
{
int ii = random.Next(100);
if (!randoms.Contains(ii))
{
squares[ii % 10, ii / 10].setSafe(false);
}
else
{
i--;
}
randoms.Add(ii);
}
for (int i = 0; i < 10; i++)
{
for (int ii = 0; ii < 10; ii++)
{
for (int iii = -1; iii < 2; iii++)
{
for (int iiii = -1; iiii < 2; iiii++)
{
try
{
if (squares[i + iii, ii + iiii].getSafe() == false)
squares[i, ii].addNumber();
}
catch (System.IndexOutOfRangeException)
{
}
}
//if (squares[i, ii].getSafe() == false) squares[i, ii].getButton().Text = squares[i, ii].getSafe().ToString();
//else squares[i, ii].getButton().Text = squares[i, ii].getNumber().ToString();
}
}
}
for (int i = 0; i < 10; i++)
{
for (int ii = 0; ii < 10; ii++)
{
for (int iii = -1; iii < 2; iii++)
{
for (int iiii = -1; iiii < 2; iiii++)
{
try
{
squares[i, ii].addList(squares[i + iii, ii + iiii]);
}
catch (System.IndexOutOfRangeException)
{
}
}
}
}
}
}
Here's the Square class:
public class Square
{
int id;
Button button;
int x;
int y;
int number;
bool safe;
List<Square> list = new List<Square>();
public Square(int id, Button button, int x, int y, int number, bool safe)
{
this.id = id;
this.button = button;
this.x = x;
this.y = y;
this.number = number;
this.safe = safe;
button.Text = "";
button.Click += button_Click;
}
public int getId()
{
return id;
}
public void setId(int i)
{
id = i;
}
public Button getButton()
{
return button;
}
public void setButton(Button b)
{
button = b;
}
public int getX()
{
return x;
}
public void setX(int i)
{
x = i;
}
public int getY()
{
return y;
}
public void setY(int i)
{
y = i;
}
public int getNumber()
{
return number;
}
public void setNumber(int i)
{
number = i;
}
public void addNumber()
{
number++;
}
public bool getSafe()
{
return safe;
}
public void setSafe(bool b)
{
safe = b;
}
private void button_Click(object sender, EventArgs e)
{
if (getSafe() == false) button.Text = getSafe().ToString();
else button.Text = getNumber().ToString();
if (getNumber() == 0) zeroReveal();
}
//---------------------------------------------------
// this is the method that reveals surrounding blocks
//---------------------------------------------------
private void zeroReveal()
{
foreach (Square s in list)
{
//revealing the blocks
s.getButton().Text = s.getNumber().ToString();
//call the same method if there's no mine
//this is the line that keeps giving me exception
if (s.getNumber() == 0) s.zeroReveal();
}
}
//-----------------------------------------------------
public List<Square> getList()
{
return list;
}
public void setList(List<Square> sl)
{
list = sl;
}
public void addList(Square s)
{
list.Add(s);
}
}
I am new to c# (or coding in general) and I guess this question is really stupid and confusing (I know I'm doing it a hard way)
This topic confuses many a new developer; don't stress out about it!
If there's no mines, same method will be applied to that block (calling the method recursively).
Recursive methods can be confusing but if you design them using the standard pattern, you will avoid SO exceptions. You have not designed yours using the standard pattern.
The standard pattern for successful recursive methods is:
Am I in a case that requires no recursion?
If yes, do the necessary computations to produce the desired effect and return. The problem is now solved.
If no, then we're going to recurse.
Break the current problem down into some number of smaller problems.
Solve each smaller problem by recursing.
Combine the solutions of the smaller problem to solve the current problem.
The problem is now solved, so return.
The most important thing about designing a recursive method is that each recursion must be solving a smaller problem, and the sequence of smaller problems must bottom out at a case that does not require recursion. If those two conditions are not met, then you will get a stack overflow.
Internalize that pattern, and every time you write a recursive method, actually write it out:
int Frob(int blah)
{
if (I am in the base case)
{
solve the base case
return the result
}
else
{
find smaller problems
solve them
combine their solutions
return the result
}
}
Fill in that template with your real code, and you will be much more likely to avoid stack overflows. I've been writing recursive methods for decades, and I still follow this pattern.
Now, in your example, what is the case that does not require recursion? There must be one, so write down what it is. Next, how will you guarantee that the recursion solves a smaller problem? That is often the hard step! Give it some thought.
The stack overflow is occurring because zeroReveal is recursively calling itself forever. To fix this we need to find ways where we do not need it to make further calls to itself.
The name of the method gives us a clue. If the square has already been revealed, then surely the method does not need to do anything, since it has already been revealed.
It looks like the button's Text property is an empty string if it has not yet been revealed. So change the foreach so that it doesn't process squares that have already been revealed:
foreach (Square s in list)
{
if (s.getButton().Text == ""))
{
// existing code in the foreach loop goes here
}
}

How to optimize recursive function for a graph for clearing and settlement

I have to make a module in an Insurance application that deals with clearing and settlement (I think this is the correct financial terminology) between insurance companies enroled in the system. Practically, the system must pair all the amounts that companies have to pay to one another, and only the unpaired (remaining) sums to be paid through the bank. For now there are about 30 companies in the system.
All the readings I did about clearing and settlement pointed me towards graphs and graphs theory (which I have studied in the highschool quite a long time ago).
For a system with 4 companies the graph would look like this:
where each company represents a node (N1 ... N4) and each weighted edge represents the amount that a company has to pay to the other. In my code, the nodes are int, representing the id's of the companies.
What I did so far... I created the graph (for test I used the Random generator for the amounts) and made a recursive function to calculate all posible cycles in the graph. Then I made another recursive function that takes all non-zero cycles starting with the longest path with maximum common sum to pair.
The algorithm seems valid in terms of final results, but for graphs bigger than 7-8 nodes it takes too long to complete. The problem is in the recursive function that creates the possible cycles in the graph. Here is my code:
static void Main(string[] args)
{
int nodes = 4;
try
{
nodes = Convert.ToInt32(args[0]);
}
catch { }
DateTime start = DateTime.Now;
Graph g = new Graph(nodes);
int step = 0;
double CompensatedAmount = 0;
double TotalCompensatedAmount = 0;
DateTime endGeneration = DateTime.Now;
Console.WriteLine("Graph generated in: " + (endGeneration - start).TotalSeconds + " seconds.");
Compensare.RunCompensation(false, g, step, CompensatedAmount, TotalCompensatedAmount, out CompensatedAmount, out TotalCompensatedAmount);
DateTime endCompensation = DateTime.Now;
Console.WriteLine("Graph compensated in: " + (endCompensation - endGeneration).TotalSeconds + " seconds.");
}
... and the main class:
public static class Compensare
{
public static void RunCompensation(bool exit, Graph g, int step, double prevCompensatedAmount, double prevTotalCompensatedAmount, out double CompensatedAmount, out double TotalCompensatedAmount)
{
step++;
CompensatedAmount = prevCompensatedAmount;
TotalCompensatedAmount = prevTotalCompensatedAmount;
if (!exit)
{
List<Cycle> orderedList = g.Cycles.OrderByDescending(x => x.CycleCompensatedAmount).ToList();
g.ListCycles(orderedList, "OrderedCycles" + step.ToString() + ".txt");
using (Graph clona = g.Clone())
{
int maxCycleIndex = clona.GetMaxCycleByCompensatedAmount();
double tmpCompensatedAmount = clona.Cycles[maxCycleIndex].CycleMin;
exit = tmpCompensatedAmount <= 0 ? true : false;
CompensatedAmount += tmpCompensatedAmount;
TotalCompensatedAmount += (tmpCompensatedAmount * clona.Cycles[maxCycleIndex].EdgesCount);
clona.CompensateCycle(maxCycleIndex);
clona.UpdateCycles();
Console.WriteLine(String.Format("{0} - edges: {4} - min: {3} - {1} - {2}\r\n", step, CompensatedAmount, TotalCompensatedAmount, tmpCompensatedAmount, clona.Cycles[maxCycleIndex].EdgesCount));
RunCompensation(exit, clona, step, CompensatedAmount, TotalCompensatedAmount, out CompensatedAmount, out TotalCompensatedAmount);
}
}
}
}
public class Edge
{
public int Start { get; set; }
public int End { get; set; }
public double Weight { get; set; }
public double InitialWeight {get;set;}
public Edge() { }
public Edge(int _start, int _end, double _weight)
{
this.Start = _start;
this.End = _end;
this.Weight = _weight;
this.InitialWeight = _weight;
}
}
public class Cycle
{
public List<Edge> Edges = new List<Edge>();
public double CycleWeight = 0;
public double CycleMin = 0;
public double CycleMax = 0;
public double CycleAverage = 0;
public double CycleCompensatedAmount = 0;
public int EdgesCount = 0;
public Cycle() { }
public Cycle(List<Edge> _edges)
{
this.Edges = new List<Edge>(_edges);
UpdateCycle();
}
public void UpdateCycle()
{
UpdateCycle(this);
}
public void UpdateCycle(Cycle c)
{
double sum = 0;
double min = c.Edges[0].Weight;
double max = c.Edges[0].Weight;
for(int i=0;i<c.Edges.Count;i++)
{
sum += c.Edges[i].Weight;
min = c.Edges[i].Weight < min ? c.Edges[i].Weight : min;
max = c.Edges[i].Weight > max ? c.Edges[i].Weight : max;
}
c.EdgesCount = c.Edges.Count;
c.CycleWeight = sum;
c.CycleMin = min;
c.CycleMax = max;
c.CycleAverage = sum / c.EdgesCount;
c.CycleCompensatedAmount = min * c.EdgesCount;
}
}
public class Graph : IDisposable
{
public List<int> Nodes = new List<int>();
public List<Edge> Edges = new List<Edge>();
public List<Cycle> Cycles = new List<Cycle>();
public int NodesCount { get; set; }
public Graph() { }
public Graph(int _nodes)
{
this.NodesCount = _nodes;
GenerateNodes();
GenerateEdges();
GenerateCycles();
}
private int FindNode(string _node)
{
for(int i = 0; i < this.Nodes.Count; i++)
{
if (this.Nodes[i].ToString() == _node)
return i;
}
return 0;
}
private int FindEdge(string[] _edge)
{
for(int i = 0; i < this.Edges.Count; i++)
{
if (this.Edges[i].Start.ToString() == _edge[0] && this.Edges[i].End.ToString() == _edge[1] && Convert.ToDouble(this.Edges[i].Weight) == Convert.ToDouble(_edge[2]))
return i;
}
return 0;
}
public Graph Clone()
{
Graph clona = new Graph();
clona.Nodes = new List<int>(this.Nodes);
clona.Edges = new List<Edge>(this.Edges);
clona.Cycles = new List<Cycle>(this.Cycles);
clona.NodesCount = this.NodesCount;
return clona;
}
public void CompensateCycle(int cycleIndex)
{
for(int i = 0; i < this.Cycles[cycleIndex].Edges.Count; i++)
{
this.Cycles[cycleIndex].Edges[i].Weight -= this.Cycles[cycleIndex].CycleMin;
}
}
public int GetMaxCycleByCompensatedAmount()
{
int toReturn = 0;
for (int i = 0; i < this.Cycles.Count; i++)
{
if (this.Cycles[i].CycleCompensatedAmount > this.Cycles[toReturn].CycleCompensatedAmount)
{
toReturn = i;
}
}
return toReturn;
}
public void GenerateNodes()
{
for (int i = 0; i < this.NodesCount; i++)
{
this.Nodes.Add(i + 1);
}
}
public void GenerateEdges()
{
Random r = new Random();
for(int i = 0; i < this.Nodes.Count; i++)
{
for(int j = 0; j < this.Nodes.Count; j++)
{
if(this.Nodes[i] != this.Nodes[j])
{
int _weight = r.Next(0, 500);
Edge e = new Edge(this.Nodes[i], this.Nodes[j], _weight);
this.Edges.Add(e);
}
}
}
}
public void GenerateCycles()
{
for(int i = 0; i < this.Edges.Count; i++)
{
FindCycles(new Cycle(new List<Edge>() { this.Edges[i] }));
}
this.UpdateCycles();
}
public void UpdateCycles()
{
for (int i = 0; i < this.Cycles.Count; i++)
{
this.Cycles[i].UpdateCycle();
}
}
private void FindCycles(Cycle path)
{
List<Edge> nextPossibleEdges = GetNextEdges(path.Edges[path.Edges.Count - 1].End);
for (int i = 0; i < nextPossibleEdges.Count; i++)
{
if (path.Edges.IndexOf(nextPossibleEdges[i]) < 0) // the edge shouldn't be already in the path
{
Cycle temporaryPath = new Cycle(path.Edges);
temporaryPath.Edges.Add(nextPossibleEdges[i]);
if (nextPossibleEdges[i].End == temporaryPath.Edges[0].Start) // end of path - valid cycle
{
if (!CycleExists(temporaryPath))
{
this.Cycles.Add(temporaryPath);
break;
}
}
else
{
FindCycles(temporaryPath);
}
}
}
}
private bool CycleExists(Cycle cycle)
{
bool toReturn = false;
if (this.Cycles.IndexOf(cycle) > -1) { toReturn = true; }
else
{
for (int i = 0; i < this.Cycles.Count; i++)
{
if (this.Cycles[i].Edges.Count == cycle.Edges.Count && !CompareEdges(this.Cycles[i].Edges[0], cycle.Edges[0]))
{
bool cycleExists = true;
for (int j = 0; j < cycle.Edges.Count; j++)
{
bool edgeExists = false; // if there is an edge not in the path, then the searched cycle is diferent from the current cycle and we can pas to the next iteration
for (int k = 0; k < this.Cycles[i].Edges.Count; k++)
{
if (CompareEdges(cycle.Edges[j], this.Cycles[i].Edges[k]))
{
edgeExists = true;
break;
}
}
if (!edgeExists)
{
cycleExists = false;
break;
}
}
if (cycleExists) // if we found an cycle with all edges equal to the searched cycle, then the cycle is not valid
{
toReturn = true;
break;
}
}
}
}
return toReturn;
}
private bool CompareEdges(Edge e1, Edge e2)
{
return (e1.Start == e2.Start && e1.End == e2.End && e1.Weight == e2.Weight);
}
private List<Edge> GetNextEdges(int endNode)
{
List<Edge> tmp = new List<Edge>();
for(int i = 0; i < this.Edges.Count; i++)
{
if(endNode == this.Edges[i].Start)
{
tmp.Add(this.Edges[i]);
}
}
return tmp;
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects).
this.Nodes = null;
this.Edges = null;
this.Cycles = null;
this.NodesCount = 0;
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~Graph() {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
I've found several articles/answers about graphs, both in Java and C# (including quickgraph), but they mainly focus on directed graphs (without cycles).
I have also read about tail call optimization, for recursion, but I don't know if/how to implement in my case.
I now there is a lot to grasp about this subject, but maybe someone had to deal with something similar and can either help me optimize the code (which as I said seems to do the job in the end), either point me to another direction to rethink the whole process.
I think you can massively simplify this.
All money is the same, so (using your example) N1 doesn't care whether it gets 350 from N2 and pays 150 to N2 and so on - N1 merely cares that overall it ends up 145 down (if I've done the arithmetic correctly). Similarly, each other N only cares about its overall position. So, summing the inflows and outflows at each node, we get:
Company Net position
N1 -145
N2 -65
N3 +195
N4 +15
So with someone to act as a central clearing house - the bank - simply arrange for N1 and N2 to pay the clearing house 145 and 65 respectively, and for N3 and N4 to receive 195 and 15 respectively from the clearing house. And everyone's happy.
I may have missed some aspect, of course, in which case I'm sure someone will point it out...

How can I improve this logic? C#

I have a library that returns CS:GO stats in real-time from the game. I'm making a program that stores the stats and analyse it.
I have this function:
private void UpdateKills(GameState gs)
{
int currentKills = -1;
if (lastKills == -1) // first time getting player info
{
int temp = gs.Player.MatchStats.Kills;
currentKills = temp;
lastKills = temp;
}
else
{
currentKills = gs.Player.MatchStats.Kills;
int dif = currentKills - lastKills;
if (currentKills == 0 && lastKills != 0) // maybe changed server/map/whatever
{
lastKills = -1;
}
else
{
if (dif != 0 && dif > 0) // player killed someone AND it was not teamkill
{
ps.Kills += dif; // add the kills to the main variable
lastKills = currentKills;
dif = 0;
playSimpleSound();
}
}
}
}
This is my function that handles the kills. The most of the time it works very well, but sometimes it just freaks out, and I don't know if the problem is my logic or if it is a library problem.
Note: I'm using this library: github.com/rakijah/CSGSI
My logic is:
Get the player kills
Increment those kills in the PlayerStats object.
Is my code logically correct? Can my code be more "correct"?
I'm still not entirely sure what this function is supposed to be doing, but I simplified it for you:
private void UpdateKills(GameState gs)
{
lastKills = currentKills;
int currentKills = gs.Player.MatchStats.Kills;
int diff = currentKills - lastKills;
if (currentKills == 0 && lastKills != 0) // maybe changed server/map/whatever
{
lastKills = -1;
}
else if (diff > 0) // player killed someone AND it was not teamkill
{
ps.Kills += diff; // add the kills to the main variable
playSimpleSound();
}
}
Well, after some research in finally undertand your problem. You DON'T have to do anything!, the API does all the work for you, watch the next image:
As you can see, the console app shows my steam name, the map and kills. I start with zero kills, then I kill a teammate and after that an enemy. The API created by #rakijah autoupdates those values.
Now the code:
static void Main(string[] args)
{
CsGoIntegration();
}
private static void CsGoIntegration()
{
var gsl = new GameStateListener(3000);
gsl.NewGameState += new NewGameStateHandler(OnNewGameState);
if (!gsl.Start())
{
Environment.Exit(0);
}
System.Console.WriteLine("Listening...");
}
private static void OnNewGameState(GameState gs)
{
System.Console.WriteLine("Map: {0}", gs.Map.Name);
System.Console.WriteLine("Player Name: {0}", gs.Player.Name);
System.Console.WriteLine("Player Kills: {0}", gs.Player.MatchStats.Kills);
}
UPDATE: The OP needs to store the total kills even when the map changes. I experimented with paper and pencil, please try running the program and tell me if it worked or not
private static void Main()
{
CsGoIntegration();
}
private static void CsGoIntegration()
{
var gsl = new GameStateListener(3000);
gsl.NewGameState += OnNewGameState;
if (!gsl.Start())
{
Environment.Exit(0);
}
Console.WriteLine("Listening...");
}
private static void OnNewGameState(GameState gameState)
{
SaveMatchsData(gameState);
}
private static int? _totalKillScore;
private static string _lastMapName;
private static int? _lastKillScore;
private static void SaveMatchsData(GameState gameState)
{
const string undefinedString = "Undefined";
// If the SaveMatchsData is running and the CSGO server is offline
if (gameState.Map.Name == undefinedString && string.IsNullOrEmpty(_lastMapName))
return;
// When the match is not started, the Round is -1
if (gameState.Map.Name != undefinedString && gameState.Map.Round > -1)
{
if (string.IsNullOrEmpty(_lastMapName))
{
UpdateData(gameState, true);
}
else
{
// Same map
if (_lastMapName == gameState.Map.Name)
{
// Check if the Score Changes
if (_lastKillScore == gameState.Player.MatchStats.Kills) return;
UpdateData(gameState);
}
// The Map Changes
else
{
UpdateData(gameState, true);
}
}
}
}
private static void UpdateData(GameState gameState, bool updateMap = false)
{
if (updateMap)
_lastMapName = gameState.Map.Name;
_lastKillScore = gameState.Player.MatchStats.Kills;
_totalKillScore += gameState.Player.MatchStats.Kills;
}
Cheers.

How to add integers in different methods

I'm very new to C# and have a very limited understanding of the "proper code" to use. I had the goal to imitate the old Pokemon battle systems as best I could with what I know and am having a hard time linking a stored int value for HP between two methods (assuming that's the right word), to calculate new Hp when the second method interacts with the main method. Had a hard time finding an answer for that in searches so here is the code:
" static void Main(string[] args)
{
Random Gen = new Random();
int enemyhealth = (150);
int playerhealth = (100); //the line i need to use
int edefense = (20);
int pattack = (30);
int rate = Gen.Next(1,5);
int critical = 0; "
static void enemyattack()
{
Random Gen1 = new Random();
int pdefense = (20);
int eattack = (20);
int erate = Gen1.Next(1, 5);
int ratattack = Gen1.Next(1,3);
int critical1 = 0;
Console.WriteLine("Enemy Ratta gets ready!");
Console.ReadKey();
Console.WriteLine("----------------------------------------------------------------------------");
Console.WriteLine("\nEnemy Ratta attacks!\n");
Console.WriteLine("----------------------------------------------------------------------------");
ratattack = Gen1.Next(1,3);
if (ratattack = 1)
{
Console.WriteLine("Enemy Ratta used Tail Whip!");
pdefense = (pdefense - erate);
Console.ReadKey();
Console.WriteLine("----------------------------------------------------------------------------");
erate = Gen1.Next(1, 5);
if (erate <= 3)
{
Console.WriteLine("\nIt wasn't very effective!");
}
else
{
Console.WriteLine("\nIt was super effective!");
}
Console.WriteLine("Squirtle's Defense decreased by " + erate + "");
Console.WriteLine("----------------------------------------------------------------------------");
}
else if (ratattack == 2)
{
Console.WriteLine("\nRatta used Tackle");
erate = Gen1.Next(1, 5);
if (erate >= 5)
{
Console.WriteLine("----------------------------------------------------------------------------");
Console.WriteLine("----------------------------------------------------------------------------");
Console.WriteLine("\nCRITICAL HIT!!!!");
Console.WriteLine("----------------------------------------------------------------------------");
Console.WriteLine("----------------------------------------------------------------------------\n");
Console.ReadKey();
Console.WriteLine("It was super effective!");
Console.ReadKey();
eattack = eattack + 10;
}
else
{
critical1 = Gen1.Next(1, 5);
eattack = critical1 + eattack;
}
phealth = Math.Abs((eattack - pdefense) - playerhealth); ***//This Line is where I'm having trouble because phealth is used in my first method as a stored integer and the new calculation for phealth won't interact with the phealth in the origional main, i simply belive I haven't learned that part of c#, I only have 5 hours of youtube tutorials.***
Console.WriteLine("Ratta dealt " + Math.Abs(eattack - pdefense) + " damage!");
eattack = 30;
Console.WriteLine("\n----------------------------------------------------------------------------");
Console.ReadKey();
Console.ReadKey();
}
}
}
}
Make Static method , or simply add your variable in the main Class (where Main method Stored)
Here example
class Program
{
int HP;
int Main()
{
HP=0; //Now you HP is 0;
Method();
}
void Method()
{
HP+=50; //Now you HP is 50
}
}
I would break things down into separate classes. For example you should have a Player class that contains all the information for the player. You can't have methods like that in your main program. You need to keep everything separate. Make a class for each object you need.
public class Player
{
int currentHp = 100;
int maxHp = 100;
int atkPower = 20;
int defense = 20;
string playerName = "Ashe"
public Player() {}
public void TakeDamage(int damage)
{
currentHp = currentHp - damage;
}
}
public class Enemy
{
int currentHp = 100;
int maxHp = 100;
int atkPower = 20;
int defense = 20;
string enemyName= "Rattata"
public Enemy(){}
public int AttackPlayer(Player player)
{
// all of your attack logic, pass in the player here
player.TakeDamage(someAmountofDamage);
}
}
Then in your main program:
static void Main(string[] args)
{
Player myPlayer = new Player();
Enemy myEnemy = new Enemy();
myEnemy.AttackPlayer(player);
}

Categories