RPSLS Code
See it in action here
SmartGuesser.java
import java.util.ArrayList; import java.util.HashMap; /** * SmartGuess add a little "AI" to guesses of an integer nature * It keeps track of the last 4 guess pattern and * stores a history of the moves made for that pattern * It then returns a move based on the most popular move * made with that pattern. If there is no history for that * pattern, it makes a random choice from 0 to max. * * @author Chris Thiel, OFMCap * @version Nov 26, 2011 * @param choices */ public class SmartGuesser { private HashMap<Integer,String> history; private int currentPattern; private int guessCount; private int maxGuess; private ArrayList<GestureButton> choices; public SmartGuesser(ArrayList<GestureButton> choices){ history=new HashMap<Integer,String>(); currentPattern = 0; guessCount=0; this.choices=choices; this.maxGuess=choices.size()-1; } public void record(int move){ if (guessCount>3){ String value=""; if (history.containsKey(currentPattern) ) value=history.get(currentPattern); history.put(currentPattern, value+move); } guessCount++; currentPattern=(10*currentPattern+move)%100; } public int getGuess(){ if (guessCount>3 && history.containsKey(currentPattern)){ int theirChoice=popularChoice(history.get(currentPattern)); int guess=0; while(choices.get(guess).beats(choices.get(theirChoice))<1){ guess++; } return guess; } return (int)((maxGuess+1)*Math.random()); } public int popularChoice(String h){ int [] count=new int[maxGuess+1]; for (int i=0; i<h.length(); i++) count[Integer.parseInt(h.substring(i, i+1))]++; int max=0; for (int i=0; i<count.length; i++) if (count[i]>count[max]) max=i; return max; } }
CircleButton.java
import java.awt.*; public class CircleButton { // instance variables - replace the example below with your own private Rectangle bounds; private Color color; private String name; private boolean hilight,pressed; private Font font=new Font("SansSerif",Font.BOLD, 14); /** * Constructor for objects of class CircleButton */ public CircleButton(int x, int y, int size, String name, Color color) { this(x,y,size,size,name,color); } public CircleButton(int x, int y, int width, int height, String name, Color color) { bounds = new Rectangle(x,y,width,height); this.color = color; this.name = name; this.hilight=false; this.pressed=false; } public void draw(Graphics g) { if (hilight){ g.setColor(Color.BLACK); g.fillOval(bounds.x-4, bounds.y-4, bounds.width+8, bounds.height+8); } if (pressed) g.setColor(Color.BLACK); else g.setColor(color); g.fillOval(bounds.x, bounds.y, bounds.width, bounds.height); g.setFont(font); if (pressed) g.setColor(Color.WHITE); else g.setColor(Color.BLACK); int x=bounds.x+(bounds.width-name.length()*7)/2; int y=bounds.y+(bounds.height/2+4); g.drawString(name, x, y); } public void setHilight(boolean b){ hilight=b;} public boolean isHilighted() {return hilight;} public void setPressed(boolean b){ pressed=b;} public boolean isPressed() { return pressed; } public boolean contains(int x, int y){ return bounds.contains(x,y); } public String getName() {return name;} public void setName(String s){name=s;} public Color getColor(){return color;} public void setColor(Color c){color=c;} public void setBounds(Rectangle r){bounds=r;} public Rectangle getBounds(){return bounds;} public int getX(){return bounds.x;} public int getY(){return bounds.y;} public int getSize(){return bounds.width;} public void setFont(Font f){font=f;} public Font getFont(){return font;} }
PointingCircleButton.java
import java.awt.*; public class PointingCircleButton extends CircleButton { public PointingCircleButton(int x, int y, int size, String name, Color color){ super(x,y,size,name,color); } public void drawArrowTo(Graphics g, CircleButton other){ g.setColor(getColor() ); if (isPressed() ) g.setColor(Color.BLACK); int x1=getX()+getSize()/2; int y1=getY()+getSize()/2; int r=other.getSize()/2; int x2=other.getX()+r; int y2=other.getY()+r; double theta = Math.atan2(y2-y1,x2-x1); Polygon arrowShaft=new Polygon(); int d=20; double t=.12; arrowShaft.addPoint(x1+(int)(r*Math.cos(theta+t)), y1+(int)(r*Math.sin(theta+t)) ); arrowShaft.addPoint(x1+(int)(r*Math.cos(theta-t)), y1+(int)(r*Math.sin(theta-t)) ); arrowShaft.addPoint(x2-(int)(r*Math.cos(theta)), y2-(int)(r*Math.sin(theta)) ); Polygon arrowHead=new Polygon(); arrowHead.addPoint(x2-(int)((r+d)*Math.cos(theta+t)), y2-(int)((r+d)*Math.sin(theta+t)) ); arrowHead.addPoint(x2-(int)((r+d)*Math.cos(theta-t)), y2-(int)((r+d)*Math.sin(theta-t)) ); arrowHead.addPoint(x2-(int)(r*Math.cos(theta)), y2-(int)(r*Math.sin(theta)) ); g.fillPolygon(arrowShaft); g.fillPolygon(arrowHead); } public void draw(Graphics g){ super.draw(g); } }
Gesture.java
interface Gesture { int beats(Gesture g); String action(Gesture g); }
GestureButton.java
import java.util.ArrayList; import java.awt.*; /** * GestureButton is a generic Gesture, designed to be a super class of * Rock, Paper, Scissors, etc. * * @author Chris Thiel, OFMCap * @version Nov 25, 2011 */ public class GestureButton extends PointingCircleButton implements Gesture { private ArrayList<GestureButton> winsOver, losesTo; private ArrayList<String> winAction, loseAction; public GestureButton(int x, int y, int size, String name, Color color){ super(x,y,size,name,color); winsOver = new ArrayList<GestureButton>(); losesTo =new ArrayList<GestureButton>(); winAction = new ArrayList<String>(); loseAction = new ArrayList<String>(); } public void winsOver(GestureButton other, String winVerb, String loseVerb){ this.winsOver.add(other); this.winAction.add(winVerb); other.losesTo.add(this); other.loseAction.add(loseVerb); } public String toString() { return getName(); } public int beats(Gesture g) { if ( winsOver.indexOf(g) >=0 ) return 1; if ( losesTo.indexOf(g) >=0 ) return -1; return 0; } public String action(Gesture g) { if (this.beats(g)>0){ return winAction.get(winsOver.indexOf(g)); } if (this.beats(g)<0){ return loseAction.get(losesTo.indexOf(g)); } return " ties with "; } public void draw(Graphics g) { for (GestureButton b:winsOver){ drawArrowTo(g,b); } super.draw(g); } }
Ngon.java
import java.awt.Polygon; public class Ngon extends Polygon { public Ngon(int sides, int left, int top, int radius){ this(sides, left, top, radius, 0); } public Ngon(int sides, int left, int top, int radius, double degrees){ double start=degrees*Math.PI/180.0; for(double theta=start; theta<2*Math.PI+start; theta+=2*Math.PI/sides) addPoint((int)(radius*Math.cos(theta)), (int)(radius*Math.sin(theta))); translate(left+radius,top+radius); } public int getX(int i){ return this.xpoints[i]; } public int getY(int i){ return this.ypoints[i]; } }
ResetButton.java
import java.awt.Color; import java.awt.Graphics; public class ResetButton extends CircleButton { private boolean visable; public ResetButton(int x, int y, int width, int height, String name, Color color) { super(x, y, width, height, name, color); visable=true; } public boolean isVisable(){return visable;} public void setVisable(boolean b){ visable=b;} public void draw(Graphics g){ if (visable) super.draw(g); } }
RockPaperScissorsLizardSpock.java
import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; import java.applet.*; import java.util.ArrayList; //import javax.swing.event.*; /** * Class CircleButtons - write a description of the class here * * @author (your name) * @version (a version number) */ public class RockPaperScissorsLizardSpock extends Applet implements MouseListener,MouseMotionListener { private ArrayList<GestureButton> btns; private String message=""; private int human, computer,ties; private boolean gameOver; private ResetButton resetBtn; private SmartGuesser ai; private Image virtualMem; private BufferedImage img; private Graphics gBuffer; public void init() { human=0; computer=0; ties=0; gameOver=false; resetBtn= new ResetButton(195,220,100,75,"Play Again", Color.MAGENTA); resetBtn.setVisable(false); Ngon pattern = new Ngon(5, 20, 30, 175, -90); GestureButton rock = new GestureButton(pattern.getX(0),pattern.getY(0),100,"Rock",Color.CYAN ); GestureButton paper = new GestureButton(pattern.getX(1),pattern.getY(1),100,"Paper", Color.RED ); GestureButton scissors = new GestureButton(pattern.getX(2),pattern.getY(2),100, "Scissors", new Color(210,125,255)); GestureButton lizard = new GestureButton(pattern.getX(3),pattern.getY(3),100,"Lizard", Color.ORANGE ); GestureButton spock = new GestureButton(pattern.getX(4),pattern.getY(4),100, "Spock", Color.GREEN ); rock.winsOver(scissors," crushes ", " crushed by "); paper.winsOver(rock, " covers ", " covered by "); scissors.winsOver(paper, " cuts ", " cut by "); lizard.winsOver(paper, " eats ", " eaten by "); spock.winsOver(rock, " vaporizes ", " vaporized by "); rock.winsOver(lizard," crushes ", " crushed by "); paper.winsOver(spock, " disproves ", " disproved by "); scissors.winsOver(lizard, " decapitates ", " decapitated by "); lizard.winsOver(spock, " poisons ", " poisoned by "); spock.winsOver(scissors, " smashes ", " smashed by "); btns=new ArrayList<GestureButton>(); btns.add(rock); btns.add(paper); btns.add(scissors); btns.add(lizard); btns.add(spock); ai=new SmartGuesser(btns); addMouseListener(this); addMouseMotionListener(this); virtualMem = createImage(getWidth(),getHeight()); gBuffer = virtualMem.getGraphics(); } /** * Paint method for applet. * * @param g the Graphics object for this applet */ public void paint(Graphics g) { // simple text displayed on applet gBuffer.setColor(Color.white); gBuffer.fillRect(0, 0, getWidth(), getHeight()); gBuffer.setColor(Color.black); gBuffer.drawString("Rock Paper Scissors Lizard Spock (with basic AI)", 20, 20); gBuffer.setColor(Color.blue); gBuffer.drawString(message, 150, 470); gBuffer.drawString("You: "+human, 58, 60); gBuffer.drawString("Computer: "+computer, 20, 80); gBuffer.drawString("Ties: "+ties, 55, 100); resetBtn.draw(gBuffer); for(GestureButton gesture:btns){ gesture.draw(gBuffer); } g.drawImage(virtualMem,0,0,this); } public void mouseClicked(MouseEvent e){} public void mousePressed(MouseEvent e){ int x=e.getX(); int y=e.getY(); if(!gameOver) for(CircleButton c:btns) c.setPressed(c.contains(x,y)); resetBtn.setPressed(resetBtn.contains(x, y)); repaint(); } public void mouseReleased(MouseEvent e){ int x=e.getX(); int y=e.getY(); if(!gameOver) for(GestureButton c:btns){ c.setPressed(false); if(c.contains(x,y)) doButton(c); }else{ if(resetBtn.contains(x, y)){ gameOver=false; resetBtn.setVisable(false); if (message.length()>2) message=message.substring(message.indexOf(" "))+" last time"; for(CircleButton c:btns) c.setPressed(false); } } repaint(); } public void mouseEntered(MouseEvent e){} public void mouseExited(MouseEvent e){} public void mouseMoved(MouseEvent e){ int x=e.getX(); int y=e.getY(); if(!gameOver) for(CircleButton c:btns){ c.setHilight(c.contains(x,y)); //c.setPressed(false); } resetBtn.setHilight(resetBtn.contains(x, y)); repaint(); } public void mouseDragged(MouseEvent e){} public void doButton(GestureButton b) { gameOver=true; GestureButton rand=btns.get(ai.getGuess()); ai.record(btns.indexOf(b)); rand.setHilight(true); b.setHilight(true); if (rand.beats(b)==0){ message="Tie! "; ties++; }else if (rand.beats(b)>0){ rand.setPressed(true); b.setPressed(false); message="Sorry, "; computer++; }else if (b.beats(rand)>0){ b.setPressed(true); rand.setPressed(false); message="Yes! "; human++; } resetBtn.setVisable(true); message+=b.getName()+b.action(rand)+rand.getName(); repaint(); } public void update(Graphics g){ paint(g); } }