Unnecessary extra input lines - c#

I am making an app that based on the input of one of player1 it creates a new number based on difficulty.
When I input the number, the app asks for number I entered+ more to display and I don't want that. Example:
If I input 4, the app will ask for 4 other inputs.
https://i.stack.imgur.com/PD2zQ.png
I don't want this to happen can anyone explain why and how to fix this?
Here is my main code.
Console.WriteLine($"Can {user[0]} select a level? If not choosen between either 30 seconds or between 1, 2, 3 it will be automatically choosen.");
Level_Select level = new Level_Select(LevelSelect());
static int LevelSelect()
{
int select;
int.TryParse(Console.ReadLine(), out select);
return select;
}
if (LevelSelect() == 1)
{
Console.WriteLine($"{Level_Select.level1()}");
}
else if (LevelSelect() == 2)
{
Console.WriteLine($"{Level_Select.level2()}");
}
else if (LevelSelect() == 3)
{
Console.WriteLine($"{Level_Select.level3()}");
}
else if ((LevelSelect() != 1) || (LevelSelect() != 2) || (LevelSelect() != 3))
{
Console.WriteLine($"{Level_Select.Default()}");
}
And this is my Level Difficulty Class.
class Level_Select
{
private int level;
public Level_Select(int level)
{
this.Level = level;
}
public int Level
{
get { return level; }
set {
if (value == 1)
{
this.level = value;
}
else if (value == 2)
{
this.level = value;
}
else if (value == 3)
{
this.level = value;
}
}
}
public static int Default()
{
int min = 000;
int max = 999;
Random num = new Random();
return num.Next(min, max);
}
public static int level1()
{
int min = 000;
int max = 99999;
Random num = new Random();
return num.Next(min, max);
}
public static int level2()
{
int min = 00000;
int max = 99999999;
Random num = new Random();
return num.Next(min, max);
}
public static int level3()
{
int min = 000000000;
long ten = 9999999999;
int max = (int)ten;
Random num = new Random();
return num.Next(min, max);
}
}

I think your problem is in your if else chain. When you put:
if (LevelSelect() == 1) // POINT A
{
Console.WriteLine($"{Level_Select.level1()}");
}
else if (LevelSelect() == 2) // POINT B
{
Console.WriteLine($"{Level_Select.level2()}");
}
At POINT A, you call LevelSelect(), which prompts for input. If this returns anything but 1, the if fails, meaning you move on to POINT B, which calls LevelSelect() again and so prompts you again, and so on, every time you call LevelSelect().
What you probably want is:
int selectedLevel = LevelSelect(); // Called only once
Level_Select level = new Level_Select(selectedLevel);
if (selectedLevel == 1)
{
Console.WriteLine($"{Level_Select.level1()}");
}
else if (selectedLevel == 2)
{
Console.WriteLine($"{Level_Select.level2()}");
}
else if (selectedLevel == 3)
{
Console.WriteLine($"{Level_Select.level3()}");
}
else // No need to retest; if it's here it's not 1, 2 or 3
{
Console.WriteLine($"{Level_Select.Default()}");
}
Though in fact, a switch is better in these cases:
int selectedLevel = LevelSelect(); // Called only once
Level_Select level = new Level_Select(selectedLevel);
switch (selectedLevel)
{
case 1:
Console.WriteLine($"{Level_Select.level1()}");
break;
case 2:
Console.WriteLine($"{Level_Select.level2()}");
break;
case 3:
Console.WriteLine($"{Level_Select.level2()}");
break;
default:
Console.WriteLine($"{Level_Select.Default()}");
break;
}

You are calling LevelSelect() on each if statement so it's normal that it will make a Console.ReadLine() each time. You should call that method only once:
var selectedLevel = LevelSelect();
var level = new Level_Select(selectedLevel);
if (selectedLevel == 1)
{
//do some stuff
Level_Select.level1();
}
else if (selectedLevel == 2)
{
// do some other stuff
Level_Select.level2();
}
And so on.

Related

How to put a variable from one function to another

I couldn't think of a good title name, so feel free to change it.
I am making a C# maths console project where the user answers addition, subtraction, multiplication, division, power and square root questions based on the difficulty they choose!
Here is my code:
using System;
using System.Collections.Generic;
namespace mathstester
{
class Program
{
public enum UserDifficulty
{
Easy,
Normal,
Hard
}
public enum MathOperation
{
Addition = 1,
Subtraction = 2,
Multiplication = 3,
Division = 4,
Power = 5,
SquareRoot = 6
}
public static (int operationMin, int operationMax) GetPossibleOperationsByDifficulty(UserDifficulty userDifficulty)
{
switch (userDifficulty)
{
case UserDifficulty.Easy:
return (1, 4);
case UserDifficulty.Normal:
return (1, 5);
case UserDifficulty.Hard:
return (3, 7);
default:
throw new Exception();
}
}
public static (string message, double correctAnswer) GetMathsEquation(MathOperation mathOperation, UserDifficulty userDifficulty)
{
int number1;
int number2;
Random randomNumber = new Random();
switch (mathOperation)
{
case MathOperation.Addition:
number1 = randomNumber.Next(1000);
number2 = randomNumber.Next(1000);
return ($"{number1} + {number2}", number1 + number2);
case MathOperation.Subtraction:
number1 = randomNumber.Next(1000);
number2 = randomNumber.Next(1000);
return ($"{number1} - {number2}", number1 - number2);
case MathOperation.Multiplication:
number1 = userDifficulty == UserDifficulty.Easy ? randomNumber.Next(13) : randomNumber.Next(1000);
number2 = userDifficulty == UserDifficulty.Easy ? randomNumber.Next(13) : randomNumber.Next(1000);
return ($"{number1} * {number2}", number1 * number2);
case MathOperation.Division:
number1 = randomNumber.Next(10000);
number2 = randomNumber.Next(1000);
return ($"{number1} / {number2}", number1 / (double)number2);
case MathOperation.Power:
number1 = randomNumber.Next(13);
number2 = randomNumber.Next(5);
return ($"{number1} ^ {number2}", Math.Pow(number1, number2));
case MathOperation.SquareRoot:
number1 = randomNumber.Next(1000);
return ($"√{number1}", Math.Sqrt(number1));
default:
throw new Exception();
}
}
public static (int operationQuestion, int operationScore) Score(MathOperation mathOperation)
{
int additionQuestion = 0;
int additionScore = 0;
int subtractionQuestion = 0;
int subtractionScore = 0;
int multiplicationQuestion = 0;
int multiplicationScore = 0;
int divisionQuestion = 0;
int divisionScore = 0;
int powerQuestion = 0;
int powerScore = 0;
int squareRootQuestion = 0;
int squareRootScore = 0;
switch (mathOperation)
{
case MathOperation.Addition:
return (additionQuestion, additionScore);
case MathOperation.Subtraction:
return (subtractionQuestion, subtractionScore);
case MathOperation.Multiplication:
return (multiplicationQuestion, multiplicationScore);
case MathOperation.Division:
return (divisionQuestion, divisionScore);
case MathOperation.Power:
return (powerQuestion, powerScore);
case MathOperation.SquareRoot:
return (squareRootQuestion, squareRootScore);
default:
throw new Exception();
}
}
public static (int, int, int) RunTest(int numberOfQuestionsLeft, UserDifficulty userDifficulty)
{
int totalScore = 0;
Random random = new Random();
var (operationMin, operationMax) = GetPossibleOperationsByDifficulty(userDifficulty);
var (operationQuestion, operationScore) = (0, 0);
while (numberOfQuestionsLeft > 0)
{
int mathRandomOperation = random.Next(operationMin, operationMax);
MathOperation mathOperation = (MathOperation)mathRandomOperation;
(operationQuestion, operationScore) = Score(mathOperation);
var (message, correctAnswer) = GetMathsEquation(mathOperation, userDifficulty);
if (mathRandomOperation == 4 || mathRandomOperation == 6)
{
Console.Write($"To the nearest integer, What is {message} =");
}
else
{
Console.Write($"What is {message} =");
}
double userAnswer = Convert.ToDouble(Console.ReadLine());
if (Math.Round(correctAnswer) == userAnswer)
{
Console.WriteLine("Well Done!");
totalScore++;
operationQuestion++;
operationScore++;
}
else
{
Console.WriteLine("Your answer is incorrect!");
operationQuestion++;
}
numberOfQuestionsLeft--;
}
return (totalScore, operationQuestion, operationScore);
}
public static void Main(string[] args)
{
Dictionary<string, UserDifficulty> dict = new Dictionary<string, UserDifficulty>();
dict.Add("E", UserDifficulty.Easy);
dict.Add("N", UserDifficulty.Normal);
dict.Add("H", UserDifficulty.Hard);
string userInputDifficulty = "";
do
{
Console.WriteLine("What difficulty level would you like to do! Please type E for Easy, N for Normal and H for hard");
userInputDifficulty = Console.ReadLine().ToUpper();
} while (userInputDifficulty != "E" && userInputDifficulty != "N" && userInputDifficulty != "H");
UserDifficulty userDifficulty = dict[userInputDifficulty];
int numberOfQuestions = 0;
do
{
Console.WriteLine("How many questions would you like to answer? Please type a number divisible by 10!");
int.TryParse(Console.ReadLine(), out numberOfQuestions);
} while (numberOfQuestions % 10 != 0);
var (totalScore, operationQuestion, operationScore) = RunTest(numberOfQuestions, userDifficulty);
Console.WriteLine($"You got a score of {totalScore} out of {numberOfQuestions}");
if(userDifficulty == UserDifficulty.Easy)
{
Console.WriteLine($"You got an addittion score of {operationScore} out of {operationQuestion}");
Console.WriteLine($"You got an addition score of {operationScore} out of {operationQuestion}");
Console.WriteLine($"You got a score of {operationScore} out of {operationQuestion}");
}
else if (userDifficulty == UserDifficulty.Normal)
{
Console.WriteLine($"You got a score of {operationScore} out of {operationQuestion}");
Console.WriteLine($"You got a score of {operationScore} out of {operationQuestion}");
Console.WriteLine($"You got a score of {operationScore} out of {operationQuestion}");
}
else if (userDifficulty == UserDifficulty.Hard)
{
Console.WriteLine($"You got a score of {operationScore} out of {operationQuestion}");
Console.WriteLine($"You got a score of {operationScore} out of {operationQuestion}");
Console.WriteLine($"You got a score of {operationScore} out of {operationQuestion}");
}
}
}
}
In my function "Score" I have quite a few variables that I want to use in my function "RunTest".
How do I move the variables without having to write them all again?
Thanks!
As noted by #devNull, Score always returns (0, 0). The function can be re-written as the following:
public static (int operationQuestion, int operationScore) Score(MathOperation mathOperation)
{
switch (mathOperation)
{
case MathOperation.Addition:
case MathOperation.Subtraction:
case MathOperation.Multiplication:
case MathOperation.Division:
case MathOperation.Power:
case MathOperation.SquareRoot:
return (0, 0);
default:
throw new Exception();
}
}
Or if you're sure that you don't need the exception handling for incompatible MathOperator:
// Note: no more parameters as well
public static (int operationQuestion, int operationScore) Score()
{
return (0, 0);
}
This will still have the same functionality in your while loop in RunTest because the variables in Score were locally defined, and are not reference values.
If you're wanting those variables to be returned as well in Score, you can extract them to their own class and return an instance of it.
For example:
public class QuestionScoreModel
{
public int AdditionQuestion {get;set;}
public int AdditionScore {get;set;}
public int SubtractionQuestion {get;set;}
public int SubtractionScore {get;set;}
public int MultiplicationQuestion {get;set;}
public int MultiplicationScore {get;set;}
public int DivisionQuestion {get;set;}
public int DivisionScore {get;set;}
public int PowerQuestion {get;set;}
public int PowerScore {get;set;}
public int SquareRootQuestion {get;set;}
public int SquareRootScore {get;set;}
}
And score can be like so:
public static QuestionScoreModel Score()
{
// Initialize it with any values required
return new QuestionScoreModel();
}
Which can be used like:
var scores = Score();
scores.AdditionQuestion++;
Which would help track what type of questions the user got right.

Program to find minimum number in string

I have a c# class like so
internal class QueuedMinimumNumberFinder : ConcurrentQueue<int>
{
private readonly string _minString;
public QueuedMinimumNumberFinder(string number, int takeOutAmount)
{
if (number.Length < takeOutAmount)
{
throw new Exception("Error *");
}
var queueIndex = 0;
var queueAmount = number.Length - takeOutAmount;
var numQueue = new ConcurrentQueue<int>(number.ToCharArray().Where(m => (int) Char.GetNumericValue(m) != 0).Select(m=>(int)Char.GetNumericValue(m)).OrderBy(m=>m));
var zeroes = number.Length - numQueue.Count;
while (queueIndex < queueAmount)
{
int next;
if (queueIndex == 0)
{
numQueue.TryDequeue(out next);
Enqueue(next);
} else
{
if (zeroes > 0)
{
Enqueue(0);
zeroes--;
} else
{
numQueue.TryDequeue(out next);
Enqueue(next);
}
}
queueIndex++;
}
var builder = new StringBuilder();
while (Count > 0)
{
int next = 0;
TryDequeue(out next);
builder.Append(next.ToString());
}
_minString = builder.ToString();
}
public override string ToString() { return _minString; }
}
The point of the program is to find the minimum possible integer that can be made by taking out any x amount of characters from a string(example 100023 is string, if you take out any 3 letters, the minimum int created would be 100). My question is, is this the correct way to do this? Is there a better data structure that can be used for this problem?
First Edit:
Here's how it looks now
internal class QueuedMinimumNumberFinder
{
private readonly string _minString;
public QueuedMinimumNumberFinder(string number, int takeOutAmount)
{
var queue = new Queue<int>();
if (number.Length < takeOutAmount)
{
throw new Exception("Error *");
}
var queueIndex = 0;
var queueAmount = number.Length - takeOutAmount;
var numQueue = new List<int>(number.Where(m=>(int)Char.GetNumericValue(m)!=0).Select(m=>(int)Char.GetNumericValue(m))).ToList();
var zeroes = number.Length - numQueue.Count;
while (queueIndex < queueAmount)
{
if (queueIndex == 0)
{
var nextMin = numQueue.Min();
numQueue.Remove(nextMin);
queue.Enqueue(nextMin);
} else
{
if (zeroes > 1)
{
queue.Enqueue(0);
zeroes--;
} else
{
var nextMin = numQueue.Min();
numQueue.Remove(nextMin);
queue.Enqueue(nextMin);
}
}
queueIndex++;
}
var builder = new StringBuilder();
while (queue.Count > 0)
{
builder.Append(queue.Dequeue().ToString());
}
_minString = builder.ToString();
}
public override string ToString() { return _minString; }
}
A pretty simple and efficient implementation can be made, once you realize that your input string digits map to the domain of only 10 possible values: '0' .. '9'.
This can be encoded as the number of occurrences of a specific digit in your input string using a simple array of 10 integers: var digit_count = new int[10];
#MasterGillBates describes this idea in his answer.
You can then regard this array as your priority queue from which you can dequeue the characters you need by iteratively removing the lowest available character (decreasing its occurrence count in the array).
The code sample below provides an example implementation for this idea.
public static class MinNumberSolver
{
public static string GetMinString(string number, int takeOutAmount)
{
// "Add" the string by simply counting digit occurrance frequency.
var digit_count = new int[10];
foreach (var c in number)
if (char.IsDigit(c))
digit_count[c - '0']++;
// Now remove them one by one in lowest to highest order.
// For the first character we skip any potential leading 0s
var selected = new char[takeOutAmount];
var start_index = 1;
selected[0] = TakeLowest(digit_count, ref start_index);
// For the rest we start in digit order at '0' first.
start_index = 0;
for (var i = 0; i < takeOutAmount - 1; i++)
selected[1 + i] = TakeLowest(digit_count, ref start_index);
// And return the result.
return new string(selected);
}
private static char TakeLowest(int[] digit_count, ref int start_index)
{
for (var i = start_index; i < digit_count.Length; i++)
{
if (digit_count[i] > 0)
{
start_index = ((--digit_count[i] > 0) ? i : i + 1);
return (char)('0' + i);
}
}
throw new InvalidDataException("Input string does not have sufficient digits");
}
}
Just keep a count of how many times each digit appears. An array of size 10 will do. Count[i] gives the count of digit i.
Then pick the smallest non-zero i first, then pick the smallest etc and form your number.
Here's my solution using LINQ:
public string MinimumNumberFinder(string number, int takeOutAmount)
{
var ordered = number.OrderBy(n => n);
var nonZero = ordered.SkipWhile(n => n == '0');
var zero = ordered.TakeWhile(n => n == '0');
var result = nonZero.Take(1)
.Concat(zero)
.Concat(nonZero.Skip(1))
.Take(number.Length - takeOutAmount);
return new string(result.ToArray());
}
You could place every integer into a list and find all possible sequences of these values. From the list of sequences, you could sort through taking only the sets which have the number of integers you want. From there, you can write a quick function which parses a sequence into an integer. Next, you could store all of your parsed sequences into an array or an other data structure and sort based on value, which will allow you to select the minimum number from the data structure. There may be simpler ways to do this, but this will definitely work and gives you options as far as how many digits you want your number to have.
If I'm understanding this correctly, why don't you just pick out your numbers starting with the smallest number greater than zero. Then pick out all zeroes, then any remaining number if all the zeroes are picked up. This is all depending on the length of your ending result
In your example you have a 6 digit number and you want to pick out 3 digits. This means you'll only have 3 digits left. If it was a 10 digit number, then you would end up with a 7 digit number, etc...
So have an algorithm that knows the length of your starting number, how many digits you plan on removing, and the length of your ending number. Then just pick out the numbers.
This is just quick and dirty code:
string startingNumber = "9999903040404"; // "100023";
int numberOfCharactersToRemove = 3;
string endingNumber = string.Empty;
int endingNumberLength = startingNumber.Length - numberOfCharactersToRemove;
while (endingNumber.Length < endingNumberLength)
{
if (string.IsNullOrEmpty(endingNumber))
{
// Find the smallest digit in the starting number
for (int i = 1; i <= 9; i++)
{
if (startingNumber.Contains(i.ToString()))
{
endingNumber += i.ToString();
startingNumber = startingNumber.Remove(startingNumber.IndexOf(i.ToString()), 1);
break;
}
}
}
else if (startingNumber.Contains("0"))
{
// Add any zeroes
endingNumber += "0";
startingNumber = startingNumber.Remove(startingNumber.IndexOf("0"), 1);
}
else
{
// Add any remaining numbers from least to greatest
for (int i = 1; i <= 9; i++)
{
if (startingNumber.Contains(i.ToString()))
{
endingNumber += i.ToString();
startingNumber = startingNumber.Remove(startingNumber.IndexOf(i.ToString()), 1);
break;
}
}
}
}
Console.WriteLine(endingNumber);
100023 starting number resulted in 100 being the end result
9999903040404 starting number resulted in 3000044499 being the end result
Here's my version to fix this problem:
DESIGN:
You can sort your list using a binary tree , there are a lot of
implementations , I picked this one
Then you can keep track of the number of the Zeros you have in your
string Finally you will end up with two lists: I named one
SortedDigitsList and the other one ZeroDigitsList
perform a switch case to determine which last 3 digits should be
returned
Here's the complete code:
class MainProgram2
{
static void Main()
{
Tree theTree = new Tree();
Console.WriteLine("Please Enter the string you want to process:");
string input = Console.ReadLine();
foreach (char c in input)
{
// Check if it's a digit or not
if (c >= '0' && c <= '9')
{
theTree.Insert((int)Char.GetNumericValue(c));
}
}
//End of for each (char c in input)
Console.WriteLine("Inorder traversal resulting Tree Sort without the zeros");
theTree.Inorder(theTree.ReturnRoot());
Console.WriteLine(" ");
//Format the output depending on how many zeros you have
Console.WriteLine("The final 3 digits are");
switch (theTree.ZeroDigitsList.Count)
{
case 0:
{
Console.WriteLine("{0}{1}{2}", theTree.SortedDigitsList[0], theTree.SortedDigitsList[1], theTree.SortedDigitsList[2]);
break;
}
case 1:
{
Console.WriteLine("{0}{1}{2}", theTree.SortedDigitsList[0], 0, theTree.SortedDigitsList[2]);
break;
}
default:
{
Console.WriteLine("{0}{1}{2}", theTree.SortedDigitsList[0], 0, 0);
break;
}
}
Console.ReadLine();
}
}//End of main()
}
class Node
{
public int item;
public Node leftChild;
public Node rightChild;
public void displayNode()
{
Console.Write("[");
Console.Write(item);
Console.Write("]");
}
}
class Tree
{
public List<int> SortedDigitsList { get; set; }
public List<int> ZeroDigitsList { get; set; }
public Node root;
public Tree()
{
root = null;
SortedDigitsList = new List<int>();
ZeroDigitsList = new List<int>();
}
public Node ReturnRoot()
{
return root;
}
public void Insert(int id)
{
Node newNode = new Node();
newNode.item = id;
if (root == null)
root = newNode;
else
{
Node current = root;
Node parent;
while (true)
{
parent = current;
if (id < current.item)
{
current = current.leftChild;
if (current == null)
{
parent.leftChild = newNode;
return;
}
}
else
{
current = current.rightChild;
if (current == null)
{
parent.rightChild = newNode;
return;
}
}
}
}
}
//public void Preorder(Node Root)
//{
// if (Root != null)
// {
// Console.Write(Root.item + " ");
// Preorder(Root.leftChild);
// Preorder(Root.rightChild);
// }
//}
public void Inorder(Node Root)
{
if (Root != null)
{
Inorder(Root.leftChild);
if (Root.item > 0)
{
SortedDigitsList.Add(Root.item);
Console.Write(Root.item + " ");
}
else
{
ZeroDigitsList.Add(Root.item);
}
Inorder(Root.rightChild);
}
}

C# BlackJack - same card dealt to player & cpu? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
i'm working on a little black jack game for no apparent reason, and I've run into an issue and i can't figure out where i'm going wrong, the only thing i can imagine is that the 'new card' method is being called twice, too quickly...
The problem is that it's giving the same card to both players :/
Here is my code
Thank you! :)
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 BlackJack_Reworked
{
public partial class BlackJack : Form
{
public BlackJack()
{
InitializeComponent();
}
class myVars
{
public static int cardsDrawn = 0;
public static int playerX = 230;
public static int playerY = 160;
public static int cpuX = 230;
public static int cpuY = 60;
public static int playerCardValue = 0;
public static int cpuCardValue = 0;
}
private PictureBox[] card = new PictureBox[100];
private void makeCard(string pickedCard, int x)
{
card[myVars.cardsDrawn] = new PictureBox();
if (x == 0)
{
card[myVars.cardsDrawn].Location = new Point(myVars.playerX, myVars.playerY);
myVars.playerX += 15;
}
if (x == 1)
{
card[myVars.cardsDrawn].Location = new Point(myVars.cpuX, myVars.cpuY);
myVars.cpuX += 15;
}
card[myVars.cardsDrawn].Image = (Image)Properties.Resources.ResourceManager.GetObject(pickedCard);
card[myVars.cardsDrawn].Size = new Size(72, 96);
card[myVars.cardsDrawn].Parent = this;
card[myVars.cardsDrawn].BringToFront();
card[myVars.cardsDrawn].Update();
myVars.cardsDrawn++;
checkScores(false);
}
private void newCard(int x)
{
Random cardPicker = new Random();
int cardChoice = cardPicker.Next(1, 13);
int houseChoice = cardPicker.Next(1, 4);
string house = null;
switch (houseChoice)
{
case 1:
house = "Hearts";
break;
case 2:
house = "Diamonds";
break;
case 3:
house = "Spades";
break;
case 4:
house = "Clubs";
break;
}
if (x == 0)
{
makeCard(house + Convert.ToString(cardChoice), 0);
myVars.playerCardValue += cardChoice;
}
if (x == 1)
{
makeCard(house + Convert.ToString(cardChoice), 1);
myVars.cpuCardValue += cardChoice;
}
}
private bool feelingLucky()
{
Random Dice = new Random();
if (myVars.cpuCardValue >= 20) { return false; }
if (myVars.cpuCardValue <= 16) { return true; }
if (myVars.cpuCardValue >= 17 && myVars.cpuCardValue <= 18) if (Dice.Next(1, 5) == 1) { return true; }
if (myVars.cpuCardValue == 19) if (Dice.Next(1, 10) == 1) { return true; }
return false;
}
private void updateHandValues()
{
lblPlayerHand.Text = "Player: " + myVars.playerCardValue.ToString();
lblCPUhand.Text = "CPU: " + myVars.cpuCardValue.ToString();
}
private void checkScores(bool stand)
{
if (stand == true)
{
if (myVars.playerCardValue <= 21 && myVars.playerCardValue > myVars.cpuCardValue)
{
MessageBox.Show("Win!");
btnNewGame.Visible = true;
}
else if (myVars.cpuCardValue <= 21 && myVars.cpuCardValue > myVars.playerCardValue)
{
btnNewGame.Visible = true;
MessageBox.Show("Lose!");
}
}
else
{
if (myVars.playerCardValue > 21)
{
MessageBox.Show("Bust!");
btnNewGame.Visible = true;
}
if (myVars.cpuCardValue > 21)
{
MessageBox.Show("Win!");
btnNewGame.Visible = true;
}
}
}
private void newGame()
{
for(int x = 0; x < myVars.cardsDrawn; x++) { card[x].Dispose(); }
myVars.cpuCardValue = 0;
myVars.playerCardValue = 0;
myVars.cpuX = 230;
myVars.playerX = 230;
btnNewGame.Visible = false;
newCard(0); newCard(1);
}
private void btnNewGame_Click(object sender, EventArgs e)
{
newGame();
}
private void btnHit_Click(object sender, EventArgs e)
{
newCard(0); newCard(1);
updateHandValues();
}
private void btnStand_Click(object sender, EventArgs e)
{
if (feelingLucky() == true) newCard(1);
else checkScores(true);
}
}
}
EDIT Here's the code to my new and working version with help from these nice guys below, just in case someone finds it useful, thanks everyone!
Here are the card picture files you'll need to add to your project's resources for this code to work.
I know my logic probably isn't great, but i feel like I've learnt from this little project, hopefully someone else might too, now, time to conjure up something new.. thanks stackoverflow.
Playing Card Pictures Download
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Text.RegularExpressions;
namespace BlackJack_Reworked
{
public partial class BlackJack : Form
{
public BlackJack()
{
InitializeComponent();
}
private PictureBox[] Card = new PictureBox[52];
static List<string> Deck = new List<string>();
class myVars
{
public static int playerX = 230;
public static int cpuX = 230;
public static int playerCardValue = 0;
public static int cpuCardValue = 0;
public static int cardsDrawn = 0;
}
private void newDeck()
{
Deck.Clear();
for (int x = 0; x < myVars.cardsDrawn; x++)
{
Card[x].Dispose();
}
for (int x = 0; x < 52; x++)
{
int cardSuite = (x / 13) + 1;
int faceValue = (x % 13) + 1;
string Suite = null;
switch (cardSuite)
{
case 1:
Suite = "Hearts";
break;
case 2:
Suite = "Diamonds";
break;
case 3:
Suite = "Spades";
break;
case 4:
Suite = "Clubs";
break;
}
Deck.Add(Suite + Convert.ToString(faceValue));
}
Extensions.Shuffle(Deck);
myVars.cardsDrawn = myVars.cpuCardValue = myVars.playerCardValue = 0;
myVars.cpuX = myVars.playerX = 230;
}
private void handCard(string recipient)
{
Random Random = new Random(); Extensions.Shuffle(Deck);
string pickedCard = Deck[Random.Next(Deck.Count)];
int cardvalue = Convert.ToInt32(Regex.Replace(pickedCard, "[^0-9]", ""));
Card[myVars.cardsDrawn] = new PictureBox();
if (recipient == "player") {
Card[myVars.cardsDrawn].Location = new Point(myVars.playerX, 160); myVars.playerX += 15;
myVars.playerCardValue += cardvalue;
}
if (recipient == "cpu") {
Card[myVars.cardsDrawn].Location = new Point(myVars.cpuX, 60); myVars.cpuX += 15;
myVars.cpuCardValue += cardvalue;
}
Card[myVars.cardsDrawn].Image = (Image)Properties.Resources.ResourceManager.GetObject(pickedCard);
Card[myVars.cardsDrawn].Size = new Size(72, 96);
Card[myVars.cardsDrawn].Parent = this;
Card[myVars.cardsDrawn].BringToFront();
Card[myVars.cardsDrawn].Update();
Deck.Remove(pickedCard); myVars.cardsDrawn++; updateHandValues();
}
private void updateHandValues()
{
lblPlayerHand.Text = "Player: " + myVars.playerCardValue.ToString();
lblCPUhand.Text = "CPU: " + myVars.cpuCardValue.ToString();
}
private void newGame()
{
lblBlackJack.Text = "♠ Blackjack ♥";
btnNewGame.Visible = false;
newDeck(); handCard("player"); handCard("cpu");
}
private void checkCards()
{
if (playerWins() == true)
{
lblBlackJack.Text = "♠ You Win! ♥";
btnNewGame.Visible = true;
}
else if (playerWins() == false)
{
lblBlackJack.Text = "♠ Dealer Wins! ♥";
btnNewGame.Visible = true;
}
}
private void tieBreak()
{
if (myVars.cpuCardValue == myVars.playerCardValue && myVars.cpuCardValue >= 17)
{
lblBlackJack.Text = "♠ Tie! ♥";
btnNewGame.Visible = true;
}
else { checkCards(); }
}
private bool? playerWins()
{
if(myVars.cpuCardValue == 21 || myVars.playerCardValue > 21) { return false; }
if(myVars.playerCardValue == 21 || myVars.cpuCardValue > 21) { return true; }
else { return null; }
}
private bool cpuShouldPlay(bool stand)
{
Random Dice = new Random();
if (stand == false)
{
if (myVars.cpuCardValue <= 15) { return true; }
if (myVars.cpuCardValue >= 20 && myVars.cpuCardValue <= 21 && myVars.cpuCardValue > myVars.playerCardValue) { return false; }
if (myVars.cpuCardValue == 19 && myVars.cpuCardValue < myVars.playerCardValue) { return true; } else { return false; }
}
else
{
if(myVars.cpuCardValue < myVars.playerCardValue)
{
return true;
}
else { return false; }
}
}
private void btnNewGame_Click(object sender, EventArgs e)
{
newGame();
}
private void btnHit_Click(object sender, EventArgs e)
{
handCard("player"); if(cpuShouldPlay(false) == true) handCard("cpu"); checkCards();
}
private void btnStand_Click(object sender, EventArgs e)
{
if (cpuShouldPlay(true) == true) handCard("cpu"); tieBreak();
}
}
public static class Extensions
{
public static void Shuffle<T>(this IList<T> list)
{
Random rng = new Random();
int n = list.Count;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}
}
If you're playing from single deck rules, you must use a 'bag' or 'no replacement' model of random value source. Initially , fill the bag with all 52 possible cards. Then each iteration, pick one card at random from what remains in the bag, removing it from the bag. When the bag is empty, refill it.
Do note that when picking a random card from a bag that has n remaining items, your random value, being the index of the item in the bag to take, must be no larger than n-1 (assuming indicies run from 0 to n-1).
However, there are models of blackjack where multiple decks are shuffled together; many casinos play like this. From Wikipedia Blackjack, rules of play at casinos:
At a casino blackjack table, the dealer faces five to seven playing positions from behind a semicircular table. Between one and eight standard 52-card decks are shuffled together.
In this above model, it is certainly possible for the same card to be dealt twice in a row; however, depending on how many decks are shuffled together, this can happen only a limited number of times.
If I understand your code correctly, you currently model a blackjack shoe that has an infinite number of decks shuffled together.
Random.Next method generates random number from current time stamp and previously generated number (known as 'seed'). As you are create new object of Random everytime, it initializes with same seed. In your case, timestamp and seed doesn't change to 'Next' method of Random.
If you use single object of Random for all your operation, seed will change for each call of 'next'.
Second: You need to keep track of which cards are already drawn, so I've create a shoe list. I will remove the cards which are already used, just like real table.
NOTE: create a new shoe, when your number of cards are let's say 20.
List<string> aShoe = new List<string>(); //shoe contains 4 to 8 decks. Depending upon blackjack version.
int numberOfDeckPerShoe = 4;
private void CreateNewDeck()
{
for(int i =0;i <numberOfDeckPerShoe;i++)
for(int j=0;j<52;j++)
{
int cardFace = (j%13)+1;
int cardSuite = (j/13) + 1;
string Suite = null;
switch (cardSuite)
{
case 1:
Suite = "Hearts";
break;
case 2:
Suite = "Diamonds";
break;
case 3:
Suite = "Spades";
break;
case 4:
Suite = "Clubs";
break;
}
aShoe.add(Suite + Convert.ToString(cardFace));
}
}
Random cardPicker = new Random(); //This is change
private void newCard(int x)
{
int cardChoice = 0;
int houseChoice = 0;
string cardDrawn = "";
int cardToDraow = cardPicker.Next(0,aShoe.length);
cardDrawn = card aShoe[cardToDraow];
card.removeAt(cardToDraow);
if (x == 0)
{
makeCard(cardDrawn, 0);
myVars.playerCardValue += cardChoice;
}
if (x == 1)
{
makeCard(cardDrawn, 1);
myVars.cpuCardValue += cardChoice;
}
}
You are declaring a new Random() within the new card method.
If the method is being called twice, and very quickly, the seed's that are automatically generated (Based on time I believe) will be so close that they will generate pretty much the same number.
The best thing to do would be to create your instance of random outside of the method, and pass the random in each time, that way you will not get the same number each call.

Postfix increment into if, c#

Code example:
using System;
public class Test {
public static void Main() {
int a = 0;
if(a++ == 0){
Console.WriteLine(a);
}
}
}
In this code the Console will write: 1. I can write this code in another way:
public static void Main() {
int a = 0;
if(a == 0){
a++;
Console.WriteLine(a);
}
}
These two examples work exactly the same (from what I know about postfix).
The problem is with this example coming from the Microsoft tutorials:
using System;
public class Document {
// Class allowing to view the document as an array of words:
public class WordCollection {
readonly Document document;
internal WordCollection (Document d){
document = d;
}
// Helper function -- search character array "text", starting
// at character "begin", for word number "wordCount". Returns
//false if there are less than wordCount words. Sets "start" and
//length to the position and length of the word within text
private bool GetWord(char[] text, int begin, int wordCount,
out int start, out int length) {
int end = text.Length;
int count = 0;
int inWord = -1;
start = length = 0;
for (int i = begin; i <= end; ++i){
bool isLetter = i < end && Char.IsLetterOrDigit(text[i]);
if (inWord >= 0) {
if (!isLetter) {
if (count++ == wordCount) {//PROBLEM IS HERE!!!!!!!!!!!!
start = inWord;
length = i - inWord;
return true;
}
inWord = -1;
}
} else {
if (isLetter) {
inWord = i;
}
}
}
return false;
}
//Indexer to get and set words of the containing document:
public string this[int index] {
get
{
int start, length;
if(GetWord(document.TextArray, 0, index, out start,
out length)) {
return new string(document.TextArray, start, length);
} else {
throw new IndexOutOfRangeException();
}
}
set {
int start, length;
if(GetWord(document.TextArray, 0, index, out start,
out length))
{
//Replace the word at start/length with
// the string "value"
if(length == value.Length){
Array.Copy(value.ToCharArray(), 0,
document.TextArray, start, length);
}
else {
char[] newText = new char[document.TextArray.Length +
value.Length - length];
Array.Copy(document.TextArray, 0, newText, 0, start);
Array.Copy(value.ToCharArray(), 0, newText, start, value.Length);
Array.Copy(document.TextArray, start + length, newText,
start + value.Length, document.TextArray.Length - start - length);
document.TextArray = newText;
}
} else {
throw new IndexOutOfRangeException();
}
}
}
public int Count {
get {
int count = 0, start = 0, length = 0;
while (GetWord(document.TextArray, start + length,
0, out start, out length)) {
++count;
}
return count;
}
}
}
// Class allowing the document to be viewed like an array
// of character
public class CharacterCollection {
readonly Document document;
internal CharacterCollection(Document d) {
document = d;
}
//Indexer to get and set character in the containing
//document
public char this[int index] {
get {
return document.TextArray[index];
}
set {
document.TextArray[index] = value;
}
}
//get the count of character in the containing document
public int Count {
get {
return document.TextArray.Length;
}
}
}
//Because the types of the fields have indexers,
//these fields appear as "indexed properties":
public WordCollection Words;
public readonly CharacterCollection Characters;
private char[] TextArray;
public Document(string initialText) {
TextArray = initialText.ToCharArray();
Words = new WordCollection(this);
Characters = new CharacterCollection(this);
}
public string Text {
get {
return new string(TextArray);
}
}
class Test {
static void Main() {
Document d = new Document(
"peter piper picked a peck of pickled peppers. How many pickled peppers did peter piper pick?"
);
//Change word "peter" to "penelope"
for(int i = 0; i < d.Words.Count; ++i){
if (d.Words[i] == "peter") {
d.Words[i] = "penelope";
}
}
for (int i = 0; i < d.Characters.Count; ++i) {
if (d.Characters[i] == 'p') {
d.Characters[i] = 'P';
}
}
Console.WriteLine(d.Text);
}
}
}
If I change the code marked above to this:
if (count == wordCount) {//PROBLEM IS HERE
start = inWord;
length = i - inWord;
count++;
return true;
}
I get an IndexOutOfRangeException, but I don't know why.
Your initial assumption is incorrect (that the two examples work exactly the same). In the following version, count is incremented regardless of whether or not it is equal to wordCount:
if (count++ == wordCount)
{
// Code omitted
}
In this version, count is ONLY incremented when it is equal to wordCount
if (count == wordCount)
{
// Other code omitted
count++;
}
EDIT
The reason this is causing you a failure is that, when you are searching for the second word (when wordCount is 1), the variable count will never equal wordCount (because it never gets incremented), and therefore the GetWord method returns false, which then triggers the else clause in your get method, which throws an IndexOutOfRangeException.
In your version of the code, count is only being incremented when count == wordCount; in the Microsoft version, it's being incremented whether the condition is met or not.
using System;
public class Test {
public static void Main() {
int a = 0;
if(a++ == 0){
Console.WriteLine(a);
}
}
}
Is not quite the same as:
public static void Main() {
int a = 0;
if(a == 0){
a++;
Console.WriteLine(a);
}
}
In the second case a++ is executed only if a == 0. In the first case a++ is executed every time we check the condition.
There is your mistake:
public static void Main() {
int a = 0;
if(a == 0){
a++;
Console.WriteLine(a);
}
}
It should be like this:
public static void Main() {
int a = 0;
if(a == 0){
a++;
Console.WriteLine(a);
}
else
a++;
}
a gets alwasy increased. This means, that in your code example count will get only increased when count == wordCount (In which case the method will return true anyway...). You basicly never increasing count.

Auto Generate alphanumeric Unique Id with C#

Total string length is 5 chars
I have a scenario, ID starts with
A0001 and ends with A9999 then
B0001 to B9999 until F0001 to f9999
after that
FA001 to FA999 then
FB001 to FB999 until ....FFFF9
Please suggest any idea on how to create this format.
public static IEnumerable<string> Numbers()
{
return Enumerable.Range(0xA0000, 0xFFFF9 - 0xA0000 + 1)
.Select(x => x.ToString("X"));
}
You could also have an id generator class:
public class IdGenerator
{
private const int Min = 0xA0000;
private const int Max = 0xFFFF9;
private int _value = Min - 1;
public string NextId()
{
if (_value < Max)
{
_value++;
}
else
{
_value = Min;
}
return _value.ToString("X");
}
}
I am a few years late. But I hope my answer will help everyone looking for a good ID Generator. None of the previous answers work as expected and do not answer this question.
My answer fits the requirements perfectly. And more!!!
Notice that setting the _fixedLength to ZERO will create dynamically sized ID's.
Setting it to anything else will create FIXED LENGTH ID's;
Notice also that calling the overload that takes a current ID will "seed" the class and consecutive calls DO NOT need to be called with another ID. Unless you had random ID's and need the next one on each.
Enjoy!
public static class IDGenerator
{
private static readonly char _minChar = 'A';
private static readonly char _maxChar = 'C';
private static readonly int _minDigit = 1;
private static readonly int _maxDigit = 5;
private static int _fixedLength = 5;//zero means variable length
private static int _currentDigit = 1;
private static string _currentBase = "A";
public static string NextID()
{
if(_currentBase[_currentBase.Length - 1] <= _maxChar)
{
if(_currentDigit <= _maxDigit)
{
var result = string.Empty;
if(_fixedLength > 0)
{
var prefixZeroCount = _fixedLength - _currentBase.Length;
if(prefixZeroCount < _currentDigit.ToString().Length)
throw new InvalidOperationException("The maximum length possible has been exeeded.");
result = result = _currentBase + _currentDigit.ToString("D" + prefixZeroCount.ToString());
}
else
{
result = _currentBase + _currentDigit.ToString();
}
_currentDigit++;
return result;
}
else
{
_currentDigit = _minDigit;
if(_currentBase[_currentBase.Length - 1] == _maxChar)
{
_currentBase = _currentBase.Remove(_currentBase.Length - 1) + _minChar;
_currentBase += _minChar.ToString();
}
else
{
var newChar = _currentBase[_currentBase.Length - 1];
newChar++;
_currentBase = _currentBase.Remove(_currentBase.Length - 1) + newChar.ToString();
}
return NextID();
}
}
else
{
_currentDigit = _minDigit;
_currentBase += _minChar.ToString();
return NextID();
}
}
public static string NextID(string currentId)
{
if(string.IsNullOrWhiteSpace(currentId))
return NextID();
var charCount = currentId.Length;
var indexFound = -1;
for(int i = 0; i < charCount; i++)
{
if(!char.IsNumber(currentId[i]))
continue;
indexFound = i;
break;
}
if(indexFound > -1)
{
_currentBase = currentId.Substring(0, indexFound);
_currentDigit = int.Parse(currentId.Substring(indexFound)) + 1;
}
return NextID();
}
}
This is a sample of the ouput using _fixedLength = 4 and _maxDigit = 5
A001
A002
A003
A004
A005
B001
B002
B003
B004
B005
C001
C002
C003
C004
C005
AA01
AA02
AA03
AA04
AA05
AB01
AB02
AB03
AB04
AB05
AC01
AC02
AC03
AC04
AC05
see this code
private void button1_Click(object sender, EventArgs e)
{
string get = label1.Text.Substring(7); //label1.text=ATHCUS-100
MessageBox.Show(get);
string ou="ATHCUS-"+(Convert.ToInt32(get)+1).ToString();
label1.Text = ou.ToString();
}
Run this query in order to get the last ID in the database
SELECT TOP 1 [ID_COLUMN] FROM [NAME_OF_TABLE] ORDER BY [ID_COLUMN] DESC
Read the result to a variable and then run the following function on the result in order to get the next ID.
public string NextID(string lastID)
{
var allLetters = new string[] {"A", "B", "C", "D", "E", "F"};
var lastLetter = lastID.Substring(0, 1);
var lastNumber = int.Parse(lastID.Substring(1));
if (Array.IndexOf(allLetters, lastLetter) < allLetters.Length - 1 &&
lastNumber == 9999)
{
//increase the letter
lastLetter = allLetters(Array.IndexOf(allLetters, lastLetter) + 1);
lastNumber = 0;
} else {
lastLetter = "!";
}
var result = lastLetter + (lastNumber + 1).ToString("0000");
//ensure we haven't exceeded the upper limit
if (result.SubString(0, 1) == "!") {
result = "Upper Bounds Exceeded!";
}
return result;
}
DISCLAIMER
This code will only generate the first set of IDs. I do not understand the process of generating the second set.
If you need to take it from the database and do this you can use something like the following.
int dbid = /* get id from db */
string id = dbid.ToString("X5");
This should give you the format you are looking for as a direct convert from the DB ID.

Categories