Java Programming Assignment 7
Requirement
Problem:
- Write a Java program to play a GUI version (your choice of Swing or AWT, application or applet) of your Prog. HW #6 Keno game. Both Prog. HW #6 & Prog. HW #7 versions will use many of the same classes and methods. The only methods you are not allowed to use from Prog. HW #6 are any of the "console" methods (the System.out and System.in methods).
- You have a choice of GUI design, as long as it includes buttons, different Layouts, at least one textfield for user input, event handling and the program is still object-oriented. Also, don't allow the program to "bomb" or hang or display incorrect info if incorrect input or out of order events occur.
Result Snapshot
Solution
public class HW7_Spot
{
private int value = 0;
private boolean chosen = false;
public HW7_Spot()
{
value = 0;
// not needed but in case
chosen = false;
}
public HW7_Spot(int i_value)
{
value = (i_value > 0)? i_value : value;
// not needed but in case
}
public int getValue()
{
return value;
}
public boolean getChosen()
{
return chosen;
}
public void setChosen(boolean b_Chosen)
{
chosen = b_Chosen;
}
}
/* Write an interface called NumberGameInterface which has only abstract public instance methods called
drawNumbers (no parameters, no return value),
getResults (no parameters, no return value) and displayResults (no parameters, no return value).
*/
public interface HW7_NumberGameInterface
{
public abstract void drawNumbers();
public abstract void getResults();
public abstract void displayResults();
}
public class HW7_KenoBoard
{
public static int MAX_KENO_NUMBER = 80;
public static int DRAWN_NUMBERS = 20;
private HW7_Spot [] kenoSpots;
private HW7_Spot [] drawnSpots;
// a constructor (no parameters)-- allocate memory for the kenoSpots (of size MAX_KENO_NUMBER+1) , allocate memory for the drawnSpots array (of size DRAWN_NUMBERS). Initialize each element in the kenoSpots array to an instance of a Spot (pass the array index to the constructor). Note: MAX_KENO_NUMBER and DRAWN_NUMBERS are declared as static in the KenoGame class
public HW7_KenoBoard()
{
kenoSpots = new HW7_Spot[MAX_KENO_NUMBER + 1];
drawnSpots = new HW7_Spot[DRAWN_NUMBERS];
for(int i=1; i < kenoSpots.length; i++)
{
kenoSpots[i] = new HW7_Spot(i);
}
}
// a method that resets the boolean variable in each Spot (OR only the ones that were set, using drawnSpots) of kenoSpots to false, and then resets each element of the drawnSpots array to null.
public void resetKenoBoard()
{
for(int i = 1; i < kenoSpots.length; i++)
// Note: Keno Spot index starts from 1, 0th index is null
kenoSpots[i].setChosen(false);
for(int i = 0; i < drawnSpots.length; i++)
drawnSpots[i] = null;
}
// an accessor (with an int parameter, Spot return value) for ONE of the kenoSpots with the index of the int pararmeter-- be sure that the int parameter is in range (check using KenoGame's static MAX_KENO_NUMBER variable) -- if in range, return the corresponding Spot, if not, return null
public HW7_Spot getKenoSpot(int i_Spot)
{
if(i_Spot > 0 && i_Spot <= MAX_KENO_NUMBER)
return kenoSpots[i_Spot];
else
return null;
}
// a method that will randomly choose Spots in kenoSpots by doing the following for each drawnSpots element:
public void createDrawnSpots()
{
int i_RandomKenoIndex;
for (int i = 0; i < drawnSpots.length; i++)
{
// formula to get random number: (int)(Math.random() * (MAX-MIN+1) ) + MIN;
i_RandomKenoIndex = (int)(Math.random() * (MAX_KENO_NUMBER - 1 + 1) ) + 1;
if(kenoSpots[i_RandomKenoIndex].getChosen())
i--;
// already chosen than loop one more time, do it silently without any warning
else
{
drawnSpots[i] = new HW7_Spot(kenoSpots[i_RandomKenoIndex].getValue());
kenoSpots[i_RandomKenoIndex].setChosen(true);
}
}
}
// toString (overriding Object's toString) that will return a string with the value of each Spot in the drawnSpots array
public String toString()
{
String s_drawnSpots = "";
for(int i = 0; i < drawnSpots.length; i++)
{
s_drawnSpots = s_drawnSpots + drawnSpots[i].getValue() + "-";
// Don't know why but "|" character is not working
}
return s_drawnSpots;
}
}
// Write a class called KenoPlayer to represent a player's chosen numbers for a Keno Game.
public class HW7_KenoPlayer
{
private HW7_Spot [] markedSpots;
private int currentIndex = 0;
private int numOfMatches = 0;
private int amountOfBet = 1;
private double amountWin = 0.00;
// To Do: constructor with int for the number of spots to choose, and an int for the bet as parameters-- initialize the appropriate instance variables to the parameters (make sure to assign only if > 0 for numbers, and the number of spots < length of the payoff array in the KenoGame class), and allocate memory for the markedSpots array, using the parameter for the number of spots (or 1 if the parameter is out of range)
public HW7_KenoPlayer(int i_numOfSpots, int i_amountOfBet)
{
if(i_numOfSpots > 0 && i_numOfSpots < HW7_KenoGame.PAYOFF.length)
markedSpots = new HW7_Spot[i_numOfSpots];
else
markedSpots = new HW7_Spot[1];
amountOfBet = (i_amountOfBet > 0)? i_amountOfBet : amountOfBet;
}
// accessors (one for the length of the markedSpots array, one for the bet, one for the number of matches, and one for the winnings)
public int getLengthOfMarkedSports()
{
return markedSpots.length;
}
public int getAmountOfBet()
{
return amountOfBet;
}
public int geNumOfMatches()
{
return numOfMatches;
}
public double getAmountWin()
{
return amountWin;
}
// a method called setSpot (with a Spot parameter and boolean return value) that assigns to the next element in this' markedSpots array, the Spot parameter-- but check if the parameter isn't null and the currentIndex < length of the array AND/OR check each element in this' markedSpots array so far (that the parameter's not already there). If it doesn't, assign, increment the current index and return true, otherwise return false.
public boolean setSpot(HW7_Spot oHW7_Spot)
{
if(currentIndex < markedSpots.length && oHW7_Spot != null)
{
for (int i = 0; i < markedSpots.length; i++)
{
if(markedSpots[i] != null)
{
if(markedSpots[i].getValue() == oHW7_Spot.getValue())
// Spot comparison
return false;
}
}
markedSpots[currentIndex] = oHW7_Spot;
currentIndex ++;
return true;
}
else
{
return false;
}
}
// a method called calcNumMatches that counts how many elements in this KenoPlayer's markedSpots that were chosen (check each element's chosen variable) and assign to your instance variable for number of matches
public void calcNumMatches()
{
numOfMatches = 0;
// reset before calculate in case
for(int i = 0; i < markedSpots.length; i++)
{
if(markedSpots[i].getChosen())
numOfMatches++;
}
}
// a method called calcWinnings (no parameters) that will access the PAYOFF static 2-dim. array in the KenoGame to find and assign the appropriate array element (multiplied by your bet), rounded to the nearest int to your instance variable for amount you won.
public void calcWinnings()
{
amountWin = Math.round(HW7_KenoGame.PAYOFF[markedSpots.length][numOfMatches] * amountOfBet);
}
// toString (overriding Object's toString) that will return a string with a label (like "Player's spots:"), each of the Spot's int values in the markedSpots array (make sure it's not null) , number of matches, bet, and winnings
public String toString()
{
// ex: Player's spots: 20 30 40 50, Player matched 2 spot(s), bet $10 and won $10
String s_PlayerSpot = "";
for(int i = 0; i < markedSpots.length; i++)
{
s_PlayerSpot = s_PlayerSpot + markedSpots[i].getValue() + "-";
}
return String.format("Player's spots: %s \nPlayer matched %d spot(s), bet $%d and won $%.2f", s_PlayerSpot, numOfMatches, amountOfBet, amountWin);
}
public String getMatchedSpots()
{
String s_MatchedSpots = "";
for(int i = 0; i < markedSpots.length; i++)
{
if(markedSpots[i].getChosen())
s_MatchedSpots = s_MatchedSpots + markedSpots[i].getValue() + "-";
}
return s_MatchedSpots;
}
}
public class HW7_KenoGame implements HW7_NumberGameInterface
{
public static final int MAX_KENO_NUMBER = 80;
public static final int DRAWN_NUMBERS = 15;
private HW7_KenoBoard oKenoBoard;
private HW7_KenoPlayer oKenoPlayer;
public static double [][] PAYOFF = {{0},
{0, 2.75},
{0, 1., 5.},
{0, 0, 2.50, 25.00},
{0, 0, 1.0, 5.0, 80.0},
{0, 0, 0, 2.0, 10.0, 600.0},
{0, 0, 0, 1.0, 8.0, 50., 1499.0},
{0, 0, 0, 0, 5.0, 10.0, 250., 1500.0},
{0, 0, 0, 0, 4.00, 8.00, 40.00, 400.00, 10000.00},
{0, 0, 0, 0, 2.00, 5.00, 20.00, 80.00, 2500.00, 15000.00},
{0, 0, 0, 0, 0, 2.00, 30.00, 100.00, 500.00, 3000.00, 17500.00},
{0, 0, 0, 0, 0, 2.00, 15.00, 50.00, 80.00, 800.00, 8000.00, 27500.00},
{0, 0, 0, 0, 0, 1.00, 5.00, 30.00, 90.00, 500.00, 2500.00, 15000.00, 30000.00},
{0, 0, 0, 0, 0, 1.00, 2.00, 10.00, 50.00, 500.00, 1000.00, 10000.00, 15000.00, 30000.00},
{0, 0, 0, 0, 0, 0, 2.00, 8.00, 32.00, 300.00, 800.00, 2500.00, 12000.00, 18000.00, 30000.00},
{0, 0, 0, 0, 0, 0, 1.00, 7.00, 21.00, 100.00, 400.00, 2000.00, 8000.00, 12000.00, 25000.00, 30000.}
};
// default constructor that instantiates a KenoBoard (and assigns to the KenoBoard instance variable)
public HW7_KenoGame()
{
oKenoBoard = new HW7_KenoBoard();
}
// a method (2 int parameters) to instantiate a new KenoPlayer passing the int parameters (and assign to the instance variable)
public void createKenoPlayer(int i_numOfSpots, int i_amountOfBet)
{
oKenoPlayer = new HW7_KenoPlayer(i_numOfSpots, i_amountOfBet);
}
// a method with an int parameter to set ONE Spot in the KenoPlayer's (if the KenoPlayer variable is not null) markedSpots array, but check the int parameter first if it's in range (between 1 and KenoBoard's static MAX_KENO_NUMBER) before passing the Spot in the KenoBoard (use the KenoBoard's accessor for one Spot) -- return -2 if the KenoPlayer hasn't been instantiated yet, -1 if the int parameter is out of range, 1 if the KenoPlayer's method returns false, 0 if it was assigned OK
public int setUserDrawnSpot(int i_Spot)
{
if(oKenoPlayer != null)
{
if(i_Spot > 0 && i_Spot <= HW7_KenoBoard.MAX_KENO_NUMBER)
{
//HW7_Spot oHW7_Spot = new HW7_Spot(i_Spot);
//oHW7_Spot.setChosen(true);
if(oKenoPlayer.setSpot(oKenoBoard.getKenoSpot(i_Spot)))
return 0;
// -- 0 if it was assigned OK
else
return 1;
// -- 1 if the KenoPlayer's method returns false
}
else
return -1;
// -- -1 if the int parameter is out of range
}
else
return -2;
// -- return -2 if the KenoPlayer hasn't been instantiated yet
}
// a method to return the length of the KenoPlayer's markedSpots array
public int getLenOfMarkedSpots()
{
return oKenoPlayer.getLengthOfMarkedSports();
}
// a method to override the interface method drawNumbers (no parameters) that calling the KenoBoard methods to reset its variables and the method to assign "randomly" to the drawnArray
public void drawNumbers()
{
oKenoBoard.resetKenoBoard();
oKenoBoard.createDrawnSpots();
}
// a method to override the interface method getResults that calls the KenoPlayer's methods to calculate how many matched and calculate its winnings
public void getResults()
{
oKenoPlayer.calcNumMatches();
oKenoPlayer.calcWinnings();
}
// a method to override the interface method displayResults that will display the KenoBoard's toString and the KenoPlayer's toString to System.out.
public void displayResults()
{
System.out.println(oKenoBoard.toString());
System.out.println(oKenoPlayer.toString());
}
// Following methods are added for HW7
public String getDrawnSpots()
{
return oKenoBoard.toString();
}
public String getMatchedSpots()
{
return oKenoPlayer.getMatchedSpots();
}
public int geKenoPlayerNumOfMatches()
{
return oKenoPlayer.geNumOfMatches();
}
public double getKenoPlayerAmountWin()
{
return oKenoPlayer.getAmountWin();
}
}
/*
Name of program: Keno Game with GUI
Programmer's name: ABC
Current Date: dd/mm/yyyy
Computer system and compiler you are using: Win 8, JDK 1.7
Brief description of the program (1-5 sentences): Play Keno game (GUI version)
Variable names (if any) and descriptions of what they represent:
*/
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.util.Scanner;
// To Do: Remove
public class HW7_KenoGameDriver extends JFrame implements ActionListener
{
static Scanner oScanner = new Scanner(System.in);
// TO Do: Remove
private static int i_Counter = 0;
private static int i_NumOfSpotToChose = 0;
// GUI Components
private JComboBox cbx_NumOfSpotToChose;
private JTextField tb_amountOfBet;
private JButton btn_playKeno;
private JButton [] btn_KenoSpots;
private JLabel lb_result;
private JButton btn_playKenoAgain;
private HW7_KenoGame oKenoGame;
public HW7_KenoGameDriver()
{
super("Keno Game");
setLayout(new BorderLayout());
JPanel p1 = new JPanel(new FlowLayout());
String [] strArray_NumOfSpotToChose = new String[HW7_KenoGame.DRAWN_NUMBERS];
for (int i = 0; i < HW7_KenoGame.DRAWN_NUMBERS; i++)
strArray_NumOfSpotToChose[i] = Integer.toString(i+1);
cbx_NumOfSpotToChose = new JComboBox(strArray_NumOfSpotToChose);
tb_amountOfBet = new JTextField(5);
// assumed max bet is 99999
btn_playKeno = new JButton("Play Keno");
btn_playKeno.addActionListener(this);
p1.add(new JLabel("How many spots do you want to choose?"));
p1.add(cbx_NumOfSpotToChose);
p1.add(new JLabel("What is your bet (min $1): "));
p1.add(tb_amountOfBet);
p1.add(btn_playKeno);
JPanel p2 = new JPanel(new GridLayout(8, 10, 1, 1));
btn_KenoSpots = new JButton[HW7_KenoGame.MAX_KENO_NUMBER];
for (int i = 0; i < btn_KenoSpots.length; i++)
{
btn_KenoSpots[i] = new JButton(Integer.toString(i+1));
btn_KenoSpots[i].setEnabled(false);
btn_KenoSpots[i].setBackground(Color.GRAY);
btn_KenoSpots[i].addActionListener(this);
p2.add(btn_KenoSpots[i]);
// avoid another for loop
}
JPanel p3 = new JPanel(new FlowLayout());
lb_result = new JLabel();
btn_playKenoAgain = new JButton("Play Another Game");
btn_playKenoAgain.setEnabled(false);
btn_playKenoAgain.addActionListener(this);
p3.add(lb_result);
p3.add(btn_playKenoAgain);
JPanel p4 = new JPanel(new GridLayout(8, 4, 2, 2));
JButton oJButton_Yellow = new JButton("Selected Spots"); oJButton_Yellow.setBackground(Color.YELLOW); oJButton_Yellow.setEnabled(false); oJButton_Yellow.setToolTipText("Selected Spot");
JButton oJButton_MAGENTA = new JButton("Drawn Spots"); oJButton_MAGENTA.setBackground(Color.MAGENTA); oJButton_MAGENTA.setEnabled(false); oJButton_Yellow.setToolTipText("Drawn Spot");
JButton oJButton_Red = new JButton("Matched Spots"); oJButton_Red.setBackground(Color.RED); oJButton_Red.setEnabled(false); oJButton_Yellow.setToolTipText("Matched Spot");
JButton oJButton_Gray = new JButton("Disabled Spots"); oJButton_Gray.setBackground(Color.GRAY); oJButton_Gray.setEnabled(false); oJButton_Gray.setToolTipText("Buttons are disabled. Please select options and click on Play Keno Game to start the game");
JButton oJButton_Cyan = new JButton("Enabled Spots"); oJButton_Cyan.setBackground(Color.CYAN); oJButton_Cyan.setEnabled(false); oJButton_Cyan.setToolTipText("Buttons are enabled for selection. Please select keno spots to see how much you win");
p4.add(oJButton_Yellow);
p4.add(oJButton_MAGENTA);
p4.add(oJButton_Red);
p4.add(oJButton_Gray);
p4.add(oJButton_Cyan);
// Arrange all panels
add(p1, BorderLayout.NORTH);
add(p2, BorderLayout.CENTER);
add(p3, BorderLayout.SOUTH);
add(p4, BorderLayout.WEST);
oKenoGame = new HW7_KenoGame();
}
public void actionPerformed(ActionEvent e)
{
Object obj = e.getSource();
int i_amountOfBet = 0;
if(obj == btn_playKeno)
{
i_NumOfSpotToChose = Integer.parseInt((String)cbx_NumOfSpotToChose.getSelectedItem());
if(tb_amountOfBet.getText().isEmpty())
{
JOptionPane.showMessageDialog(null, "Please enter value in Amount of bet box before click Play again", "Input Error", JOptionPane.ERROR_MESSAGE);
return;
}
try
{
i_amountOfBet = Integer.parseInt(tb_amountOfBet.getText());
if (i_amountOfBet == 0)
{
JOptionPane.showMessageDialog(null, "Must enter amount greater than 0.", "Input Error", JOptionPane.ERROR_MESSAGE);
return;
}
}
catch( NumberFormatException nfe )
{
JOptionPane.showMessageDialog(null, "Must enter digits only in amount of bet box!", "Input Error", JOptionPane.ERROR_MESSAGE);
return;
}
oKenoGame.drawNumbers();
oKenoGame.createKenoPlayer(i_NumOfSpotToChose, i_amountOfBet);
for (int i = 0; i < btn_KenoSpots.length; i++)
{
btn_KenoSpots[i].setEnabled(true);
btn_KenoSpots[i].setBackground(Color.CYAN);
}
cbx_NumOfSpotToChose.setEnabled(false);
tb_amountOfBet.setEnabled(false);
btn_playKeno.setEnabled(false);
lb_result.setText("Select " + i_NumOfSpotToChose + " keno numbers");
lb_result.setForeground(Color.RED);
}
else if(obj == btn_playKenoAgain)
{
// To Do:
btn_playKenoAgain.setEnabled(false);
for (int i = 0; i < btn_KenoSpots.length; i++)
{
btn_KenoSpots[i].setEnabled(false);
btn_KenoSpots[i].setBackground(Color.GRAY);
}
cbx_NumOfSpotToChose.setEnabled(true);
tb_amountOfBet.setEnabled(true);
btn_playKeno.setEnabled(true);
lb_result.setText("");
// No reset for amount of bet and number of spots to chose, since it might helpful for user if want to keep the same numbers and try one more time OR modification is easier
i_Counter = 0;
i_NumOfSpotToChose = 0;
oKenoGame = new HW7_KenoGame();
// To Do:
}
else if(obj instanceof JButton && Character.isDigit(((JButton)obj).getText().charAt(0)))
// To Do: bad logic, how to determine keno spot buttons, probably need new action listener, check range 1 to 80
{
JButton btn_kenoSpot = (JButton)obj;
btn_kenoSpot.setEnabled(false);
btn_kenoSpot.setBackground(Color.YELLOW);
oKenoGame.setUserDrawnSpot(Integer.parseInt(btn_kenoSpot.getText()));
i_Counter ++;
if(i_Counter == i_NumOfSpotToChose)
{
oKenoGame.getResults();
// Calculated number of matches and amount of Win
//System.out.println(oKenoGame.getDrawnSpots());
// For Test Only
String [] a_drawnSpots = oKenoGame.getDrawnSpots().split("-");
for(int i = 0; i < a_drawnSpots.length; i++)
{
// System.out.println(a_drawnSpots[i]);
// For Test Only
btn_KenoSpots[Integer.parseInt(a_drawnSpots[i])-1].setBackground(Color.MAGENTA);
}
String s_MatchedSpots = oKenoGame.getMatchedSpots();
//System.out.println(s_MatchedSpots);
// For Test Only
if(!s_MatchedSpots.isEmpty())
{
String [] a_matchedSpots = s_MatchedSpots.split("-");
for(int i = 0; i < a_matchedSpots.length; i++)
{
btn_KenoSpots[Integer.parseInt(a_matchedSpots[i])-1].setBackground(Color.RED);
}
}
for (int i = 0; i < btn_KenoSpots.length; i++)
{
btn_KenoSpots[i].setEnabled(false);
}
lb_result.setText("You matched "+ oKenoGame.geKenoPlayerNumOfMatches() + " Spot(s), You won $" + oKenoGame.getKenoPlayerAmountWin() +" ");
btn_playKenoAgain.setEnabled(true);
}
}
}
public static void main(String[] args)
{
//HW7_KenoGame oKenoGame = new HW7_KenoGame();
HW7_KenoGameDriver oKenoGameDriver = new HW7_KenoGameDriver();
oKenoGameDriver.setSize(650,650);
oKenoGameDriver.setVisible(true);
oKenoGameDriver.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Note: In GUI version following line is not needed (keep it here for future reference)
//boolean b_IsGameContinue = true;
// determine if user want to repeat
//while(b_IsGameContinue)
//{
//
oKenoGame.drawNumbers();
//
getKenoGameUserChoices(oKenoGame);
//
oKenoGame.getResults();
//
oKenoGame.displayResults();
//
b_IsGameContinue = isGameContinue();
// Ask if user wants to repeat
//}
}
// Not needed (Keep it here for future reference)
public static void getKenoGameUserChoices(HW7_KenoGame oKenoGame)
{
int i_NumOfSpotToChose = 0;
int i_amountOfBet = 0;
while (i_NumOfSpotToChose < 1 || i_NumOfSpotToChose >= HW7_KenoGame.PAYOFF.length)
{
System.out.print("How many spots do you want to choose? (max. " + HW7_KenoGame.DRAWN_NUMBERS + "): ");
i_NumOfSpotToChose = oScanner.nextInt();
// if (i_NumOfSpotToChose < 1 || i_NumOfSpotToChose >= HW7_KenoGame.PAYOFF.length)
// display error message
}
while(i_amountOfBet <= 0)
{
System.out.print("What is your bet (at least $1): ");
i_amountOfBet = oScanner.nextInt();
}
oKenoGame.createKenoPlayer(i_NumOfSpotToChose, i_amountOfBet);
int i_Counter = 0;
while (i_Counter < i_NumOfSpotToChose)
{
System.out.print(String.format("Enter number (1-%d) #%d: ", HW7_KenoGame.MAX_KENO_NUMBER, (i_Counter+1)));
switch(oKenoGame.setUserDrawnSpot(oScanner.nextInt()))
{
case -1:
System.out.println(String.format("Number is out of range (1-%d)", HW7_KenoGame.MAX_KENO_NUMBER));
break;
case 1:
System.out.println("You already chose that number!");
break;
case 0:
i_Counter++;
break;
default:
break;
}
}
}
// Ask if user wants to repeat --> Copied this method from HW2 --> Not needed (Keep it here for reference)
public static boolean isGameContinue()
{
boolean isGameContinue;
System.out.print("Play another game? (y for yes): ");
String s_UserInput = oScanner.next();
if(s_UserInput != null && ! s_UserInput.isEmpty())
{
System.out.println(s_UserInput.substring(0, 0).toUpperCase());
isGameContinue = (s_UserInput.toUpperCase().charAt(0) == 'Y')? true : false;
}
else
isGameContinue = false;
return isGameContinue;
}
}
/*
Output:
- GUI output of different steps in word document
*/