Engr 691 Special Topics in Engineering Science Software Architecture Spring Semester 2004 Lecture Notes - PowerPoint PPT Presentation

About This Presentation
Title:

Engr 691 Special Topics in Engineering Science Software Architecture Spring Semester 2004 Lecture Notes

Description:

class Graphics in Java API provides many drawing primitives ... Better to just use Vector directly. Notes on Class DeckPile (continued) ... – PowerPoint PPT presentation

Number of Views:34
Avg rating:3.0/5.0
Slides: 45
Provided by: gradst3
Category:

less

Transcript and Presenter's Notes

Title: Engr 691 Special Topics in Engineering Science Software Architecture Spring Semester 2004 Lecture Notes


1
Engr 691Special Topics in Engineering Science
Software ArchitectureSpring Semester
2004Lecture Notes
2
Solitaire Case Study (Budd's UOOPJ, Ch. 9)
  • This is a set of slides to accompany chapter 9 of
  • Timothy Budd's textbook
  • Understanding Object-Oriented Programming with
    Java,
  • Updated Edition
  • (Addison-Wesley, 2000)

3
The Solitaire Game
  • Good example of inheritance in action
  • Constructed from classes for cards, card piles,
    and the game application

4
Class Card
  • import java.awt.
  • public class Card
  • // public constants for card dimensions
  • public final static int width 50
  • public final static int height 70
  • // public constants for card suits
  • public final static int heart 0
  • public final static int spade 1
  • public final static int diamond 2
  • public final static int club 3

5
Class Card (continued)
  • // constructors
  • public Card (int sv, int rv)
  • s sv
  • r rv
  • faceup false
  • // mutators
  • public final void flip()
  • faceup ! faceup

6
Class Card (continued)
  • // accessors
  • public final int rank ()
  • return r
  • public final int suit()
  • return s
  • public final boolean faceUp()
  • return faceup

7
Class Card (continued)
  • public final Color color()
  • if (faceUp())
  • if (suit() heart suit() diamond)
  • return Color.red
  • else
  • return Color.black
  • return Color.yellow
  • public void draw (Graphics g, int x, int y)
    / ... /
  • // internal data fields
  • private boolean faceup // card
    face exposed?
  • private int r
    // card rank
  • private int s
    // card suit

8
Notes on Class Card
  • Class implements playing card abstraction
  • Textbook code rearranged into our standard format
  • import makes package java.awt available to
    programpart of Java API
  • Variables and classes can be used before defined
    (except local variables in methods)

9
Notes on Class Card (continued)
  • Java has no global variables, constants, or
    enumerated data types
  • static data fields (i.e., class variables) used
    for global
  • final data fields used for constants assigned
    once, then not redefined
  • Three internal data fields
  • rank and suit are read-only accessors but no
    mutators
  • faceup can be modified flip() mutator
  • draw is complex method accessor with side
    effects
  • final methods accessors rank(), suit(),
    faceup(), and color(), and mutator flip()
  • cannot be overridden in subclasses
  • can be optimized expanded inline like a macro
    efficient but inhibits reuse!
  • draw is not final implementation may be
    somewhat platform dependent

10
Card Images
  • See Figure 9.3 on page 145 of Budd's
  • UOOPJ.

11
Method draw
  • import java.awt.
  • public class Card
  • // ...
  • public void draw (Graphics g, int x, int y)
  • String names "A", "2", "3", "4",
    "5", "6", "7", "8", "9",
  • "10", "J",
    "Q", "K"
  • // clear rectangle, draw border
  • g.clearRect(x, y, width, height)
  • g.setColor(Color.blue)
  • g.drawRect(x, y, width, height)
  • // draw body of card
  • g.setColor(color())

12
Method draw (continued)
  • if (faceUp())
  • g.drawString(namesrank(), x3, y15)
  • if (suit() heart)
  • g.drawLine(x25, y30, x35, y20)
    g.drawLine(x35, y20, x45, y30)
  • g.drawLine(x45, y30, x25, y60)
    g.drawLine(x25, y60, x5, y30)
  • g.drawLine(x5, y30, x15, y20)
    g.drawLine(x15, y20, x25, y30)
  • else if (suit() spade)
  • g.drawLine(x25, y20, x40, y50)
    g.drawLine(x40, y50, x10, y50)
  • g.drawLine(x10, y50, x25, y20)
    g.drawLine(x23, y45, x20, y60)
  • g.drawLine(x20, y60, x30, y60)
    g.drawLine(x30, y60, x27, y45)
  • else if (suit() diamond)
  • g.drawLine(x25, y20, x40, y40)
    g.drawLine(x40, y40, x25, y60)
  • g.drawLine(x25, y60, x10, y40)
    g.drawLine(x10, y40, x25, y20)
  • else if (suit() club)
  • g.drawOval(x20, y25, 10, 10)
    g.drawOval(x25, y35, 10, 10)
  • g.drawOval(x15, y35, 10, 10)
    g.drawLine(x23, y45, x20, y55)
  • g.drawLine(x20, y55, x30, y55)
    g.drawLine(x30, y55, x27, y45)

13
Method draw (continued)
  • else
  • // face down
  • g.drawLine(x15, y5, x15, y65)
  • g.drawLine(x35, y5, x35, y65)
  • g.drawLine(x5, y20, x45, y20)
  • g.drawLine(x5, y35, x45, y35)
  • g.drawLine(x5, y50, x45, y50)

14
Notes on Method draw
  • Displays the card on screen
  • Parameter is current graphics context
  • argument is object of class java.awt.Graphics
  • class Graphics in Java API provides many drawing
    primitives
  • methods for printing bit-maps available for more
    sophisticated visuals
  • Constants such as Color.red and Color.black
    defined in class java.awt.Color
  • draw is instance method every card responsible
    for drawing itself

15
The Game
  • See Figure 9.4 on page 145 of Budd's UOOPJ.

16
Class CardPile
  • import java.awt.
  • import java.util.Stack
  • import java.util.EmptyStackException
  • public class CardPile
  • // constructors
  • public CardPile (int xl, int yl)
  • x xl
  • y yl
  • thePile new Stack()

17
Class CardPile (continued)
  • //mutators
  • public final Card pop()
  • try
  • return (Card) thePile.pop()
  • catch (EmptyStackException e)
  • return null
  • public void addCard (Card aCard) // sometimes
    overridden
  • thePile.push(aCard)
  • public void select (int tx, int ty) // sometimes
    overridden
  • / do nothing /

18
Class CardPile (continued)
  • // accessors
  • public final Card top()
  • return (Card) thePile.peek()
  • public final boolean isEmpty()
  • return thePile.empty()
  • public boolean includes (int tx, int ty) //
    sometimes overridden
  • return x lt tx tx lt x Card.width
  • y lt ty ty lt y Card.height
  • public boolean canTake (Card aCard) // sometimes
    overridden
  • return false
  • public void display (Graphics g) // sometimes
    overridden
  • g.setColor(Color.blue)

19
Class CardPile (continued)
  • // protected data fields
  • // coordinates of the card pile
  • protected int x
  • // (x,y) is upper left corner
  • protected int y
  • // cards in the pile
  • protected Stack thePile

20
Notes on Class CardPile
  • Implementation of card deck abstraction
  • base class extended for specific behaviors
  • Uses generic container Stack from Java API for
    pile of cards
  • empty initially
  • Stack operations implement Card operations
    adapter pattern
  • Cast objects back to Card when taken from stack
  • Uses global symbolic constants Card.width and
    Card.height
  • access to static fields using class name, not
    instance name (actually, either works)
  • pop, top, and isEmpty implementation for
    subclasses -- final methods
  • addCard, select, includes, canTake, and display
    part of abstraction, but implementation varies
    among subclasses
  • protected data fields accessible by subclasses
  • Instructor's comment
  • protected data fields usually bad practice
    trusts subclasses (perhaps in different package)
    to manipulate internal fields correctly safer
    to provide appropriate protected mutators and
    accessors instead (perhaps final)

21
Informal Specification of CardPile's Non-final
Methods
  • Methods may need to be overridden to give the
    card deck the appropriate behaviors.
  • addCard(c)
  • adds card c to the card pile
  • select(x,y)
  • performs an action in response to mouse click at
    (x,y)
  • includes(x,y)
  • determines whether (x,y) within boundary of the
    pile
  • canTake(c)
  • determines whether the pile can take card c
    (according to the rules governing the pile)
  • display(g)
  • displays the pile using graphics context g

22
Class SuitPile
  • class SuitPile extends CardPile
  • // constructors
  • public SuitPile (int x, int y)
  • super(x, y)
  • // accessors
  • public boolean canTake (Card aCard)
  • // overrides parent
  • if (isEmpty())
  • return aCard.rank() 0
  • Card topCard top()
  • return (aCard.suit()
    topCard.suit())
  • (aCard.rank() 1
    topCard.rank())

23
Notes on Class SuitPile
  • Represents one of the (4) piles of cards at top
    of playing surface built up in suit from Ace
    (1) to King (13)
  • Keyword extends indicates inheritance from
    CardPile
  • super indicates parent in constructor used to
    call parent's constructor for initialization
    first statement only
  • Method canTake overridden by replacement
    canTake if pile empty or card is next higher of
    same suit

24
Class DeckPile
  • import java.util.Random
  • class DeckPile extends CardPile
  • // constructors
  • public DeckPile (int x, int y)
  • // first initialize parent
  • super(x, y)
  • // then create the new deck, first put
    them into a local pile
  • for (int i 0 i lt 4 i)
  • for (int j 0 j lt 12 j)
  • addCard(new Card(i, j))
  • // then shuffle the cards
  • Random generator new Random()
  • for (int i 0 i lt 52 i)
  • int j Math.abs(generator.nextInt
    () 52)
  • // swap the two card values
  • Object temp thePile.elementAt(i)
  • thePile.setElementAt(thePile.eleme
    ntAt(j), i)
  • thePile.setElementAt(temp, j)

25
Notes on Class DeckPile
  • Represents the original deck of cards
  • Uses super in constructor for basic
    initialization, new code for specific
    initialization
  • Accesses static (class) methods absolute value
    function Math.abs()
  • Overrides method select by replacement if pile
    nonempty, add top card to discard pile
  • Java API Stack extends Vector select uses the
    "ranked sequence" methods of Vector
  • Instructor's comment
  • Stack extending Vector is poor design in the Java
    API! Similarly, the choice of Stack is a
    questionable design. Better to just use Vector
    directly

26
Notes on Class DeckPile (continued)
  • Accesses utility class java.util.Random to
    generate pseudo-random numbers
  • Accesses static (class) variables to share single
    copies
  • Solitaire.discardPile
  • Author has only one discard pile, so made this
    class access that instance directly
  • Instructor's comment
  • Hard-coding of reference to static discard pile
    inhibits reusability of the deck
  • Probably better to pass discard deck to
    constructor of DeckPile, store reference,
    manipulate it

27
Notes on Class DeckPile(continued)
  • Manipulates protected field thePile from parent
    class CardPile
  • Possible alternatives to use of protected data
    fields
  • Add (protected?) "ranked sequence" get and set
    operations to CardPile abstraction?
  • Add constructor or (protected?) set operation to
    CardPile that takes a sequence (vector, array,
    etc.) of cards to (re)initialize pile? get
    method?
  • Add shuffle operation to CardPile abstraction?

28
Class DiscardPile
  • import java.util.Random
  • class DiscardPile extends CardPile
  • // constructors
  • public DiscardPile (int x, int y)
  • super (x, y)
  • // mutators
  • public void addCard (Card aCard)
  • if (! aCard.faceUp())
  • aCard.flip()
  • super.addCard(aCard)

29
Class DiscardPile (continued)
  • //mutators
  • public void select (int tx, int ty)
  • if (isEmpty())
  • return
  • Card topCard pop()
  • for (int i 0 i lt 4 i)
  • if (Solitaire.suitPilei.canTake(topCa
    rd))
  • Solitaire.suitPilei.addCard(top
    Card)
  • return
  • for (int i 0 i lt 7 i)
  • if (Solitaire.tableaui.canTake(topCard
    ))
  • Solitaire.tableaui.addCard(topC
    ard)
  • return
  • // nobody can use it, put it back on our
    list
  • addCard(topCard)

30
Notes on Class DiscardPile
  • Represents the discard pile in a Solitaire game
  • Constructor refines parent's constructor uses
    super call in initialization
  • select method overrides and replaces one in
    parent
  • checks whether topmost card can be played any
    suit pile or tableau pile
  • addCard method overrides and refines one in
    parent
  • executes parent method (super.addCard), but also
    adds new behavior
  • flips card faceup when put on discard pile
  • Hard-coded access to static variables for the (4)
    suit piles and (7) tableau piles
  • probably better to pass these to constructor,
    store references, and manipulate via local
    references

31
Class TablePile
  • import java.util.Enumeration
  • class TablePile extends CardPile
  • // constructors
  • public TablePile (int x, int y, int c)
  • // initialize the parent class
  • super(x, y)
  • // then initialize our pile of cards
  • for (int i 0 i lt c i)
  • addCard(Solitaire.deckPile.pop())
  • // flip topmost card face up
  • top().flip()

32
Class TablePile (continued)
  • // mutators
  • public void select (int tx, int ty)
  • if (isEmpty()) return
  • // if face down, then flip
  • Card topCard top()
  • if (! topCard.faceUp())
  • topCard.flip()
  • return
  • // else see if any suit pile can take card
  • topCard pop()
  • for (int i 0 i lt 4 i)
  • if (Solitaire.suitPilei.canTake(topCard))
  • Solitaire.suitPilei.addCard(topCard
    )
  • return
  • // else see if any other table pile can
    take card
  • for (int i 0 i lt 7 i)
  • if (Solitaire.tableaui.canTake(topCard))
  • Solitaire.tableaui.addCard(topCard)
  • return

33
Class TablePile (continued)
  • // accessors
  • public boolean canTake (Card aCard)
  • if (isEmpty())
  • return aCard.rank() 12
  • Card topCard top()
  • return (aCard.color() !
    topCard.color())
  • (aCard.rank()
    topCard.rank() - 1)
  • public boolean includes (int tx, int ty)
  • // don't test bottom of card
  • return x lt tx tx lt x Card.width
    y lt ty
  • public void display (Graphics g)
  • int localy y
  • for (Enumeration e thePile.elements()
    e.hasMoreElements())
  • Card aCard (Card)
    e.nextElement()
  • aCard.draw (g, x, localy)
  • localy 35

34
Notes on Class TablePile
  • Represents one of the (7) tableau piles on the
    lower part of the playing surface
  • Initialized with cards from deck constructor
    argument gives number needed
  • Top card is face up
  • Add card to empty pile only if King
  • Add card to nonempty pile only if opposite color
    to top and one rank lower
  • Selection action moves any cards from this table
    pile to suit pile or another table pile
  • Uses super in constructor for basic
    initialization, new code for specific
    initialization
  • Methods select, canTake, includes, and display
    override and replace ones in parent
  • Method display
  • Uses java.util.Enumeration object returned by the
    Stack to iterate through the tableau pile
  • Displays each card slightly offset from the one
    below it
  • Accesses protected field thePile from parent
    class CardPile
  • Perhaps define (protected?) elements()
    method in CardPile to return a pile-Enumeration
    object to avoid protected fields
  • Another alternative method to return cards
    in pile as sequence (e.g., array or vector)

35
The Game Class Solitaire
  • import java.awt.
  • import java.awt.event.
  • public class Solitaire
  • // public class variables for the various
    card piles of game
  • static public DeckPile deckPile
  • static public DiscardPile discardPile
  • static public TablePile tableau
  • static public SuitPile suitPile
  • // single array to alias all above piles --
    aids polymorphism
  • static public CardPile allPiles

36
The Game Class Solitaire (continued)
  • // application entry point
  • static public void main (String args)
  • Solitaire world new Solitaire()
  • // constructors
  • public Solitaire ()
  • window new SolitaireFrame()
  • init()
  • window.show()

37
The Game Class Solitaire (continued)
  • //mutators
  • public void init ()
  • // first allocate the arrays
  • allPiles new CardPile13
  • suitPile new SuitPile4
  • tableau new TablePile7
  • // then fill them in
  • allPiles0 deckPile new DeckPile(335,
    30)
  • allPiles1 discardPile new
    DiscardPile(268, 30)
  • for (int i 0 i lt 4 i)
  • allPiles2i suitPilei new
    SuitPile(15 (Card.width10) i, 30)
  • for (int i 0 i lt 7 i)
  • allPiles6i tableaui
  • new TablePile(15
    (Card.width5) i, Card.height 35, i1)

38
The Game Class Solitaire (continued)
  • // inner classes
  • private class SolitaireFrame extends Frame
  • / expanded later /
  • // internal data fields
  • private Frame window// the application
    window

39
Notes on Class Solitaire
  • Class declares and allocates class (static)
    variables for piles of cards on playing surface
  • Class sets up allpiles array to "alias" all other
    piles, regardless of subclass
  • Control goes initially to class method main
  • main creates an instance of Solitaire application
    (its only action)
  • Solitaire constructor creates window for
    application, initializes the playing surface, and
    displays window
  • SolitaireFrame is an inner class
  • inner class (from the glossary to Budd's
    UOOPJ textbook)
  • a class definition that appears inside another
    class. Inner classes are allowed access to both
    the private data fields and the methods of the
    surrounding class. Inner classes are frequently
    used in building listener objects for handling
    events.
  • SolitaireFrame manages the application window

40
Inner Class SolitaireFrame
  • // part of Class Solitaire
  • private class SolitaireFrame extends Frame
  • private class RestartButtonListener
    implements ActionListener
  • public void actionPerformed
    (ActionEvent e)
  • init()
  • window.repaint()

41
Inner Class SolitaireFrame(continued)
  • private class MouseKeeper extends MouseAdapter
  • public void mousePressed (MouseEvent e)
  • int x e.getX()
  • int y e.getY()
  • for (int i 0 i lt 13 i)
  • if (allPilesi.includes(x,
    y))
  • allPilesi.select(x,
    y)
  • repaint()

42
Inner Class SolitaireFrame(continued)
  • public SolitaireFrame()
  • setSize(600, 500)
  • setTitle("Solitaire Game")
  • addMouseListener (new MouseKeeper())
  • Button restartButton new Button("New
    Game")
  • restartButton.addActionListener(
  • new RestartButtonListener())
  • add("South", restartButton)
  • public void paint(Graphics g)
  • for (int i 0 i lt 13 i)
  • allPilesi.display(g)

43
Notes on Class SolitaireFrame
  • GUI window for the Solitaire game application
  • Extends java.awt.Frame class
  • Event-driven program system GUI manager in
    control, user code "called back" in response to
    GUI events
  • SolitaireFrame constructor
  • sets window size, title
  • adds mouse listener "callback" code to respond to
    mouse events
  • adds restart button at bottom of window ("South")
    and "callback" code to respond to button events

44
Notes on Class SolitaireFrame (continued)
  • Inner class MouseKeeper's method mousePressed
    called on mouse click event
  • determines which pile selected
  • performs select operation for that pile
  • note use of polymorphism
  • action depends on pile type (i.e., on which
    subclass)
  • repaints window
  • Inner class RestartButtonListener method
    actionPerformed called on button event
  • reinitializes game
  • repaints window
  • Method paint of SolitaireFrame called by GUI when
    frame needs to be displayed
  • note use of polymorphism
Write a Comment
User Comments (0)
About PowerShow.com