How To Add User Input From Main To An Object Array In Object Class
Chapter 12 Arrays of Objects
During the next 3 capacity, we volition develop programs that work with playing cards and decks of cards. Hither is an outline of the road ahead:
- In this affiliate, we ascertain a
Carte du jour
class and write methods that piece of work with cards and arrays of cards. - In Affiliate 13.1, we define a
Deck
grade that encapsulates an array of cards, and we write methods that operate on decks. - In Affiliate 14, we introduce a way to ascertain new classes that extend existing classes. Then we use
Card
andDeck
to implement the game Crazy Eights.
There are 52 cards in a standard deck. Each menu belongs to one of four suits and one of 13 ranks. The suits are Clubs, Diamonds, Hearts, and Spades. The ranks are Ace, 2, iii, 4, 5, vi, seven, 8, 9, 10, Jack, Queen, and King.
If you are unfamiliar with traditional playing cards, now would be a skillful time to get a deck or read through https://en.wikipedia.org/wiki/Standard_52-card_deck.
12.1 Card Objects
If we want to define a course to represent a playing menu, it is pretty clear what the instance variables should exist: rank
and adapt
. Information technology is not every bit obvious what types they should be.
I possibility is a String
containing things like "Spade"
for suits and "Queen"
for ranks. A trouble with this choice is that it would not be easy to compare cards to see which had a higher rank or suit.
An alternative is to use integers to encode the ranks and suits. Past encode, we don't hateful to encrypt or interpret into a secret code. We hateful to define a mapping between a sequence of numbers and the things nosotros want to represent.
Here is a mapping for suits:
Clubs | ↦ | 0 |
Diamonds | ↦ | 1 |
Hearts | ↦ | ii |
Spades | ↦ | 3 |
We utilize the mathematical symbol ↦ to make it articulate that these mappings are not part of the program. They are part of the program design, just they never appear explicitly in the code.
Each of the numerical ranks (2 through 10) maps to the corresponding integer. For the face cards, we tin can use the post-obit:
Ace | ↦ | 1 |
Jack | ↦ | 11 |
Queen | ↦ | 12 |
King | ↦ | 13 |
With this encoding, the form definition for the Card
type looks like this:
public class Carte { private int rank; private int suit; public Card(int rank, int suit) { this.rank = rank; this.suit = suit; } }
The instance variables are individual
: we can admission them from inside this class, merely not from other classes.
The constructor takes a parameter for each example variable. To create a Menu
object, we use the new
operator:
Card threeOfClubs = new Carte du jour(three, 0);
The result is a reference to a Menu
that represents the 3 of Clubs.
12.2 Card toString
When you create a new course, the offset footstep is to declare the example variables and write constructors. A skillful next step is to write toString
, which is useful for debugging and incremental development.
To display Menu
objects in a way that humans can read easily, we need to "decode" the integer values as words. A natural way to practice that is with an assortment of String
s. For example, we tin create the array like this:
String[] suits = new String[four];
And so assign values to the elements:
suits[0] = "Clubs"; suits[1] = "Diamonds"; suits[two] = "Hearts"; suits[3] = "Spades";
Or we can create the array and initialize the elements at the aforementioned time, as you saw in Section 7.3:
Cord[] suits = {"Clubs", "Diamonds", "Hearts", "Spades"};
The memory diagram in Figure 12.one shows the effect. Each element of the assortment is a reference to a String
.
Nosotros likewise need an array to decode the ranks:
String[] ranks = {nada, "Ace", "ii", "3", "iv", "5", "6", "7", "8", "ix", "ten", "Jack", "Queen", "Male monarch"};
The zeroth chemical element should never be used, because the just valid ranks are 1–xiii. We fix it to null
to indicate an unused element.
Using these arrays, we can create a meaningful String
past using suit
and rank
equally indexes.
String s = ranks[this.rank] + " of " + suits[this.accommodate];
The expression ranks[this.rank]
means "use the instance variable rank
from this
object every bit an index into the array ranks
." Nosotros select the cord for this.accommodate
in a similar mode.
Now we can wrap all the previous code in a toString
method:
public String toString() { Cord[] ranks = {goose egg, "Ace", "2", "3", "4", "v", "6", "seven", "8", "9", "10", "Jack", "Queen", "King"}; String[] suits = {"Clubs", "Diamonds", "Hearts", "Spades"}; Cord s = ranks[this.rank] + " of " + suits[this.adjust]; return due south; }
When we display a carte du jour, println
automatically calls toString
. The output of the post-obit code is Jack of Diamonds:
Card card = new Card(11, 1); System.out.println(card);
12.3 Class Variables
So far you have seen local variables, which are declared inside a method, and example variables, which are declared in a class definition, usually before the method definitions. Now it's time to larn virtually class variables. They are shared across all instances of the course.
Like instance variables, class variables are defined in a course definition, earlier the method definitions. Simply they are identified by the keyword static
. Here is a version of Card
in which RANKS
and SUITS
are divers as form variables:
public class Card { public static final String[] RANKS = { null, "Ace", "ii", "3", "4", "v", "6", "7", "eight", "ix", "10", "Jack", "Queen", "Rex"}; public static concluding String[] SUITS = { "Clubs", "Diamonds", "Hearts", "Spades"}; // instance variables and constructors go here public Cord toString() { return RANKS[this.rank] + " of " + SUITS[this.suit]; } }
Class variables are allocated when the programme begins and persist until the plan ends. In dissimilarity, example variables like rank
and suit
are allocated when the program creates new
objects, and they are deleted when the object is garbage-collected (run across Section ten.ix).
Class variables are ofttimes used to store constant values that are needed in several places. In that case, they should also be declared as terminal
. Note that whether a variable is static
or terminal
involves 2 separate considerations: static
means the variable is shared, and final
ways the variable (or in this case, the reference) is constant.
Naming staticfinal
variables with capital letter letters is a common convention that makes it easier to recognize their role in the class. In the toString
method, we refer to SUITS
and RANKS
as if they were local variables, but we tin tell that they are class variables.
1 advantage of defining SUITS
and RANKS
as class variables is that they don't need to be created (and garbage-collected) every time toString
is called. They may too be needed in other methods and classes, then it'south helpful to brand them available everywhere.
12.4 The compareTo Method
Equally you saw in Department 11.vii, information technology'southward helpful to create an equals
method to examination whether two objects are equivalent:
public boolean equals(Card that) { return this.rank == that.rank && this.accommodate == that.suit; }
It would as well be nice to have a method for comparing cards, and then we tin can tell if i is higher or lower than another. For primitive types, we can use comparison operators similar <
and >
to compare values. But these operators don't work for object types.
For strings, Java provides a compareTo
method, every bit y'all saw in Section 6.10. We can write our own version of compareTo
for the classes that we define, as we did for the equals
method.
Some types are "totally ordered", which means that y'all tin can compare whatsoever two values and tell which is bigger. Integers and strings are totally ordered. Other types are "unordered", which means that there is no meaningful way to say that one element is bigger than another. In Java, the boolean
type is unordered; if you try to compare true <false
, you get a compiler error.
The set of playing cards is "partially ordered", which means that sometimes nosotros can compare cards and sometimes not. For example, we know that the 3 of Clubs is college than the two of Clubs, and the 3 of Diamonds is higher than the 3 of Clubs. But which is better, the 3 of Clubs or the 2 of Diamonds? One has a higher rank, simply the other has a college conform.
To make cards comparable, we accept to decide which is more important: rank or accommodate. The choice is capricious, and it might be different for dissimilar games. But when y'all buy a new deck of cards, it comes sorted with all the Clubs together, followed by all the Diamonds, then on. And so for now, let'south say that adjust is more important. With that decided, we can write compareTo
as follows:
public int compareTo(Card that) { if (this.accommodate < that.suit) { render -one; } if (this.suit > that.suit) { render 1; } if (this.rank < that.rank) { return -1; } if (this.rank > that.rank) { return 1; } return 0; }
compareTo
returns -i
if this
is a lower card, +1
if this
is a college bill of fare, and 0
if this
and that
are equivalent. It compares suits first. If the suits are the aforementioned, information technology compares ranks. If the ranks are besides the same, it returns 0
.
12.5 Cards Are Immutable
The instance variables of Card
are private
, so they can't be accessed from other classes. Nosotros can provide getters to allow other classes to read the rank
and suit
values:
public int getRank() { return this.rank; } public int getSuit() { return this.suit; }
Whether or non to provide setters is a design decision. If we did, cards would be mutable, so you could transform 1 card into another. That is probably not a feature we want, and in general, mutable objects are more error-prone. So it might be better to make cards immutable. To practice that, all we have to practise is not provide whatsoever modifier methods (including setters).
That'south easy enough, but it is non foolproof, because a fool might come forth later and add a modifier. We tin can prevent that possibility by declaring the case variables final
:
public class Card { private last int rank; private final int suit; ... }
You can initialize these variables inside a constructor, but if someone writes a method that tries to modify them, they'll become a compiler error. This kind of safeguard helps forbid future mistakes and hours of debugging.
12.6 Arrays of Cards
Just as you tin create an assortment of String
objects, you tin can create an assortment of Card
objects. The post-obit argument creates an array of 52 cards. Effigy 12.2 shows the retentivity diagram for this array.
Card[] cards = new Card[52];
Although nosotros call information technology an "array of cards", the array contains references to cards; it does not comprise the Card
objects themselves. Initially the references are all null
.
Even so, you lot can admission the elements of the array in the usual manner:
if (cards[0] == cypher) { System.out.println("No card withal!"); }
But if you try to access the instance variables of non-existent Card
objects, you will go a NullPointerException
:
System.out.println(cards[0].rank); // NullPointerException
That lawmaking won't work until we put cards in the array. One way to populate the array is to write nested for
loops:
int index = 0; for (int conform = 0; arrange <= 3; accommodate++) { for (int rank = 1; rank <= xiii; rank++) { cards[index] = new Card(rank, suit); index++; } }
The outer loop iterates suits from 0 to 3. For each adjust, the inner loop iterates ranks from one to thirteen. Since the outer loop runs 4 times, and the inner loop runs 13 times for each adapt, the torso is executed 52 times.
We use a separate variable alphabetize
to proceed rail of where in the array the adjacent carte should go. Figure 12.3 shows what the array looks like after the first two cards have been created.
When you piece of work with arrays, it is user-friendly to have a method that displays the contents. You lot accept seen the pattern for traversing an array several times, then the following method should be familiar:
public static void printDeck(Carte du jour[] cards) { for (Card bill of fare : cards) { System.out.println(bill of fare); } }
Since cards
has type Card[]
, pronounced "bill of fare array", an element of cards
has type Card
. So println
invokes the toString
method in the Card
class.
Then again, we don't accept to write our own printDeck
method. The Arrays
grade provides a toString
method that invokes toString
on the elements of an array and concatenates the results:
System.out.println(Arrays.toString(cards))
12.7 Sequential Search
The next method nosotros'll write is search
, which takes an array of cards and a Card
object as parameters. It returns the index where the Card
appears in the array, or -1
if information technology doesn't. This version of search
uses the algorithm in Section 7.five, which is called sequential search:
public static int search(Card[] cards, Bill of fare target) { for (int i = 0; i < cards.length; i++) { if (cards[i].equals(target)) { return i; } } render -1; }
The method returns equally soon equally it discovers the card, which ways we don't accept to traverse the unabridged array if we discover the target. If we get to the end of the loop, we know the card is not in the array.
If the cards in the array are not in club, there is no mode to search faster than sequential search. Nosotros have to expect at every card, because otherwise we tin can't be certain the carte du jour we want is not there. But if the cards are in club, we can use better algorithms.
Sequential search is relatively inefficient, especially for big arrays. If you pay the cost to keep the array sorted, finding elements becomes much easier.
12.8 Binary Search
When you await for a word in a dictionary, you don't search page past page from forepart to dorsum. Since the words are in alphabetical guild, you probably employ a binary search algorithm:
- Kickoff on a folio nearly the middle of the lexicon.
- Compare a word on the page to the word you are looking for. If you notice it, stop.
- If the word on the page comes before the give-and-take you lot are looking for, flip to somewhere after in the dictionary and go to pace 2.
- If the word on the page comes after the word you are looking for, flip to somewhere earlier in the lexicon and get to step 2.
This algorithm is much faster than sequential search, because it rules out half of the remaining words each fourth dimension you make a comparing. If at whatsoever indicate you discover 2 adjacent words on the page, and your discussion comes between them, yous can conclude that your discussion is not in the dictionary.
Getting back to the array of cards, we can write a faster version of search
if nosotros know the cards are in order:
public static int binarySearch(Card[] cards, Card target) { int depression = 0; int loftier = cards.length - one; while (low <= loftier) { int mid = (depression + high) / 2; // step 1 int comp = cards[mid].compareTo(target); if (comp == 0) { // step 2 render mid; } else if (comp < 0) { // step 3 low = mid + 1; } else { // pace iv high = mid - 1; } } render -ane; }
First, we declare low
and high
variables to represent the range we are searching. Initially, we search the unabridged array, from 0
to cards.length - 1
.
Inside the while
loop, nosotros repeat the four steps of binary search:
- Cull an alphabetize between
depression
andhigh
—call itmid
—and compare the card atmid
to the target. - If you constitute the target, render its index (which is
mid
). - If the card at
mid
is lower than the target, search the range frommid + 1
toloftier
. - If the card at
mid
is college than the target, search the range fromlow
tomid - 1
.
If low
exceeds high
, there are no cards in the range, so we stop the loop and render -1
.
This algorithm depends on just the compareTo
method of the object, so we can use this code with whatsoever object type that provides compareTo
.
12.9 Tracing the Code
To come across how binary search works, information technology's helpful to add together the post-obit print argument at the beginning of the loop:
Arrangement.out.println(low + ", " + high);
Using a sorted deck of cards, we can search for the Jack of Clubs similar this:
Menu card = new Card(xi, 0); System.out.println(binarySearch(cards, card));
We look to discover this card at position 10 (since the Ace of Clubs is at position 0). Here is the output of binarySearch
:
0, 51 0, 24 0, eleven vi, eleven 9, eleven x
You can see the range of cards shrinking as the while
loop runs, until eventually index 10 is establish. If we search for a card that's not in the array—similar new Card(15, one)
, or the 15 of Diamonds—we get the following:
0, 51 26, 51 26, 37 26, 30 26, 27 -ane
Each time through the loop, we cutting the distance between low
and loftier
in one-half. After k iterations, the number of remaining cards is 52 / ii k . To detect the number of iterations it takes to complete, we set 52 / 2 yard = 1 and solve for yard. The result is log2 52, which is about 5.vii. So nosotros might have to look at 5 or six cards, as opposed to all 52 if we did a sequential search.
More more often than not, if the array contains northward elements, binary search requires logii north comparisons, and sequential search requires north. For large values of northward, binary search is essentially faster.
12.10 Vocabulary
- encode:
- To correspond one fix of values using another fix of values by constructing a mapping betwixt them.
- course variable:
- A variable declared within a class equally
static
. There is simply i re-create of a class variable, no matter how many objects in that location are. - sequential search:
- An algorithm that searches array elements, i by i, until a target value is found.
- binary search:
- An algorithm that searches a sorted array by starting in the middle, comparison an element to the target, and eliminating half of the remaining elements.
12.eleven Exercises
The code for this chapter is in the ch12 directory of ThinkJavaCode2. Meet page ?? for instructions on how to download the repository. Before you start the exercises, we recommend that you compile and run the examples.
Do 1
Encapsulate the deck-building code from Section 12.half-dozen in a method called makeDeck
that takes no parameters and returns a fully populated array of Card
south.
Exercise 2
In some card games, Aces are ranked higher than Kings. Modify the compareTo
method to implement this ordering.
Exercise three
In Poker a "flush" is a hand that contains five or more cards of the aforementioned adjust. A paw can comprise any number of cards.
- Write a method called
suitHist
that takes an array of cards as a parameter and returns a histogram of the suits in the hand. Your solution should traverse the assortment only once, every bit in Department 7.vii . - Write a method called
hasFlush
that takes an array of cards as a parameter and returnstrue
if the mitt contains a affluent (andimitation
otherwise). - A "royal flush" includes the Ace, Male monarch, Queen, Jack, and ten (all in the same suit). Write a method called
hasRoyal
that determines whether an array of cards contains a majestic flush.
Exercise four
Working with cards is more fun if you tin can display them on the screen. If you accept not already read Appendix C about 2D graphics, you should read it before working on this exercise. In the lawmaking directory for this affiliate, ch12, you will find the post-obit:
- cardset-oxymoron
A directory containing images of playing cards. - CardTable.java
A sample program that demonstrates how to read and display images.
CardTable.java demonstrates the use of a 2D assortment; specifically, an array of card images. The declaration looks like this:
private Image[][] images;
The variable images
refers to a 2D array of Image
objects, which are divers in the java.awt
packet. Here'south the code that creates the assortment itself:
images = new Image[xiv][iv];
The array has 14 rows (one for each rank, plus an unused row for rank 0) and 4 columns (one for each suit). Here'south the loop that populates the array:
String cardset = "cardset-oxymoron"; Cord suits = "cdhs"; for (int suit = 0; accommodate <= 3; arrange++) { char c = suits.charAt(conform); for (int rank = i; rank <= 13; rank++) { String s = String.format("%south/%02d%c.gif", cardset, rank, c); images[rank][suit] = new ImageIcon(south).getImage(); } }
The variable cardset
is the proper noun of the directory that contains the image files. suits
is a cord that contains the single-letter abbreviations for the suits. These strings are used to assemble s
, which contains the filename for each image. For example, when rank=1
and suit=2
, the value of south
is "cardset-oxymoron/01h.gif"
, which is an epitome of the Ace of Hearts.
The last line of the loop reads the image file, extracts an Image
object, and assigns it to a location in the array, equally specified by the indexes rank
and suit
. For example, the image of the Ace of Hearts is stored in row 1, cavalcade 2.
If you compile and run CardTable.coffee, you lot should run across images of a deck of cards laid out on a green table. You can utilize this form as a starting place to implement your own bill of fare games.
As a starting place, effort placing cards on the table in the starting configuration for the solitaire game Klondike ( https://en.wikipedia.org/wiki/Klondike_(solitaire) ).
Yous tin get the paradigm for the back of the card by reading the file back192.gif.
How To Add User Input From Main To An Object Array In Object Class,
Source: https://books.trinket.io/thinkjava2/chapter12.html
Posted by: minertherry.blogspot.com
0 Response to "How To Add User Input From Main To An Object Array In Object Class"
Post a Comment