How to check the order in which variables activate? - c#

I'm trying to make a system to check in what order do variables activate in order to prevent certain bugs. I'm sorry if it sounds confusing.
Example:
I have the following Bools
bool firstCheck
bool secondCheck
bool thirdCheck
I want to check if the variables activate in the following order (from left to right):
firstCheck == true > secondCheck == true > thirdCheck == true > //Do code
For simplicity, suppose that when a variable is activated, the following checks continue, but the original variable changes its condition to false.
I also want to check if, say, once firstCheck is true and secondCheck is true, and proceeds to the next check(remember that they change back to false ), suddenly, the variable secondCheck is true, meaning that whatever the process was, it went "back". If that happens, I want to do some code.
I don't know if I explained it correctly if you have any doubts and would like to help, don't worry and ask them

It's probably best to address the first issue of terminology, variables don't get activated, a better way to describe what's happening is to describe them as set/assigned or initialized. Value types are set, nullable value types and reference types are initialized, both can be assigned.
Depending what you need, an enum can be mutually exclusive and have multiple values.
Example:
Given
public enum State
{
First,
Second,
Third,
Finished
}
Nonsensical state machine example
var state = State.First;
while (state != State.Finished)
{
switch (state)
{
case State.First:
Console.WriteLine($"You are state {state}. Type something");
Console.ReadLine();
state = State.Second;
break;
case State.Second:
Console.WriteLine($"You have progressed, State = {state}. Type something");
Console.ReadLine();
state = State.Third;
break;
case State.Third:
Console.WriteLine($"You are good at this, State = {state}. Type something else");
Console.ReadLine();
state = State.Finished;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
Console.WriteLine($"Game over, you can type stuff. State = {state}");
Output
You are state First. Type something
sgf
You have progressed, State = Second. Type something
fgh
You are good at this, State = Third. Type something else
fghfg
Game over, you can type stuff. State = Finished

Related

error: cs0131 The left-hand side of an assingnment must be a variable, property or indexer

I've tried to make a text adventure and a got an error when I get to the "if" part. I got it to work once but not like I wanted it.
I changed it a bit and then gave up and went to the original script but it wasn't working like last time and instead gave me this error:
cs0131 The left-hand side of an assingnment must be a variable,
property or indexer
Here is my code:
Console.WriteLine("What's your name");
string name = Console.ReadLine();
Console.Write("Hello " + name);
Console.WriteLine(" do you like games?");
Console.WriteLine("yes or no");
string yes = Console.ReadLine();
string no = Console.ReadLine();
if (Console.ReadKey() = yes) { Console.WriteLine("Great!, Lets play one"); }
//the error is at "if (console.readkey()"
In C# and many languages, there is a distinction between assigning a variable is equal to a value and testing for equality.
In C# = is used to assign values. int x = 1; will create a variable with the value 1.
== is used to test a value, so you would write if (x == 100) { /* something */ }
Going on your current code, you probably should have something more like this:
Console.WriteLine("yes or no");
string answer = Console.ReadLine();
if (answer == "yes") { Console.WriteLine("Great!, Lets play one"); }
Major differences are:
You are reading the answer a user types after asking yes or no, however in your code you are then trying to re-read another answer. Which doesn't quite make sense. The console will hang until the user enters another response.
As JamesFaix said, you are then trying to assign a value to Console.ReadKey() of whatever the user responded with first, after you asked them if they want to play. Instead you should be checking if the user's response was a positive reply.

How to use value assigned within a for loop

I declare the variable setPassword outside of the loop and then give it a value within the loop. Then in the next do-while loop I try to use the value assigned but it says "Use of unassigned local variable".
profile[I] is an array of objects that are created prior to the loops. Is the value being assigned in the loop not saving or is the value of profile[I].Password null because the object hasn't been created yet?
bool good = false;
string username;
do
{
bool broke = false;
Console.WriteLine("Please create a username");
username = Console.ReadLine();
for (int i = 0; i < profile.Count; i++)
{
if (username == profile[i].Username)
{
Console.WriteLine("The username already exists");
broke = true;
break;
}
}
if (broke == false)
{
good = true;
}
} while (good == false);
Console.WriteLine("Please create a password");
string password = Console.ReadLine();
profile.Add(new Users(username, password, 0));
string setPassword;
bool validUser = false;
do
{
Console.Clear();
Console.WriteLine("Enter your username");
string tryUsername = Console.ReadLine();
for (int i = 0; i < profile.Count; i++)
{
if (profile[i].Username == tryUsername)
{
setPassword = profile[i].Password;
validUser = true;
}
}
if (validUser == false)
{
Console.WriteLine("Invalid username. Usernames are case sensitive");
Thread.Sleep(2500);
}
} while (validUser == false);
bool validPass = false;
do
{
Console.WriteLine("Enter your password");
string tryPass = Console.ReadLine();
if (tryPass == setPassword) //this is the error
{
validPass = true;
}
else
{
Console.WriteLine("Invalid password. Passwords are case sensitive");
}
} while (validPass == false);
The compiler can't know it will actually get assigned (and it doesn't if not all if statements you have evaluate to true).
Assign a default value and you will be fine:
string setPassword = null;
I initiate the variable setPassword outside of the loop and then give it a value within the loop.
This is the problem. The system cannot guarantee that a value is assigned before it is used.
It is possible that the loop iterates 0 times.
It is also possible that condition of the surrounding if statement evaluates to false.
Both of these situations lead to setPassword never getting a value.
So the compiler gives you an error, it is possible that you are using setPassword before it has a value.
The solution is to set it to a default value outside the loop, and outside the if.
This is because the compiler canĀ“t know that your for-loop is executed at least once and in particular that the if-statement within the loop also passes at least for one iteration of that loop. Thus - at least from the perspective of the compiler - it is possible that setPassword is never assigned a value and thus you get that error.
Assign null at the start:
string setPassword = null;
Basically the problem is this :
You are using them in mostly the if statements, the if statements uses a variable. But you only declared but never defined the variable globally/locally, which automatically gives an error, despite the variable will be taking a user's input locally, the if statement is unfortunately too stupid to detect that for you, plus it also takes the possibility that the user skips the step of giving an input too. Hence, you need to set a default value.
Like what they stated, you can use :
string setPassword = null; or string setPassword = "";
[Don't need to mind nullables , strings can be null by default]
To solve your problem, you should assign setPassword to string.Empty, null, or some other value, based on your use case
If you are curious about -
Why does the compiler complain that the variable is unassigned even though you assigned a value to it in while loop?
This is called the Definite Assignment behavior of the C# language. A variable is considered to be definitely assigned if
The variable was initialized at the time of declare - either with a default value or an explicitly value
Otherwise, if the compiler can prove, by static flow analysis (in simple words, compile time checks), that all possible execution paths leading up to the first use of variable will assign a value to the variable. Note, the static flow analysis is the key here, the compiler does not evaluate or take for granted that any run-time possibilities (conditions in if, while, for etc. control statements) will eventually assign the variable a value.
See Definite assignment at MSDN for more info. It is an archived document but should still be good a reference.
Also DotNetPerls Page describes it in simple language.
Disclaimer: I have no association with DotNetPerls.

Unassigned variable in return statement

for some reason I don't seem to be able to put the return in a fashion that captures this stored procedure's return value (0 or -1), either it returns the value which was used to initialize the variable or keeps telling me the local variable is unassigned.
public int changePass(int idUsuario, String old_pass, String new_pass)
{
int result;
try
{
DataTable tablaResultado =
DataBaseAccess.advanceStoredProcedureRequest(
"pa_usuario_change_pass",
new SPP[]
{
new SPP("id_usuario", idUsuario.ToString()),
new SPP("old_pass", old_pass.ToString()),
new SPP("new_pass", new_pass.ToString())
});
if (tablaResultado.Rows.Count > 0)
{
if (tablaResultado.Rows[0] != null)
{
result = (int.Parse(tablaResultado.Rows[0].ItemArray[0].ToString()));
}
}
return result;
}
catch (System.Data.SqlClient.SqlException sqlException)
{
throw sqlException;
}
}
I have multiple methods which follow the same pattern and all of those works, I have been trying to get this to work for awhile now, and I'm sure I'm overlooking something very, very obvious. Either way I cannot find it right now so I was hoping someone could refresh my memory or give me a tip.
The code only assigns a value to the result variable if two different conditions both happen to be true. That is, if the row count is > 0 and the first row is non-null. The compiler is telling you, completely legitimately, that your code contains a path to the return statement where the variable being used hasn't been assigned a value yet.
You need to decide what the method should return if either of those conditions are not true, and then assign that value to the result variable as part of its initialization.
EDIT:
To be clear: it seems you may be overlooking the possibility that your code won't successfully execute the stored procedure. But it can only return a value to be assigned to result when those two conditions are true. You either need to pick a default value that is reasonable to return when one or the other of the conditions aren't true, or you need to fix the code so that those conditions are always both true (and so the SP always executes successfully).

Function does not return negative value

I am doing a small project on 4x4 tic-tac-toe game. I am using Alpha Beta Search for finding the next best move. In the alpha beta search, I am using a cutoff evaluation function that is being called in "utility" function of the following algorithm
I implemented everything successfully, but the problem is the utility function doesn't return a negative value and I really don't know why! Following is the function
private static int utility(GameTreeNode gtn, bool isMin = false)
{
int nodeValue = 0;
switch (gtn.NodeBoard.getBoardStatus())
{
case Status.Success:
nodeValue = 50;
if (isMin) nodeValue = -50; /// here
break;
case Status.Incomplete:
if (isMin)
nodeValue = gtn.evaluate(State.X);
else
nodeValue = gtn.evaluate(State.O);
break;
}
// case Status.Draw:
return nodeValue;
}
isMin is set to true, when it is called from MinValue function
isMin is the move of O and the AI's move is X. If O wins the utility is supposed to return -50. But it returns only 0. I debugged the program and it actually assigns -50 to nodeValue (nodeValue changes in the debugger to -50), but when I receive in the Min or Max function, it is zero.
Note: All the int used in the entire project is signed int. No unsigned keyword is used, if you are thinking the function-caller is unsigned
The full code of alpha-beta search is here: http://pastie.org/8538015
Please friends, help as soon as possible.
Since you're using an optional parameter in your method signature, I'd caution you to pay attention to what your code is actually running when entering your function. You said you debugged it and the value gets assigned, but I don't have enough context to know if it only happens in one of many cases or not. Anyway, just be careful with those!
I would rewrite your function like this:
private static int utility(GameTreeNode gtn, bool isMin)
{
switch (gtn.NodeBoard.getBoardStatus())
{
case Status.Success:
return isMin
? -50
: 50;
case Status.Incomplete:
return isMin
? gtn.evaluate(State.X)
: gtn.evaluate(State.O);
default:
throw new NotImplementedException("The status is not implemented.");
}
}
A few improvements I see with this approach:
You don't need to store a value and return it at the end. In your case, you're always storing 50 into nodeValue when you take the Status.Success path, and then sometimes assigning -50 to it. Unless you're adamant about one return in your function, I think this approach is more clear. Might just be my opinion though.
There's a default in the switch statement so that you'll explicitly throw an exception in the case where you have a status that isn't implemented.
There is no optional parameter to your function. I don't see the benefit of making this parameter optional. In my opinion, it only looks like it's adding room to make things harder to debug.
EDIT:
Based on the code at:http://pastie.org/8538015#33,43
It looks like the only time you can ever get utility to return a negative value is when if (gtn.Nodes.Count == 0) return utility(gtn, true); is hit in the private static int MinValue(GameTreeNode gtn, int alpha, int beta) function. Otherwise, unless there's more code which you haven't posted, no other call to the utility function will hit the logical path your going for. You've mentioned when you step into there, you can see the value for nodeValue get properly assigned.
I'm suggesting you change:
// if Terminal-test(state) then return utitly(state)
if (gtn.Nodes.Count == 0) return utility(gtn, true);
gtn.Value = Globals.MAXINT;
To
// if Terminal-test(state) then return utitly(state)
if (gtn.Nodes.Count == 0)
{
int retVal = utility(gtn, true);
return retVal;
}
gtn.Value = Globals.MAXINT;
At least temporarily, and then put a breakpoint on return retVal. If your utility function is actually setting the value you expect like you say, there's no way that it could magically go away when it returns it to the MinValue function. I have a feeling something fishy is happening and the code isn't actually executing the path you expect.

infinite loop even when I switch off capslock

I am trying break; out of frustration. Is there an event handler I need to know about in console?
You're only setting the value of capslock once, prior to entering the loop. bool is a value type, so you get a copy of the Console.CapsLock property, not a reference to it. Your variable is never going to change value after that first assignment. What you want is something like:
while(Console.CapsLock)
{
// inform user, perhaps remove the loop and just tell them once
}
Or
capslock = Console.CapsLock;
while(capslock)
{
Console.WriteLine("CapsLock on");
capslock = Console.CapsLock;
}
On a side note, writing a message as fast as possible in a loop is probably a bad idea since it's just going to fill up the screen before the user has a chance to do anythign about it.
Not to answer your original question but it appears the reason you are checking for caps lock is you want the username that is going to be typed in in all lowercase so you can do a users.Contains(username) or something similar below where you provided in the screenshot.
A better way to do it is use the contains overload that lets you set a comparer, then use a case insensitive string comparer to test.
if(users.contains(username, StringComparer.OrdinalIgnoreCase))
{
//username existed
}
else
{
//username did not exist
}
There are similar overloads for String.Equals that lets you ignore case too
//This would return true if "username = marietjie" and "testUsername = MARIETJIE"
if(username.Equals(testUsername, StringComparison.OrdinalIgnoreCase))
{
//username matched
}
else
{
//username did not match
}
The solution for this kind of problem!!

Categories

Resources