Go here to see the full Java Docs. A link to the actual Java source code for each class is in their respective documentation.
The solitaire game engine code is based off of a C++ version. The source for the GUI packages, view and view.awt, are pretty much crap. This was my first GUI in Java and a lot of hacking was done to get descent drag and drop performance.
I stopped working on the Java version when I started working on nyse.com.
Here is a source code sample. This is card.games.Canfield.java which creates and defines Canfield.
If it helps, note that my set methods always return a this which enables code like:
somePile.available(...).build(...).deal(...);which is equavalent to:
somePile.available(...); somePile.build(...); somePile.deal(...);
/*
* Copyright (c) 1999 David Mannies. All Rights Reserved.
*/
package card.game;
import card.*;
import java.util.*;
/**
* <A href="javascript:window.location = window.location.href.substring(0, window.location.href.indexOf('.')) + '.java.html'">view source</A><BR><BR>
*
* Class for generating Canfield game setup.
*
* @author David Mannies
*/
public class Canfield extends card.Game
{
//************************** PUBLIC METHODS ******************************
/**
* Default constructor.
*/
public Canfield()
{}
class SetFoundationStart extends card.Event
{
public card.build.Exact exact()
{return exact_;}
public SetFoundationStart exact(card.build.Exact e)
{exact_ = e; return this;}
protected boolean doHandleEvent(Parameters p)
{
if(p.pile().cards().size() > 0)
{
Card card = p.pile().cards().firstCard();
exact().card(new card.Card().value(card.value()));
}
return true;
}
card.build.Exact exact_ = null;
}
protected Pile doGetAutoPlay(Pile to, Pile from, Card card)
{
Pile ret = to;
// stop moving of top card back and forth
if(to != null)
if(from.type() == Pile.TYPE_TABLEAU && to.type() == Pile.TYPE_TABLEAU)
if(display(from) != card)
ret = null;
return ret;
}
//************************ PROTECTED METHODS *****************************
/**
* Does actual object creation for this game.
*/
protected void doCreate()
{
deck(new card.deck.Standard());
layout(new Layout().x(6.5).y(2));
indexStart(createPiles(11));
indexEnd(indexStart() + 12 - 1);
int index = indexStart();
//foundation
int foundationIndex = index;
card.build.Exact exact = new card.build.Exact();
for(int loop =0; loop<4; loop++)
((Pile)piles().elementAt(index++))
.available(new card.available.Top())
.build(new card.build.Count().count(1).first(exact).and(new card.build.Suit(card.build.Suit.SAME).and(new card.build.Value(card.build.Value.UP).continuous(true))))
.deal(((loop == 0) ? (new card.deal.All().count(1).next(new card.deal.Show(card.deal.Show.ALL))) : (Deal)null))
.type(card.Pile.TYPE_FOUNDATION)
.layout(new Layout().x(2.5 + loop).y(0).layout(card.Layout.LAYOUT_STACK | card.Layout.LAYOUT_DISPLAY_EMPTY))
;
((Pile)piles().elementAt(foundationIndex))
.event(new SetFoundationStart().exact(exact).events(card.Event.EVENT_START))
;
//reserve
int reserveIndex = indexStart();
((Pile)piles().elementAt(reserveIndex = index++))
.available(new card.available.Top())
.build((Build)null)
.deal(new card.deal.All().count(13).next(new card.deal.Show(card.deal.Show.ALL)))
.type(card.Pile.TYPE_RESERVE)
.layout(new Layout().x(1).y(1).layout(card.Layout.LAYOUT_VERTICAL | card.Layout.LAYOUT_FEATHER).maxFacing(13).maxFacingTypical(13))
;
//stock
((Pile)piles().elementAt(index++))
.build((Build)null)
.deal(new card.deal.All().count(34).next(new card.deal.Show(card.deal.Show.ALL)))
.type(card.Pile.TYPE_STOCK)
.layout(new Layout().x(0).y(0).layout(card.Layout.LAYOUT_DISPLAY_AS_HIDDEN))
.event(new card.event.TurnCard().to(index).events(card.Event.EVENT_SELECTED))
;
//discard
((Pile)piles().elementAt(index++))
.available(new card.available.Top())
.build((Build)null)
.deal((Deal)null)
.type(card.Pile.TYPE_DISCARD)
.layout(new Layout().x(1).y(0))
;
//tableau
for(int loop =0; loop<4; loop++)
((Pile)piles().elementAt(index++))
.available(new card.available.Display().or(new card.available.Top()))
.build(new card.build.Suit(card.build.Suit.ALTERNATE).and(new card.build.Value(card.build.Value.DOWN).continuous(true)))
.deal(new card.deal.All().count(1).next(new card.deal.Show(card.deal.Show.ALL)))
.type(card.Pile.TYPE_TABLEAU)
.layout(new Layout().x(2.5 + loop).y(1).layout(card.Layout.LAYOUT_VERTICAL | card.Layout.LAYOUT_SPREAD).maxFacing(13).maxFacingTypical(8))
.event(new card.event.GetCard().from(reserveIndex).events(card.Event.EVENT_EMPTY))
;
}
}