For my code, it is a number guessing game. They get 10 guesses before they lose, and it tells them if it is too low, too high etc. In my output when I'm telling them if they are too high or too low, I also wanted to display how many guesses they have left. But currently it tells them they have 9 guesses left every time and I'm not sure why.
The rest of the program works. So after 10 guesses it will tell them they lost, just every guess up until then it says they have 9 guesses left.
namespace NumberGuessingGame
{
public class GuessingGame
{
int myGuess = 0;
int guessesLeft = 10;
int gamesPlayed = 0;
int gamesWon = 0;
int gamesLost = 0;
Random rand;
int number = 0;
public GuessingGame()
{
rand = new Random();
number = rand.Next(1, 100);
}
public void ResetGame()
{
number = rand.Next(1, 100);
guessesLeft = 10;
}
public int CheckGuess(int newGuess)
{
myGuess = newGuess;
if (guessesLeft < 1)
{
gamesLost++;
gamesPlayed++;
ResetGame();
return 2;
}
else if (myGuess > number)
{
guessesLeft--;
return 1;
}
else if (myGuess < number)
{
guessesLeft--;
return -1;
}
else
{
gamesPlayed++;
gamesWon++;
ResetGame();
return 0;
}
}
}
}
Code for form class
namespace NumberGuessingGame
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
GuessingGame myGuess = new GuessingGame();
private void btnCheck_Click(object sender, EventArgs e)
{
int inputGuess = Convert.ToInt32(txtGuess.Text);
int result = myGuess.CheckGuess(inputGuess);
int guessesLeft = 10;
if(result == 2)
{
MessageBox.Show("You ran out of guesses and lost!");
}
else if(result == 1)
{
guessesLeft--;
MessageBox.Show("Your guess was too high, try again!" + "\n You have " + guessesLeft + " guesses left");
}
else if(result == -1)
{
guessesLeft--;
MessageBox.Show("Your guess was too low, try again!" + "\n You have " + guessesLeft + " guesses left");
}
else if(result == 0)
{
MessageBox.Show("You won!");
}
}
}
}
Every time the button is clicked, you set guessesLeft to 10, which causes the issue. If you make guessesLeft a private field it will be fixed.
Like this:
public partial class frmMain : Form
{
private int guessesLeft = 10;
etc.
private void btnCheck_Click(object sender, EventArgs e)
{
int guessesLeft = 10;
This guessesLeft is a local variable on the stack of btnCheck_Click(). It is destroyed when the function returns, and is re-created and reinitialized to 10 every time the button is pressed and the function is called.
You need to expose the guessesLeft from your GuessingGame class. The best way would be via a read-only property:
public class GuessingGame
{
// ...
public int GuessesRemaining
{
get { return guessesRemaining; }
}
You have 2 separate guessesLeft variables - one in your btnCheck_Click event method, and one in your GuessingGame class. Every time you click the button, it initializes a new guessesLeft and sets it to 10, decrements it, and then the variable goes out of scope. You should only have one variable that holds that information, and the best place would be in your guessingGame class as a public property:
public class GuessingGame
{
public int GuessesLeft { get; private set; }
}
and use that in your click event:
MessageBox.Show("Your guess was too high, try again!" + "\n You have "
+ myGuess.GuessesLeft + " guesses left");
You are re-initializing the guessesLeft variable to 10 everytime the button is clicked. You instead want to query the variable from the GuessingGame object you created called myGuess.
Related
I'm having issues creating a program that is a number guessing program. I think I have the written part right but possibly not the order of it? I have to use multiple methods such as a method for number generator of the number that is supposed to be guessed, a method for collecting the guess input, and method for checking the guess to see if it's right. I've literally have tried just about everything for days but all I get is rather a repeat of, "Enter the number: " even if its right, although it's supposed to repeat if it's too high or low. Or sometimes the console won't print anything. what is wrong? Here is the code:
using System;
namespace GuessTheNumber
{
class Program
{
public static int RandomNumberGenerator()
{
Random random = new Random();
return random.Next(1, 21);
}
public static int InputGetter()
{
Console.Write("Enter in a number: ");
int guess = Convert.ToInt32(Console.ReadLine());
return guess;
}
public static String GuessChecker(int guess, int secretNumber)
{
if(guess > secretNumber)
{
return "Too high!";
}
else if (guess < secretNumber)
{
return "Too low!";
}
else
{
return "Correct";
}
}
static void Main(string[] args)
{
int secretNumber = 10;
Console.WriteLine("" + secretNumber);
while (true)
{
while (InputGetter() != secretNumber)
{
InputGetter();
GuessChecker(InputGetter(), secretNumber);
}
if (GuessChecker(InputGetter(), secretNumber) == ("Correct!"))
{
Console.WriteLine("Would you like to play again?");
String input = Console.ReadLine();
if (GuessChecker(InputGetter(), secretNumber) == ("Yes"))
{
secretNumber = RandomNumberGenerator();
}
else if (GuessChecker(InputGetter(), secretNumber) == ("No"))
{
break;
}
}
}
}
}
}
You are invoking InputGetter() multiple times and your logic is incorrect.
It has nothing to do with Random instance being used.
I have quickly modified your code and it should work now as follows:
New number is generated, if you enter low/high message is displayed, if you enter correct number you are presented with the Would you like to try again message.
EDIT: I did not want to change original code much,In general Comparing strings is bad, you should not use it. Creating enum like and comparing would be much better
class Program
{
public static int RandomNumberGenerator()
{
Random random = new Random();
var generatedNumber = random.Next(1, 21);
Console.WriteLine($"New Number generated! {generatedNumber}");
return generatedNumber;
}
public static int InputGetter()
{
Console.Write("Enter in a number: ");
int guess = Convert.ToInt32(Console.ReadLine());
return guess;
}
public static String GuessChecker(int guess, int secretNumber)
{
if (guess > secretNumber)
{
Console.WriteLine("Too High");
return "Too high!";
}
else if (guess < secretNumber)
{
Console.WriteLine("Too low!");
return "Too low!";
}
else
{
Console.WriteLine("Correct");
return "Correct";
}
}
static void Main(string[] args)
{
int secretNumber = 10;
Console.WriteLine("" + secretNumber);
while (true)
{
int enteredNumber = 0;
do
{
enteredNumber = InputGetter();
} while (GuessChecker(enteredNumber, secretNumber)!="Correct");
Console.WriteLine("Would you like to play again?[Yes/No]");
String input = Console.ReadLine();
if (input=="Yes")
{
secretNumber = RandomNumberGenerator();
}
else
{
break;
}
}
}
}
I'm trying to get my program to start the user with 20 lives and while Lives is greater than 0, flip a coin (random number generator 0(Tails) or 1(Heads)). Every time the user gets Heads it adds 1 to Heads counter and 1 to Flips counter. Every time the user gets Tails it takes 1 from Lives and adds 1 to Flips counter. I think my only problem is my random number generator!? Please be kind, total n00b :)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Coin_Flip_2015
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Random r = new Random(1);
private void cmdFlipCoin_Click(object sender, EventArgs e)
{
int rand = r.Next(1);
int Heads;
int counterFlips;
int Lives;
Lives = 20;
Heads = 0;
counterFlips = 0;
while (Lives > 0)
if (rand == 0)
{
Lives = Lives -= 1;
counterFlips++;
}
else if (rand == 1)
{
Heads = Heads += 1;
counterFlips++;
}
lblFlips.Text = "Flips = " + counterFlips.ToString();
lblHeads.Text = "Heads = " + Heads.ToString();
lblLivesLeft.Text = "Lives Left = " + Lives.ToString();
MessageBox.Show("sorry you are out of lives m8");
}
}
}
The Random.Next(int) method
Returns a non-negative random integer that is less than the specified maximum.
So r.Next(1) is always 0. Use r.Next(2) to get 0 or 1.
You should also move the rand = r.Next(1); inside the while loop. Now it's only assigned once, at the beginning of the method.
I'll take a swing at fixing all the issues:
public partial class Form1 : Form
{
int Heads, counterFlips, Lives;
public Form1()
{
InitializeComponent();
Lives = 20;
Heads = 0;
counterFlips = 0;
}
private Random r = new Random();
private void cmdFlipCoin_Click(object sender, EventArgs e)
{
int rand = r.Next(2);
if (Lives > 0)
{
if (rand == 0)
{
Lives -= 1;
counterFlips++;
}
else
{
Heads += 1;
counterFlips++;
}
}
else
MessageBox.Show("sorry you are out of lives m8");
lblFlips.Text = "Flips = " + counterFlips.ToString();
lblHeads.Text = "Heads = " + Heads.ToString();
lblLivesLeft.Text = "Lives Left = " + Lives.ToString();
}
}
Issues:
The Heads, counterFlips and Lives variables were stored locally, they need to be global
The code was changed so that you flip a coin each time you click the button (changed the while to an if). while loops that have the capability of never exiting should not be used in UI threads.
private Random r = new Random() notice removed the 1, use the default constructor to seed it properly.
Added an "else" to show when the lives were used, it shows your message
Changed the Lives = Lives -= 1 (same with Heads) to proper code
Used r.Next(2) to get either 0 or 1, since the upper bound is exclusive.
Other than that, I'm not sure what you are doing with the Lives and Heads numbers, so I'll leave that up to you to fix.
Here one that is a bit different.. snap beat me by a few seconds!
public partial class Form1 : Form
{
// Leave the seed alone on this line
private readonly Random _r = new Random();
// these need to be outside of your Click event
private int _counterFlips;
private int _heads;
private int _lives = 20;
public Form1()
{
InitializeComponent();
}
private void cmdFlipCoin_Click(object sender, EventArgs e)
{
// x = starting number, y = ending number + 1
// This should be either a zero or one:
int rand = _r.Next(0, 2);
switch (rand)
{
default:
_lives --;
_counterFlips++;
break;
case 1:
_heads ++;
_counterFlips++;
break;
}
if (_lives < 1)
{
MessageBox.Show(#"sorry you are out of lives m8");
button1.Enabled = false;
return;
}
lblFlips.Text = #"Flips = " + _counterFlips;
lblHeads.Text = #"Heads = " + _heads;
lblLivesLeft.Text = #"Lives Left = " + _lives;
}
}
I'm very new to C# and have a very limited understanding of the "proper code" to use. I had the goal to imitate the old Pokemon battle systems as best I could with what I know and am having a hard time linking a stored int value for HP between two methods (assuming that's the right word), to calculate new Hp when the second method interacts with the main method. Had a hard time finding an answer for that in searches so here is the code:
" static void Main(string[] args)
{
Random Gen = new Random();
int enemyhealth = (150);
int playerhealth = (100); //the line i need to use
int edefense = (20);
int pattack = (30);
int rate = Gen.Next(1,5);
int critical = 0; "
static void enemyattack()
{
Random Gen1 = new Random();
int pdefense = (20);
int eattack = (20);
int erate = Gen1.Next(1, 5);
int ratattack = Gen1.Next(1,3);
int critical1 = 0;
Console.WriteLine("Enemy Ratta gets ready!");
Console.ReadKey();
Console.WriteLine("----------------------------------------------------------------------------");
Console.WriteLine("\nEnemy Ratta attacks!\n");
Console.WriteLine("----------------------------------------------------------------------------");
ratattack = Gen1.Next(1,3);
if (ratattack = 1)
{
Console.WriteLine("Enemy Ratta used Tail Whip!");
pdefense = (pdefense - erate);
Console.ReadKey();
Console.WriteLine("----------------------------------------------------------------------------");
erate = Gen1.Next(1, 5);
if (erate <= 3)
{
Console.WriteLine("\nIt wasn't very effective!");
}
else
{
Console.WriteLine("\nIt was super effective!");
}
Console.WriteLine("Squirtle's Defense decreased by " + erate + "");
Console.WriteLine("----------------------------------------------------------------------------");
}
else if (ratattack == 2)
{
Console.WriteLine("\nRatta used Tackle");
erate = Gen1.Next(1, 5);
if (erate >= 5)
{
Console.WriteLine("----------------------------------------------------------------------------");
Console.WriteLine("----------------------------------------------------------------------------");
Console.WriteLine("\nCRITICAL HIT!!!!");
Console.WriteLine("----------------------------------------------------------------------------");
Console.WriteLine("----------------------------------------------------------------------------\n");
Console.ReadKey();
Console.WriteLine("It was super effective!");
Console.ReadKey();
eattack = eattack + 10;
}
else
{
critical1 = Gen1.Next(1, 5);
eattack = critical1 + eattack;
}
phealth = Math.Abs((eattack - pdefense) - playerhealth); ***//This Line is where I'm having trouble because phealth is used in my first method as a stored integer and the new calculation for phealth won't interact with the phealth in the origional main, i simply belive I haven't learned that part of c#, I only have 5 hours of youtube tutorials.***
Console.WriteLine("Ratta dealt " + Math.Abs(eattack - pdefense) + " damage!");
eattack = 30;
Console.WriteLine("\n----------------------------------------------------------------------------");
Console.ReadKey();
Console.ReadKey();
}
}
}
}
Make Static method , or simply add your variable in the main Class (where Main method Stored)
Here example
class Program
{
int HP;
int Main()
{
HP=0; //Now you HP is 0;
Method();
}
void Method()
{
HP+=50; //Now you HP is 50
}
}
I would break things down into separate classes. For example you should have a Player class that contains all the information for the player. You can't have methods like that in your main program. You need to keep everything separate. Make a class for each object you need.
public class Player
{
int currentHp = 100;
int maxHp = 100;
int atkPower = 20;
int defense = 20;
string playerName = "Ashe"
public Player() {}
public void TakeDamage(int damage)
{
currentHp = currentHp - damage;
}
}
public class Enemy
{
int currentHp = 100;
int maxHp = 100;
int atkPower = 20;
int defense = 20;
string enemyName= "Rattata"
public Enemy(){}
public int AttackPlayer(Player player)
{
// all of your attack logic, pass in the player here
player.TakeDamage(someAmountofDamage);
}
}
Then in your main program:
static void Main(string[] args)
{
Player myPlayer = new Player();
Enemy myEnemy = new Enemy();
myEnemy.AttackPlayer(player);
}
I have been trying to figure out what is happening with my code. I wrote an application where the user is able to enter marks of the student through a GUI application. The first form shows options, the next form is to enter the student information (name, number, mark), and the last form is to display a summary of the student information (total number of students, highest mark, lowest mark, name of student with highest mark, list of students).
To store all the student entries, I had made a student class. I created a static Student array and placed it in my ProgramFunctions class file (which is all static methods).
When I try to run the form which displays the student summary, thats where it crashes - If I look at the Auto's tab, it tells me the value of student[a] is null (I made use of a for loop to go through each student object in the array). I did trace through the adding of students and it does show that I have added new entries to the Student array.
Exceptions would be thrown at my calculation methods (highestMark, lowestMark, average). Here is my code:
class ProgramFunctions
{
private static Student[] studentList = new Student[25];
private static int counter = 0;
public static void addNewStudent(Student newStudent)
{
if (studentList.Count() == counter)
{
MessageBox.Show("The Student List is Full", "List is Full");
}
else
{
studentList[counter] = newStudent;
counter++;
}
}
public static void displayErrorMessage(String message, String title)
{
MessageBox.Show(message, title);
}
public static TextBox validateTextBox(int textboxNumber, TextBox thisTextBox)
{
if (textboxNumber.Equals(1)) //Student Name textbox
{
if (thisTextBox.Text.Length < 0 || thisTextBox.Text.Length > 100)
{
displayErrorMessage("The Student Name specified is out of allowed region (greater than 100 or less than 0 characters. Please fix this", "Student Name Error");
}
else
{
thisTextBox.Text = thisTextBox.Text.Trim();
return thisTextBox;
}
}
else if (textboxNumber.Equals(2)) //Student number text box (only 10 characters allowed)
{
if (thisTextBox.Text.Length < 0 || thisTextBox.Text.Length > 10)
{
displayErrorMessage("The student number you specified is greater than 10 characters or less than 0. Please fix this", "Student Number Error");
}
else
{
thisTextBox.Text = thisTextBox.Text.Trim();
return thisTextBox;
}
}
else
{
if (thisTextBox.Text.Length > 2 || thisTextBox.Text.Length < 0)
{
displayErrorMessage("Invalid Length for exam mark", "Invalid Exam Mark");
}
else
{
thisTextBox.Text = thisTextBox.Text.Trim();
return thisTextBox;
}
}
return null;
}
public static int getMaximumMarkPosition()
{
int highestMark = -999;
int positionFound = -1;
for (int a = 0; a < counter; a++)
{
if (studentList[a].getExamMark > highestMark)
{
highestMark = studentList[a].getExamMark; //This is where the error would occur
positionFound = a;
}
}
return positionFound;
}
public static int getHighestMark(int position)
{
return studentList[position].getExamMark;
}
public static int getLowestMark(int position)
{
return studentList[position].getExamMark;
}
public static string getHighestStudentMarkName(int position)
{
return studentList[position].getStudentName;
}
public static int getLowestMarkPosition()
{
int lowestMark = 999;
int positionFound = -1;
int studentMark = 0;
for (int a = 0; a < studentList.Count(); a++)
{
studentMark = studentList[a].getExamMark; //This is where the error would occur
if (studentMark < lowestMark)
{
lowestMark = studentMark;
positionFound = a;
}
}
return positionFound;
}
public static double calculateClassAverage()
{
double sum = 0;
double average = 0;
for (int a = 0; a < studentList.Count(); a++)
{
sum = sum + studentList[a].getExamMark;
}
average = sum / studentList.Count();
return average;
}
public static int getTotalNumberOfStudents()
{
return counter;
}
public static RichTextBox getTextBoxData(RichTextBox thisTextBox)
{
thisTextBox.Text = "STUDENT MARK DATA: \n\n";
for (int a = 1; a < studentList.Count(); a++)
{
Student currentStudent = returnStudentInformation(a);
thisTextBox.Text = thisTextBox.Text + "\n" + currentStudent.getStudentName + "\t\t" + currentStudent.getExamMark + "\t" + currentStudent.getStudentNumber;
}
return thisTextBox;
}
public static Student returnStudentInformation(int index)
{
return studentList[index];
}
}
}
It seems to me that if the student list isn't full accessing any index at counter or higher will result in a null object. I would suggest only looping up to counter:
for (int a = 1; a < counter; a++)
{
Student currentStudent = returnStudentInformation(a);
thisTextBox.Text = thisTextBox.Text + "\n" + currentStudent.getStudentName + "\t\t" + currentStudent.getExamMark + "\t" + currentStudent.getStudentNumber;
}
All this begs the question why use a static array for dynamic data when List<T> is available and is made for dynamic data.
I'm working on a small programme for booking seats on an airplane - And I keep getting this error. i want the programme to show me which seats on the plane (flysaeder) are being booking by what passenger (passagerer). Only, If I enter in more seats than I have passengers, it won't run - I need it to allow open seats (less "passagerer" than "flysaeder"). What am I doing wrong?
I'm kinda new at this, so I apologize for poor explanation.
Error occurs on "listeOverPassagerer[index] = listeOverPassagerer[i];".
namespace eksamenvingerne
{
public partial class Form1 : Form
{
int flysaeder;
int passagerer;
Random tilfældighed = new Random();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
listBox2.Items.Clear();
{
int.TryParse(txtsaeder.Text, out flysaeder);
int.TryParse(txtantalpassagere.Text, out passagerer);
if (passagerer > flysaeder)
{
MessageBox.Show("Ingen frie pladser!");
}
else
{
int[] listeOverPassagerer = Enumerable.Range(0, passagerer).ToArray();
int[] flypladser = new int[flysaeder];
for (int i = 0; i < flysaeder; i++)
{
int index = tilfældighed.Next(0, passagerer);
flypladser[i] = tilfældighed.Next(i, passagerer);
flypladser[i] = listeOverPassagerer[index];
listeOverPassagerer[index] = listeOverPassagerer[i];
}
for (int i = 0; i < flypladser.Length; i++)
{
listBox1.Items.Add("Sæde #" + i + ": Passagernr.:" + flypladser[i]); //listboxen udskriver indholdet af hver eneste plads.
}
}
}
}
}
}
Your logic actually is causing this problem:
First you make sure that passagerer <= flysaeder
if (passagerer > flysaeder)
{
MessageBox.Show("Ingen frie pladser!");
}
Then you do a for loop from 0 to flysaeder -1
for (int i = 0; i < flysaeder; i++)
But flysaeder might be larger than passagerer hence your access of listeOverPassagerer[i] will throw an exception since listeOverPassagerer is of length passagerer