141 lines
3.0 KiB
Ceylon
141 lines
3.0 KiB
Ceylon
import ceylon.random {
|
|
Random,
|
|
DefaultRandom
|
|
}
|
|
|
|
abstract class Feature() of Color | Symbol | NumberOfSymbols | Shading {}
|
|
|
|
abstract class Color()
|
|
of red | green | purple
|
|
extends Feature() {}
|
|
object red extends Color() {
|
|
string => "red";
|
|
}
|
|
object green extends Color() {
|
|
string => "green";
|
|
}
|
|
object purple extends Color() {
|
|
string => "purple";
|
|
}
|
|
|
|
abstract class Symbol()
|
|
of oval | squiggle | diamond
|
|
extends Feature() {}
|
|
object oval extends Symbol() {
|
|
string => "oval";
|
|
}
|
|
object squiggle extends Symbol() {
|
|
string => "squiggle";
|
|
}
|
|
object diamond extends Symbol() {
|
|
string => "diamond";
|
|
}
|
|
|
|
abstract class NumberOfSymbols()
|
|
of one | two | three
|
|
extends Feature() {}
|
|
object one extends NumberOfSymbols() {
|
|
string => "one";
|
|
}
|
|
object two extends NumberOfSymbols() {
|
|
string => "two";
|
|
}
|
|
object three extends NumberOfSymbols() {
|
|
string => "three";
|
|
}
|
|
|
|
abstract class Shading()
|
|
of solid | open | striped
|
|
extends Feature() {}
|
|
object solid extends Shading() {
|
|
string => "solid";
|
|
}
|
|
object open extends Shading() {
|
|
string => "open";
|
|
}
|
|
object striped extends Shading() {
|
|
string => "striped";
|
|
}
|
|
|
|
class Card(color, symbol, number, shading) {
|
|
shared Color color;
|
|
shared Symbol symbol;
|
|
shared NumberOfSymbols number;
|
|
shared Shading shading;
|
|
|
|
value plural => number == one then "" else "s";
|
|
string => "``number`` ``shading`` ``color`` ``symbol````plural``";
|
|
}
|
|
|
|
{Card*} deck = {
|
|
for(color in `Color`.caseValues)
|
|
for(symbol in `Symbol`.caseValues)
|
|
for(number in `NumberOfSymbols`.caseValues)
|
|
for(shading in `Shading`.caseValues)
|
|
Card(color, symbol, number, shading)
|
|
};
|
|
|
|
alias CardSet => [Card+];
|
|
|
|
Boolean validSet(CardSet cards) {
|
|
|
|
function allOrOne({Feature*} features) =>
|
|
let(uniques = features.distinct.size)
|
|
uniques == 3 || uniques == 1;
|
|
|
|
return allOrOne(cards*.color) &&
|
|
allOrOne(cards*.number) &&
|
|
allOrOne(cards*.shading) &&
|
|
allOrOne(cards*.symbol);
|
|
}
|
|
|
|
{CardSet*} findSets(Card* cards) =>
|
|
cards
|
|
.sequence()
|
|
.combinations(3)
|
|
.filter(validSet);
|
|
|
|
Random random = DefaultRandom();
|
|
|
|
class Mode of basic | advanced {
|
|
|
|
shared Integer numberOfCards;
|
|
shared Integer numberOfSets;
|
|
|
|
shared new basic {
|
|
numberOfCards = 9;
|
|
numberOfSets = 4;
|
|
}
|
|
|
|
shared new advanced {
|
|
numberOfCards = 12;
|
|
numberOfSets = 6;
|
|
}
|
|
}
|
|
|
|
[{Card*}, {CardSet*}] deal(Mode mode) {
|
|
value randomStream = random.elements(deck);
|
|
while(true) {
|
|
value cards = randomStream.distinct.take(mode.numberOfCards).sequence();
|
|
value sets = findSets(*cards);
|
|
if(sets.size == mode.numberOfSets) {
|
|
return [cards, sets];
|
|
}
|
|
}
|
|
}
|
|
|
|
shared void run() {
|
|
value [cards, sets] = deal(Mode.basic);
|
|
print("The cards dealt are:
|
|
");
|
|
cards.each(print);
|
|
print("
|
|
Containing the sets:
|
|
");
|
|
for(cardSet in sets) {
|
|
cardSet.each(print);
|
|
print("");
|
|
}
|
|
|
|
}
|