Building a simple app here; the methods in question:
static coin class
public static void SetUpCoins() {
coin1 = new Coin();
coin2 = new Coin();
}
public static void PlayConsole() {
SetUpCoins();
OutputWinner();
}
public static void OutputWinner() {
if (coin1.ToString() == "Heads" && coin2.ToString() == "Heads") {
Console.WriteLine("You threw Heads - you win");
++point_player;
} else if (coin1.ToString() == "Tails" && coin2.ToString() == "Tails") {
Console.WriteLine("You threw Tails - I win");
++point_comp;
} else {
Console.WriteLine("You threw Odds");
WaitForKey_ConsoleOnly("Press any key to throw again");
PlayConsole();
}
Console.WriteLine("You have {0} points and the computer has {1} points", point_player, point_comp);
if (WantToPlayAgain_ConsoleOnly()) { // ask user if they want to play again; return bool
PlayConsole();
}
}
private static bool WantToPlayAgain_ConsoleOnly() {
string input;
bool validInput = false;
do {
Console.Write("Play Again? (Y or N): ");
input = Console.ReadLine().ToUpper();
validInput = input == "Y" || input == "N";
} while (!validInput);
return input == ("Y");
}
If false was to return from WantToPlayAgain_ConsoleOnly() the program does not exit. Here is an example of the output, which explains my problem:
Why, when WantToPlayAgain_ConsoleOnly is false, does the program not pass control the playConsole method then exit. instead of this repetition.
After OutputWinner is finished running, it then jumps into PlayConsole, and then back into the else statement of the OutputWinner - not sure why.
Because you are calling PlayConsole() after "Press any key to throw again". Once that call returns the program will unconditionally continue with "You have {0} points and the computer has {1} points", regardless of what happened during the call.
Try rewriting the logic to be iterative rather than recursive?
As the previous answers said, you have a problem when you throw odds.
Because at that point you call the exact same method again and when that call returns, you resume right at the score display and the player is asked again to play.
Because you are calling PlayConsole recursively, that means for every time you throw "Odd", you will get one more prompt that you didn't ask for.
You could restructure the method like this:
public static void OutputWinner() {
do {
// Game code
}
while (WantToPlayAgain_ConsoleOnly());
}
That also gets rid of the recursion.
Related
Im new to programming in C# and i encountered some problems, I am trying to create a countdown Console Command but im stuck on how to terminate the loop using a user input (in this case, when the user presses the "Enter" Button)
Here is the code that I currently have
using System;
using System.Threading;
class stopWatch {
public static void Main (string[] args) {
Console.WriteLine ("Access The Clock? Y/N");
string yN = Console.ReadLine();
if ((yN == "y") || (yN == "Y")) {
Console.WriteLine ("Timer (T) or Stopwatch (S)?");
var sT = Console.ReadLine();
if ((sT == "s") || (sT == "S")) {
Console.WriteLine ("Press the 'Enter' Button to Start");
Console.ReadLine();
Console.WriteLine("Stopwatch Started");
Console.WriteLine("Press the 'Enter' Button again to Stop");
for(int i = 0; i >= 0; i ++) {
Console.WriteLine(i);
Thread.Sleep(1000);
}
}
}
else if ((yN =="n") || (yN == "N")) {
Console.WriteLine ("Alright, Thank You");
Environment.Exit(0);
}
else {
Console.WriteLine ("Wrong Input");
Environment.Exit (0);
}
}
}
keep in mind im very new to c# and loops, i'm getting a hard time translating and trying on everything, it'd be really grateful of me to get an extra explanation for your answers
You need to use separate thread for that. Threads is advanced theme, but the basic goal is to do several things at once (in your example run stopwatch and wait for user input). Here is full working code based on your sample:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp13
{
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Access The Clock? Y/N");
string yN = Console.ReadLine().ToLower();
if (yN == "y")
{
Console.WriteLine("Timer (T) or Stopwatch (S)?");
var sT = Console.ReadLine().ToLower();
if (sT == "s")
{
Console.WriteLine("Press the 'Enter' Button to Start");
Console.ReadLine();
bool runStopWatch = true;
Task.Run(() =>
{
for (int i = 0;; i++)
{
Console.WriteLine(i);
Thread.Sleep(1000);
if (!runStopWatch)
{
break;
}
}
});
Console.WriteLine("Stopwatch Started");
Console.WriteLine("Press the 'Enter' Button again to Stop");
Console.ReadLine();
runStopWatch = false;
}
}
else if (yN == "n")
{
Console.WriteLine("Alright, Thank You");
Environment.Exit(0);
}
else
{
Console.WriteLine("Wrong Input");
Environment.Exit(0);
}
}
}
}
Task.Run starts a new thread, so your stopwatch runs independent of the main thread (which waits for user to press Enter). Variable runStopWatch is shared between threads (don't think about it right now), so when main thread sets it to false, stopwatch's thread sees it and terminated the loop.
Side mote. More proper way to do this is to use CancellationToken istead of bool variable. But again. don't worry about it right now.
Since you're new im going to try to explain it as simple as possible. The solution you're trying to create is a solution to a multi-threaded problem. This means you will have to do an action while another action takes place. This can be resolved using async methods, this might be too advanced for now, so I will suggest reading up on loops and then multi-threaded programming first.
But for an answer i will have to refer to this post here on how to fix this particular problem. (Look at the second part of the accepted answer).
I’m trying to make a game where you have to choose a random number, and the computer will tell you if you’re right or not. But in the code I have, the loop will just keep executing what is in the if command. If I try to break it’ll just do what’s in the while part of it. I want to be able to enter a number, tell you if it’s right or not, and then let you guess again. Thanks for the help! Also, ignore how part of the code isn’t counting as code. I couldn’t get it to go into the code part, and I didn’t try very hard either. Also sorry about the abnormal variable names.
using System;
using System.Threading;
namespace newProject
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("useless intro");
int shortOut;
Random rnd = new Random();
int daNumber = rnd.Next(9);
string userNumber = Console.ReadLine();
bool isParsable = Int32.TryParse(userNumber, out shortOut);
if (isParsable)
{
do
{
if (shortOut != daNumber)
{
Console.WriteLine("no");
}
} while (shortOut != daNumber);
Console.WriteLine("that's it yeah");
}
}
}
}
Your code is asking for the user input only once. It then checks if it is an int and, if it is, it then starts the loop that never changes the variables. It's going to loop forever.
You need to ask for the user's input repeatedly until they guess correctly. Asking for the input needs to be in the loop. And you should only break out of the loop when they get it right.
Here's how I would do it:
Random rnd = new Random();
//choose a number between 0 and 8 inclusive
int daNumber = rnd.Next(9);
// start with a value that the user would never enter
int daGuess = int.MinValue;
//loop if the two numbers are not the same
while (daGuess != daNumber)
{
Console.WriteLine("Enter your guess:");
if (int.TryParse(Console.ReadLine(), out daGuess))
{
if (daGuess != daNumber)
{
Console.WriteLine("no");
}
else
{
Console.WriteLine("that's it yeah");
}
}
}
You don't need to check the guess match twice. What you want is an infinite loop that breaks when the condition is true.
int daNumber = new Random().Next(9);
while(true)
{
if (Int32.TryParse(Console.ReadLine(), out int shortOut))
{
if (shortOut == daNumber)
{
Console.WriteLine("that's it yeah");
break;
}
Console.WriteLine("no ");
}
else
{
Console.WriteLine("cannot be parsed as int");
}
}
}
I'm trying to write a simple console game application & I'm running into some idk moments. Okay, so in the code I'm trying to get a Y/N input and have start the game over if Y, or Exit if N. I'd love to hear some various solutions & there's bonus <3 for a coding sample that assigns random door number every time the game is started or played.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
namespace Desicions
// Typo I know.
{
class Program
{
static void Main(string[] args)
{
bool WrongInput = true;
while (WrongInput)
{
Console.Clear();
Console.WriteLine("Would you perfer what's behind door 1, 2, or 3?");
string userValue = Console.ReadLine();
if (userValue == "1")
{
Console.WriteLine("You won a new car!");
WrongInput = false;
}
else if (userValue == "2")
{
Console.WriteLine("You won a boat!");
WrongInput = false;
}
else if (userValue == "3")
{
Console.WriteLine("Aww, you did not win this time please play again.");
WrongInput = false;
}
else
{
Console.WriteLine("Please choose door number 1, 2, or 3. Press Enter to return to game.");
Console.ReadLine();
}
}
Thread.Sleep(2000);
Console.WriteLine();
Console.WriteLine("Would you like to play again? (Y/N)");
while ((Console.ReadLine() == "Y") || (Console.ReadLine() == "y"))
//Should I use this instead?
//while String.Equals(Console.ReadLine(), "y", StringComparison.CurrentCultureIgnoreCase);
//if so, why?
{
//What goes here for (Y)/(y) input to return into top of while (WrongInput) loop?
Console.WriteLine("Currently in Dev [:");
}
while ((Console.ReadLine() == "N") || (Console.ReadLine() == "n"))
{
//I would like for a (N)/(n) input to WriteLine("Exiting game..."); Thread.Sleep(2000); then exit. Solutions plz por favor?
}
//BONUS c# <3 for code sample for setting doors numbers randomly!
Console.ReadLine();
}
}
}
Here's a somewhat robust approach to tackle this problem:
using System;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
while (true)
{
Console.WriteLine("Choose 1, 2, 3 or X to exit.");
// read input
var s = Console.ReadLine();
// shall we exit ?
if (s != null && s.Trim().Equals("X", StringComparison.InvariantCultureIgnoreCase))
{
Console.WriteLine("Bye bye !");
break;
}
// user picked an activity
int result;
if (!int.TryParse(s, out result)) continue; // failed to read input
// at this point, do something interesting
Console.WriteLine("You selected : " + result);
}
}
}
}
As you'll see,
it won't matter whether user typed in upper case or lower case, with leading/trailing spaces -> the approach handles that
you will compare against a number the user has choosen VS a string (better)
etc ...
Go on and improve on that :)
EDIT : choose a random door
const int maxDoors = 3;
var doors = new Dictionary<int, string>
{
{0, "Door 1"},
{1, "Door 2"},
{2, "Door 3"}
};
var random = new Random();
while (true)
{
// integrate this inside the previous example loop
var door = random.Next(maxDoors);
var doorName = doors[door];
Console.WriteLine("You have chosen the door: " + doorName);
}
You would benefit greatly from simply doing Console.ReadLine().ToLower() (Or ToUpper()), to ignore any case issues.
As for what you currently have, by saying (Console.ReadLine() == "foo" || Console.ReadLine() == "bar"), you are calling the command to take in user input twice, meaning the user will need to input whether they'd like to play again twice before you break into while loop.
As for your random door number, check out System.Random, and assign it to a variable at the start of your game.
https://msdn.microsoft.com/en-us/library/system.random(v=vs.110).aspx
Also, rather than calling an empty Console.WriteLine();, simply add in "\n" to your string to create a newline.
And finally, it's "prefer," not "perfer."
I saw this on the top questions, and I may be stepping over my own limit. Currently learning Java. Just trying to help, sorry If I am of no use.
But couldn't you use a do while loop and towards the end ask for input from the user. Perform the check at the end with the do while loop, if Y/yes continue if N/no don't?
chicken scratch:
do
{
//Game code
//ask for input
} while input == Y | input == y
In my C# code (I am currently trying to learn it), I am trying to make a text - console based adventure game. The first 'Section' works, and I copy pasted it over to and changed the name of the variables etc. (Its a repetitive code), but it just wont work.
Here is the code:
using System;
namespace LearningC
{
class MainClass
{
public static void Main (string[] args)
{
lvl_1_start: //LEVEL ONE
Console.WriteLine ("Welcome to AlexAdventureLand.\nPlease press the enter key to start.");
Console.ReadKey ();
Console.WriteLine ("You are a rabbit in a burrow. There is a badger outside. \nPress 1 to leave the burrow. \nPress 2 to wait.");
int lvl_1 = Convert.ToInt32 (Console.ReadLine ());
if (lvl_1 == 1) {
Console.WriteLine ("The badger sees you and eats you. \nYou fail. \n\nPress enter to try again.");
Console.ReadKey ();
goto lvl_1_start;
} else if (lvl_1 == 2) {
Console.WriteLine ("The badger scurries away!");
goto lvl_2_start;
} else {
Console.WriteLine ("You pressed the wrong button. Start again.");
goto lvl_1_start;
}
lvl_2_start: //LEVEL TWO
Console.WriteLine ("Now what do you want to do? \nPress 1 to leave burrow. \nPress 2 to wait.");
Console.ReadKey ();
int lvl_2 = Convert.ToInt32 (Console.Read ());
if (lvl_2 == 1) {
Console.WriteLine ("You leave the burrow and look around.");
Console.ReadKey ();
goto lvl_3_prt_a_start;
} else if (lvl_2 == 2) {
Console.WriteLine ("You wait a little longer. \nYou can hear footsteps around your burrow. You wonder whether it's your friend - troy - or the badger still.");
goto lvl_3_prt_b_start;
} else {
Console.WriteLine ("You pressed the wrong button. Start again.");
goto lvl_2_start;
}
lvl_3_prt_a_start: //LEVEL THREE PART A
Console.WriteLine ("PlaceHolder");
Console.ReadKey ();
lvl_3_prt_b_start:
Console.WriteLine ("PlaceHolder");
Console.ReadKey ();
}
}
}
The problem occurs when running it. The first section works fine, and pressing '1', '2' or any other number works - but on section two, it always comes up with the else section, none of the if or if else clauses. Any quick help would be great. Thanks!
The problem is that you're calling both ReadKey and Read. These each read a single character, so ReadKey gets your selection, and Read just gets your \r (first character of newline). ReadKey returns info about your keypress (which is ignored), and Read returns an int corresponding to the char value you entered (note that int and char are numeric types, and converting one of those ToInt32 is different from parsing a string!).
You should use code like your working code to read input:
int lvl_2 = Convert.ToInt32(Console.ReadLine()); // or, does the same thing:
int lvl_2 = int.Parse(Console.ReadLine());
(the Convert class supports conversions in a wide range of types; if all you need to do is parse a string to an int, int.Parse is the more common option and gives you more choices)
Also, you should avoid gotos in C#. They lend themselves to writing spaghetti code, and overall are a bad idea (except for very rare exceptions). I can see that they're already leading to your method being a God Method. Here's an example that should put you more on the right track:
static void Main(string[] args)
{
Level1();
}
static void Level1()
{
Console.WriteLine("Welcome to AlexAdventureLand.\nPlease press the enter key to start.");
Console.ReadKey();
Console.WriteLine("You are a rabbit in a burrow. There is a badger outside. \nPress 1 to leave the burrow. \nPress 2 to wait.");
int selection = int.Parse(Console.ReadLine());
if (selection == 1)
{
Console.WriteLine("The badger sees you and eats you. \nYou fail. \n\nPress enter to try again.");
Console.ReadKey();
Level1();
}
else if (selection == 2)
{
Console.WriteLine("The badger scurries away!");
Level2();
}
else
{
Console.WriteLine("You pressed the wrong button. Start again.");
Level1();
}
}
static void Level2()
{
Console.WriteLine("Now what do you want to do? \nPress 1 to leave burrow. \nPress 2 to wait.");
int selection = int.Parse(Console.ReadLine());
if (selection == 1)
{
Console.WriteLine("You leave the burrow and look around.");
Console.ReadKey();
Level3A();
}
else if (selection == 2)
{
Console.WriteLine("You wait a little longer. \nYou can hear footsteps around your burrow. You wonder whether it's your friend - troy - or the badger still.");
Level3B();
}
else
{
Console.WriteLine("You pressed the wrong button. Start again.");
Level2();
}
}
static void Level3A()
{
Console.WriteLine("PlaceHolder");
Console.ReadKey();
}
static void Level3B()
{
Console.WriteLine("PlaceHolder");
Console.ReadKey();
}
I made a program that asks for input and returns a value. After, I want to ask if the user wants to continue. But I don't know what to use.
You want to use a do / while loop, or an infinite while loop with a conditional break.
A do-while loop is often used:
bool #continue = false;
do
{
//get value
#continue = //ask user if they want to continue
}while(#continue);
The loop will be executed once before the loop condition is evaluated.
This only allows 2 keys (Y and N):
ConsoleKeyInfo keyInfo;
do {
// do you work here
Console.WriteLine("Press Y to continue, N to abort");
do {
keyInfo = Console.ReadKey();
} while (keyInfo.Key != ConsoleKey.N || keyInfo.Key != ConsoleKey.Y);
} while (keyInfo.Key != ConsoleKey.N);
I would use a do..while loop:
bool shouldContinue;
do {
// get input
// do operation
// ask user to continue
if ( Console.ReadLine() == "y" ) {
shouldContinue = true;
}
} while (shouldContinue);
You probably want a while loop here, something like:
bool doMore= true;
while(doMore) {
//Do work
//Prompt user, if they refuse, doMore=false;
}
use Do While Loop. something similar will work
int input=0;
do
{
System.Console.WriteLine(Calculate(input));
input = GetUserInput();
} while (input != null)
Technically speaking, any loop will do it, a for loop for example (which is another way to write a while(true){;} )
for (; true; )
{
//Do stuff
if (Console.ReadLine() == "quit")
{
break;
}
Console.WriteLine("I am doing stuff");
}