Vb conceptual understanding of creating objects within a class - vb.net

I was wondering if you could help me understand how to create a Card object (with a value and suit) and use 52 of those cards to make an object called deck.
I have created my card class how do I initialize every card inside the deck class? Should I do it one by one? How do I link all those cards to one deck.
Thanks

As it happen I did read your previous question earlier today.
First, create a suit enum.
Public Enum Suit As Integer
Hearts = 1
Diamonds = 2
Clovers = 3
Spades = 4
End Enum
Then create the card class. Notice that the properties are read only as a card never changes its value. (Maybe not true if you're a magician)
Public Class Card
Public Sub New(suit As Suit, value As Integer)
Me.m_suit = suit
Me.m_value = value
End Sub
Public ReadOnly Property Suit() As Suit
Get
Return Me.m_suit
End Get
End Property
Public ReadOnly Property Value() As Integer
Get
Return Me.m_value
End Get
End Property
Private m_suit As Suit
Private m_value As Integer
End Class
Finally, create the deck class and populate 52 cards.
Public Class Deck
Public Sub New()
Dim cards = New Card(52 - 1) {}
Dim num As Integer = 0
For s As Integer = 1 To 4
For v As Integer = 1 To 13
cards(num) = New Card(CType(s, Suit), v)
num += 1
Next
Next
Me.m_cards = New Collections.ObjectModel.ReadOnlyCollection(Of Card)(cards)
End Sub
Public ReadOnly Property Cards() As Collections.ObjectModel.ReadOnlyCollection(Of Card)
Get
Return Me.m_cards
End Get
End Property
Private ReadOnly m_cards As Collections.ObjectModel.ReadOnlyCollection(Of Card)
End Class

You need two Enumerations and two Classes:
Enumerations
CardFaceValue - with values ranging from Ace-10 (inclusive), Jack, Queen, King.
CardFaceType - with values Hearts, Spades, Clubs, Diamonds
Classes
Deck - Has one property to contain the collection of all cards
Cards - of Type Array of Cards, sized 52.
Card - Has two properties
CardFaceValue
CardFaceType
In the constructor of the Deck class run a loop within a loop. The outer loop will run for 4 times for each of the CardFaceType enumeration, and the inner loop will run for 13 times for cards 1-10, J, Q, K.
With these loops iterate through the enumeration values and add cards to your Deck.

This is just a quick draft of what I envision
You'll need the card class first.
Public Class Card
Private cSuit As String
Private cValue As Integer
Public Property suit() As String
Get
Return cSuit
End Get
Set(ByVal value As String)
cSuit = value
End Set
End Property
Public Property value() As Integer
Get
Return cValue
End Get
Set(ByVal value As Integer)
value = cValue
End Set
End Property
Public Sub New(ByVal TheSuit As String, ByVal TheValue As Integer)
cSuit = TheSuit
cValue = TheValue
End Sub
Then you can make a new object for each card and add it to the deck collection.
Dim Deck As New List(Of Card)
Dim Suit As String = "Spade"
Dim Value As Integer = 11
Dim AceOfSpades As New Card(Suit, Value)
Deck.Add(AceOfSpades)

Related

Adding member to list overides previous members

I need to read from an Excel file a list of dogs with their birth date, and store them in a list. The read works well, and every time I add a new dog to the list, the list count grows. So far so good.
The problem is that when I add the 2nd record, the first record is replaced by the first record content, so I have two identical records. And so on with every new record. In the end, I have many same records - all with the value of the last dog.
The dog class is:
Public Class DogClass
Public Name As String
Public Dob As Date
Public Age As Integer
Public Sex As String
Public Sub setDogName(ByVal _name As String)
Name = _name
End Sub
Public Sub setDogDOB(ByVal _dob As Date)
Dob = _dob
End Sub
Public Sub setDogAge(ByVal _age As String)
Age = _age
End Sub
Public Sub setDogSex(ByVal _sex As String)
Sex = _sex
End Sub
End Class
The class of the list is:
Public Class DogsListClass
Public dogsList As New List(Of DogClass)
Public Function DodgsCnt() As Integer
DodgsCnt = dogsList.Count()
End Function
Public Function DogExsists(_dogName As String) As Boolean
Dim res As Boolean = False
For Each item As DogClass In dogsList
If item.Name = _dogName Then
res = True
End If
Next
Return res
End Function
Public Sub AddDog(_dog As DogClass)
dogsList.Add(_dog)
End Sub
End Class
The calling:
Dim tdog As New DogClass
Dim DogsList As New DogsListClass
Do
tdog.setDogName(MyExcel.Cells(row_cnt, col_cnt).text)
tdog.setDogDOB(MyExcel.Cells(row_cnt, col_cnt + 1).value)
DogsList.AddDog(tdog)
Loop
Any idea why the records are being overridden?
DogsList variable must be declared outside the Do...Loop, otherwise you are creating a "New" DogsList at each iteration and, based on this code, you should end up having one single item in the collection, not many.
Also, declaring DogsList in the loop, prevents you from using it outside in the rest of your code.

Can't iterate through each property of a custom object

I have this class:
Public Class clsServCasam
Public ID As Long
Public CANT As Decimal
Public PRICE As Decimal
End Class
I create a variable of that type and get the object from an API result:
Dim myObj As clsServCasam()
Dim rsp As HttpWebResponse = CType(rq.GetResponse(), HttpWebResponse)
If rsp.StatusCode = HttpStatusCode.OK Then
Using sr = New StreamReader(rsp.GetResponseStream())
myObj = JsonConvert.DeserializeObject(Of clsServCasam())(sr.ReadToEnd())
End Using
Then I try to get the field names from the object:
For Each p As System.Reflection.PropertyInfo In myObj.GetType().GetProperties()
Debug.Print(p.Name, p.GetValue(myObj, Nothing))
Next
But, instead of class fields (ID, PRICE, ...) I got:
- Length
- LongLength
- Rank
Update
As Steven Doggart pointed out, the above loop won't work because it looks for properties rather than fields. So, I tried changing the loop to this:
For Each p As FieldInfo In myObj.GetType.GetFields()
Debug.Print(p.Name)
Next
But now I'm getting no results at all.
In your code, myObj is not declared as clsServCasam. Rather, it is declared as clsServCasam(), which means it's an array of clsServCasam objects. So, when you use reflection to iterate over its properties, you're getting the properties of the array rather than the actual clsServCasam type.
For instance, this would work more like you're expecting:
For Each item As clsServCasam in myObj
For Each p As PropertyInfo In item.GetType().GetProperties()
Debug.Print(p.Name, p.GetValue(item, Nothing))
Next
Next
However, I think you'll find that that still won't work because it iterates over the properties rather than the fields. In the definition of the clsServCasam class, all of the members are fields rather than properties, so the only properties that it have would be ones that are inherited from Object. You will need to either iterate over the fields using GetFields, like this:
For Each item As clsServCasam in myObj
For Each f As FieldInfo In item.GetType().GetFields()
Debug.Print(f.Name, f.GetValue(item))
Next
Next
Or you'll need to change them to properties:
Public Class clsServCasam
Public Property ID As Long
Public Property CANT As Decimal
Public Property PRICE As Decimal
End Class
Or, if you are using an older version of the VB compiler which doesn't support auto-properties:
Public Class clsServCasam
Public Property ID As Long
Get
Return _id
End Get
Set(value As Long)
_id = value
End Set
End Property
Public Property CANT As Decimal
Get
Return _cant
End Get
Set(value As Decimal)
_cant = value
End Set
End Property
Public Property PRICE As Decimal
Get
Return _price
End Get
Set(value As Decimal)
_price = value
End Set
End Property
Private _id As Long
Private _cant As Decimal
Private _price As Decimal
End Class

How to add enum to a list

I have a class named Card with a property of CardNumbers
Private _number As CardNumbers
Public Property Number() As CardNumbers
Get
Return _number
End Get
Set(ByVal value As CardNumbers)
_number = value
End Set
End Property
I have this enum of cards numbers that was used as the property of Card.
Enum CardNumbers
Ace = 1
Two = 2
Three = 3
Four = 4
Five = 5
Six = 6
Seven = 7
Eight = 8
Nine = 9
Ten = 10
Jack = 11
Queen = 12
King = 13
End Enum
Now, I have a loop to insert CardNumbers into a Dim Cards As New List(Of Card), but I do not know how to add each of the CardNumbers into the List. Been researching awhile. Can anyone help? Thanks.
UPDATE:
I have now this code to add create an instance of the class Card and then add to the list of Card called Cards:
Dim c As New Card()
For Each n As CardNumber.CardNumbers In [Enum].GetValues(GetType(CardNumber.CardNumbers))
c.Number = n
Cards.Add(c)
Next
But then, I get a NullReferenceException error.
Some classes that can be used for cards and decks.
Public Enum aRank
Two = 2
Three = 3
Four = 4
Five = 5
Six = 6
Seven = 7
Eight = 8
Nine = 9
Ten = 10
Jack = 11
Queen = 12
King = 13
Ace = 14
End Enum
Public Enum aSuit
Clubs
Diamonds
Hearts
Spades
End Enum
Class Card
Private _rank As aRank
Private _suit As aSuit
Public ReadOnly Property Rank As aRank
Get
Return Me._rank
End Get
End Property
Public ReadOnly Property Suit As aSuit
Get
Return Me._suit
End Get
End Property
Public Sub New(rank As aRank, suit As aSuit)
Me._rank = rank
Me._suit = suit
End Sub
End Class
Class DeckOfCards
Private _deck As List(Of Card)
Private Shared _prng As New Random
Public Sub New()
Me.Shuffle()
End Sub
Public Sub Shuffle()
Me._deck = New List(Of Card)
For Each r As aRank In [Enum].GetValues(GetType(aRank))
For Each s As aSuit In [Enum].GetValues(GetType(aSuit))
Me._deck.Add(New Card(r, s))
Next
Next
End Sub
Public Function GetCard() As Card
If Me.CardsRemaining > 0 Then
Dim idx As Integer = DeckOfCards._prng.Next(Me._deck.Count)
Dim rvcard As Card = Me._deck(idx)
Me._deck.RemoveAt(idx)
Return rvcard
Else
'''TODO
'code for no more cards error
Return Nothing
End If
End Function
Public ReadOnly Property CardsRemaining As Integer
Get
Return Me._deck.Count
End Get
End Property
End Class
Say you have this line:
Dim n As CardNumbers = 1
Then this will get you "Ace":
Dim s As String = [Enum].GetName(GetType(CardNumbers), n)
You can create a list of 13 cards by doing it like this:
Dim list As New List(Of Card)((From item In [Enum].GetValues(GetType(CardNumbers)) Select New Card With {.Number = CType(item, CardNumbers)}))
With that being said, you might also want to look at my answer in this SO post:
Vb conceptual understanding of creating objects within a class

VB trouble instantiating object when constructor has a structure data type

I really like the community. I am trying to teach myself vb by trying out what I have learned. I am learning how to use enum's, structures and objects so I thought I would mix them all together ti get a better understanding of whats going on. I am using a Card as an example (been practicing everything with cards)
I created an enum called Suit
Public Enum suit As Integer
Spades = 0
Diamonds =1
Clovers = 2
Hearts = 3
End Enum
Next I created structure that uses the enum data type I just created
Public structure cardValue
Public cardSuit As suit <--- enum
Public cardName As Integer
End Structure
Lastely I created a class of a card
Public Class Card
Private actualCard As cardValue
Get
Return actualCard
End Get
Set(value As cardValue)
End Set
actualCard=value
End Property
Sub New (actualCard As cardValue)
Me.actualCard = actualCard
End Sub
End Class
Now here is my problem
When I goto create a object of the class Card I am not sure how to pass the arguments into the constructor?
Dim myCard As Card = New Card ( I want Spade , and a card value of 10 )
not sure how to pass it a Value, everything I try I get errors of not valid type
I am also not sure how to make the code grey, I am very sorry about that.
With your actual constructor you could do :
Dim c As New Card(New cardValue With {.cardSuit = suit.Spades, .cardName = 10})
But the easiest way would be to change your constructor :
Public Sub New(suitValue As suit, cardValue As Integer)
ActualCard = New cardValue With {.cardSuit = SuitValue, .cardName = CardValue}
End Sub

How to accumulate the sum in VB?

Dim index As Integer
Dim choice As String
Dim total As Integer
total = 0
index = NumericUpDown1.Value
Dim arr(4) As Integer
arr(0) = 10
arr(1) = 5
arr(2) = 21
arr(3) = 33
If index > 0 Then
choice = (Combobox1.SelectedItem.ToString + " x " + NumericUpDown1.Value.ToString)
ListBox1.Items.Add(choice)
CheckedListBox1.Items.Add(choice)
total += arr(Combobox1.SelectedIndex) * index
TotalLabel.Text = total.ToString()
Else
MsgBox("error.")
End If
I can calculate the total of single choice, but fail to accumulate to sum.
What's wrong of the code?
Current Situation:
Step 1:
choose arr(0), index = 2
total = 20
Step 2:
choose arr(2), index = 1
total = 21
Correct Situation:
Step 1:
choose arr(0), index = 2
total = 20
Step 2:
choose arr(2), index = 1
total = 41
You'll need a either a global variable or a class with a public variable. You should create a Transaction class to store the data about the transaction and probably a Product class to store the data about the product. What you put in it is up to you, but I'd start out with something like this:
Public Class Transaction
Private _productsList As List(of Product)
Private _transationNumber As Integer
'...more stuff...
'you'll want to remember what products are in your "cart" for the transaction
Public Property ProductsList As List(of Product)
'your get/set accessors
End Property
Public Property TransactionNumber As Integer
'your get/set accessors
End Property
Public Property TotalTransactionCost() As Double
Get
'this will sum of the prices of all of the products you have stored in your
'list of products for this transaction
Return _productsList.Sum(product => product.Price)
End Get
End Property
Public Sub New()
'...constructor stuff
End Sub
Public Sub AddProductToTransaction(byval product)
_productsList.Add(product)
End Sub
End Class
Public Class Product
Private _price As Double
Private _productName As String
Private _UPC As String
Public Property Price() As Double
'your get/set accessors
End Property
Public Property ProductName() As String
'your get/set accessors
End Property
Public UPC As String () As String
'your get/set accessors
End Property
Public Sub New()
'constructor stuff
End Sub
End Class
These are a couple class shells to get you started. If you're serious about making a product, this is a step in the right direction. If you're going to write code, write it the right way.
If you're just looking for a quick and dirty solution, you can declare a global variable and just keep a running sum. Just don't forget to clear it out before you start a new transaction.
You'll want to do something like:
Private TransactionCost As Double in your form outside of all your methods.
Again, I would recommend the first way of going about things. You'll need at least those two classes and they'll definitely be more fleshed out for a real product.
I hope this helps and answers your question. If it does, hit me with an upvote and accept the answer. Welcome to SO.