I'm trying to use an if statement with a bool that will make it that if a code runs once it will not run again. Here is the code I am using.
int random = Program._random.Next(0, 133);
if (random < 33) {
bool done = false;
if(done)
{
continue; // Error is shown for this statement
}
Console.WriteLine("Not done!");
done = true;
}
The error that Visual Studio is displaying is: "No enclosing loop out of which to break or continue".
Depending on the class/method requirements, you could possibly reverse your logic:
if (!done)
{
Console.WriteLine("Not done!");
done = true;
}
You can't use a continue only inside a loop. So you must live without this:
int random = Program._random.Next(0, 133);
if(random < 33)
{
bool done = false;
if(!done)
{
Console.WriteLine("Not done!");
done = true;
}
}
In this case, you should reverse the if with if (!done) { ... }
You can't use continue like that, it can only be used in a loop. The continue statement will go to the end of the loop and continue with the next iteration, without a loop there is no end of the loop to go to.
You can use else instead:
if (done) {
// anything to do?
} else {
Console.WriteLine("Not done!");
done = true;
}
If there is nothing to do if the variable is true, you can just reverse the expression instead:
if (!done) {
Console.WriteLine("Not done!");
done = true;
}
Note: You need to store the variable done outside the scope. Now you have a local variable that is always set to false, so the code will never be skipped.
The exception is telling you that continue is ineffective here. It simply has nothing to do, and doesn't know where to continue. It is meant to be used within the iteration of a loop.
Related
I'm just starting out so I'm in the middle of writing my first console application from scratch. I have this line of code, when I hit d it correctly takes me to the next step and sets disadvantage to true, however if I hit a it executes the else statement for some reason. Any ideas what the cause is?
Console.WriteLine("Press the A key for advantage, or the D key for disadvantage");
var rollType = Console.ReadKey();
Console.WriteLine(System.Environment.NewLine);
if (rollType.Key == ConsoleKey.A)
{
advantage = true;
}
if (rollType.Key == ConsoleKey.D)
{
disadvantage = true;
}
else
{
Console.WriteLine("Invalid Input");
StartApp();
}
Just add make this small change! (Adding else in your second conditional)
if (rollType.Key == ConsoleKey.A)
{
advantage = true;
}
else if (rollType.Key == ConsoleKey.D)
{
disadvantage = true;
}
else
{
Console.WriteLine("Invalid Input");
StartApp();
}
What was happening before is your Console would read an A key and enter the first conditional. Since the second and third conditional was separate from the first, the second would also be checked and if not true (which in this case it would not be true) it would no matter what enter the else statement. Hope this helps.
Seems like the program is being executed exactly as you’ve written it to.
if (rollType.Key == ConsoleKey.A)
{
advantage = true;
} // First conditional check ends here
// This is another conditional block
if (rollType.Key == ConsoleKey.D)
{
disadvantage = true;
}
else // You pressed A, so this block is executed
{
Console.WriteLine("Invalid Input");
StartApp();
}
If you hit A, it will excude A and else part of D. After all, A equals A but A does not equal D.
What you want is propably a switch/case statement.
switch(rollType){
case ConsoleKey.A:
advantage = true;
break;
case ConsoleKey.D:
disadvantage = true;
break;
default:
Console.WriteLine("Invalid Input");
break;
}
switch/case statement and do/while loop - these two are the fundament of console programm flow.
I'm pretty new to C# and coding in general so it is hard for me to explain
and this might be something simple.
The program I am trying to make changes values in the game (Assault Cube).
Without the inner while loops, it just changes the values, I would like them to loop.
I have one outer while loop with multiple loops inside.
The inner while loops are there to loop the function but it stops the outer while loop.
I would like multiple inner loops to run along with the outer one.
I have tried what feels like everything. I tried Booleans, Breaks, Returns.
But nothing I have tried has fixed my problem. It may not be because they don't work, it may just be me using them wrong.
while (true) //outer loop
{
Console.Title = "SlavScripts";
int address1 = LocalPlayer + Health;
int address2 = LocalPlayer + Armor;
string Player = "";
Console.WriteLine("---SlavScripts v2.0---");
Console.WriteLine("");
Console.WriteLine("[1] Player Options");
Console.WriteLine("");
string answer = "";
answer = Console.ReadLine();
if (answer == "1")
{
Console.WriteLine("--Player Options--");
Console.WriteLine("");
Console.WriteLine("[1] Godmode");
Console.WriteLine("[2] Armor");
Console.WriteLine("");
Player = Console.ReadLine();
if (Player == "1")
{
Console.WriteLine("Godmode Enabled");
Console.WriteLine("");
while (true)
{
vam.WriteInt32((IntPtr)address1, 6969); //value to loop.
}
}
else if (Player == "2")
{
Console.WriteLine("Infinite Armor Enabled");
Console.WriteLine("");
while (true)
{
vam.WriteInt32((IntPtr)address2, 6969); //value to loop.
}
}
}
}
(full code: https://pastebin.com/bBcBPYs6)
Expected:
I enter the corresponding digit to activate the function
The function that was activated loops, and original text appears which allows me to navigate to another function.
Actual:
I enter the corresponding digit to activate the function.
The function activates and loops, but does not show opening text and disallows my to type further.
Think about what is happening in your code. Each instruction in your code is executing one after the other (superficially thinking - this might not be exactly true at assembly execution level but you get the idea). For example the line if (answer == "1") will only executed when the line before it (that is answer = Console.ReadLine();) completes its execution.
When you create the "outer while loop" (as you called), everything inside the loop will execute 1 instruction at a time following the order they are written and when the last instruction inside the loop is executed, the execution will jump back to the first line of code inside the loop.
If you put another while loop inside the "outer one", and say it will not have an exit condition (by declaring while(true) you are creating a loop that will never stop executing its embedded statements). Therefore when the execution reaches one of these while(true) loops it will be trapped inside them looping its embedded statements forever.
What I described is how instructions are executed. The other part you need to know is what is a thread. You can think of a thread as an isolated machine where every code is executed. When you don't deal with threads directly in your code, the compiler will automatically asks the operating system to create a thread to run your code at - this is usually referred to as the main thread.
So, what you actually need in your code is to inform the operating system to put the execution of each one of those "inner while(true)" loops inside a thread other than the main one and leaving the main thread to execute only code that can sequentially be executed.
You can learn how to use threads in your application here.
And as a side-note: that is probably not what you want to create a loop spinning code every cycle. You should consider pausing the execution inside those "inner loops" by putting the thread that is executing it to sleep for some time each time it iterates through (you can do this by just calling System.Threading.Thread.Sleep(100) - it will pause the thread execution by 100 milliseconds and will save some cpu execution time).
As per your expectation,
Please find the sample code snippet for getting user input continuously - achieved using Task in C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SampleTaskStop
{
class Program
{
static public void SetValue(string address, int value)
{
while (!_cancelled)
{
//vam.WriteInt32((IntPtr)address1, 6969); //value to loop.
}
Console.WriteLine(address + " - completed");
}
static bool _cancelled = false;
static void Main(string[] args)
{
while (true) //outer loop
{
Console.Title = "SlavScripts";
Console.WriteLine("---SlavScripts v2.0---");
Console.WriteLine("");
Console.WriteLine("[1] Player Options");
Console.WriteLine("");
string answer = "";
answer = Console.ReadLine();
_cancelled = false;
if (answer == "1")
{
var acceptUserInput = Task.Factory.StartNew(AcceptUserInput);
acceptUserInput.Wait();
}
}
}
private static void AcceptUserInput()
{
// Task to perform the value setting in the
Task computationTask = null;
Console.WriteLine("Enter Player Input");
Console.WriteLine("1 God Mode");
Console.WriteLine("2 Armour Mode");
Console.WriteLine("Press Esc to cancel");
var key = Console.ReadKey(true);
while (key.Key != ConsoleKey.Escape)
{
if (key.Key == ConsoleKey.D1 || key.Key == ConsoleKey.NumPad1 )
{
Console.WriteLine("Godmode Enabled");
Console.WriteLine("");
_cancelled = true;
if (computationTask != null)
{
computationTask.Wait(new System.Threading.CancellationToken());
}
_cancelled = false;
computationTask = Task.Factory.StartNew(() => SetValue("data1", 6979));
}
else if (key.Key == ConsoleKey.D2 || key.Key == ConsoleKey.NumPad2)
{
Console.WriteLine("Infinite Armor Enabled");
Console.WriteLine("");
_cancelled = true;
if (computationTask != null)
{
computationTask.Wait(new System.Threading.CancellationToken());
}
_cancelled = false;
computationTask = Task.Factory.StartNew(() => SetValue("data2", 6979));
}
key = Console.ReadKey(true);
}
_cancelled = true;
Console.Write("Computation was cancelled");
}
}
}
Thanks to everyone who replied!
Multi-Threading sounds alot harder than it actually is and it also simplified my code alot!
Still have to add Thread.Sleep's :D
Cheers!
New & Improved - pastebin.com/qN7ci0By
The code below is a snippet from a working code that is for a castle maze game in c#.
The if else structure only prints correctly the dun.roomend == true). The tow.roomEnd now displays when the tre.isExit should be displayed. The tre.isExit doesn't display at all.
I have declared the current variables as:
public bool isExit;
public bool deadEnd;
public bool roomEnd;
tre.isExit = true;
dun.deadEnd = true;
tow.roomEnd = true;
if (dun.roomEnd == true)
{
Console.WriteLine("You've fallen into the Dungeons of the Dead. Try again");
return;
}
if (tow.roomEnd == true)
{
Console.WriteLine("You been caught by the Kings guard and have been placed in the tower for life.Try again");
return;
}
else if (tre.isExit == true)
{
Console.WriteLine("You have found the treaure... now run!!");
return;
}
else
{
Console.WriteLine("Too scared.....");
}
That's because you immediately return when one of your conditions is true.
// Don't explicitly compare to true - just write if (dun.roomEnd)
if (dun.roomEnd == true)
{
Console.WriteLine("You've fallen into the Dungeons of the Dead. Try again");
// You end the method here, so none of the rest of the code after this will execute
return;
}
Also, the fact that you do
else if (tre.isExit == true)
means that this won't execute if
tow.roomEnd == true
is also true. "Else if" means "if the current condition is true and the previous condition is false", so
if (A) {
// do work
}
else if (B) {
// Do work
}
is semantically equivalent to
if (A) {
// Do work
}
if (!A && B) {
// Do work
}
Finally, I mentioned this in passing, but I'd like to reiterate that it's not necessary to explicitly compare to true or false, so
if (tow.roomEnd == true)
should just be
if (tow.roomEnd)
Also, I don't think it makes sense for all of those conditions to be true at once. Can something actually be a room end, a dead end, and an exit at the same time? At a minimum, it seems like a particular location can't be both an exit and a dead end. If the data says that several of those things are true at once, it needs to be corrected in order for the program to function properly.
In every if statement you have keyword return;. The return statement terminates execution of the method and because of that only first Console.WriteLine is shown.
Read carefully: return (C# Reference)
Reading through what you've done, if I'm understanding this correctly what you're after is as follows.
public bool isExit;
public bool deadEnd;
public bool roomEnd;
tre.isExit = true;
dun.deadEnd = true;
tow.roomEnd = true;
if (dun.roomEnd == true)
{
Console.WriteLine("You've fallen into the Dungeons of the Dead. Try again");
}
else if (tow.roomEnd)
{
Console.WriteLine("You been caught by the Kings guard and have been placed in the tower for life.Try again");
}
else if (tre.isExit)
{
Console.WriteLine("You have found the treaure... now run!!");
}
else
{
Console.WriteLine("Too scared.....");
}
return
This will evaluate each condition individually, and then return once complete.
What this code is effectively saying is "if condition 1 is true, display the text and exit the if block, then return. Otherwise if condition 2 is true do the same, condition 3 / 4 do the same thing also.
I think this is what you're after at least. It could be refactored to make it a little simpler but don't have the time to go over that at the moment.
Assuming it is showing the Dungeons of the Dead and the Kings Guard message, you need to add an "else" to the if for tow.roomEnd.
I have a program that is completely functional, and I am now refactoring it. I am just in the process of learning c# so the original code was pretty terrible despite the fact that it ran just fine. One of the requirements of the program is that the user be able to return to the main menu at any point. I accomplished this as follows:
static bool bouncer = false
static void Exit(string input)
{
if (input == "\t")
{
bouncer = true
}
}
static string Prompt(string msg)
{
// takes input and passes it to Exit() then returns the input
}
static string FunctionA()
{
while(true)
{
if (bouncer == true)
{
break;
}
Prompt("whatever")
if (bouncer == true)
{
break;
}
Prompt("whatever")
if (bouncer == true)
{
break;
}
// return some stuff
}
}
static void Main()
{
bouncer = false
// writes the menu to console and handles UI
// FunctionA
{
The variable bouncer gets set to true if the user enters the "tab" character at any input point. The proliferation of break statement conditionals provides the structure that actually breaks out back to Main(). This is obviously not a very good solution and it makes the code hard to read.
Other attempts that I considered to accomplish the same task are:
Goto statement that jumps straight back to Main(). I scrapped this because goto has a very limited scope in c# and I don't think there is any good way to make it workable in this situation.
Calling Main() directly from Exit(). This is probably a bad idea, and I can't do it anyway because apparently Main() is "protected" in some way.
Using an event to react to TAB or ESC being pressed. It's unclear to me how I could use an event to do this since I still wouldn't be able to break right out of the event. My understanding is that the break statement has to actually be contained in the loop that needs to be broken as opposed to being written into a different function that is called from within the loop.
Any suggestions are greatly appreciated. I'm hoping there's something to be done with event handling or that I've overlooked something more simple. Thanks!
As a matter of coding style, the way it is works, but is seen as ugly. Unfortunately, if you need to break out immediately between sections of work, there is not a lot of ways around that.
You can change your current format of using breaks to using "if( bContinue ) { /* do next section of work */ }" control style. It changes the code from break out of the while loop to this:
static string FunctionA()
{
bool bContinue = true;
while( true == bContinue )
{
// Do initital work.
//
// Initial work can set bContinue to false if any error condition
// occurs.
if( true == bContinue )
{
// Do more work.
int returnCheck = MakeACall(); // Presume MakeACall returns negative interger values for error, 0 or positive values for success or success with condition/extra information.
if( 0 < returnCheck )
{
bContinue = false;
}
}
if( true == bContinue )
{
Prompt("whatever")
// Do more work.
bContinue = MakeASecondCall(); // Presume that MakeASecondCall returns true for success, false for error/failure
}
if( true == bContinue )
{
Prompt("whatever")
// Do more work.
// If error encountered, set bContinue to false.
}
if( true == bContinue )
{
Prompt("whatever else")
// Do more work.
// If error encountered, set bContinue to false.
}
// Done with loop, so drop out.
bContinue = false;
// return some stuff
}
}
Looking at your pseudo code, it reads like you only do a single pass through your work loop. If so, you can switch to a Do-While(false) format, and use the break to just drop to the bottom. Or, if you are only doing a single pass through your FunctionA, just do away with the While or Do-While control structure, and just use the if(true==bContinue){ /* Do more work */ }. It is not the cleanest of code, but when you perform long periods of serial work, you end up with such structures if you are not going to use a while or do-while for controlling the flow.
The disadvantage to using the if(bContinue){} style is that when an error condition occurs during the early stages of the process, the code does not exit out as quickly from the function as a break out of the while() or do-while() structure if the error occurs near the top of the work, as there will be the series of if statements that the code will test and then skip over. But it is readable, and if you use a descriptive name for your control variable (ie, nContinue or bContinue or workLoopControl) it should be fairly obvious that it is the master control flag for the function's work flow to whoever works or reviews the code after you.
Instead of an infinite loop and break statements, try using a conditional flag instead.
static void FunctionA()
{
bool done = false;
string response = string.Empty;
while (!done)
{
response = Prompt("whatever");
if(response == '\t')
{
done = true;
}
}
}
As a side note, I'm not sure why you have 'string' as the return type of several methods (e.g., 'FunctionA') when you aren't using the return value. That's why the code I gave above has it as 'void'.
I've got the following code in an async method in my app
b_saving = true;
while (b_saving == true)
{
try
{
if (1 == 1)
b_saving = false;
// anything down here should not execute?
i_should_not_run();
}
catch{
}
finally{
}
}
My expectation with this code is that it will stop as soon as b_saving is set to false. Yet when I run it, this is not the case. Breakpoints show the method continues on even when b_saving is false.
Do while loops not work this way in C#?
the loop will continue even after you set the b_saving to false, unless you put a break command in there, the while loop will continue executing until the end of its block and only then re-evaluate the condition and in this case most likely avoid another iteration of the loop, unless you set back b_saving to true inside your i_should_not_run method.
PS you can write a simpler condition in the while, no need to put the ==...
while (b_saving)
b_saving = true;
while (b_saving == true)
{
try
{
bool stop = true;
if (stop == true)
{
b_saving = false;
break;
}
// anything down here should not execute?
i_should_not_run();
}
catch{
}
finally{
}
}
You need to use break to stop execution like following
b_saving = true;
while (b_saving == true)
{
try
{
if (1 == 1){
b_saving = false;
break; // Will exit the loop
}
// anything down here should not execute?
i_should_not_run();
}
catch{
}
finally{
}
}
Read :
The break statement terminates the closest enclosing loop or switch statement in which it appears. Control is passed to the statement that follows the terminated statement, if any.
In order for the while loop to stop and not continue to execute the method your if statement should be like this:
if(1 == 1)
{
b_saving = false;
break;
}
The break keyword will exit the loop.
This has nothing to do with the async or the try/catch.
Setting b_saving to false is only part of the story - it has nil effect until you actually test its value and take an action based on that (in this case exit the while loop).
This is the way while loops always run.
You might also get interesting results from a compiler (depending on the language) - some of that code may get eliminated as it is effectively useless.
This loop should execute once as the first time b_saving == true. within the loop you set b_saving to false so it won't execute a second time.
To prevent i_should_not_run from being called add a break statement.
Few points:
The code above would complete the entire loop after setting the
m_saving flag to false, i you want it to stop right away you should
state it using the break keyword.
Judging by the name of the "m_saving" member you use, it's a local variable, therefore in a multithreaded scenario you should use read and write to it using atomic operation mechanisms.
Should the catch block be empty?
Just a template to consider
for{;;}
{
try
{
if(hasToStop)
{
break;
}
}
catch { hasToStop = true;}
}
Well it will carry on running for one run through the code, until the While check is carried out.
If you want to break out of the loop early then you want a break; statement.