Join 135,951 C# Programmers for FREE! Get instant access to thousands of C# experts, tutorials, code snippets, and more! There are 2,666 people online right now. Registration is fast and FREE... Join Now!
This is not homework, but was an assignment that was optional. I am only doing it now to see if I can.
The easy part is done. The textboxes will contain a number or letter from a deck of cards, when the user clicks the button, and it will randomize them. I still have to add the characters for the heart, spade, diamond and club. And if possible, change everything to the appropriate colors. Then I have to figure out how to keep from repeating the same card. Please don't tell me yet, if you know. I'd like to try it first.
My question is about the textboxes. Is there a way to NOT have to write out each textbox? Something like:
CODE
for (int i =1; i<=52; i++) { textbox[i].Text = GetValues(); }
...but not that because it didn't work when I tried it. (Should I use something other than a textbox for this?)
Here's what I mean....too many textboxes!
CODE
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms;
namespace DeckOfCards { public partial class Form1 : Form { public Form1() { InitializeComponent(); } Random RandomClass = new Random(); //create method to assign values to textboxes public string GetValues() {
//populate textboxes with random numbers from 1 to 13 // use "A" for 1, "J" for 11, "Q" for 12, and "K" for 13
string Num = Convert.ToString(RandomClass.Next(1,13)); if (Num == "1") { Num = "A"; } else if (Num == "11") { Num = "J"; }
else if (Num == "12") { Num = "Q"; } else if (Num == "13") { Num = "K"; } return Num;
edit-Now I have it all done except the colors and how to keep the cards from repeating. I have a feeling that is going to be the most difficult part of this.
CODE
public string GetChars() { //return either a heart, spade, diamond or club string c = Convert.ToString(RandomClass.Next(1, 5)); if (c == "1") { //make it a heart //use alt + 3 c = "♥"; //change font color to red? } else if (c == "2") { //make it a diamond //use alt + 4 c = "♦"; //change font color to red? } else if (c == "3") { //make it a spade //use alt + 6 c = "♠"; } else if (c == "4") { //make it a club //use alt + 5 c = "♣"; } return c; }
//code here
private void button1_Click(object sender, EventArgs e) { //when the user clicks the button populate textboxes with //random values equal to a deck of cards textBox1.Text = GetValues() + GetChars();
Thanks for the suggestion BeaverDono. Do you know how to do it?
This post has been edited by OliveOyl3471: 12 May, 2008 - 10:31 PM
My question is about the textboxes. Is there a way to NOT have to write out each textbox?
Good question. Since you've already created the things the easiest way would be to create an array that references all of them and use that.
csharp
// you can't initialize this here, the form needs to do it's thing private TextBox[] boxes;
public Form1() { InitializeComponent(); // now the form has all it's objects lined up, we gather them up into an array this.boxes = new TextBox[] { textBox1,textBox2,textBox3,textBox4,textBox5,textBox6, textBox7,textBox8,textBox9,textBox10,textBox11,textBox12, textBox13,textBox14,textBox15,textBox16,textBox17,textBox18, textBox19,textBox20,textBox21,textBox22,textBox23,textBox24, textBox25,textBox26,textBox27,textBox28,textBox29,textBox30,textBox31,textBox32,
private void Form1_Load(object sender, EventArgs e) { // Just a little test, to make sure we got them all int i = 1; foreach (TextBox tb in boxes) { tb.Text = (i++).ToString(); } }
I didn't do it exactly as you wrote it (using this.), because it caused errors. Here is what I have now, which will work.
As it is now, the textboxes come out the proper color, but I haven't attempted to keep the cards from repeating, yet. That is all that is left to do.
CODE
namespace DeckOfCards {
public partial class Form1 : Form { Random RandomClass = new Random();
TextBox[] boxes = null; //had to add this to get access to 'boxes' in button click event
public Form1() {
InitializeComponent(); // now the form has all it's objects lined up, we gather them up into an array //it doesn't like 'this.boxes = ...' boxes = new TextBox[]{ textBox1,textBox2,textBox3,//and the rest
//code here
public string GetChars() { //return either a heart, spade, diamond or club string c = Convert.ToString(RandomClass.Next(1, 5)); if (c == "1") { //make it a heart //use alt + 3 c = "♥"; } else if (c == "2") { //make it a diamond //use alt + 4 c = "♦"; } else if (c == "3") { //make it a spade //use alt + 6 c = "♠"; } else if (c == "4") { //make it a club //use alt + 5 c = "♣"; }
return c; }
//code here
private void button1_Click(object sender, EventArgs e) { //when the user clicks the button populate textboxes with //random values equal to a deck of cards //change font color for diamonds and hearts to red, leave spades and clubs black
foreach (TextBox tb in boxes) { tb.ForeColor = Color.Black; }
foreach (TextBox tb in boxes) { { string c = GetChars(); tb.Text = GetValues() + c; if (c == "♦" || c == "♥")
{ tb.ForeColor = Color.Red; } } }
I'll keep trying and come back and edit this with the correct code when/if I get it.
I have to go make dinner now so I can't work on this again until tonight.
edit--added this code at the bottom and now every card is the same when the user clicks the button. It is still randomized when the button is clicked again tho.
I must have something backwards.
CODE
//compare the contents of each textbox and replace any duplicates for(int i =0; i<=50; i++) { while (string.Compare(boxes[i].ToString(), boxes[i+1].ToString()) != 0) { //replace content in second textbox being compared, if a duplicate is found string c = GetChars(); boxes[i + 1].Text = GetValues() + c; boxes[i + 1].ForeColor = Color.Black; if (c == "♦" || c == "♥")
{boxes[i + 1].ForeColor = Color.Red; } } }
If I make this ==0 instead of !=0, then the cards will still have duplicates. (maybe it needs another loop somewhere?) while (string.Compare(boxes[i].ToString(), boxes[i+1].ToString()) != 0)
This post has been edited by OliveOyl3471: 13 May, 2008 - 08:06 PM
Ok...I admit defeat. I am stumped. How do you prevent duplicates in the textboxes?
As is, the program runs, but I'm not yet playing with a full deck, since there are duplicates.
The program does compare some of the textboxes and replace duplicate text, but it doesn't keep comparing each textbox to every other one and replace the text until there are no more duplicates.
Is there something like a 'do until' loop in C#?
Am I looking in the right place, or is there a logic error somewhere else? Should I do the random differently, so it doesn't create the duplicates in the first place?
This post has been edited by OliveOyl3471: 14 May, 2008 - 06:40 AM
It's simple, though probably not so if you've never seen it.
You want to create something like a CardDeck class, with all possible cards, usually 52. You then randomly pick a card from that deck, returning the chosen card and removing it from the deck. Rinse and repeat.
Without giving you the guts of it, your code might look like this
csharp
CardDeck deck = new CardDeck(); deck.Fill(); // load up all possible
for(int i=0; i<52; i++) { Card card = deck.Deal(); // this removes a card at random from the deck and returns that value if (card==null) { boxes[i].Text = "Out of Cards"; } else { boxes[i].Text = card.ToString(); } }
Now, for your code...
First, buy a method; they don't cost anything. Also, I think your loop is one shy.
I had to comment some of it out to get it to work. It still repeats. I don't know how to remove a card from the array once it's used.
This is probably not like it ought to be done.
CODE
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms;
namespace DeckOfCards3 { public partial class Form1 : Form { Random RandomClass = new Random(); TextBox[] boxes = null; CardDeck deck = new CardDeck(); CardDeck card = new CardDeck();
public class CardDeck {
public string Deal() { //create array to hold all card values string[] values = new string[] {"A♥","A♦","A♣","A♠","K♥","K♦","K♣","K♠","Q♥","Q♦","Q♣","Q♠","J♥","J♦","J♣","J♠", "10♥","10♦","10♣","10♠","9♥","9♦","9♣","9♠","8♥","8♦","8♣","8♠","7♥","7♦","7♣","7♠","6♥","6♦","6♣","6♠", "5♥","5♦","5♣","5♠","4♥","4♦","4♣","4♠","3♥","3♦","3♣","3♠","2♥","2♦","2♣","2♠"};
Random RandomClass = new Random(); int acard = RandomClass.Next(51); return values[acard]; // Remove the element at acard // values.RemoveAt(acard);//this doesn't work because it isn't arrayList
// this removes a card at random from the deck and returns that value for (int i = 0; i < 52; i++) { string card = deck.Deal(); if (card == null) { boxes[i].Text = "Out of Cards"; } else { boxes[i].Text = card.ToString(); //remove each card from array as it's added to textbox
}
//remove a card at random from the deck and returns that value
I'm afraid you're not really following the "CardDeck object as a container for cards that's depleated" idea. You called a RemoveAt method that's found in collections; let's use that:
csharp
// here, our CardDeck class is extends a string collection class, since our cards are being represented by strings. class CardDeck : List<string> { // hold the suit and value lists for easy population private static string[] cardValues = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" }; private static string[] cardSuits = { "S", "H", "C", "D" };
// we'll need a randomize, we'll create it for the object, // so we don't have to keep creating and dropping it. private Random rnd = new Random();
public CardDeck() { // fill the list, using our suit and value lists foreach (string cardSuit in cardSuits) { foreach (string cardValue in cardValues) { this.Add(cardValue + cardSuit); } } }
public string DealCard() { // if we're out of card, throw a null if (this.Count == 0) { return null; }
// get a random index, based on the number of entries we currently have int cardIndex = rnd.Next(this.Count); // save the value we picked to a variable string card = this[cardIndex]; // remove the card we picked from our list this.RemoveAt(cardIndex); // return the card return card; } }
// test code // create and instance of CardDeck // it starts out full of cards CardDeck deck = new CardDeck(); // while it has cards, print them while (deck.Count > 0) { Debug.WriteLine(deck.DealCard()); }
No idea if its still the topic, or even still relevant to topic, its 0130AM and im exhausted but anyway... Ive had to do a similar thing (shuffling and dealing a deck of cards) as part of my AI honours project and i think that the priciple can be applied here (or maybe not...) so modifying the code that i have and adding in bits and pieces from the posts above...
CODE
for (int i = 0; i < 52; i++) { int place = r.Next(1, 53)); // randomly pick a textbox from the array if (boxes[place].Text == "") boxes[place].Text = card[i].ToString(); else i--; //yes i know im cheating, if there is something already in the box, make it think <i> is 1 less so it repeats the placing of card[i] }
ok that looks nothing like my code now
btw : the object "card" is an array, obviously, of a class, and its ToString() method just produces a string representation of the card held at index i.
i sincerely hope that made sense, it should provide a way of stopping duplicates from happening. as you must assign each card at most and at least once to an empty textbox
No idea if its still the topic, or even still relevant to topic, its 0130AM and im exhausted but anyway... Ive had to do a similar thing (shuffling and dealing a deck of cards) as part of my AI honours project and i think that the priciple can be applied here (or maybe not...) so modifying the code that i have and adding in bits and pieces from the posts above...
CODE
for (int i = 0; i < 52; i++) { int place = r.Next(1, 53)); // randomly pick a textbox from the array if (boxes[place].Text == "") boxes[place].Text = card[i].ToString(); else i--; //yes i know im cheating, if there is something already in the box, make it think <i> is 1 less so it repeats the placing of card[i] }
ok that looks nothing like my code now
btw : the object "card" is an array, obviously, of a class, and its ToString() method just produces a string representation of the card held at index i.
i sincerely hope that made sense, it should provide a way of stopping duplicates from happening. as you must assign each card at most and at least once to an empty textbox
good luck
Yes it makes sense, and yes it is on topic. And, yes, I tried your suggestion and it works!
I just couldn't get it to work the way you showed me, baavgai.
I tried both of these, but could only make the second one work. 1. to select a card at random and fill the textboxes in order. and 2. to select a textbox at random and load the cards in order.
Thank you so much, both of you, for all of your help. I know it takes a lot of time to do this and I really appreciate it.
my finished program (and yours, lol):
CODE
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms;
namespace DeckOfCards3 { public partial class Form1 : Form { Random RandomClass = new Random(); TextBox[] boxes = null;
Random r = new Random(); string[] cards = new string[] {"A♥","A♦","A♣","A♠","K♥","K♦","K♣","K♠","Q♥","Q♦","Q♣","Q♠","J♥","J♦","J♣","J♠", "10♥","10♦","10♣","10♠","9♥",