Ten Apples Puzzle

<< Trivia Game | Applications | How To Convert Your Applet To An Application >>

Node.java

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
/**
 * A Node in the Blocking Game is a circular disc 
 * that can be linked to other Nodes
 * 
 * The Instance fields are:
 * 1. Its color (of type Color)
 * 2. The x,y coords of the Top Left corner
 * 3. The radius
 * 4. If it is selected (of type boolean)
 * 5. An ArrayList of type Node that has the nodes it can be linked to
 * 
 * The constructor should have three fields: the x,y Coords of the the
 * top left corner, and the radius, sets the Color to Color.WHITE and 
 * selected to false.
 * 
 *
 * 
 * @author Chris Thiel
 * @version 19 May 2016
 */
public class Node 
{
	private int x;
	private int y;
	private int radius;
	private Color color;
	private boolean selected, occupied;
	public Node(int x, int y, int radius)
	{
		this(x,y,radius, Color.WHITE);
	}
	public Node(int x, int y, int radius, Color c)
	{
		this.x=x;
		this.y=y;
		this.radius=radius;
		color=c;
		selected = false;
		setOccupied(false);
	}
	/**
	 * Draws itself in the correct color as well as
	 * indicating it is selected.
	 * @param g the Graphics object to draw itself upon
	 */
	public void draw(Graphics g){
		g.setColor(Color.BLACK);
		if (selected)
			g.setColor(Color.RED);

		g.fillOval(x-3, y-3, 2*radius+6, 2*radius+6);
		g.setColor(color);
		g.fillOval(x, y, 2*radius, 2*radius);	
		if (occupied){
			g.setColor(Color.RED);
			int r=20;
			g.fillOval(centerX()-r, centerY()-r, 2*r, 2*r);	
		}
	}
	/**
	 * Using the pythagorean theorem, detects if a coordinate
	 * is within the node's circular area
	 * @param h the horizontal location of the point to test
	 * @param k the vertical location of the point to test
	 * @return true if (h,k) is inside the node
	 */
	public boolean contains(int h, int k)
	{
		return (h-centerX())*(h-centerX())+(centerY()-k)*(centerY()-k) < radius*radius;
	}
	public ArrayList<Node> legalMoves( ArrayList<Link> links){
		ArrayList<Node> result = new ArrayList<Node>();
		for (Link link:links){
			if (link.hasEnd(this))
				if (link.isLegal(this, link.otherEnd(this))){
					result.add(link.otherEnd(this));
				}
		}
		return result;
	}
	/**
	 * Other Accessor methods:
	 */
	public void toggle()	{ selected=!selected;}
	public void deselect(){selected=false;	}
	public void select()	{selected=true;}
	public void setColor(Color color){this.color=color;}
	public int centerX(){return x+radius;}
	public int centerY(){return y+radius;} 
	public boolean isSelected(){return selected;}
	public Color color(){return color;}
	public boolean isOccupied() {
		return occupied;
	}
	public void setOccupied(boolean occupied) {
		this.occupied = occupied;
	}

}

Link.java

import java.awt.Color;
import java.util.ArrayList;

/**
 * 
 * @author Chris Thiel, ofmcap
 * version 18 May 2016
 *
 *  Links are for describing possible connections
 *  between nodes that require one to 
 *  jump over an occupied node as in checkers
 *  or droughts
 */
public class Link {
	private Node[] ends;
	private Node middle;

	public Link(Node end0, Node middle, Node end1){
		ends = new Node[2];
		ends[0]=end0;
		ends[1]=end1;
		this.middle=middle;
	}

	public boolean hasEnd(Node n) {
		return n==ends[0] || n==ends[1];
	}
	public Node otherEnd(Node n){
		if (n==ends[0])
			return ends[1];
		return ends[0];
	}

	public boolean isLegal(Node from, Node to){		
		return from.isOccupied() && !to.isOccupied() && middle.isOccupied();
	}
}

TenApplesPuzzle.java

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * 
 * @author Chris Thiel
 * @version 19 March 2016
 *
 */
public class TenApplesPuzzle extends JPanel implements MouseListener
{
	public static int WIDTH=800,HEIGHT=600, TOP=100, LEFT=55, GAP=80, SIZE=40;
    private Font titleFont, regularFont, giantFont;
    private Node[] nodes;
    private ArrayList<Link> links;
    private String message, message2, message3;
    private Color bgColor; 
    private Color currentPlayer;
    private Node selectedNode;
    /**
	 * The class constructor will initialize the ArrayList<Balloon>
	 * and other object fields (variables), including a Timer
	 * object from the javax.swing.* library.  The timer will
	 * generate an Action Event, so that something happens
	 * in regular intervals without the user typing anything.
	 */
    public TenApplesPuzzle()
    { 	
    	//initialize variables here...
    	this.currentPlayer=null;
    	this.selectedNode=null;
    	titleFont = new Font("SansSerif", Font.BOLD, 24);
    	giantFont = new Font("SansSerif", Font.BOLD, 72);
    	regularFont = new Font("Serif", Font.PLAIN, 18);
    	message="message";
    	message2="message2";
    	message3="message3";

    	bgColor = Color.GREEN;
    	nodes=new Node[16];
    	links=new ArrayList<Link>();
    	for(int r=0; r<4; r++){
    		for(int c=0; c<4;c++){
    			int x=LEFT+c*(GAP+SIZE);
    			int y=TOP+r*(GAP+SIZE);
    			nodes[r*4+c]=new Node(x,y,SIZE);
    		}
    	}
    	for (int r=0; r< 16; r+=4 ){
    		links.add(new Link(nodes[r], nodes[r+1], nodes[r+2]));
    		links.add(new Link(nodes[r+1], nodes[r+2], nodes[r+3]));    		
    	}

    	for (int c=0; c< 4; c++ ){
    		links.add(new Link(nodes[c], nodes[c+4], nodes[c+8]));
    		links.add(new Link(nodes[c+4], nodes[c+8], nodes[c+12]));    		
    	}

    	reset();




    repaint();

    }
    public void reset(){
    	for (Node n:nodes){
    		n.deselect();
    		n.setColor(Color.WHITE);
    		n.setOccupied(false);
    	}
    	nodes[0].setOccupied(true);
    	nodes[1].setOccupied(true);
    	nodes[2].setOccupied(true);
    	nodes[3].setOccupied(true);
    	nodes[4].setOccupied(true);
    	nodes[7].setOccupied(true);
    	nodes[8].setOccupied(true);
    	nodes[11].setOccupied(true);
    	nodes[12].setOccupied(true);
    	nodes[13].setOccupied(true);
    	nodes[10].setOccupied(true);
    	nodes[15].setOccupied(true);
    }
	/**
	 * the main method makes an instance of our application and puts it in a JFrame 
	 * that will end the application when it is closed.
	 * 
	 */
	public static void main(String[] args) {
		TenApplesPuzzle app= new TenApplesPuzzle();
		JFrame window = new JFrame("Blocking Game");
		window.setSize(WIDTH, HEIGHT);
		window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		window.getContentPane().add(app);
		window.getContentPane().addMouseListener(app);
		window.setVisible(true);

	}

	/**
	 *  This is the method to change what is drawn to the screen:
	 */
	public void paintComponent(Graphics g){
		//super.paintComponent(g);
		if (this.currentPlayer!=null)
			bgColor=new Color(200, 255, 200);
		g.setColor(bgColor);
		g.fillRect(0, 0, getWidth(),getHeight());
		g.setColor(Color.BLUE);
		g.setFont(titleFont);
		g.drawString("Ten Apples Puzzle ver. 1.0", 20, 30);

		g.setColor(Color.RED);
		g.setFont(giantFont);
		//g.drawString("LEVEL ", WIDTH-300, TOP+100);
		g.setColor(Color.BLACK);
		g.setFont(regularFont);
		g.drawString(message, 20, 60);
		g.drawString(message2, WIDTH-400, TOP-80);
		g.drawString(message3, WIDTH-400, TOP-50);

		for (Node n: nodes)
			n.draw(g);

	}


	/**
	 * getLegalMoves will return the Nodes that are white
	 * that are connected to the current player's nodes.
	 * If there is no current player it returns the 
	 * non-white nodes.  If the size of the result is 
	 * zero, there are no legal moves left.
	 * @return
	 */

	/**
	 * New Turn will switch the current player
	 * then check to see if the game is over
	 * that is, the new current player has no move to make
	 */
	public void newTurn()
	{
		String winner="";

		if (currentPlayer.equals(Color.CYAN)){
			currentPlayer=Color.RED;
			winner="Blue";
		}else{
			currentPlayer=Color.CYAN;
			winner="Red";
		}


	}
	/**
	 * These 5 methods need to be declared to implement the MouseListener Interface
	 */

	@Override
	public void mouseClicked(MouseEvent e) {}
	@Override
	public void mousePressed(MouseEvent e) {}
	@Override

	public void mouseReleased(MouseEvent e) {
		int x=e.getX();
		int y=e.getY();
		if (this.selectedNode==null)
			checkForNodeSelection(x,y);
		else
			checkForDestination(x,y);
		repaint();
	}
	public void checkForDestination(int x, int y) {
		ArrayList<Node> legal = selectedNode.legalMoves(links);
		if (legal.size()<1){
			message="Select an apple to move";
			message2="No moves possible";
			selectedNode=null;
			return;
		}
		Node to = null;
		Node from = selectedNode;
		for(int i=0; i< legal.size(); i++)
		{
			Node n=nodes[i];
			if(n.contains(x, y)){
				to = n;
				selectedNode=null;
				from.deselect();
				from.setOccupied(false);
				to.setOccupied(true);
				message2= selectedNode.legalMoves(links).size()  +" legal moves "; //diag
				message3="node "+i; //diag
				message="Select an apple to move";
			}
		}
		if (to==null){
			message2="Not a legal move";
		}
	}
	public void checkForNodeSelection(int x, int y) {
		for(int i=0; i< nodes.length; i++)
		{
			Node n=nodes[i];
			if(n.contains(x, y)){
				message2= n.legalMoves(links).size()  +" legal moves "; //diag
				message3="node "+i; //diag
				if(n.legalMoves(links).size()>0){
					selectedNode=n;
					message="Select destination";
					selectedNode.select();
				}else{
					message="No moves possable from there-select another";
				}

			}
		}
	}
	@Override
	public void mouseEntered(MouseEvent e) {}
	@Override
	public void mouseExited(MouseEvent e) {}

}