Windows forms application random math game c# - c#

I am having problems with putting a max number of question limit I'm new to windows forms so I tried a changing the textbox of the questions number text box to int then putting a loop using (while();) but the program just freezes + how do I tell the user answer if his answer is right or wrong using (if) didn't work for me I don't know where to put it or if my way of changing the text box to int is right here is my code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication6
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
numrange.Items.Add("1,100");
numrange.Items.Add("1,500");
numrange.Items.Add("1,1000");
operation.Items.Add("+");
operation.Items.Add("-");
operation.Items.Add("*");
operation.Items.Add("/");
}
private void label1_Click(object sender, EventArgs e)
{
}
int[] Rand(int v)
{
Random r = new Random();
int a = r.Next(1,v);
int b = r.Next(1,v);
int[] N = { Math.Max(a,b) , Math.Min(a,b)};
return N;
}
void generate()
{
int range = 0;
switch (numrange.SelectedIndex)
{
case 0:
range = 100;
break;
case 1:
range = 500;
break;
case 2:
range = 1000 ;
break;
default :
MessageBox.Show("Please Insert a range!!");
break;
}
int[] Numbers = Rand(range);
int numofquest = Convert.ToInt32(maxquestion.Text);
int numofquestleft;
numofquestleft = numofquest;
while (numofquest > 0)
{
switch (operation.SelectedIndex)
{
case 0:
questionbox.Text = string.Format("{0} + {1} = ", Numbers[0], Numbers[1]);
break;
case 1:
questionbox.Text = string.Format("{0} - {1} = ", Numbers[0], Numbers[1]);
break;
case 2:
questionbox.Text = string.Format("{0} * {1} = ", Numbers[0], Numbers[1]);
break;
case 3:
questionbox.Text = string.Format("{0} / {1} = ", Numbers[0], Numbers[1]);
break;
default:
MessageBox.Show("Please insert an operation!!");
break;
}
numofquestleft--;
}
}
private void Startbutton1_Click(object sender, EventArgs e)
{
generate();
}
private void Nextbutton_Click(object sender, EventArgs e)
{
generate();
}
}
}
}
}

You did'nt change numofquest in the while loop, therefore numofquest > 0 is always true.
It should be while numofquestleft > 0. Be sure it;s numofquestleft and not numofquest
Aside from that, if you want to generate a different question each time you hit the button, consider putting the generate() with no loop inside the clickfunction, a loop will run all in one go. Something like this:
private int numofquestleft;
private int answer;
private void Start_Click(object sender, EventArgs e)
{
numofquestleft = Convert.ToInt32(maxquestion.Text);
if (numofquestleft > 0) generate();
numofquestleft--;
}
private void Nextbutton_Click(object sender, EventArgs e)
{
if (Convert.ToInt32(userinput.Text) == answer){ MessageBox.Show("Correct");}
else {MessageBox.Show("Incorrect");}
if(numofquestleft > 0) generate();
numofquestleft--;
}
To check user's answer, first calculate the result:
switch(operation.SelectedIndex)
{
case 0:
questionbox.Text = string.Format("{0} + {1} = ",Numbers[0],Numbers[1]);
answer = Numbers[0] + Numbers[1];
break;
case 1:
questionbox.Text = string.Format("{0} - {1} = ",Numbers[0],Numbers[1]);
answer = Numbers[0] - Numbers[1];
break;
case 2:
questionbox.Text = string.Format("{0} * {1} = ",Numbers[0],Numbers[1]);
answer = Numbers[0] * Numbers[1];
break;
case 3:
questionbox.Text = string.Format("{0} / {1} = ",Numbers[0],Numbers[1]);
answer = Numbers[0] / Numbers[1];
break;
}
Then compare it with user input (convert to int), assuming when you hit Next:
private void Nextbutton_Click(object sender, EventArgs e)
{
if (Convert.ToInt32(userinput.Text) == answer){ MessageBox.Show("Correct");}
else {MessageBox.Show("Incorrect");}
if(numofquestleft > 0) generate();
numofquestleft--;
}
This will check the answer of a question, then generate a new question when you click Next.

Related

Windows forms Random Timed Math quiz c#

My problem is that I want to put a max number limit where the user would put a max question of 2 like an example and my program would show random question only 2 times but it keeps generating numbers I think my problem is with changing the textbox to int and where to place it I'm new to windows forms the first button generate random questions the second button should do the same but minus a number of question every time the user clicks I tried a lot operationbox is for the user to choose his operation(+,-,*,/) and the range box is the range of the random numbers.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication7
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
rangebox1.Items.Add("[1,100]");
rangebox1.Items.Add("[1,500]");
rangebox1.Items.Add("[1,1000]");
Operationbox1.Items.Add("+");
Operationbox1.Items.Add("-");
Operationbox1.Items.Add("*");
Operationbox1.Items.Add("/");
}
int[] Rand(int v)
{
Random r = new Random();
int a = r.Next(1,v);
int b = r.Next(1,v);
int[] N = {Math.Max(a,b) , Math.Min(a,b)};
return N;
}
void generate()
{
int range = 0;
switch (rangebox1.SelectedIndex)
{
case 0:
range = 100;
break;
case 1:
range = 500;
break;
case 2:
range = 1000;
break;
default:
MessageBox.Show("Put a range !");
break;
}
int[] numbers = Rand(range);
switch (Operationbox1.SelectedIndex)
{
case 0:
questionlbl1.Text = string.Format("{0} + {1} =",numbers[0],numbers[1]);
break;
case 1:
questionlbl1.Text = string.Format("{0} - {1} =" , numbers[0], numbers[1]);
break;
case 2:
questionlbl1.Text = string.Format("{0} * {1} =" , numbers[0], numbers[1]);
break;
case 3:
questionlbl1.Text = string.Format("{0} / {1} =" , numbers[0], numbers[1]);
break;
default:
MessageBox.Show("Please insert a operation");
break;
}
}
void numberquest()
{
int numofquestionleft = Convert.ToInt32(numofquest1.Text);
int r = int.Parse(numofquest1.Text);
if (numofquestionleft > 0) generate();
numofquestionleft--;
}
private void genbutton1_Click(object sender, EventArgs e)
{
generate();
}
private void button1_Click(object sender, EventArgs e)
{
numberquest();
}
}
}
As far as I understood your question, you are facing issue with numofquestionleft variable and you want to restrict user to make max two number request. You need to modify your code. The way you are doing will not work. One solution could be,
Declare numofquestionleft as class level.
public partial class Form1 : Form
{
int numofquestionleft = 2; //here
public Form1()
{
And your numberquest() method would look like
void numberquest()
{
if (numofquestionleft > 0)
{
generate();
}
numofquestionleft--;
//You can use the textBox to communicate with user about number of turns left
//as
numofquest1.Text ="Request left " +numofquestionleft;
}
But if you still want to read max request from the textBox then the purpose of restricting users to make only two requests is lost (a user may enter some other number and you need to validate input in that case), moreover, you need to find a way to read data once.
Hope it helps. 

Converting Distance using C#

Program Problem: I am trying to convert from one type of distance to the next after the user inputs the data. The user must select from one list to convert to the other list in distance. For example, selecting inches in one list to convert to yards in another list.
My code:
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 Distance_Converter
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void ConvertButton_click(object sender, EventArgs e)
{
//int Inches = 1;
//int Feet = 12;
//int Yards = 36;
int distance_to_convert;
string lengthOption1;
string lengthOption2;
int inches_feet;
int inches_yard;
lengthOption1 = FromListBox.SelectedItem.ToString();
lengthOption2 = ToListBox.SelectedItem.ToString();
distance_to_convert = int.Parse(distancetoconvertTextBox.Text);
if ((FromListBox.SelectedIndex) != -1 && (ToListBox.SelectedIndex) != -1)
{
switch (lengthOption1)
{
case "Inches":
if (lengthOption2 == "Inches")
{
//object distancetoconvert = null;
ConvertedDistanceTextBox = distance_to_convert.ToString();
}
else if (lengthOption2 == "Feet")
{
inches_feet = distance_to_convert / 12;
ConvertedDistanceTextBox = inches_feet.ToString();
}
else if (lengthOption2 == "Yards")
{
inches_yard = distance_to_convert / 36;
ConvertedDistanceTextBox = inches_yard.ToString();
}
break;
case "Feet":
if (lengthOption2 == "Inches")
{
int feet_inches = distance_to_convert * 12;
ConvertedDistanceTextBox = feet_inches.ToString();
}
else if (lengthOption2 == "Feet")
{
ConvertedDistanceTextBox = distance_to_convert.ToString(); ;
}
else if (lengthOption2 == "Yards")
{
int feet_yard = distance_to_convert / 3;
ConvertedDistanceTextBox = feet_yard.ToString();
}
break;
case "Yards":
if (lengthOption2 == "Inches")
{
int Yards_inches = distance_to_convert * 36;
ConvertedDistanceTextBox = Yards_inches.ToString();
}
else if (lengthOption2 == "Feet")
{
int Yards_feet = distance_to_convert * 3;
ConvertedDistanceTextBox = Yards_feet.ToString();
}
else if (lengthOption2 == "Yards")
{
ConvertedDistanceTextBox = distance_to_convert.ToString(); ;
}
break;
}
}
}
private void Exitbutton_click(object sender, EventArgs e)
{
this.Close();
}
}
}
My dilemma: The code looks correct in every sense. However, when I try to convert from int to string on multiple occasions the IDE gives me a red line. The code won't compile and creates build errors. I am thinking that I will have to create a separate class to convert from int to string.
The error states: "Error CS0029 Cannot implicitly convert type 'string' to 'System.Windows.Forms.TextBox' "
It appears on line - 42, 47, 52, or any line that begins with ConvertedDistanceTextBox = .
My apologies, I am new to coding and I am trying to learn. And I am relatively new to stackoverflow.
You should set your string values to the text property of your textbox
ConvertedDistanceTextBox.Text = inches_yard.ToString();

Ensure first and last characters of text box are numbers c#

Im currently creating a windows form that must only allow a password through when it matches certain criteria. Im close to finishing however im a bit stuck with one element. "the first and last characters of the password HAVE to be numbers".
looking at my current code how would i go about this because i have ZERO idea. so baby steps and patience would be appreciated.
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;
using System.Text.RegularExpressions;
namespace password_test
{
public partial class Form1 : Form
{
bool Finished = false;
private bool TestPassword(string passwordText, int minimumLength = 5, int maximumLength = 12, int minimumNumbers = 1, int minimumLetters = 1)
{
int letters = 0;
int digits = 0;
int minLetters = 0;
if (passwordText.Length < minimumLength)
{
MessageBox.Show("You must have at least " + minimumLength + " characters in your password.");
return false;
}
if (passwordText.Length > maximumLength)
{
MessageBox.Show("You must have no more than " + maximumLength + " characters in your password.");
return false;
}
foreach (var ch in passwordText)
{
if (char.IsLetter(ch)) letters++;
if (char.IsDigit(ch)) digits++;
if (ch > 96 && ch < 123)
{
minLetters++;
}
}
if (digits < minimumNumbers)
{
MessageBox.Show("You must have at least " + minimumNumbers + " numbers in your password.");
return false;
}
if (minLetters < minimumLetters)
{
MessageBox.Show("You must have at least " + minimumLetters + " letter in your password");
return false;
}
Finished = true;
return true;
}
public Form1()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void butConfirm_Click(object sender, EventArgs e)
{
if (txtPassword.Text == txtRetypePassword.Text)
{
bool temp = TestPassword(txtPassword.Text, 10, 100, 1, 1);
if (Finished == true)
{
MessageBox.Show("Password Accepted");
Application.Exit();
//this.Hide();
//Form2 f2 = new Form2();
//f2.ShowDialog();
}
}
else
{
MessageBox.Show("Please ensure the passwords you have typed match");
return;
}
}
private void txtPassword_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsLetterOrDigit(e.KeyChar))
{
e.Handled = true;
}
else
{
return;
}
}
private void txtRetypePassword_TextChanged(object sender, EventArgs e)
{
}
}
}
Before Finished = true; you can simply do your check:
if (!char.IsDigit(passwordText[0]) || !char.IsDigit(passwordText[passwordText.Length - 1]))
{
MessageBox.Show("The first and last characters of the password have to be numbers");
return false;
}
Finished = true;
You should also enforce a minimum length in your method.
Or you can use Regex Test Pattern
// ^\d = start with digit
// \d$ end with digit
// .{3,10} including start and ending, min 5 max 12
if (!Regex.IsMatch(str, #"\d.{3,10}\d$")
{
// Invalid
}
Use \D to reverse.

Visual C# switch command using range of integers - course assignment requirement

First, my apologies if this is posted twice. I think the site may have burped.
I have an apparently impossible requirement for a clinical trials pharma application in my C# course. Please, someone tell me if I'm interpreting this part of the assignment incorrectly (copied verbatim from handout):
"MONTHS NUMBER OF TREATMENTS (use a Switch command)
1 -19 10 -30
20 - 39 31 -60
40 - 59 61 - 100
60 - 79 101 - 130
80 - 99 131 - 180
For Example:
If the randomly chosen # of months is from 20 through 39 - the number of treatments will be a random number from 31 through 60. If the # of months is 82 - the number of treatments is from 131 through 180."
The number of months the patient is available for the trial is input directly into a text box; my code supplies the random ACTUAL months the patient is participating in the clinical trial. I already know that ranges CANNOT be used in switch commands. Since this instructor also teaches Visual Basic, which apparently does support ranges in a switch command, she may have gotten the two confused (which, sadly, happens with alarming frequency). At any rate, everything I have read said this is flatly impossible with a switch case.
I have no idea how to accomplish this without an if/else tree instead of a switch. Can anyone give me any ideas? PLEASE, no regex or LINQ. We are not covering either one.
Here's all of my code. What is here works; file read/write isn't implemented yet, but I already understand that part.
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;
using System.IO;
namespace NallyKProgram3ClinicalTrials
{
public partial class NallyKClinicalTrialsForm : Form
{
public NallyKClinicalTrialsForm()
{ InitializeComponent(); }
private StreamWriter outputFile;
private StreamReader inputFile;
int numberOfMonthsInTrialRangeInteger;
int numberAssignedToPatientInteger;
int numberOfMonthsInTrialInteger;
int numberOfTreatmentPlanInteger;
int numberOfTreatmentsInteger;
// const string CASE_STRING; this attempt didn't work
Random rndNumber = new Random();
Boolean duplicateNameBoolean;
private void NallyKClinicalTrialsForm_Load(object sender, EventArgs e)
{
reportLabel.ResetText();
removePatientButton.Enabled = false;
writeFileButton.Enabled = false;
}
private void addPatientButton_Click(object sender, EventArgs e)
{
if (patientNameTextBox.Text.Trim() != string.Empty)
{
checkForDuplicateNames();
generatePatientNumber(rndNumber);
if (duplicateNameBoolean == false)
{
if (numberOfMonthsTextBox.Text.Trim() != string.Empty)
{
if (int.TryParse(numberOfMonthsTextBox.Text.Trim(), out numberOfMonthsInTrialRangeInteger))
{
if (numberOfMonthsInTrialRangeInteger < 1 || numberOfMonthsInTrialRangeInteger > 99)
{
errorProvider1.SetError(numberOfMonthsTextBox, "The number of months available for participation in this trial must not be less than 1 or greater than 99.");
numberOfMonthsTextBox.Focus();
numberOfMonthsTextBox.SelectAll();
}
else
{
generateNumberOfMonthsInTrial(rndNumber);
generateTreatmentPlan(rndNumber);
// determineCaseString(); NOPE!
// determineNumberOfTreatments(rndNumber); TO DO
addToListBox();
addToNamesListBox();
readFileButton.Enabled = false;
removePatientButton.Enabled = true;
writeFileButton.Enabled = true;
}
}
else
{
errorProvider1.SetError(numberOfMonthsTextBox, "Please enter a number.");
numberOfMonthsTextBox.Focus();
numberOfMonthsTextBox.SelectAll();
}
}
else
{
numberOfMonthsTextBox.Text = " ";
errorProvider1.SetError(numberOfMonthsTextBox, "You must enter a number of months.");
numberOfMonthsTextBox.Focus();
numberOfMonthsTextBox.SelectAll();
}
}
else
{
errorProvider1.SetError(namesListBox, patientNameTextBox.Text + " is a duplicate name. Please enter a different name.");
patientNameTextBox.Focus();
patientNameTextBox.SelectAll();
}
}
else
{
patientNameTextBox.Text = " ";
errorProvider1.SetError(patientNameTextBox, "You must enter a patient name.");
patientNameTextBox.Focus();
patientNameTextBox.SelectAll();
}
}
private void checkForDuplicateNames()
{
int indexInteger = 0;
duplicateNameBoolean = false;
while (indexInteger < namesListBox.Items.Count)
{
if (patientNameTextBox.Text.ToLower().Trim() ==
namesListBox.Items[indexInteger].ToString().ToLower())
{
duplicateNameBoolean = true;
indexInteger = namesListBox.Items.Count;
}
indexInteger++;
}
}
private Random generatePatientNumber(Random rndNumber)
{
numberAssignedToPatientInteger = rndNumber.Next(1000, 9999);
return rndNumber;
}
private Random generateNumberOfMonthsInTrial(Random rndNumber)
{
numberOfMonthsInTrialInteger = rndNumber.Next(1, numberOfMonthsInTrialRangeInteger);
return rndNumber;
}
private Random generateTreatmentPlan(Random rndNumber)
{
numberOfTreatmentPlanInteger = rndNumber.Next(1, 5);
return rndNumber;
}
//private void determineCaseString() NOPE, NOPE, NOPE
//{
// if ((numberOfTreatmentPlanInteger >= 1) && (numberOfTreatmentPlanInteger < 20)) CASE_STRING = "a"; // clever, but error!
// if ((numberOfTreatmentPlanInteger >= 20) && (numberOfTreatmentPlanInteger < 40)) CASE_STRING = "b";
// if ((numberOfTreatmentPlanInteger >= 41) && (numberOfTreatmentPlanInteger < 60)) CASE_STRING = "c";
// if ((numberOfTreatmentPlanInteger >= 60) && (numberOfTreatmentPlanInteger < 80)) CASE_STRING = "d";
// if ((numberOfTreatmentPlanInteger >= 80) && (numberOfTreatmentPlanInteger < 100)) CASE_STRING = "e";
//}
//private Random determineNumberOfTreatments(Random rndNumber)
//{
// numberOfTreatmentsInteger = rndNumber.Next(10, CASE_STRING);
//}
private void addToListBox()
{
patientInformationListBox.Items.Insert(0, numberAssignedToPatientInteger.ToString() + "," + numberOfTreatmentPlanInteger + "," + numberOfMonthsInTrialInteger + "," + Environment.NewLine); // number of treatments goes after the final comma
}
private void addToNamesListBox()
{
namesListBox.Items.Insert(0, patientNameTextBox.Text.Trim());
}
private void exitButton_Click(object sender, EventArgs e)
{
this.Close();
}
private void removePatientButton_Click(object sender, EventArgs e)
{
if (patientInformationListBox.SelectedIndex > -1)
patientInformationListBox.Items.RemoveAt(patientInformationListBox.SelectedIndex);
else MessageBox.Show("You must select an entry you wish to remove from the list.", "SELECT AN ITEM TO REMOVE", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void patientNameTextBox_TextChanged(object sender, EventArgs e)
{
errorProvider1.SetError(patientNameTextBox, "");
errorProvider1.SetError(patientInformationListBox, "");
}
private void numberOfMonthsTextBox_TextChanged(object sender, EventArgs e)
{
errorProvider1.SetError(numberOfMonthsTextBox, "");
}
}
}
You're right in that C# does not allow you to use ranges in the switch-statement. In fact, C# only allows you to write a case X: where X is a single constant literal value.
However, C# does allow you to fall through from one case to another, and thus allows you to list all the cases for which you can write one single body of code to execute.
As such, you can write the code like this:
switch (months)
{
case 1:
case 2:
case 3:
...
case 19:
treatments = r.Next(10, 31);
break;
case 20:
case 21:
case 22:
...
case 39:
treatments = r.Next(30, 61);
break;
case 40:
...
Now, is that the best you can do?
No. You can notice a pattern in the ranges here. Each range goes from X to X+19, where X is a number divisible by 20, so you can use the fact that integer division will truncate downwards:
int monthsSection = months / 20; // 0-19 --> 0, 20-39 --> 1, etc.
switch (monthsSection)
{
case 0: // 0-19
treatments = r.Next(10, 31);
break;
case 1: // 20-39
treatments = r.Next(30, 61);
break;
case 2: // 40-59
...
Yes, this will include 0 as well. If that is a problem then I would simply add a specific if-statement in front to filter it out.
If you have to use a switch, you could divide your months by 20, and then do a switch on that. Something like this:
int monthValue = numberOfTreatmentPlanInteger / 20;
switch (monthValue)
{
case 0:
// between 10 and 30 treatments
break;
case 1:
// between 31 and 60 treatments
break;
case 2:
// between 61 and 100 treatments
break;
// and so on
}

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.

Categories