Java programming idea enumeration type
Basic enum characteristics
Call the values() method of enum to traverse the Enum instance. The values method returns the Enum instance array, and the elements in the array are strictly kept in the order when they are declared in enum
public enum Shrubbery { GROUND, CRAWLING, HANGING } public class EnumClass { public static void main(String[] args) { for (Shrubbery s : Shrubbery.values()) { // The coordinate method returns an int value, which is the order of each enum instance when it is declared starting from 0 System.out.println(s + "orginal " + s.ordinal()); System.out.println("_________________"); // The enum class implements the Comparable interface, so it has the compareTo method System.out.println(s.compareTo(Shrubbery.CRAWLING ) + ""); System.out.println("_________________"); // You can use = = to compare the enum instance compiler to automatically provide equal and hashcode methods System.out.println(s == Shrubbery.CRAWLING); System.out.println("_________________"); // The getDeclaringClass method tells us which enum class we belong to System.out.println(s.getDeclaringClass()); System.out.println("_________________"); // Name method name of repeated enum instance declaration System.out.println(s.name()); } for (String s:"jdddh hfhfj jfjkfjf".split(" ")) { // valueOf returns the corresponding enum instance according to the given name Shrubbery shrubbery = Enum.valueOf(Shrubbery.class,s); System.out.println(shrubbery); } } }
Add new methods to enum
You can add methods to enum, which can even have the main() method
public enum OzWitch { // The enumeration class instance can return the description of itself, and can provide a constructor to handle this extra information // Then add a method to return this description // If you plan to add your own method, add a semicolon at the end of the enum instance sequence // At the same time, you need to define enum instance first, then any method or property // Instances must be defined first, before methods: WEST("Miss Gulch, aka the Wicked Witch of the West"), NORTH("Glinda, the Good Witch of the North"), EAST("Wicked Witch of the East, wearer of the Ruby " + "Slippers, crushed by Dorothy's house"), SOUTH("Good by inference, but missing"); private String description; // Constructor must be package or private access: private OzWitch(String description) { this.description = description; } public String getDescription() { return description; } public static void main(String[] args) { for(OzWitch witch : OzWitch.values()) print(witch + ": " + witch.getDescription()); } }
Coverage enum method
public enum SpaceShip { // Override toString method // Generate string descriptions the way we want SCOUT, CARGO, TRANSPORT, CRUISER, BATTLESHIP, MOTHERSHIP; public String toString() { String id = name(); String lower = id.substring(1).toLowerCase(); return id.charAt(0) + lower; } public static void main(String[] args) { for(SpaceShip s : values()) { System.out.println(s); } } }
Using enum in Switch
public enum Signal { GREEN, YELLOW, RED, } public class TrafficLight { // Using enum in switch Signal color = Signal.RED; public void change() { switch(color) { // Note that you don't have to say Signal.RED // in the case statement: case RED: color = Signal.GREEN; break; case GREEN: color = Signal.YELLOW; break; case YELLOW: color = Signal.RED; break; } } public String toString() { return "The traffic light is " + color; } public static void main(String[] args) { TrafficLight t = new TrafficLight(); for(int i = 0; i < 7; i++) { print(t); t.change(); } } }
Values() method
public enum Explore { HERE, THERE } public class Reflection { // Where does the values method come from? // Take a look at the reflection mechanism public static Set<String> analyze(Class<?> enumClass) { print("----- Analyzing " + enumClass + " -----"); print("Interfaces:"); for(Type t : enumClass.getGenericInterfaces()) print(t); print("Base: " + enumClass.getSuperclass()); print("Methods: "); Set<String> methods = new TreeSet<String>(); for(Method m : enumClass.getMethods()) methods.add(m.getName()); print(methods); return methods; } public static void main(String[] args) { Set<String> exploreMethods = analyze(Explore.class); Set<String> enumMethods = analyze(Enum.class); print("Explore.containsAll(Enum)? " + exploreMethods.containsAll(enumMethods)); printnb("Explore.removeAll(Enum): "); exploreMethods.removeAll(enumMethods); print(exploreMethods); // Decompile the code for the enum: // OSExecute.command("javap Explore"); } }
Implementation, non inheritance
enum can implement one or more interfaces
public enum CartoonCharacter implements Generator<CartoonCharacter> { SLAPPY, SPANKY, PUNCHY, SILLY, BOUNCY, NUTTY, BOB; private Random rand = new Random(47); public CartoonCharacter next() { return values()[rand.nextInt(values().length)]; } } //public class EnumImplementation { // // public static <T> void printNext(Generator<T> rg) { // System.out.print(rg.next() + ", "); // } // public static void main(String[] args) { //// Choose any instance: // CartoonCharacter cc = CartoonCharacter.BOB; // for(int i = 0; i < 10; i++) // printNext(cc); // } // // //}
Random selection
Using generic
public class Enums { // Random selection // < T extends enum < T > > indicates that t is an Enum instance // Class < T > as a parameter, we can use the class object to get the array of enum instances private static Random rand = new Random(47); public static <T extends Enum<T>> T random(Class<T> ec) { return random(ec.getEnumConstants()); } public static <T> T random(T[] values) { return values[rand.nextInt(values.length)]; } }
Example of random() method:
public enum Activity { SITTING, LYING, STANDING, HOPPING, RUNNING, DODGING, JUMPING, FALLING, FLYING } public class RandomTest { public static void main(String[] args) { for(int i = 0; i < 20; i++) System.out.print(Enums.random(Activity.class) + " " + "\n"); } }
Using interfaces to organize enumerations
Within an interface, create an enumeration that implements the interface
public interface Food { // An enumeration that implements the interface is created inside the interface to group elements // Suppose you want to use enum to represent different things, and you want each enum element to remain food type enum Appetizer implements Food { SALAD, SOUP, SPRING_ROLLS; } enum MainCourse implements Food { LASAGNE, BURRITO, PAD_THAI, LENTILS, HUMMOUS, VINDALOO; } enum Dessert implements Food { TIRAMISU, GELATO, BLACK_FOREST_CAKE, FRUIT, CREME_CARAMEL; } enum Coffee implements Food { BLACK_COFFEE, DECAF_COFFEE, ESPRESSO, LATTE, CAPPUCCINO, TEA, HERB_TEA; } // For eunum, implementing interfaces is the only way to subclass it // So every enum embedded in food implements the food interface public class TypeFod { public static void main(String[] args) { Food food = Food.Appetizer.SALAD; food = Food.MainCourse.LASAGNE; food = Food.Dessert.GELATO; food = Food.Coffee.CAPPUCCINO; } } }
Enumeration in enumeration:
public enum Course { // Create an enumeration of enumerations APPETIZER(Food.Appetizer.class), MAINCOURSE(Food.MainCourse.class), DESSERT(Food.Dessert.class), COFFEE(Food.Coffee.class); private Food[] values; private Course(Class<? extends Food> kind) { values = kind.getEnumConstants(); } public Food randomSelection() { return Enums.random(values); } // Each instance of Course takes its corresponding Class object as the constructor's parameter // Get enumconstants to get all enum instances of a Food subclass // } public class Meal { // Randomly select a food from each Course instance to generate a menu public static void main(String[] args) { for (int i = 0; i < 5; i++) { for (Course course : Course.values()) { Food food = course.randomSelection(); System.out.println(food); } System.out.println("-------------"); } } }
Enum is nested in an enum:
public enum SecurityCategory { // A more efficient and concise way to manage enumeration // Nesting one enum in another STOCK(Security.Stock.class), BOND(Security.Bond.class); Security[] values; SecurityCategory(Class<? extends Security> kind) { values = kind.getEnumConstants(); } // The Security interface is to combine the enum s it contains into a common type interface Security { enum Stock implements Security { SHORT, LONG, MARGIN } enum Bond implements Security { MUNICIPAL, JUNK } } public Security randomSelection() { return Enums.random(values); } public static void main(String[] args) { for(int i = 0; i < 10; i++) { SecurityCategory category = Enums.random(SecurityCategory.class); System.out.println(category + ": " + category.randomSelection()); } } }
Use EnumSet instead of flag
public enum AlarmPoints { // The element of enumset must come from an enum // The following enum is in a building // Location of alarm sensor STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3, OFFICE4, BATHROOM, UTILITY, KITCHEN } public class EnumSets { // Use EnumSets to track the status of alarms public static void main(String[] args) { EnumSet<AlarmPoints> points = EnumSet.noneOf(AlarmPoints.class); // Empty set points.add(BATHROOM); print(points); points.addAll(EnumSet.of(STAIR1, STAIR2, KITCHEN)); print(points); points = EnumSet.allOf(AlarmPoints.class); points.removeAll(EnumSet.of(STAIR1, STAIR2, KITCHEN)); print(points); points.removeAll(EnumSet.range(OFFICE1, OFFICE4)); print(points); points = EnumSet.complementOf(points); print(points); } }
enum more than 64 elements? :
public class BigEnumSet { // The basis of EnumSet is long. A long value has 64 bits, and an enum instance only needs one bit to indicate whether it exists // That is to say, EnumSets can be applied to enums with no more than 64 elements under the condition of no more than one long expression ability // So what happens if there are more than 64 elements? enum Big { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75 } public static void main(String[] args) { EnumSet<Big> bigEnumSet = EnumSet.allOf(Big.class); System.out.println(bigEnumSet); } }
Using EnumMap
Command design mode:
public interface Command { void action(); } public class EnumMaps { // EnumMap is a special kind of Map, which requires that the key must come from an enum public static void main(String[] args) { EnumMap<AlarmPoints,Command> em = new EnumMap<AlarmPoints,Command>(AlarmPoints.class); em.put(KITCHEN, new Command() { public void action() { print("Kitchen fire!"); } }); em.put(BATHROOM, new Command() { public void action() { print("Bathroom alert!"); } }); for(Map.Entry<AlarmPoints,Command> e : em.entrySet()) { printnb(e.getKey() + ": "); e.getValue().action(); } try { // If there's no value for a particular key: em.get(UTILITY).action(); } catch(Exception e) { print(e); } } }
Constant related methods
public enum ConstantSpecificMethod { // Java's enum has an interesting feature that allows you to write methods for ENUM instances to give each Enum instance different behaviors // To do this, you need to define one or more abstract methods for enum and then implement the abstract methods for each enum instance DATE_TIME { String getInfo() { return DateFormat.getDateInstance().format(new Date()); } }, CLASSPATH { String getInfo() { return System.getenv("CLASSPATH"); } }, VERSION { String getInfo() { return System.getProperty("java.version"); } }; abstract String getInfo(); public static void main(String[] args) { for(ConstantSpecificMethod csm : values()) System.out.println(csm.getInfo()); } }
But we can't really use enum instances as a type:
public enum LikeClasses { WINKEN { void behavior() { print("Behavior1"); } }, BLINKEN { void behavior() { print("Behavior2"); } }, NOD { void behavior() { print("Behavior3"); } }; abstract void behavior(); } public class NotClasses { // The compiler doesn't allow us to treat an enum instance as a class type // void f1(LikeClasses.WINKEN instance) {} // Nope }
Car wash example:
public class CarWash { // About car washing // Provide a selection menu when washing the car. Each selection corresponds to a different action // You can associate a constant related method to a selection // Use another enumset to save the customer's choice public enum Cycle { UNDERBODY { void action() { print("Spraying the underbody"); } }, WHEELWASH { void action() { print("Washing the wheels"); } }, PREWASH { void action() { print("Loosening the dirt"); } }, BASIC { void action() { print("The basic wash"); } }, HOTWAX { void action() { print("Applying hot wax"); } }, RINSE { void action() { print("Rinsing"); } }, BLOWDRY { void action() { print("Blowing dry"); } }; abstract void action(); } EnumSet<Cycle> cycles = EnumSet.of(Cycle.BASIC, Cycle.RINSE); public void add(Cycle cycle) { cycles.add(cycle); } public void washCar() { for(Cycle c : cycles) c.action(); } public String toString() { return cycles.toString(); } public static void main(String[] args) { CarWash wash = new CarWash(); print(wash); wash.washCar(); // Order of addition is unimportant: wash.add(Cycle.BLOWDRY); wash.add(Cycle.BLOWDRY); // Duplicates ignored wash.add(Cycle.RINSE); wash.add(Cycle.HOTWAX); print(wash); wash.washCar(); } }
Override constant related methods:
public enum OverrideConstantSpecific { // Can I override constant dependent methods? Certainly. NUT, BOLT, WASHER { void f() { print("Overridden method"); } }; void f() { print("default behavior"); } public static void main(String[] args) { for(OverrideConstantSpecific ocs : values()) { printnb(ocs + ": "); ocs.f(); } } }
Responsibility chain using enum
public class Mail { // Design mode of responsibility chain // Programmers solve a problem in different ways and link them together // Taking a post office model as an example, the post office needs to process every mail in a general way as much as possible, and try to process the mail until it is identified as a dead letter // Each key feature of a message can be represented by enum, which means that the program will randomly generate Mail objects // The NO's lower the probability of random selection: enum GeneralDelivery {YES,NO1,NO2,NO3,NO4,NO5} enum Scannability {UNSCANNABLE,YES1,YES2,YES3,YES4} enum Readability {ILLEGIBLE,YES1,YES2,YES3,YES4} enum Address {INCORRECT,OK1,OK2,OK3,OK4,OK5,OK6} enum ReturnAddress {MISSING,OK1,OK2,OK3,OK4,OK5} GeneralDelivery generalDelivery; Scannability scannability; Readability readability; Address address; ReturnAddress returnAddress; static long counter = 0; long id = counter++; public String toString() { return "Mail " + id; } public String details() { return toString() + ", General Delivery: " + generalDelivery + ", Address Scanability: " + scannability + ", Address Readability: " + readability + ", Address Address: " + address + ", Return address: " + returnAddress; } // Generate test Mail: // Responsible for randomly creating mail for testing public static Mail randomMail() { Mail m = new Mail(); m.generalDelivery= Enums.random(GeneralDelivery.class); m.scannability = Enums.random(Scannability.class); m.readability = Enums.random(Readability.class); m.address = Enums.random(Address.class); m.returnAddress = Enums.random(ReturnAddress.class); return m; } public static Iterable<Mail> generator(final int count) { return new Iterable<Mail>() { int n = count; public Iterator<Mail> iterator() { return new Iterator<Mail>() { public boolean hasNext() { return n-- > 0; } public Mail next() { return randomMail(); } public void remove() { // Not implemented throw new UnsupportedOperationException(); } }; } }; } } public class PostOffice { enum MailHandler { GENERAL_DELIVERY { boolean handle(Mail m) { switch(m.generalDelivery) { case YES: print("Using general delivery for " + m); return true; default: return false; } } }, MACHINE_SCAN { boolean handle(Mail m) { switch(m.scannability) { case UNSCANNABLE: return false; default: switch(m.address) { case INCORRECT: return false; default: print("Delivering "+ m + " automatically"); return true; } } } }, VISUAL_INSPECTION { boolean handle(Mail m) { switch(m.readability) { case ILLEGIBLE: return false; default: switch(m.address) { case INCORRECT: return false; default: print("Delivering " + m + " normally"); return true; } } } }, RETURN_TO_SENDER { boolean handle(Mail m) { switch(m.returnAddress) { case MISSING: return false; default: print("Returning " + m + " to sender"); return true; } } }; abstract boolean handle(Mail m); } static void handle(Mail m) { for(MailHandler handler : MailHandler.values()) if(handler.handle(m)) return; print(m + " is a dead letter"); } public static void main(String[] args) { for(Mail mail : Mail.generator(10)) { print(mail.details()); handle(mail); print("*****"); } } }
State machine using enum
public enum Input { NICKEL(5), DIME(10), QUARTER(25), DOLLAR(100), TOOTHPASTE(200), CHIPS(75), SODA(100), SOAP(50), ABORT_TRANSACTION { public int amount() { // Disallow throw new RuntimeException("ABORT.amount()"); } }, STOP { // This must be the last instance. public int amount() { // Disallow throw new RuntimeException("SHUT_DOWN.amount()"); } }; int value; // In cents Input(int value) { this.value = value; } Input() {} int amount() { return value; }; // In cents static Random rand = new Random(47); public static Input randomSelection() { // Don't include STOP: return values()[rand.nextInt(values().length - 1)]; } } public enum Category { MONEY(NICKEL, DIME, QUARTER, DOLLAR), ITEM_SELECTION(TOOTHPASTE, CHIPS, SODA, SOAP), QUIT_TRANSACTION(ABORT_TRANSACTION), SHUT_DOWN(STOP); private Input[] values; Category(Input... types) { values = types; } private static EnumMap<Input,Category> categories = new EnumMap<Input,Category>(Input.class); static { for(Category c : Category.class.getEnumConstants()) for(Input type : c.values) categories.put(type, c); } public static Category categorize(Input input) { return categories.get(input); } } public class VendingMachine { private static State state = State.RESTING; private static int amount = 0; private static Input selection = null; enum StateDuration { TRANSIENT } // Tagging enum enum State { RESTING { void next(Input input) { switch(Category.categorize(input)) { case MONEY: amount += input.amount(); state = ADDING_MONEY; break; case SHUT_DOWN: state = TERMINAL; default: } } }, ADDING_MONEY { void next(Input input) { switch(Category.categorize(input)) { case MONEY: amount += input.amount(); break; case ITEM_SELECTION: selection = input; if(amount < selection.amount()) print("Insufficient money for " + selection); else state = DISPENSING; break; case QUIT_TRANSACTION: state = GIVING_CHANGE; break; case SHUT_DOWN: state = TERMINAL; default: } } }, DISPENSING(StateDuration.TRANSIENT) { void next() { print("here is your " + selection); amount -= selection.amount(); state = GIVING_CHANGE; } }, GIVING_CHANGE(StateDuration.TRANSIENT) { void next() { if(amount > 0) {print("Your change: " + amount); amount = 0; } state = RESTING; } }, TERMINAL { void output() { print("Halted"); } }; private boolean isTransient = false; State() {} State(StateDuration trans) { isTransient = true; } void next(Input input) { throw new RuntimeException("Only call " + "next(Input input) for non-transient states"); } void next() { throw new RuntimeException("Only call next() for " + "StateDuration.TRANSIENT states"); } void output() { print(amount); } } static void run(Generator<Input> gen) { while(state != State.TERMINAL) { state.next(gen.next()); while(state.isTransient) state.next(); state.output(); } } public static void main(String[] args) { Generator<Input> gen = new RandomInputGenerator(); if(args.length == 1) gen = new FileInputGenerator(args[0]); run(gen); } }
Multichannel distribution
"Scissors and stone cloth game"
public enum Outcome { // Result WIN, LOSE, DRAW } public class Paper implements Item{ // Corresponding to the cloth in scissors and stone cloth @Override public Outcome compete(Item item) { return item.eval(this); } // It's a draw @Override public Outcome eval(Paper paper) { return Outcome.DRAW; } // @Override public Outcome eval(Scissors scissors) { return Outcome.WIN; } @Override public Outcome eval(Rock rock) { return Outcome.LOSE; } @Override public String toString() { return "Paper{}"; } } public class Rock implements Item{ // Corresponding to the stone in scissors and stone cloth @Override public Outcome compete(Item item) { return item.eval(this); } @Override public Outcome eval(Paper paper) { return Outcome.WIN; } @Override public Outcome eval(Scissors scissors) { return Outcome.LOSE; } @Override public Outcome eval(Rock rock) { return Outcome.DRAW; } @Override public String toString() { return "Rock{}"; } } public class Scissors implements Item{ // //Corresponding to scissors in stone cloth @Override public Outcome compete(Item item) { return item.eval(this); } @Override public Outcome eval(Paper paper) { return Outcome.LOSE; } @Override public Outcome eval(Scissors scissors) { return Outcome.DRAW; } @Override public Outcome eval(Rock rock) { return Outcome.WIN; } @Override public String toString() { return "Scissors{}"; } } public interface Item { Outcome compete(Item item); Outcome eval(Paper paper); Outcome eval(Scissors scissors); Outcome eval(Rock rock); } public class RoShamBo1 { static final int SIZE = 20; private static Random random = new Random(47); // Random scissors and stone cloth public static Item newItem(){ switch (random.nextInt(3)){ default: case 0: return new Scissors(); case 1: return new Paper(); case 2: return new Rock(); } } public static void match(Item a,Item b){ System.out.println( a + "vs " + b + ": " + a.compete(b) ); } public static void main(String[] args) { // 20 random games for (int i = 0; i < SIZE; i++) { match(newItem(),newItem()); } } }
Using enum distribution
public enum RoShamBo2 implements Competitor<RoShamBo2>{ // Using enum distribution PAPER(DRAW, LOSE, WIN), SCISSORS(WIN, DRAW, LOSE), ROCK(LOSE, WIN, DRAW); private Outcome vPAPER, vSCISSORS, vROCK; RoShamBo2(Outcome paper,Outcome scissors,Outcome rock) { this.vPAPER = paper; this.vSCISSORS = scissors; this.vROCK = rock; } public Outcome compete(RoShamBo2 it) { switch(it) { default: case PAPER: return vPAPER; case SCISSORS: return vSCISSORS; case ROCK: return vROCK; } } public static void main(String[] args) { RoShamBo.play(RoShamBo2.class, 20); } }
Use constant dependent methods
public enum RoShamBo3 implements Competitor<RoShamBo3> { // Use constant dependent methods PAPER { public Outcome compete(RoShamBo3 it) { switch(it) { default: // To placate the compiler case PAPER: return DRAW; case SCISSORS: return LOSE; case ROCK: return WIN; } } }, SCISSORS { public Outcome compete(RoShamBo3 it) { switch(it) { default: case PAPER: return WIN; case SCISSORS: return DRAW; case ROCK: return LOSE; } } }, ROCK { public Outcome compete(RoShamBo3 it) { switch(it) { default: case PAPER: return LOSE; case SCISSORS: return WIN; case ROCK: return DRAW; } } }; public abstract Outcome compete(RoShamBo3 it); public static void main(String[] args) { RoShamBo.play(RoShamBo3.class, 20); } }
Simplify:
public enum RoShamBo4 implements Competitor<RoShamBo4> { ROCK { public Outcome compete(RoShamBo4 opponent) { return compete(SCISSORS, opponent); } }, SCISSORS { public Outcome compete(RoShamBo4 opponent) { return compete(PAPER, opponent); } }, PAPER { public Outcome compete(RoShamBo4 opponent) { return compete(ROCK, opponent); } }; Outcome compete(RoShamBo4 loser, RoShamBo4 opponent) { return ((opponent == this) ? Outcome.DRAW : ((opponent == loser) ? Outcome.WIN : Outcome.LOSE)); } public static void main(String[] args) { RoShamBo.play(RoShamBo4.class, 20); } }
Distribution with EnumMap
public enum RoShamBo5 implements Competitor<RoShamBo5> { // Distribution with EnumMap PAPER, SCISSORS, ROCK; static EnumMap<RoShamBo5, EnumMap<RoShamBo5, Outcome>> table = new EnumMap<RoShamBo5, EnumMap<RoShamBo5,Outcome>>(RoShamBo5.class); static { for(RoShamBo5 it : RoShamBo5.values()) table.put(it, new EnumMap<RoShamBo5,Outcome>(RoShamBo5.class)); initRow(PAPER, DRAW, LOSE, WIN); initRow(SCISSORS, WIN, DRAW, LOSE); initRow(ROCK, LOSE, WIN, DRAW); } static void initRow(RoShamBo5 it, Outcome vPAPER, Outcome vSCISSORS, Outcome vROCK) { EnumMap<RoShamBo5,Outcome> row = RoShamBo5.table.get(it); row.put(RoShamBo5.PAPER, vPAPER); row.put(RoShamBo5.SCISSORS, vSCISSORS); row.put(RoShamBo5.ROCK, vROCK); } public Outcome compete(RoShamBo5 it) { return table.get(this).get(it); } public static void main(String[] args) { RoShamBo.play(RoShamBo5.class, 20); } }
Using a two-dimensional array
public enum RoShamBo6 implements Competitor<RoShamBo6> { // Distribution by array PAPER, SCISSORS, ROCK; private static Outcome[][] table = { { DRAW, LOSE, WIN }, // PAPER { WIN, DRAW, LOSE }, // SCISSORS { LOSE, WIN, DRAW }, // ROCK }; public Outcome compete(RoShamBo6 other) { return table[this.ordinal()][other.ordinal()]; } public static void main(String[] args) { RoShamBo.play(RoShamBo6.class, 20); } }