Sunday, July 28, 2013

Saturday, July 27, 2013

Last Program -- The Menagerie

This program is MUCH easier than many of the programs of the summer.  There will be a lot of classes involved (and one interface), but each of them is simple as pie.  Here is my best attempt at a UML diagram of all but the driver class:

The methods called roam, eat, vocalize, and play simply print to the output with System.out.println.

My Menagerie class didn't contain anything but a main.  It created an ArrayList (although an array would work fine) and then created a Dog, a Cat, a Wolf, and a Tiger.  It added each of those to the ArrayList.  Then it traversed the list and, for each animal, it printed the animal's name and age using the toString, then called roam, eat, vocalize, and play (calling play only if the animal was a pet).

That's it!  Write if you have questions.

Wednesday, July 17, 2013

Finished

I would suggest that you read my Yahtzee postings in reverse order.

I finished writing the Yahtzee program.  I ended up with these classes:  Die, DiceTray, Scorer, Player, Game, and Yahtzee.  Here is a link to a UML diagram that summarizes the structure of my code:
http://www.cs.appstate.edu/~dap/classes/1440/yahtzee.jpg

The takeTurn method in the Player class does the following:

  • Say whose turn it is.
  • Print the Scorer object.
  • Roll the dice.
  • Print the DiceTray object.
  • Ask the user which dice to reroll.
  • for two more times:
    • Read the user's answer to the reroll question.
    • Make the boolean array to pass to the roll method.
    • Pass the array to the roll method.
    • Print the Scorer object.
    • Print the DiceTray object.
    • If it's the first of two rerolls, ask the user again which ones to reroll.
  • Ask the user how to score the roll.
  • Get the answer.
  • Call the tally method.

My Yahtzee class is very simple:

import java.util.Scanner;

public class Yahtzee
{
    public static void main(String[] args)
    {
        Scanner keyboard = new Scanner(System.in);
        System.out.print("How many players? ");
        int numPlayers = keyboard.nextInt();
        Game g = new Game(numPlayers);
        g.play();
    }
}

The constructor of the Game class gets passed the number of players.  It makes an array of Player objects of that size and then runs a loop that same number of times.  Each time through the loop it asks for a player's name, allocates a new Player object, sets its name, and adds it to the array of Players.

The play method in the Game class does the following:

  • Run a loop 13 times.  Each time through that loop, run another loop that goes through the array of players calling the takeTurn method on each one.
  • Find the largest score by going through the array of players and calling the getScore method on each one.
  • Declare the winner.



More about Scorer

The first thing I did in my Scorer class was create an enumerated data type for all the categories of scoring.  I made it public, but I'm thinking that it could be private.  I'll hold off on changing it.  Here it is:

public enum Category { ONES, TWOS, THREES, FOURS, FIVES, SIXES,
TKIND, FKIND, HOUSE, LOW, HIGH, YAHTZEE, CHANCE }

This came in very handy in several ways.  In my tally method, which is where all the mess of tallying up a score was done, I had a big switch statement.  I passed a DiceTray and a Category to the tally method and I switched on the Category.  Inside the switch my cases were things like:

switch (cat)
{
    case ONES:
        ...
    case TWOS:
        ...

etc.

Another way that the enumerated type came in handy is that the ordinal values of the various categories could be used as indexes into arrays.  I had a boolean array that I called taken where I kept track of whether or not a given category had been used yet.  I could say something like this:

case TKIND:
    if (!taken[Category.TKIND.ordinal()])
    {
       ...

Now let's talk about how the scoring was done.  First let's talk about scoring the ones through sixes, all of which require the same algorithm.  I made a helper (private) method called scoreUpper to avoid having a lot of duplication in the first six cases.  I called this method from the tally method like this, where t was the DiceTray that got passed to tally:
switch(cat)
{
    case ONES:
        scoreUpper(t, Category.ONES);
        break;
    case TWOS:
        scoreUpper(t, Category.TWOS);
        break;
    case THREES:
        scoreUpper(t, Category.THREES);
        break;
    case FOURS:
        scoreUpper(t, Category.FOURS);
        break;
    case FIVES:
        scoreUpper(t, Category.FIVES);
        break;
    case SIXES:
        scoreUpper(t, Category.SIXES);
        break;

If a player chooses to score a DiceTray as one of these upper values, you have to add up the occurrences of that value in the tray.  For example, if your dice values are 3, 4, 5, 3, 3 and the player says to score it as Threes, then the value of that round will be the sum of three 3's or 9. Here is how the algorithm for scoreUpper works:

  • Set a local variable, value, to 0.
  • If the category has not been taken already,
    • walk through the dice tray (t) and if the value of a die is of the category being used (cat), then add it to value. Here is how I did that.  Keep in mind that the ordinal value of ONES is zero, but when I'm counting ones I want to add up 1's.  The ordinal value of the first six categories is one less than the face value of that category.  So I have to add 1 to the ordinal value.

      for (int i = 0; i < 5; i++)
          if (t.getValue(i) == cat.ordinal()+1)
              value += cat.ordinal()+1;
      
      
    • Put that value into the scores array at the location of the category being used. (scores[cat.ordinal()] = value)
    • Set the location in the taken array (the one that corresponds to the category) to true.
    • Add the value onto the subtotal field.
    • If the subtotal is 63 or more and the bonus has not yet been taken, then set the bonus to  35.
    • Add value and bonus to total.
I didn't make any other helper methods.  I just handled the other cases right in the tally method.

I found it useful to have a local integer array in the tally method that I called count.  I made it be of size 7 but I never used the 0 cell.  I used cells 1 through 6 to correspond to the values of dice.  I started all the cells of count at 0.  I used this count array in almost every case.  The first thing I did in almost every one of my cases was to go through the dice tray and add 1 to the count of each possible dice value.  If the dice in the tray were 3, 4, 1, 4, 5, then after I looked through the tray my count array would have the values in the table below (the top row shows the indexes of the cells of the array and the bottom row shows the values in the array).  There is 1 one, no twos, 1 three, 2 fours, 1 five, and no sixes.  I don't use the 0 cell.
0123456
0101210

Doing that count is easy:

for (int i = 0; i < 5; ++i)
    count[t.getValue(i)]++;

One you have the counts of the various dice, you can check to see if one of the counts is 3 (good for three of a kind) or 4 (good for four of a kind) or 5 (yahtzee!)  For a full house you can check to see if one count is 2 and another is 3.

So my Scorer class is finished now.  I am going to work on Player and then put it all together somehow.  I expect I'm going to have a Yahtzee class that will contain the main.  I'll write more when I get finished.

Player and Scorer

So the next thing I'm going to do is create a Player class.  A player needs a name, a DiceTray, and a Scorer. I'm thinking of a Scorer as some sort of automated scoring gizmo.  Maybe I'd better deal with the Scorer class before the Player class.

The Scorer is going to have to keep a total, a subtotal of the upper categories (the ones through the sixes),  and a bonus.  Those will all be ints.  It's also going to have to keep track of which of the categories have been used and which have not been used.  I'll use an array of booleans for that.

Here is a screen shot of my C++ version while it's running:

I like having those values by each of the categories so you can see how many points you got for something.  So my Scorer is also going to have to keep an array of individual values.  I'll keep them in the order they're listed in that screen shot.  Both the boolean array that's keeping track of which categories have been used and the points array will be in that order.

My Scorer class constructor is going to create the two arrays (of size 13) set all the values to 0's, including the ints where I'm keeping tracks of totals.  I know Java sets things to 0 by default but it's better to make it explicit.  I might need a reset method that will set everything back to 0, so I'll make that.  I'll probably need getters for my int fields.  I'll definitely need a toString method that will print out a score sheet that looks like the above.  And I think it makes sense to have a tally method to which you pass a DiceTray and a category. The tally method will examine the DiceTray to see how many points can be awarded for that category, given the current values of the dice in the tray, and will update the fields accordingly.

I'll implement the Scorer and then make another posting.

Starting Yahtzee

Thinking about each of you and how you should approach this project, first you really have to understand how to play the game of Yahtzee.  I would suggest that you play the game online if you don't understand how it works.  There is a version here:  http://www.yahtzeeonline.org/  Click Roll each time you want to roll -- you get up to three rolls per round.  Once you are out of rolls or have a combination that you can use, click on one of the boxes at the top that represent the scoring categories and hit Enter.  To keep a die at its current value so that rerolling doesn't change it, click Hold by that die.

We won't be implementing a pretty GUI (graphical user interface) for the game, but anybody who knows how to do that can go right on and do it.  If you watch this week's webinar you can see how a version I wrote in C++ a few years back runs in a console window.  In C++ I could clear the screen before I printed the "board" so it appears that the stuff on screen isn't scrolling.  We can't do that in Java so you can just let your output scroll.

I'm going to begin with the tray of dice.  First I'll make a class called Die that represents just one die.  I'm going to make a constructor for a Die that sets it to a random value between 1 and 6, a roll method that does the same thing, and a getValue method that returns the value of the die.  Once I have this Die class, I'll make the DiceTray class.  The field in that class will be an array of five Die.  In the constructor of the DiceTray class, I'll create the array and then I'll walk through the array and create the Die objects.  Like this:

public DiceTray()
{
tray = new Die[5];
for (int i = 0; i < 5; i++)
{
tray[i] = new Die();
}
}

So now I have a tray of dice.  I need to be able to tell the tray that I want to roll only certain dice in the tray. I could make a roll method to which I would pass the index of the die to be rolled and that would work fine. But I think I'm going to handle this differently. I think I'm going to pass an array of five boolean values to the roll method so it can walk through the boolean array and use the values in that array to decide whether or not to roll the corresponding Die. This choice might make it a little harder to write the code that deals with playing the game because when the user says which dice need to be re-rolled, the code will have to create the array of booleans. But I'll worry about that later.  For right now, here is my roll method in the DiceTray class:

public void roll(boolean[] rollMe)
{
    for (int i = 0; i < 5; i++)
    {
        if (rollMe[i])
        {
            tray[i].roll();
        }
    }
}

I need to be able to get the values of the individual dice, so I'm going to pass an index to a getValue method and have that method call the getValue method in the Die class (on the die that corresponds to that index of the tray) and return the value of that die.

Finally, I need the DiceTray to be able to print itself so I need a toString method.  I'm going to do what I did in my C++ program and not try to print the dots on the dice.  Instead I'm going to print a number surrounded by lines.  Like this:
_____    _____    _____    _____    _____
| 3 |    | 1 |    | 3 |    | 4 |    | 2 |
-----    -----    -----    -----    -----

Finally I'll make a main in the DiceTray class that I'll use to test things with.  Here is my idea for a main:

public static void main(String[] args)
{
    DiceTray t = new DiceTray();
    System.out.println(t);
    boolean[] rollers = {true, true, false, false, true};
    t.roll(rollers);
    System.out.println(t);

}


That's the plan for right now.  I'll do that and then come back to the blog.

Thursday, July 4, 2013

Finished the program

This is a time-consuming program to write. Those are the fun ones, though, because they make you feel good when they work.

I ended up adding some methods to my Ticket class so that I could get some of the information off a ticket when I was producing the report.  I ended up with the two constructors, getClient, getAgent, getProblem, getTicketID, toString, and equals as methods in the Ticket class.

In the TechSupportSystem class I ended up with the following:

  • the constructor
  • getDate
  • getFileNames
  • readTickets
  • readOneTicket
  • readAgents
  • readOneAgent
  • main


The time stuff is a little confusing.  Here is an example.

Say that the client is a Basic level client and his request came in 50 minutes ago.  We have promised to fix problems for Basic clients in 60 minutes so we only have 10 minutes left.  Say that we assign the ticket to Brandon who averages 10 minutes per machine.  In that case we can project that the request is on time.  But if we assign the ticket to Dee who averages 20 minutes per machine, then we can project that we are 10 minutes behind schedule.

When you are assigning tickets to agents, you will always have one agent who handles PCs, one who handles Macs, and one who can handle anything.  Just match the client's system to the specialty of the agents.  Assign PCs to the PC agent, Macs to the Mac agent, and all others to the agent who can handle anything.

Keep working.  To make the wisest use of your time, write the easy classes first and then work on Ticket and TechSupportSystem.  I found it useful to have the text files open in TextPad along with the Java files I was working on.  I also compiled and tested as I worked.  Saving compilation and testing until the end is just asking to be frustrated beyond words.

Program Six -- Tech Support System

I've been working on the sixth program.  So far I've created a Ticket class, a Client class, an Agent class, and the TechSupportSystem class.  The latter is the hard one.  Client and Agent are the easy ones.  The description of the assignment lays out the specifications for those two classes and the Ticket class very well.

My Client class has fields for a name, a phone number, a system type and a level of service.  For constructors I have a constructor with four arguments, one with three arguments, and a copy constructor. For methods I have an equals method, a toString method, and getters/setters for all the fields.

My Agent class has fields for a name, an employee ID, a specialty, and a time.  For constructors I have one with four arguments and a copy constructor.  For methods I have a toString method and all the getters and setters.

In my Ticket class I have fields for a ticket ID, the problem, the time, the Client, the Agent, and a static field that helps assign ticket numbers.  I initialized that one to 0 and incremented at the beginning of the constructor before I used it to make the ticket ID.  I currently have only one constructor for the Ticket class and it receives values for all the fields.  I was careful to make a copy of both the Client and Agent parameters before assigned them to the corresponding fields.  That's why Client and Agent need copy constructors.  I'm not finished with the Ticket class, I suspect, but so far I have a toString method, an equals method, a predictTime method, and an isOverdue method.

So far in my TechSupportSystem class I have these methods:

  • the constructor : This one is the guiding force.  It calls the others in the right order.
  • getDate
  • getFileNames
  • readAgents
  • readOneAgent
  • readTickets
  • main : All this does is make a new TechSupportSystem object (and this activates the constructor).
I am not finished with the class and may need other methods.  


Thursday, June 13, 2013

The Fish Market Program is (almost) Done!

I made some good progress on my program and I'm happy with it.  I still need to go through and look for ways to check what the user types to be sure it is correct input.

I have four classes:
  1. SaltyFishMarket:  Control begins here in main.  All main does is declare a new SaltyFishMarket object and that activates the constructor.  The constructor sets up the DecimalFormat object and the Scanner, then calls the buyFish method three times.  The buyFish method returns a Fisherman object which gets used to access the amount of fish each fisherman caught.  The buyFish method also updates a field that keeps track of Salty's total cost.  After the constructor calculates the price that Salty paid per pound, it calls a method to set the price per pound that customers will have to pay.  Finally, the constructor calls a method that sells fish to customers.

    I decided to have five customers.  I made a sellToOneCustomer method and had the sellFish method call it five times.  I could change the number of customers by putting in more or fewer calls to sellToOneCustomer.  After the five calls to sellToOneCustomer, the sellFish method calculates Salty's profit for the day and announces what kind of day Salty had.
  2. Fisherman:  The fields of my Fisherman class are a name, a fish count, a total weight of fish caught, a String for the weather, a probability that corresponds to the weather, and a random number generator.  The constructor gets activated when a Fisherman object is declared (which happens in the SaltyFishMarket class).  The constructor receives a name as an argument and sets the name field.  After that the constructor declares a Weather object then queries that object to find out what the weather is.  Based on the string that is returned by the Weather object, the constructor sets the probability.

    One thing I did to avoid code duplication is make a method in the Fisherman class called goFishing that gets called by the SaltyFishMarket class after it makes a new Fisherman object.  Since a fisherman casts his line five times, I made another method called FishOnce and I had the goFishing method call that one five times.  The FishOnce method gets a random number between 0 and 1 and sees if that number is less than the probability.  If so, a fish is caught.  For example, suppose it's a windy day and the probability is 0.8.  When you get a random double, if it's something like .4 or .6 or anything less than .8, you treat that as a signal that a fish was caught.  About 80% of the numbers between 0 and 1 are less than .8, so that trick works well.

    If a fish is caught, I declare a new Fish object.  Then I query that object for the weight and length of the fish and that's how I decide whether to keep it or not.

    I made the program more fun to run by printing out what happens as the fisherman fishes.  For example, here is a partial run of my code.  The specs didn't say we had to do this, but it's entertaining to see how the program is different every time it runs.

  3. Fish:  This is a really simple class.  The fields are a length, a weight, and a random number generator.  The constructor uses the random number generator to set the length and weight of the fish within the bounds specified.  Brandon showed how to do that in our webinar.
  4. Weather:  This is a really simple class, too.  Its only field is a random number generator.  When a Weather object is created by the Fisherman class, the random number generator is used to get one of four possible values.  I made a getWeather method that returns one of the four strings ("sunny", "cloudy", "windy", or "rainy").

My SaltyFishMarket program

So, if you watched the webinar, you know that my first rendering of this program did not entirely meet the specs.  I got started writing the program and was having so much fun with it that I didn't read the specs carefully enough.  That's not entirely bad... it's not going to be hard for me to correct the way I wrote it in order to make it match specs.

At first I only had a class for the market and a class for a fisherman.  I've now decided to add a class for weather and a class for fish.


The weather class constructor is not going to take any arguments.  All the class needs is a field for a random number generator.  The constructor can allocate the Random object.  I'll also make a method that can be called to get the weather.  It can use the Random object to get one of four possible values and return one of the weather strings. Each fisherman is supposed to check the weather, so I'll add that to my fisherman class.  Every time something calls the getWeather method, a new random number will be generated and the weather will change.


I'll call the class that will contain the main SaltyFishMarket.  Here's my plan for that class.  My main will be ultra-simple:


public static void main(String[] args)
{
    SaltyFishMarket sfm = new SaltyFishMarket();
}

Originally my main was really long.  To make it short like that, I'm going to take all the variables I had in main and make them be fields of this class.  The work that my original main was doing could be divided up as follows:


  1. set up the decimal format and scanner stuff
  2. buy fish from three fishermen
  3. figure out the price to charge
  4. sell fish to some customers
I'll have the constructor set things up.  After it does that, it will call some other methods.  I'll make a buyFish and a setPrice and a sellFish method that the constructor can call.

Okay, I'll get to work on this and will post again when I've made some progress.




Saturday, June 8, 2013

Third Program

I have been waiting to get some ideas from your blogs about what to write about, and most people are not really able to write a lot just now.  Brandon has suggested that I blog about my own programming process.  He is the one who creates the programming assignments, then I write the code to test his idea and give him some feedback.  I think blogging as I go is a good idea and I hope you find it helpful.

The third program is similar to the second one.  It's about a business that needs a report generated.  This time the business is a lawn care service and the report is about one customer.  The program collects data from a user.  It asks for the customer's name, address, and phone number.  It asks how many years that customer has had an account with the company, and it asks about their yard -- its length and width, how many flower beds the customer has, and how many shrubs.

The difference between the third program and the second is that we now know how to create classes (and objects, which are just variables of that class type) to help solve such problems.  So now instead of keeping all the data inside the main method, I'll read the data from the user and then stash all the data inside a new object.  I'll be able to later get the data out of that object whenever and wherever I need it.

It seems sort of silly right now to make a new object for the data when all I have is one customer and that one customer's data is already in main.  But imagine that I have 10 customers or 100 customers.  Soon we're going to learn about writing loops.  I could run a loop a bunch of times and each time collect data about one customer, then put all that customer's data in an object.  We're also going to learn about containers that can hold multiple objects.  I could declare a container of customers and put all of my customer objects into a container.  All that is down the road...

Here is how I will structure my program.  I'll have main do this:

  1. Read in all the data about a customer.  
  2. Declare a new customer object and pass the data to the constructor of the customer class.
  3. Read in all the data about that customer's yard.
  4. Declare a new yard object and pass the data to the constructor of the yard class.
  5. Calculate the charge for that customer's yard.  When I need some piece of data I'll use an accessor method on the appropriate object.
  6. Print out the report.
I'll put my main in a class file that will be called something like "TestLawnService" or "MyLawnService" or some such thing.  The only thing in this class will be my main.  I'll need two more files, one for my customer class and one for my yard class.

One thing you might find useful is printing a percent as a whole number with a percent sign.  Once you learn about the DecimalFormat class in chapter 4, it will become easy.  But you can do it with printf, too.  Suppose my percent variable contains a real number between 0 and 100, such as 45.678.  I can print this as 46% with this printf statement:

printf("The percentage is %.0f%%.", percentage);

The %.0f is a placeholder that says to round the corresponding value to a whole number.  The %% is a placeholder that turns into the % character.  

Program 3 was easier than program 2 for me because I already understood something about programs that read data and make a report.




Tuesday, May 28, 2013

I just finished grading the first program.  Everyone who turned in a program was successful in getting Java to compile and run that program.  I enjoyed reading all the haikus, too.

In the second program you need to use appropriate style (according to the Department's style guidelines).  You also need to remember to write in the blog as you go through the programming process -- I want to look over your shoulder through your blog.

Thursday, May 23, 2013

Getting Started

Hi, class!

I have blog addresses from a little more than half of you.  I hope this experiment in following you through the programming process turns out to be very enlightening to me and helpful to you.