Why do these errors appear? c# - hangman game - c#

I'm fairly new to coding (especially c#) - this is an assignment for a programming fundamentals class - I'm not looking for the answer - I'm looking for someone to explain why I get these two 'error's for a boolean method I'm supposed to create to check if the user's guess for a letter or the full word in a game of hangman.
The errors I get are - 'Unreachable Code detected - for the idx++ part - which doesn't make sense as I've used it in other separate methods..
And Program.CheckGuess(char[], char[], char[], string: not all code paths return a value.
I know I'm not fully finished the aspect. It's probably staring at me in the face - just looking for some guidance. Thanks.
static bool CheckGuess(char[] secrets, char[] mask, char[] letters, string guess)
{
int misses = 0; bool condition = false;
for (int idx = 0; idx < secret.Length; idx++)
{
guess.ToCharArray();
if (mask[idx] == guess[idx])
{
//reveal character or word
condition = true;
}
else
{
misses = misses + 1;
condition = false;
}
return condition;
}
}

You should understand that a return statement, when executed, makes the control jump out of the method and back to the caller.
In your code, your return is statement is placed inside the for loop. When an iteration of the for loop is executed, the control jumps out of the method immediately and goes back to the caller of the method.
As you know, the last part in a for loop header (idx++) is executed when an iteration has finished executing. However, in your case, an iteration will never finish because it just jumps back to the caller when control reaches return. This is why the first error occurred.
You should also understand that every method which doesn't have void as the return type needs to return no matter what.
So what if the for loop's condition (the middle part) is never true? The for loop will never be executed, right? If the for loop isn't executed, then what should the method return?
The error says that not all code path returns a value because the method would not return if the for loop isn't executed.
To fix this, you just need to move the return statement out of the for loop:
static bool CheckGuess(char[] secrets, char[] mask, char[] letters, string guess)
{
int misses = 0; bool condition = false;
for (int idx = 0; idx < secret.Length; idx++)
{
guess.ToCharArray();
if (mask[idx] == guess[idx])
{
//reveal character or word
condition = true;
}
else
{
misses = misses + 1;
condition = false;
}
}
return condition;
}

Because you have a return statement.
When this return inside your for loop is reached, the program jumps out of the loop and thus makes you i++ unreachable.

Related

Precisely how is the exit condition in a for loop computed?

NOTE: see edit below before you read this.
I have a function that takes in a string and outputs an enum of a specified type if that string matches any members of that enum. I.e., I have some enum SupportedFunctions with members CVT, VIS, etc, and the function will return SupportedFunctions.CVT when passed "CVT".
I have the following two functions:
parse_enum:
private bool parse_enum<EnumType>(string input, out EnumType out_enum)
{
EnumType current_enum = (EnumType)(object)0;
bool seeking = current_enum.ToString() != "0";
for (int i = 0; seeking; i++)//THIS LINE
{
current_enum = (EnumType)(object)i;
Console.WriteLine(current_enum);
seeking = current_enum.ToString() != i.ToString();
if (current_enum.ToString().ToLower() == input)
{
out_enum = current_enum;
return true;
}
}
and parse_enum_2:
private bool parse_enum_2<EnumType>(string input, out EnumType out_enum)
{
EnumType current_enum = (EnumType)(object)0;
for (int i = 0; current_enum.ToString() != i.ToString(); i++)//THIS LINE
{
current_enum = (EnumType)(object)i;
Console.WriteLine(current_enum);
if (current_enum.ToString().ToLower() == input)
{
out_enum = current_enum;
return true;
}
}
Note that both functions are exactly the save save for one thing: parse_enum computes the logical seeking and uses that for the loop exit condition, while parse_enum_2 computes the equivalent expression for seeking in the for loop statement and uses that.
The WriteLine statement is temporary for debugging. The strange thing is that parse_enum works just fine, i.e. has output
VIS
CVT
CLR
3 <-----terminates since it has exhausted enum terms
while parse_enum_2 has output
VIS
CVT
CLR
3
4
5
6
7
...
and never exits.
Why is this? I realize that there is an easier way to do this, but that is not the point here. I did a trick like this a while ago and compiled using CSC and it seemed to work. I am using Mono on Ubuntu at the moment, might that be making the difference?
EDIT: Thanks to those of you who have described how the condition works, but I do believe my question is more subtle than that. I will simplify the code: I have two functions:
Here is the first one, func1:
private static void func1()
{
ConsoleColor current = (ConsoleColor)0;
bool end = current.ToString() == 0.ToString();
for (int i = 0; !end; i++)//HERE
{
current = (ConsoleColor)i;
end = current.ToString() == i.ToString();
Console.WriteLine("enum:" + current + ", i:" + i + ", condition:" + end);
Console.ReadLine();//For stepping through
}
}
and the second one, func2:
private static void func2()
{
ConsoleColor current = (ConsoleColor)0;
for (int i = 0; current.ToString() != i.ToString(); i++)//HERE
{
current = (ConsoleColor)i;
Console.WriteLine("enum:" + current + ", i:" + i + ", condition:" + (current.ToString() != i.ToString()));
Console.ReadLine();//For stepping through
}
}
I have simplified the code so there isn't as much going on. I have printed i, the name of the current enum and the exit condition: the logical end in the first case, and the equivalent expression in the second case. This is the output I get:
For func1:
enum:Black, i=0, condition:True
enum:DarkBlue, i=1, condition:True
...
enum:White, i=15, condition:True
enum:16, i=16, condition:False //Program terminates
but for func2:
enum:Black, i=0, condition:True
enum:DarkBlue, i=1, condition:True
...
enum:White, i=15, condition:True
enum:16, i=16, condition:False
enum:17, i=17, condition:False
enum:18, i=18, condition:False
... //Program does not terminate
Perhaps I asked this the wrong way. However, it is very clear in the second case that current.ToString() != i.ToString() returns false, yet the loop keeps going. Again, I think this is actually a far more subtle issue than it appears. Perhaps I am missing something glaringly obvious?
The language reference states that the condition section executes before each loop iteration.
The condition section, if present, must be a boolean expression. That expression is evaluated before every loop iteration. If the condition section is not present or the boolean expression evaluates to true, the next loop iteration is executed; otherwise, the loop is exited.
The iterator section happens after each loop iteration.
The iterator section defines what happens after each iteration of the body of the loop.
Given your example, i will increment at the end of the loop, and then the new value of i will be compared to the value of current_enum before current_enum is assigned to the new value of i.

The field "program.endgame" is assigned but its value is never used

I am making a game in c# and I need to set up a loop to check if one of the player's score hits 6. When it does, static bool endgame would be true and the loop I used for player turns will break to display the winner. I keep getting the error "The field "program.endgame" is assigned but its value is never used" Do not know why I get it but need a fix
static bool endgame = false;
static void Main()
{
for (int r = 0; r < PlayerNumber; r++)
{// make a move for player i
if (players[r].Score == 6)
{
Console.WriteLine(players[r].Nick + " wins the game.");
endgame = true;
break;
}
}
}
It's just a warning, not an error. You are getting the warning because you never reference the endgame variable. The compiler is thinking "you could just remove this variable and your program would be exactly the same" which is true.
If you are assigning the variable for your own debugging purposes, or because you plan on using it later, feel free to ignore the warning.
The part you are looking for is the following, but it's still useless, if you're not planning on using it.
for (int r = 0; r < Player Number && !endgame; r++)
This is not an error, but a Warning, which doesn't stopping you from Running the application, but warns you that you're declaring a variable and assigning it, but never using its value.
Unless you plan to do anything with the endgame variable, you can remove it. The break will end the loop.
But if you had any code later that checks endgame, you won't get that error any more.

Why does this simple method not work?

It must be simple, but i can't seem to find the explanation. Why does the following generates these errors:
Unreachable code detected (on result++)
WindowsFormsApplication1.Form1.GetResult(int, int): not all code paths return a value
private int GetResult(int start, int end)
{
for (int result = start; result < end; result++)
{
return result;
}
}
Anyone who could please help me out? Thnx in advance :)
EDIT:
First of all, thanks for the many (fast) replys. Stupid of mine...but i didn't see it.
And sorry, i needed to be a little more precise of what it is i wanted to accieve..
I need a method that adds 1 to a value (result) starting from the given start value (int start) untill it reaches another value (int end).
So it might also add directly to start integer if I’m not mistaking. And return that value?
Because your method is returning an int type, and the compiler can't determine whether you will get inside the loop.
What if the result is greater than or equal to end, in that case, the statement inside the loop will not execute and hence you get the error.
From MSDN - For Loop
Because the test of a conditional expression occurs before the
execution of the loop, a for statement executes zero or more times.
This gives you the reason behind the error "not all code path returns a value", because if the for loop executes 0 times then the method will not return anything
For warning "Unreachable code detected", the reason is that your update expression result++ executes after the execution of the for block. Since your for block contains return statement, you will never reach your update expression
What a clever compiler!
for (int result = start; result < end; result++)
{
return result;
}
... is equivalent to:
int result = start;
while(result < end) {
return result;
result++;
}
If start >= end as we go into this code, the content of the while loop will never run. In that case, the program flow won't hit a return statement: Not all code paths return a value.
If start < end as we enter the function, the program flow will go into the loop, hit the return statement, and the method will return. It can't hit the result++ statement. Unreachable code detected.
In response to your edit:
public int getResult(int start, int end) {
int result = start;
while(result < end) {
result++;
}
return result;
}
... does what you describe. However it's a wasteful way to get that result. If start=0 and end=1000000, the program will loop a million times.
You'd get exactly same result more efficiently with:
public int getResult(int start, int end) {
if(end > start) {
return end;
} else {
return start;
}
}
Or even:
public int getResult(int start, int end) {
return Math.Max(start,end);
}
(Although it's still not clear what you want the result to be if start > end)
There are two different cases at the beginning of the method:
Case start < end: You always return result immediately in the
first loop run. Therefore result is never going to be incremented.
Case start >= end: You never enter the loop, therefore you'd need
another return statement outside of it.
It is obvious that result++ is unreachable. You would reach it after the first execution of the loop, if any - but in this very first execution of the loop, you return, thus exiting the function.
For the second part of the question, see Habib's answer.
private int GetResult(int start, int end)
{
int result = 0;
for (result = start; result < end; result++)
{
return result;
}
return result;
}
This way the function should work.
You are calling the for loop.
It sets result=start compares if condition is true
and then returns result.
How shall it ever reach result++ ?
=Unreachable code detected (on result++)
could be that the loop never enters when result > end so
=not all code paths return a value
lets assume that the condition "result < end" is true. The control will then go the statement inside the loop. Since it is a return statement, control will come out of the function/method GetResult. So, the control never reaches to "result++". That is why you get - unreachable code.
Let me know, if it is useful.
All the best !!!
If you add a return statement after the for loop it will compile without errors.
private int GetResult(int start, int end)
{
int result = 0;
for (result = start; result < end; result++)
{
return result;
}
return result;
}
This function returns start if start < end, else it doesn't return anything.
What was the intention of your method ?
Let us consider a scenario in which your condition result < end got failed . so the control
will not enter into loop and will come out of loop. but outside there is no return statement so what would it return as other end is expecting some integer to be return , so that's why you are getting error.
this will work :-
private int GetResult(int start, int end)
{
for (int result = start; result < end; result++)
{
return result;
}
return 0;
}
if the start > end value ,the code inside the loop will never be executed and hence there wont be anything to return from the function and hence you will get those errors.
Moreover there is no point of using for loop as u did since in the first step itself if start
private int GetResult(int start, int end)
{
if(start<end)
return start;
return -1;
}
I don't think for and return do what you think they do. As I read your code, it could be dumbed down to this:
private int GetResult(int start, int end)
{
if (start < end)
{
return start;
}
else
{
return 0; // or another default for when start >= end
}
}
Because return will, well, return from the method. Since the first iteration of the loop (if start < end) will immediately return result, which has been set to the value of start.
As your code shows, the else part is missing. Therefore the compiler doesn't know what you want to return when start >= end and also result++ is never called because you directly return, so it'll throw the error and warning shown.
Because if start >= end, the loop will not be entered
private int GetResult(int start, int end)
{
for (int result = start; result < end; result++)
{
return result;
}
return -1; // Path here exists
}
Out of interest, if you want to return each of the integers between start and end, you should look at yield return instead:
private IEnumerable<int> GetResult(int start, int end)
{
for (int result = start; result < end; result++)
{
yield return result;
}
// Now we don't need a return, because the loop will eventually complete
}
Edit Looking at the comments, OP may well want a sequence of numbers.
The above method can be iterated
foreach (int anInt in GetResult(40, 50))
{
Console.WriteLine(string.Format("Next value is {0}", anInt));
}

stop iterating after returning a true?

(couldn't think of a better title, feel free to edit it to a title that describes the question better)
I have the following method:
bool CalculateNewState(int adjacent, bool currentState)
{
if (currentState == true)
{
foreach (int n in liveRule)
{
if (adjacent == n)
{
return true;
}
}
return false;
}
else
{
foreach (int n in becomeAliveRule)
{
if (adjacent == n)
{
return true;
}
}
return false;
}
}
This is for a game of life clone. What I want to implement is that a user can make his own rules.
The bool currentState tells the method whether the cell is alive or not. the int adjacent tells the method how many alive neighbors the cell has.
What I want to achieve with this is that when the user says:
2,3 and 5 neighbors keep the cell alive. That it will iterate through an array (liveRule) that holds 2,3 and 5. when any match occurs it should return true, else false.
What happens here is that, after returning a true, it keeps iterating and will eventually return whether the last element in liveRule matched.
What do I need to do, to stop iterating after a match has occurred?
It is of course possible I'm taking the wrong approach to this problem. I started from the suggestions here.
(tried to describe it to the best of my abilities, but it still seems quite unclear)
This is C# in Unity3D.
The code you've implemented says "if adjacent is unequal to any of 2, 3 or 5, then return". Obviously adjacent cannot be equal to all of them!
Start over. Rename your methods so that they are more clear. Booleans should answer a true/false question, so choose names that ask a question:
bool IsCellAlive(int adjacentCount, bool isAlive)
{
if (isAlive)
return liveRule.Contains(adjacentCount);
else
return deadRule.Contains(adjacentCount);
}
"Contains" is slower than a foreach loop, so this might cause a performance problem. Don't worry about it for now; you haven't even got the code correct yet. Write the code so that it is obviously correct, and then use a profiler to find the slow spot if it is not fast enough.
Remember: make it correct, then make it clear, then make it fast.
Your return statements will exit the CalculateNewState method immediately. If you find that the iteration is continuing, either you are not hitting the return statements (adjacent == n is never true), or possibly CalculateNewState is being called repeatedly from elsewhere in your code.
You can probably rewrite it much more simply to something like:
if (currentState)
return liveRule.Contains(adjacent);
return becomeAliveRule.Contains(adjacent);
Well you can always use a "break" statement to terminate the loop. Do something like:
bool CalculateNewState(int adjacent, bool currentState)
{
if(currentState)
{
return IsStateMatch(adjacent, liveRule);
}
else
{
return IsStateMatch(adjacent, becomeAliveRule);
}
}
bool IsStateMatch(int adjacent, int[] rules)
{
bool finalState = false;
if(rules != null)
{
for(int i = 0; i < rules.length; i++)
{
if(adjacent == rules[i])
{
finalState = true;
break;
}
}
}
return finalState;
}
I broke down the methods a little more, just for readability, but I think this is the basic idea. Now, I do agree with the other posters about what could be happening. If your loop is continuing after a break / return statement, then you most likely have buggy code elsewhere incorrectly calling the method.
It looks like your equality test is the culprit... shouldn't you be testing adjacent == n instead of adjacent != n? That way it will return true for the matches and only return false if no match.
The iterator will NOT continue after a return exits the loop.
Can you use a for loop instead of foreach with an additional variable?
bool CalculateNewState(int adjacent, bool currentState)
{
if (currentState == true)
{
bool match = false;
for(int n = 0; n < liveRule.length && !match; n++)
{
if (adjacent != n)
{
match = true;
}
}
return match;
}
else
{
bool match = false;
for(int n = 0; n < becomeAliveRule.length && !match; n++)
{
if (adjacent != n)
{
match = true;
}
}
return match;
}
}

c# syntax question - for loop and end of line

I am currently learning c# and reading a few books. I can do quite a few things, however only from modifying examples - it really frustrates that I do not actually understand how/why some of the more basic items work.
I have just done a console application that takes arguments and displays them all one by one.
The code is:
using System;
class test
{ static int Main(string[] argsin)
{
for (
int i = 0;
i < argsin.Length;
i++
)
Console.WriteLine("Argument: {0}", argsin[i]);
Console.ReadLine();
return -1;
}
}
Now, this works perfectly, but coming from a basic (no pun!) understand of Visual Basic, how/why does it know to print the correct argument and then go on to the next without quitting the application after the first Console.WriteLine... I feel I have missed the fundamentals of how this works!
Next, why is it that inside the for loop, each line ends with a semicolon apart from i++?
I keep forgetting to add it from time to time, and then when trying to work out why it wasn't compiling, I added one where I wasn't meant to!
Your code is formatted a bit strangely, if you reformat it as this I think it's easier to understand:
using System;
class test
{
static int Main(string[] argsin)
{
for (int i = 0; i < argsin.Length; i++)
{
Console.WriteLine("Argument: {0}", argsin[i]);
}
Console.ReadLine();
return -1;
}
}
So as you can see int i = 0; i < argsin.Length; i++ are not 3 different lines, they are all just arguments to the for loop.
And adding the { and } makes it easier to see what lines of code are inside the for loop.
I will try to explain the loop by comparing to VB syntax.
In C#: for (int i = 0; i < 5; i++)
In VB: For i = 0 To 4
The i = 0 part is the same in both, so I guess it's clear - this is used to initialize the loop iterator.
The i < 5 part in C# becomes 0 to 4 in VB.... you can think of this as though VB is doing a "shortcut", but the meaning in both is the same: that is the loop condition, i.e. what is the condition that the loop will keep running, in this case the loop will keep running as long as i is less then 5.
And finally, the i++ part which is required in C# to tell "what will happen to the iterator after each iteration?" is not needed in good old friendly VB that will simply increment it by 1 for you, always - by default.
Why having semicolon after each part of the loop? Because each part has its own meaning and usage so the compiler must know how to separate the parts when building the final code. Why not having semicolon after the i++ part? Same reason that you don't have comma after last argument passed to function e.g. Console.WriteLine("Argument: {0}", argsin[i], );
About the loop having no "block" only one line, it was explained in the other answers, rule of thumb is that C# allow single line blocks to appear without the brackets.
By convention c# and all c like languages when presented with a for loop (or and if statement etc) will run the line immediately after. Personally I don't like writing code like this, i feel it lacks readability.
To clarify we can add curly braces to denote scope
for (
int i = 0;
i < argsin.Length;
i++
)
{
Console.WriteLine("Argument: {0}", argsin[i]);
}
Console.ReadLine();
return -1;
now what the for loop executes is clearly defined (and if we wanted to do more in our loop we would add the extra instructions in between the curly braces).
edit:
The reason for the semi colons as you define your for loop is that each part of that definition is a separate statement.
int i = 0; //creates an integer i and sets its value to 0
i < argsin.Length; sets our comparison operation to define when the loop ends
i++ //what to do at the end in this case increment i by 1
Each needs to be treated independent of the others and as the semi colon denotes the end of a statement in c# (which is why each line ends in it) we use it to break up the statements so the compiler can read it.
While the 2 semicolons are mandatory the arguments are not we could if we wanted change it to be this.
int i = 0;
for (;;)
{
if(i>=argsin.Length){
break;
}
Console.WriteLine("Argument: {0}", argsin[i]);
i++;
}
This is functionally identical to the way you wrote it but I've moved all the logic out of the for statement to its equivalent position inside (or outside in the case of defining i) the loop
The reason why you application prints the right number of arguments is that the WriteLine statement is part of the loop. In C# if you've only got one line of code after a for statement then you don't need curly brackets. (This is the same for if too)
So
for (int i = 0; i < argsin.Length; i++)
Console.WriteLine("Argument: {0}", argsin[i]);
is the same as
for (int i = 0; i < argsin.Length; i++)
{
Console.WriteLine("Argument: {0}", argsin[i]);
}
As the for the semi-colon after the i++ thats just how it is. Normally the for statement is written on one line as I've done in my samples above.
Hope this helps.
I've brushed your formatting a little up, which gives you an easier understanding on how it works.
using System;
class test
{
static int Main(string[] argsin)
{
for (int i = 0; i < argsin.Length; i++ )
Console.WriteLine("Argument: {0}", argsin[i]);
Console.ReadLine();
return -1;
}
}
There's a special rule for C-like languages: You define it's scope using if(true) { ... } similar to If True Then ... End If, but if you only have one line, you can decide not to use brackets. Therefor the next line after the if or for[each] will be used for the scope.
The i++ does not end with a ; because it is within the declaration of the for.
Also, don't forget to have a look at the foreach loop.
If I rewrite your method with different formatting (but identical syntax), it may make things clearer:
static int Main(string[] argsin)
{
for (int i = 0; i < argsin.Length; i++)
{
Console.WriteLine("Argument: {0}", argsin[i]);
}
Console.ReadLine();
return -1;
}
Remember that c# doesn't use a line break for statement termination (unlike VB). The "third line" in your 'for' loop isn't actually a "line," it's just the third expression, and is terminated by the closing bracket.
The reason the loop continues rather than quitting is because (without squiggly brackets to indicate a statement block) the 'for' loop will only loop the single statement immediately following the loop - that is, the 'Console.WriteLine'. I'm guessing that you thought that the 'ReadLine' and 'return' statements would be part of the loop but, in C# syntax, that's not the case. (I added the bracess to my version to make the scope of the loop clearer).
I'll answer the part of your question...
for is a construct that has initializer, loop statement, and terminating condition.
So
for (X, Y, Z) { }
would be equivalent to
X;
while (Y)
{
// code
Z;
}
As for your question about not quiting the application - for () will bind to first NEXT statement, or statement BLOCK. In your case, you have only one line as a statement. If there would be more lines, you should write them encased in { and }.
Typical syntax for a for loop is:
for( int i = 0; i < argsin.Length; i++ )
{
//<CODE>
}
So you'd read it (in your mind) as: "With the temporary value 'i' starting at the value 0, while 'i' is less than 'argsin.Length', do '//' with i as the value, always ending with 'i++'"
A for loop just gets translated to:
{
int i = 0;
while( i < argsin.Lenth )
{
//<CODE>
i++;
}
}
(The extra surrounding braces are to say that 'i' goes out of scope and can no longer be used when the brace closes). Like any 'if' or 'while' statement the closing parenthesis provides the 'end-of-statement' "Character" (if you will) and so the semicolon is unnecessary. Earlier they are a must because you have to know where to end each statement.
[EDIT]
By the way: there's a little more to it than a straight translation. There are cases where you can include multiple initializations, and multiple 'at the end of each loop' instructions. Don't worry about those until you understand what's going on.
That is the basic of the for loop, in that loop, you declare that the starting value of integer i is zero and it should continue to loop until i is equal to the length of string[] argsin and increase the value of i on each iteration. Which means if the length of your argsin array is 5, the loop will
// first run
for(int i = 0;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[0]);
// second run
for(int i = 1;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[1]);
// third run
for(int i = 2;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[2]);
// forth run
for(int i = 3;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[3]);
// fifth run
for(int i = 4;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[4]);
After 5 runs, i will be 5 and will not meet 5 < 5 and quit this loop and go on with the next statement.

Categories