I am a novice coder learning C# for my class and am having trouble with a practice exercise where we have to make a deck of cards and deal them out.
We need to make a class that creates cards by receiving parameters from another class through a constructor. Then use those values in a Tostring method to set the value and suit of those cards with switch statements and return a card. In the second class we populate an array with cards and call the Tostring method in a Dealing method to randomly generate a user specified amount of cards by pulling them out of the array.
The problem is my array isn't being populated I have tried to Console.WriteLine parts of the array directly after they would be assigned and they are empty. You don't have to give me the full answer put just put me on the right track.
Here is the code:
This is the card creation class
` class Card
{
static int value;
static int suit;
static string cdvalue;
static string cdsuit;
string card;
public Card(int ranvalue, int ransuit) //constructor that sets value and suit
{
value = ranvalue;
suit = ransuit;
}
public override string ToString()
{
switch (value) //switch statement for card value
{
case 1: cdvalue = "ace";
break;
case 2: cdvalue = "two";
break;
case 3: cdvalue = "three";
break;
case 4: cdvalue = "four";
break;
case 5: cdvalue = "five";
break;
case 6: cdvalue = "six";
break;
case 7: cdvalue = "seven";
break;
case 8: cdvalue = "eight";
break;
case 9: cdvalue = "nine";
break;
case 10: cdvalue = "ten";
break;
case 11: cdvalue = "jack";
break;
case 12: cdvalue = "queen";
break;
case 13: cdvalue = "king";
break;
}
switch (suit) // switch for card suit
{
case 1: cdsuit = "Hearts ";
break;
case 2: cdsuit = "Spades ";
break;
case 3: cdsuit = "Diamonds ";
break;
case 4: cdsuit = "Clubs ";
break;
}
card = cdvalue + " of " + cdsuit;
return card;// returns a string in the form of "value of suit"`
This class creates the deck
class Deck
{
Random rng = new Random(); //Random object
private static Card[] deck;
static string[] cards;
public Deck()
{
deck = new Card[52];//creates array of 52 elements
int l = 0;
for (int i = 1; i <= 13; i++)//loops to create cards
{
for (int j = 1; j <= 4; j++)
{
deck[l++] = new Card(i,j); // populates the array with all 52 cards
}
}
}
static string dealt;
static int Rndm;
public string deal(int number)//parameter received from user
{
cards = new string[number];//creates an array to contain dealt card objects
int m = 0;
for (int num=0;num<number;num++) // determines the amount of cards to be dealt
{
Rndm = rng.Next(0,53);
cards[m++] = deck[Rndm].ToString();//fills the card array with randomly dealt cards from the deck
dealt = string.Join(" ", cards); // turns the card array into a single string of the cards dealt
}
return dealt;//returns the cards dealt
This is the test class
static void Main(string[] args)
{
// get the number of cards from the user - must be between 1 and 52
int cardsDealt = -1;
do
{
Console.Write("Enter number of cards to get (1-52): ");
String dealStr = Console.ReadLine();
Boolean parsed = int.TryParse(dealStr, out cardsDealt);
} while (cardsDealt < 1 || cardsDealt > 52);
// create a Deck object
Deck cardDeck = new Deck();
// Call the deal method
String cards = cardDeck.deal(cardsDealt);
// List the result
Console.WriteLine("\nCards dealt:\n" + cards);
In your Card class you have the variables value and suit marked as static.
private static int value;
private static int suit;
Because these two variables are static, the reference to these variables will be maintained across instances of the Card objects. What this means is that every time you create a new Card object you are inadvertently updating all the other Card objects value and suit variables with the same value. So now whenever you get an instance of a Card it will be the same card as all other instances (the last Card that was created).
Remove the static keyword from these declarations and you should be ok.
Also I would suggest reading up on static to more familiarize yourself with its usage: Static keyword in c#
Your code is very close to being correct. You seem to have a misunderstanding of when to use static or not.
If you need a variable that is shared amongst all instances of a class, then use static. But if you need per instance values, then don't.
There are no variables in your code that should be static.
Also, just to help you with your code, you don't need to define all of your variables at the class-level. A lot can (and should) be declared within each method.
Here's the refactored version of your code so that you can see what should be done.
void Main()
{
// get the number of cards from the user - must be between 1 and 52
int cardsDealt = -1;
while (cardsDealt < 1 || cardsDealt > 52)
{
Console.Write("Enter number of cards to get (1-52): ");
String dealStr = Console.ReadLine();
Boolean parsed = int.TryParse(dealStr, out cardsDealt);
}
// create a Deck object
Deck cardDeck = new Deck();
// Call the deal method
String cards = cardDeck.deal(cardsDealt);
// List the result
Console.WriteLine("\nCards dealt:\n" + cards);
}
public class Card
{
private int value;
private int suit;
public Card(int ranvalue, int ransuit) //constructor that sets value and suit
{
value = ranvalue;
suit = ransuit;
}
public override string ToString()
{
string cdvalue = null;
switch (value) //switch statement for card value
{
case 1:
cdvalue = "ace";
break;
case 2:
cdvalue = "two";
break;
case 3:
cdvalue = "three";
break;
case 4:
cdvalue = "four";
break;
case 5:
cdvalue = "five";
break;
case 6:
cdvalue = "six";
break;
case 7:
cdvalue = "seven";
break;
case 8:
cdvalue = "eight";
break;
case 9:
cdvalue = "nine";
break;
case 10:
cdvalue = "ten";
break;
case 11:
cdvalue = "jack";
break;
case 12:
cdvalue = "queen";
break;
case 13:
cdvalue = "king";
break;
}
string cdsuit = null;
switch (suit) // switch for card suit
{
case 1:
cdsuit = "Hearts ";
break;
case 2:
cdsuit = "Spades ";
break;
case 3:
cdsuit = "Diamonds ";
break;
case 4:
cdsuit = "Clubs ";
break;
}
string card = cdvalue + " of " + cdsuit;
return card;// returns a string in the form of "value of suit"`
}
}
public class Deck
{
private Random rng = new Random(); //Random object
private Card[] deck;
public Deck()
{
deck = new Card[52];//creates array of 52 elements
int l = 0;
for (int i = 1; i <= 13; i++)//loops to create cards
{
for (int j = 1; j <= 4; j++)
{
deck[l++] = new Card(i, j); // populates the array with all 52 cards
}
}
}
public string deal(int number)//parameter received from user
{
string[] cards = new string[number];//creates an array to contain dealt card objects
for (int num = 0; num < number; num++) // determines the amount of cards to be dealt
{
int Rndm = rng.Next(deck.Length);
cards[num] = deck[Rndm].ToString();//fills the card array with randomly dealt cards from the deck
}
string dealt = string.Join(" ", cards); // turns the card array into a single string of the cards dealt
return dealt;//returns the cards dealt
}
}
The only other concern with this is that your dealing code produces duplicate cards. You may need to do something about that.
If I were coding this, this is how I would do it:
public class Card
{
private int value;
private int suit;
public Card(int ranvalue, int ransuit)
{
value = ranvalue;
suit = ransuit;
}
public override string ToString()
{
var values = new []
{
"ace", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "jack", "queen", "king"
};
var suits = new []
{
"Hearts", "Spades", "Diamonds", "Clubs"
};
return String.Format("{0} of {1}", values[value - 1], suits[suit - 1]);
}
}
public class Deck
{
private Random rng = new Random();
private Card[] deck;
public Deck()
{
deck =
(
from value in Enumerable.Range(1, 13)
from suit in Enumerable.Range(1, 4)
select new Card(value, suit)
).ToArray();
}
public string deal(int number)
{
string dealt = string.Join(" ", deck.OrderBy(x => rng.Next()).Take(number));
return dealt;
}
}
This fixes the duplicate card issue.
Related
public class ChineseZodiac
{
public static void Main(String[] args)
{
Console.Write("Enter a year: ");
var year = Convert.ToInt64(Console.ReadLine());
switch (year % 12)
{
case 0:
Console.WriteLine("monkey");
break;
case 1:
Console.WriteLine("rooster");
break;
case 2:
Console.WriteLine("dog");
break;
case 3:
Console.WriteLine("pig");
break;
case 4:
Console.WriteLine("rat");
break;
case 5:
Console.WriteLine("ox");
break;
case 6:
Console.WriteLine("tiger");
break;
case 7:
Console.WriteLine("rabbit");
break;
case 8:
Console.WriteLine("dragon");
break;
case 9:
Console.WriteLine("snake");
break;
case 10:
Console.WriteLine("horse");
break;
case 11:
Console.WriteLine("sheep");
break;
}
}
}
I'm trying to get the formula in the switch statement block to output a zodiac sign based on the user's input. I'm also supposed to have the switch statement converted to a switch expression with the same results. I was able to run it without any errors in VS Code as a switch statement but I'm confused about the difference between a switch statement and a switch expression.
Switch expressions return a value, so you couldn't do exactly what you're doing now (since the action is happening within the switch), but you could use it to return the string and then display it:
var yearMod12 = year % 12;
var yearOf = yearMod12 switch
{
0 => "monkey",
1 => "rooster",
...
};
Console.WriteLine(yearOf);
An enum or Dictionary<int, string> would be a good choice for this type of mapping as well.
I suggest extracting model (animals) into a collection; try keeping data and actions separatedly:
public class ChineseZodiac {
// Model (data): Zodiac animals
private static readonly IReadOnly<string> s_Animals = new string[] {
"monkey", "rooster", "dog",
"pig", "rat", "ox",
"tiger", "rabbit", "dragon",
"snake", "horse", "sheep",
};
// An action which is based on the model
public static void Main(String[] args) {
Console.Write("Enter a year: ");
Console.WriteLine(s_Animals[int.Parse(Console.ReadLine()) % s_Animals.Count]);
}
}
Hit everyone! I'm still learning C# and I would like to print different string for each loop based on the switch cases.
static Random rand = new Random();
static void Main(string[] args){
string someString = "";
int someRandom = rand.Next(4);
switch(someRandom) {
case 0:
someString = "Woa";
break;
case 1:
someString = "Waa";
break;
case 2:
someString = "Wee";
break;
case 3:
someString = "Wow!";
break;
}
int someCount = 5;
for (int someInt = 0; someInt < someCount; someInt++) {
Console.WriteLine(someString);
}
Console.Read();
}
What it should do: display random string each loop from the switch.
What it actually does: Selects case randomly and prints the same case in each loop.
I couldn't produce a random string, why is that? I tried adding someRandom = rand.Next(4) inside the for loop but still produces same.
I already tried searching but couldn't find an answer that could solve my problem.
It seems that you are only setting somestring once, and then printing it a bunch. You should put the switch statement in the for loop.
You need to generate the random number (and set the someString variable) inside the loop, otherwise you only pick one random number and then display it multiple times in the loop.
Here's an example but with some slightly better names (IMO):
static Random rand = new Random();
static void Main()
{
int count = 5;
for (int i = 0; i < count; i++)
{
string output;
switch(rand.Next(4))
{
case 0:
output = "Woa";
break;
case 1:
output = "Waa";
break;
case 2:
output = "Wee";
break;
case 3:
output = "Wow!";
break;
default:
output = "This shouldn't happen";
break;
}
Console.WriteLine(output);
}
Console.Read();
}
This question already has answers here:
Get int value from enum in C#
(29 answers)
How do I cast int to enum in C#?
(32 answers)
Closed 2 years ago.
I simply need to use enum with entered number, but I don't know how to convert. Do I have to create an additional variable of int and than convert?
public enum Actions
{
delete,
add,
edit
};
Actions ac = Actions.Parse(Concole.Readline());
switch (ac)
{
case Actions.delete:
int k = int.Parse(Console.ReadLine());
Delete(flights[k]);
Console.WriteLine("");
break;
case 2:
Add();
Console.WriteLine("");
break;
case 3:
Edit();
Console.WriteLine("");
break;
default:
Console.WriteLine("Incorrect number!");
break;
}
You can take in a string and convert it to Enum using Enum.Parse
Actions ac = (Actions)Enum.Parse(typeof(Actions), Console.ReadLine());
// THen use switch on ac.
switch (ac)
{
case Actions.add:
// do something here
break;
case Actions.delete:
// do something here
break;
default:
throw new ApplicationException("Error");
}
Enums, by default, starts with 0. If you want to start with a 1, then assign the int values
public enum Actions
{
delete = 1,
add = 2,
edit = 3
};
from this answer: https://stackoverflow.com/a/29485/4394435
public enum Actions
{
delete, // 0
add, // 1
edit // 2, you can change those by setting them like this: edit = 2
};
class Program
{
static void Main(string[] args)
{
Actions ac = (Actions) Enum.Parse(typeof(Actions), Console.ReadLine());
switch (ac)
{
case Actions.delete:
int k = int.Parse(Console.ReadLine());
Delete(flights[k]);
Console.WriteLine("");
break;
case Actions.add:
Add();
Console.WriteLine("");
break;
case Actions.edit:
Edit();
Console.WriteLine("");
break;
default:
Console.WriteLine("Incorrect number!");
break;
}
}
}
Sorry for posting this wall of garbage code :( I didn't want to leave anything out! Im still new and got a little ahead of myself. I wanted to put the "switch case" in a new class so I could reference it faster while also learning to make a new class file. Unfortunately I ran into one bug after another and I couldn't figure out why. The main issue i had is that when I call the case number in the main method, it only returns the string.
Ex. I want the output to be:
"Well [user created name], are you ready to begin your journey to the edge of the world?"
It seems there is an issue with the two classes communicating with eachother.
I have made it worse throwing "public static" at everything to try to make it work. I would really appreciate the help.
using System;
using Test;
public class Scripts
{
public Program p { get; set; }
public void Script(int s)
{
switch (s)
{
case 1:
p.output = "Quest to the edge of the world!";
p.WriteLine();
break;
case 2:
p.output = "Hello! I am your instructor. What is your name apprentice?";
p.WriteLine();
break;
case :
p.output = p.name + " you say? My, what a strange name.";
p.WriteLine();
break;
case 4:
p.output = "Well " + p.name + ", are you ready to begin your journey to the edge of the world?";
p.WriteLine();
break;
case 5:
p.output = " (y)Yes on (n)No";
p.WriteLine();
break;
case 6:
p.output = "OK! Before we go lets go over our gear. What should we prioritize? (1)Magic, (2)Melee, or (3)Ranged?";
p.WriteLine();
break;
case 7:
p.output = "Well I'll just come back tomorrow then.";
p.WriteLine();
break;
case 8:
p.output = "I'm sorry... that's not an option.";
p.WriteLine();
break;
case 9:
p.output = "I'm pretty good at " + p.combatStyle + " combat myself, I'll be sure to teach you everything I know.";
p.WriteLine();
break;
case 10:
p.output = "OK! Let's hit the road and make camp at sundown.";
p.WriteLine();
break;
case 11:
p.output = "Chapter " + p.chapter;
p.WriteLine();
break;
case 12:
p.output = p.name + ", wake up!Were under attack by a couple of goblins!";
p.WriteLine();
break;
case 13:
p.output = "I guess this is the perfect chance to teach you a new" + p.form + "called";
p.WriteLine();
break;
case 14:
p.output = "It makes quick work of their health, but your" + p.energyBar + " will go down just as fast so use it wisely!";
p.WriteLine();
break;
case 15:
p.output = "I'll take care of the one on the right, you engage the one on the left.";
p.WriteLine();
break;
case 16:
p.output = "Press (f) to enter combat. Then press (1) to make an attack";
p.WriteLine();
break;
default:
break;
}
}
}
using System;
using System.Threading;
namespace Test
{
public class Program
{
public Scripts s { get; set; }
// Class Global Variables
public static string input;
public static string output;
public static string name = "bob";
private static string yes = "y";
private static string no = "n";
private static string option1 = "1";
private static string option2 = "2";
private static string option3 = "3";
private static string pathA;
private static string pathB;
private static string pathC;
public static string combatStyle;
private static string weapon;
public static string chapter = "Zero";
public static string form;
public static string energyBar;
private static string healthBar;
Program p = new Program();
public static string[] numbers = new string[] { "One","Two", "Three", "Four", "Five" };
private static int mp = 100;
private static int stamina = 100;
private static int script;
//ReadLine & WriteLine Methods
private static void ReadLine()
{
Console.SetCursorPosition((Console.WindowWidth - 110) / 2, Console.CursorTop);
input = Console.ReadLine();
}
public static void WriteLine()
{
Thread.Sleep(2000);
Console.SetCursorPosition((Console.WindowWidth - output.Length) / 2, Console.CursorTop);
Console.WriteLine(output);
}
//Next Chapter Screen
private static void nextChapter()
{
Thread.Sleep(3000);
Console.Clear();
Thread.Sleep(1500);
output = "\r\n\r\n\r\n\r\n";
WriteLine();
//output = script[12] + chapter;
WriteLine();
Console.Beep();
Thread.Sleep(1500);
Console.Clear();
}
//Yes or No Decision
private static void YesNo()
{
while (input != yes && input != no)
{
ReadLine();
if (input == yes)
{
output = pathA;
WriteLine();
}
else if (input == no)
{
output = pathB;
WriteLine();
}
else
{
//output = script[8];
WriteLine();
}
}
input = "";
}
//Multiple Choice Decision
private static void Choice()
{
while (input != option1 && input != option2 && input != option3)
{
ReadLine();
if (input == option1)
{
output = pathA;
WriteLine();
}
else if (input == option2)
{
output = pathB;
WriteLine();
}
else if (input == option3)
{
output = pathC;
WriteLine();
}
else
{
//output = //script[8];
//WriteLine();
}
}
input = "";
}
//Combat Loop
private static void combatLoop()
{
if (input == "f")
{
}
else
{
//output = script[8];
WriteLine();
combatLoop();
}
}
//Main Method
static void Main()
{
//Chapter Zero "Intro"
Scripts s = new Scripts();
s.Script(1);
s.Script(2);
ReadLine();
name = input;
Console.WriteLine(input);
Console.WriteLine(name);
s.Script(3);
//Chapter One "Combat"
//Chapter Two "Trading"
//Chapter Three "Dungeon"
//Chapter Four "Sailing"
//Chapter Five "The Edge"
// Keep the console open in debug mode.
Console.WriteLine("Press any key to quit game.");
Console.ReadKey();
}
}
}
Looks like your class is in a separate namespace, and the existing namespace for program is not using a using statement for including your separate class.
If you're using static methods / variables, you shouldn't use the object, you should use the class itself:
Program.output = "bla";
Program.WriteLine();
instead of
p.output = "bla";
p.WriteLine();
As your field p isn't even initalized, your current code shouldn't compile. If you want to use the object, you should pass it like that:
public void Script (int s, Program p)
Then you could also make your methods non-static.
Also I'm wondering why you're setting your cursor position to half the length of the text from the right - why not the full offset?
Furthermore you're saying that
The main issue i had is that when I call the case number in the main method, it only returns the string.
What do you mean by returning the string? Your Script method doesn't even have a return type (except for void).
The last but 3rd line of code is not recognizing variables that I have declared and filled with strings.
static void Main(string[] args)
{
string inputNumber = "1979";
string input1 = inputNumber.Substring(0, 1);
string input2 = inputNumber.Substring(1, 1);
string input3 = inputNumber.Substring(2, 1);
string input4 = inputNumber.Substring(3, 1);
int intInput1;
int intInput2;
int intInput3;
int intInput4;
intInput1 = Convert.ToInt32(input1);
intInput2 = Convert.ToInt32(input2);
intInput3 = Convert.ToInt32(input3);
intInput4 = Convert.ToInt32(input4);
string stringOutput1;
string stringOutput2;
string stringOutput3;
string stringOutput4;
// 1000 Input.
switch (intInput1)
{
case 1:
stringOutput1 = "M";
break;
default:
break;
}
//100 Input
switch (intInput2)
{
case 9:
stringOutput2 = "CM";
break;
default:
break;
}
//10 Input
switch (intInput3)
{
case 7:
stringOutput3 = "LXX";
break;
default:
break;
}
//1 Input
switch (intInput4)
{
case 9:
stringOutput4 = "IX";
break;
default:
break;
}
//Use of unassigned local variable error is showing for 'stringOutput1', 'stringOutput2', 'stringOutput3' and 'stringOutput4'
Console.WriteLine("{0} is {1}{2}{3}{4} in Roman Numerals",inputNumber, stringOutput1, stringOutput2, stringOutput3, stringOutput4);
Console.CursorVisible = false;
Console.ReadKey();
}
P.S. I know that the variables are being filled by commenting out
Console.WriteLine("{0} is {1}{2}{3}{4} in Roman Numerals",inputNumber, stringOutput1, stringOutput2, stringOutput3, stringOutput4);
and using break point and stepping over the code.
This is because your variables might not have been assigned anything yet. Variables must be guaranteed to have been assigned something before they can be used. As a simple fix, you can use declarations like this:
string stringOutput1 = "";
Try assigning nulls to the declarations
string stringOutput1 = null;
string stringOutput2 = null;
string stringOutput3 = null;
string stringOutput4 = null;
You have to initialize your variables, do it like this.
string stringOutput1 , stringOutput1, stringOutput3, stringOutput4 = string.Empty;
and you can also assign default values per variable.
string stringOutput1 = "foo1", stringOutput1 = "foo2"
, stringOutput3= "foo3", stringOutput4 = "foo4";