Source: sketch.js

/*******************************************************************************
*   @file sketch.js
*   @brief Recreation of Towers of Hanoi puzzle
*
*   @author <a href='mailto:omareq08@gmail.com'> Omar Essilfie-Quaye </a>
*   @version 1.0
*   @date 29-Dec-2018
*
*******************************************************************************/

/**
*	A global variable that holds the information for the first Tower object.
*
*	@type {Tower}
*/
let tower1;

/**
*	A global variable that holds the information for the second Tower object.
*
*	@type {Tower}
*/
let tower2;


/**
*	A global variable that holds the information for the third Tower object.
*
*	@type {Tower}
*/
let tower3;

/**
*	A variable that holds which tower was last clicked
*
*	@type {number}
*/
let towerSelected = 0;

/**
*	A variable that dictates how many plates will be in the puzzle
*
*	@type {number}
*/
let plates = 7;

/**
*	A variable that stores the highest value plate of the last clicked tower.
*
*	@type {number}
*/
let topPlate;

/**
*	A variable that dictates if the AI is solving the puzzle or if the user is.
*
*	@type{boolean}
*/
let autoSolve = true;

/**
*	Flag to see if the AI resets and continues to solve the puzzle once it has
*	reached to goal state.
*
*	@type{boolean}
*/
let loopSolve = true;

/**
*
*
*	@type {number}
*/
let solveIndex = 0;

/**
*	An array that stores a list of Pos objects which make up the solution of
*	the puzzle from a given state.
*
*	@type{Array<Pos>}
*/
let solution = [];

/**
*	Function that determines if a mouse has been pressed or not and handles the
*	movement of the plates between the towers.
*/
function mousePressed() {
// TODO omar(omareq08@gmail.com): refactor to use arrays
	if(!autoSolve) {
		let towerPressed = 0;

		if(tower1.pressed()) {
			towerPressed = 1;
			if(towerSelected == 0) {
				topPlate = tower1.peek();
				towerSelected = 1;
				return;
			}
		}
		if(tower2.pressed()) {
			towerPressed = 2;
			if(towerSelected == 0) {
				topPlate = tower2.peek();
				towerSelected = 2;
				return;
			}
		}
		if(tower3.pressed()) {
			towerPressed = 3;
			if(towerSelected == 0) {
				topPlate = tower3.peek();
				towerSelected = 3;
				return;
			}
		}

		if(towerPressed == 0) {
			towerSelected = 0;
			topPlate = 0;
			return;
		}

		if(towerSelected == 1) {
			if(towerPressed == 2 && tower2.push(topPlate)) {
				tower1.pop();
			} else if(towerPressed == 3 && tower3.push(topPlate)) {
				tower1.pop();
			}
		} else if(towerSelected == 2) {
			if(towerPressed == 1 && tower1.push(topPlate)) {
				tower2.pop();
			} else if(towerPressed == 3 && tower3.push(topPlate)) {
				tower2.pop();
			}
		} else if(towerSelected == 3) {
			if(towerPressed == 1 && tower1.push(topPlate)) {
				tower3.pop();
			} else if(towerPressed == 2 && tower2.push(topPlate)) {
				tower3.pop();
			}
		}
		tower1.isPressed = false;
		tower2.isPressed = false;
		tower3.isPressed = false;
		towerSelected = 0;
		topPlate = 0;
	}
}

/**
*   Function to find the solution from the current state of the towers.  If the
*   current state is in a solution that has already been calculated the function
*   will not recalculate the solution.
*/
function solve() {
	let start = currentPos();
	if(solution.length > 0 && contains(solution, start)) {
		solveIndex = find(solution, start);
	} else {
		solution = solveBFS(currentPos());
		solveIndex = 0;
		loopSolve = false;
	}
	tower1.isPressed = false;
	tower2.isPressed = false;
	tower3.isPressed = false;
}


/**
*	Function to handle key presses.  Will toggle autosolve or reset towers.
*/
function keyPressed() {
	if(key.toLowerCase() == "s") {
		autoSolve = !autoSolve;
		if(autoSolve) {
			solve();
		}
	} if(key.toLowerCase() == "r") {
			tower1.setAsFull();
			tower2.empty();
			tower3.empty();
			solve();
			loopSolve = true;
			autoSolve = true;
	} if(key.toLowerCase() == "l") {
		loopSolve = !loopSolve;
	}
}

/**
*	Function to get the current state of the towers.
*
*	@returns {Pos} Pos state of the towers
*/
function currentPos() {
	return new Pos(tower1, tower2, tower3);
}

/**
 * p5.js setup function, used to create a canvas and instantiate the tower
 * objects
 */
function setup() {
	let canvas = createCanvas(0.8*windowWidth, 0.8 * windowHeight);
	canvas.parent('sketch');

	let yPos = 0.75 * height;
	let towerW = 0.25 * width;
	let towerH = 0.5 * height;

	let r = "#ff0000";
	let g = "#00ff00";
	let b = "#0000ff";

	tower1 = new Tower(plates, 0.20 * width, yPos, towerW, towerH, r, true );
	tower2 = new Tower(plates, 0.50 * width, yPos, towerW, towerH, g, false);
	tower3 = new Tower(plates, 0.80 * width, yPos, towerW, towerH, b, false);

	if(autoSolve) {
		solve();
		loopSolve = true;
	}
}

/**
*	p5.js draw function, used to draw all towers
*/
function draw() {
	background(255);
	textSize(0.035 * height);
	textAlign(LEFT, TOP);
	text("Toggle Auto Solve (S), Reset (R) ", 0, 0);

	if(autoSolve && frameCount % 20 == 0) {
		solveIndex++;
		if(solveIndex == solution.length) {
			if(loopSolve) {
				solveIndex = 0;
			} else {
				autoSolve = false;
				solveIndex--;
			}
		}
		tower1.setStack(solution[solveIndex].state[0]);
		tower2.setStack(solution[solveIndex].state[1]);
		tower3.setStack(solution[solveIndex].state[2]);
	}

	tower1.draw("A");
	tower2.draw("B");
	tower3.draw("C");
}

Documentation generated by JSDoc 3.6.3 on Sun Jun 05 2022 20:20:10 GMT+0100 (BST)