I am comparing two excel files and for my current test - I have two files exactly the same each containing one column and 5 rows. When I check if they are equal or not, it fails and says that one of the files has added items to it.
Not sure if I am checking something the wrong way:
bool areEqual = false;
if (fileB.excelRows.Count() == fileA.excelRows.Count())
{
int i = 0;
while ((i < fileB.excelRows.Count()) && (fileB.excelRows[i] == fileA.excelRows[i]))
{
i += 1;
}
if (i == fileB.excelRows.Count())
{
areEqual = true;
}
}
if (areEqual)
MessageBox.Show("The files are the same");
else
{
....
}
Use the SequenceEqual method on excelRows[i].rowHash.
Instead of:
while ((i < fileB.excelRows.Count()) && (fileB.excelRows[i] == fileA.excelRows[i]))
Change it to:
while ((i < fileB.excelRows.Count()) &&
(fileB.excelRows[i].rowHash.SequenceEqual(fileA.excelRows[i].rowHash)))
Related
I'm following along with a tutorial about creating a mini-RTS in Unity, but I've hit something of a roadblock when it comes to the selection feature for assigning selection groups for multiple units.
The pertinent parts are below:
In the Update() method of my UnitsSelection class
//manage selection groups with alphanumeric keys
if (Input.anyKeyDown)
{
int alphaKey = Utils.GetAlphaKeyValue(Input.inputString);
if (alphaKey != -1)
{
if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))
{
_CreateSelectionGroup(alphaKey);
}
else
{
_ReselectGroup(alphaKey);
}
}
}
And the GetAlphaKeyValue method from Utils:
public static int GetAlphaKeyValue(string inputString)
{
if (inputString == "0") return 0;
if (inputString == "1") return 1;
if (inputString == "2") return 2;
if (inputString == "3") return 3;
if (inputString == "4") return 4;
if (inputString == "5") return 5;
if (inputString == "6") return 6;
if (inputString == "7") return 7;
if (inputString == "8") return 8;
if (inputString == "9") return 9;
return -1;
}
This is the code that is used in the tutorial, but to my understanding there is no way that _CreateSelectionGroup() would ever be called.
I've seen the tutorial demonstrate this functionality working, but whenever I try to run it GetAlphaKeyValue turns the Left and Right control keys into a -1 value so the if statement that checks for them never runs.
Am I missing something here? How does Unity normally handle things like Ctrl+1?
If you use the inputString I would always rather check for Contains instead of an exact string match. However, I tried to use the inputString in the past and I found it too unpredictable for most usecases ^^
While holding control keys your Keyboard most likely simply won't generate any inputString.
Only ASCII characters are contained in the inputString.
But e.g. CTRL+1 will not generate the ASCII symbol 1 but rather a "non-printing character", a control symbol - or simply none at all.
You should probably rather use e.g.
public static bool GetAlphaKeyValue(out int alphaKey)
{
alphaKey = -1;
if (Input.GetKeyDown(KeyCode.Alpha0) alphaKey = 0;
else if (Input.GetKeyDown(KeyCode.Alpha1) alphaKey = 1;
else if (Input.GetKeyDown(KeyCode.Alpha2) alphaKey = 2;
else if (Input.GetKeyDown(KeyCode.Alpha3) alphaKey = 3;
else if (Input.GetKeyDown(KeyCode.Alpha4) alphaKey = 4;
else if (Input.GetKeyDown(KeyCode.Alpha5) alphaKey = 5;
else if (Input.GetKeyDown(KeyCode.Alpha6) alphaKey = 6;
else if (Input.GetKeyDown(KeyCode.Alpha7) alphaKey = 7;
else if (Input.GetKeyDown(KeyCode.Alpha8) alphaKey = 8;
else if (Input.GetKeyDown(KeyCode.Alpha9) alphaKey = 9;
return alphaKey >= 0;
}
And then use it like
//manage selection groups with alphanumeric keys
if(Utils.GetAlphaKeyValue(out var alphaKey)
{
if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))
{
_CreateSelectionGroup(alphaKey);
}
else
{
_ReselectGroup(alphaKey);
}
}
As it turns out it may just be an issue with my keyboard. Different keyboards handle key presses in different ways. Mine just refuses to tell Unity that control + (some other key) are being pressed together. Changed the code to respond to Shift + (some other key) and it works fine.
This question already has answers here:
C# compiler error: "not all code paths return a value"
(9 answers)
Closed 1 year ago.
I am trying to write a function that receives an array and check that the array size is an odd number and that all the numbers preceding the middle index are bigger than it and all that follows are smaller and if so return true. I wrote the function but it keeps giving me this error.
this is my code:
thanks in advance.
static bool Balance(int[] array)
{
int count = 0, middle;
bool check = true;
foreach (int item in array)
{
count++;
}
if (count % 2 == 0)
check = false;
else
{
middle = array.Length / 2;
for (int i = 0; i < array.Length; i++)
{
if (i < middle)
{
if (array[i] < array[middle])
{
check = false;
continue;
}
}
if(i > middle)
if(array[i] > array[middle])
{
check = false;
}
}
}
if (check == false)
return false;
if (check == true)
return true;
The problem is that the compiler isn't as smart as you might think.
It doesn't know that the two last if cases covers all cases.
Switch to:
if (check == false)
return false;
else
return true;
And it will work!
Or just simplify:
return check;
When you write a method with a return type specified, make sure your code returns a value.
static bool Balance(int[] array)
{
int count = 0, middle;
bool check = true;
foreach (int item in array)
{
count++;
}
if (count % 2 == 0)
check = false;
else
{
middle = array.Length / 2;
for (int i = 0; i < array.Length; i++)
{
if (i < middle)
{
if (array[i] < array[middle])
{
check = false;
continue;
}
}
if(i > middle)
if(array[i] > array[middle])
{
check = false;
}
}
}
return check; // since you are checking the value in two `if` blocks, it would raise the error because compiler doesn't see the else part where the code flow will certainly go. this is the cleanest way in your code to return the value.
}
That's because compiler doesn´t know logic about your code and every path of your code needs to return a value.
In your case your simply can return the value of variable "check" at the end of your function.
change the last if to else and remove (check == true)
or just add 1 more line of code to your function
return false;
The error is occurred because in the end of your code you are using only if condition, you haven't returned any value for else condition.
if (check == false)
return false;
if (check == true)
return true;
You should write it in this way,
if(check == false)
{
return false;
}else return true;
Or simply you can just return the "check" variable as you are ultimately just returning the true value of this variable,
return check;
I have a bowling game that takes the list of bowls and then runs them through this code to produce a string that goes through the frames on the UI. If the user bowls a gutter (0) or strike (10) the code works fine. However, if it is between 1 and 9, it fails to produce a string. Why is this? I've searched and tried many other ways to do this, but this seems to be the only way it will work.
public static StringBuilder FormatRolls (List<int> rolls) {
StringBuilder output = new StringBuilder();
for (int i=0; i < rolls.Count; i++) {
if (rolls.Count >= 19 && rolls[i] == 10) { //Bonus End-Frame Strike
output.Append ("X");
} else if (rolls[i] == 0) { //Gutter
output.Append ("-");
} else if (rolls[i-1] + rolls[i] == 10 && rolls.Count > 1) { //Spare
output.Append ("/");
} else if (rolls[i] == 10 && rolls[i+1] == 0) { //Strike
output.Append ("X");
} else { //Normal bowls 1-9
output.Append (rolls[i].ToString());
}
}
output.ToString();
return output;
}
This is the code that then writes to all of the frames:
public void FillRolls (List<int> rolls) {
StringBuilder scoresString = FormatRolls(rolls);
for (int i=0; i<scoresString.Length; i++) {
frameText[i].text = scoresString[i].ToString();
}
}
Any help is greatly appreciated, I've been stuck for DAYS trying to get this to work...
output.ToString(); is a pure function and you are not using its return value (so, you are converting to a string, and then throwing that string away without using/storing/returning it). I guess you really want to return the fully built and formatted string, not the StringBuilder instance. Use:
return output.ToString();
That said, other codepaths should not produce a value either.
After rolling through all the comments and suggestions from others, I took away the try-catch section that blocked me from seeing past my catch error. Then, added debug.log statements to help find the correct position and used Unity's built-in errors to find this wasn't the string's fault at all. It was trying to find an index rolls[i]-1 that didn't exist. After a few attempts I found that if I changed the else if (rolls[i-1] + rolls[i] == 10 && rolls.Count > 1) to a nested if statement and used the output.Length instead of rolls.Count it would no longer return an error. Thank you everyone who tried to help me solve this, you pointed me in the right direction and really got me thinking! Here is the finished code:
public static string FormatRolls (List<int> rolls) {
StringBuilder output = new StringBuilder();
for (int i=0; i < rolls.Count; i++) {
if (rolls.Count >= 19 && rolls[i] == 10) { //Bonus End-Frame Strike
output.Append ("X");
} else if (rolls[i] == 0) { //Gutter
output.Append ("-");
} else if (rolls[i] == 10 && output.Length % 2 == 0) { //Strike
output.Append (" X");
} else if (output.Length >= 1 && output.Length % 2 != 0) { //Spare
if (rolls[i-1] + rolls[i] == 10) {
output.Append ("/");
}
} else { //Normal bowls 1-9
output.Append (rolls[i]);
}
}
return output.ToString();
}
Once again I cannot find a solution myself (I have tried using Array.IndexOf(db, accnum) with a pos > -1 return boolean, but have reverted to this loop after I couldn't make it work).
So, I thought using db.Length would leave 'a' at the length of all the non-null elements in the array, however it seems to count the whole array, meaning that when the loop reaches a null element it causes an error. Is there a way to halt the loop count when it runs out of objects in the array?
void withdrawal()
{
int accnum;
double withdrawal;
//get and parse input details
accnum = int.Parse(tbNameEnt.Text);
withdrawal = double.Parse(tbBalaEnt.Text);
//check if account exists within existing objects
int a = db.Length;
for (int i = 0; i < a; i++)
{
if (db[i].GetAccNo() == accnum)
{
pos = i;
//deduct from balance
db[pos].SetBalance(db[pos].GetBalance() - withdrawal);
WithMess(); //success message
hide_form();
MakeWith2.Visible = false;
show_menu();
break;
}
else if ((db[i].GetAccNo() != accnum) && (i == db.Length - 1))
{
//account doesn't exist message
MessageBox.Show("Account does not exist");
}
}
}
If there are null items that pad the array.. break out of the loop when you reach one:
for (int i = 0; i < a; i++) {
if (db[i] == null)
break;
// the rest
Alternatively, use LINQ to filter the null items out:
foreach (var item in db.Where(x => x != null)) {
// loop here
}
I have a game kinda like minecraft, but from a top down perspective, adding blocks is done by when the player left-clicks it adds the block at the specified position, right-clicking on a placed block deletes the block.
The problem I was having was that when the player left-clicks it adds the block and its position to a list (for saving to XML later), so the logical conclusion is that when the player right-clicks it removes said block from the game, and its position from its list.
This is the method that I was using which generated lag:
for (int b = 0; b < game.blocklist.Count; b++)
{
for (int v = 0; v < game.blockpos1.Count; v++)
{
if (game.blocklist[b].visible == true)
{
if (game.cursor.boundingbox.Intersects(game.blocklist[b].blockrectangle) && mousestate.RightButton == ButtonState.Pressed && game.player.Builder == true)
{
if (game.blocklist[b].blockposition.X == game.blockpos1[v].X && game.blocklist[b].blockposition.Y == game.blockpos1[v].Y)
{
game.blockpos1.RemoveAt(v);
game.blocklist.RemoveAt(b);
break;
}
}
}
}
}
Now this is the method that I replaced it with which reduces lag immensely and still achieves the same effect I want:
for (int b = 0; b < game.blocklist.Count; b++)
{
if (game.blocklist[b].visible == true)
{
if (game.cursor.boundingbox.Intersects(game.blocklist[b].blockrectangle) && mousestate.RightButton == ButtonState.Pressed && game.player.Builder == true)
{
if (game.blocklist[b].blockposition.X == game.blockpos1[b].X && game.blocklist[b].blockposition.Y == game.blockpos1[b].Y)
{
game.blockpos1.RemoveAt(b);
game.blocklist.RemoveAt(b);
break;
}
}
}
}
Why does this generate so much lag? I just need clarification as to what I did wrong so I don't do it again.
for (int b = 0; b < game.blocklist.Count; b++)
{
for (int v = 0; v < game.blockpos1.Count; v++)
{
if (game.blocklist[b].visible == true)
{
in this version, basically for every item in blocklist ( X ) whether it was visible or not you are iterating every item in blockpos1 (Y). So you do X * Y loops. You then reduced it to X loops and only evaluated visible items.
Given the way the code is written in the question, I'd check these two things before even trying to loop
mousestate.RightButton == ButtonState.Pressed && game.player.Builder == true
because they will never change during those loops. so if they aren't true to start with, don't even bother looping.
Also as Preseton says in the comments, no need to compare things to true.... you only need to do
mousestate.RightButton == ButtonState.Pressed && game.player.Builder
and
if (game.blocklist[b].visible)