./exe/sixteen/readme.txt
This is a variant on the fifteen sliding puzzle, but all sixteen squares are presnet. You might ask where is there to slide anything, and that's correct. If we treat the space as a rectangle, there is nowhere for the pieces to go, but if we treat it like the left side is joined to the right side, and top to bottom, like a torus, [https://en.wikipedia.org/wiki/Torus], then we can slide the pieces around which is done with the 

		[ ][i][ ]
		[j][k][l]

keyset. This kind of motion is still not enough to scramble the pices however, and you can see that if you do only these moves, you can always just slide it back to the original position easily. 

To be able to actually scramble it, we need to not only join the sides right-left, top-bottom, but to join them with a "flip" like on a mobius strip [https://en.wikipedia.org/w/index.php?title=Mobius_strip]. So, for example, if we slide the board left in this manner, the left row will portal over to the right side, but come out upside down. If we press up, the top row cycles around and displaces the bottom row from below, also with a flip, coming up backwards. It will be easier to just play around with it and see. The mobius strip type shifts can be done with the 


		[ ][w][ ]
		[a][s][d]

keyset. 

Those are the only controls. Scramble it and then try to put it back together. It's actually really hard and I haven't been able to do it yet myself from a deep scramble. 

TODO: 
-I would like to add touch controls for mobile/ipad
./exe/sixteen/main.html
<!DOCTYPE HTML>

<html>
	<head>
		<meta charset="UTF-8">   
		<link rel="stylesheet" href="style.css">

		<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"
			integrity="sha256-/SIrNqv8h6QGKDuNoLGA4iret+kyesCkHGzVUUV0shc=" 
			crossorigin="anonymous">
		</script>

	</head>
	
	<body>
		<canvas id = "puzzle_space"></canvas>
		<script src="sixteens.js"></script>
	</body>
</html>
./exe/sixteen/style.css
body { 	
	background-color: #006699; 
	cursor: crosshair;
}

canvas {
	border:5px solid white;
	padding-left: 0;
	padding-right: 0;
	margin-left: auto;
	margin-right: auto;
	display: block;
	cursor: none;
}
./exe/sixteen/sixteens.js
$(function  ()
{
	// Get the canvas element using the DOM
	var canvas = document.getElementById('puzzle_space');
	var context = canvas.getContext('2d');
	var grid = 	[
				[1 ,2 ,3 ,4 ],
				[5 ,6 ,7 ,8 ],
				[9 ,10,11,12],
				[13,14,15,16]
			];
	const colors = 	["#b13", "#136", "#69b", "#369"];

	//TODO
	//transpose function!
	//array[0].map((_, colIndex) => array.map(row => row[colIndex]));

	//--------------------------------------------------------------------motion functions
	function torus_up()	{let temp = grid.shift(); grid.push(temp);}
	function torus_down()	{let temp = grid.pop(); grid.unshift(temp);}
	function torus_left()	{for (let i = 0; i < 4; i++) 
				{let temp = grid[i].shift(); grid[i].push(temp)}}
	function torus_right()	{for (let i = 0; i < 4; i++) 
				{let temp = grid[i].pop(); grid[i].unshift(temp)}}
	function mobius_up()	{let temp = grid.shift(); grid.push(temp.reverse())}
	function mobius_down()	{let temp = grid.pop(); grid.unshift(temp.reverse());}
	function mobius_left()	{let row = []; for (let i = 0; i < 4; i++)
				{row.unshift(grid[i].shift());}
				for (let j = 0; j < 4; j++){grid[j].push(row[j]);}}
	function mobius_right()	{let row = []; for (let i = 0; i < 4; i++)
				{row.unshift(grid[i].pop());}
				for (let j = 0; j < 4; j++){grid[j].unshift(row[j]);}}
	//------------------------------------------------------------------------------------	
	function grid_to_canvas(){
		var width = canvas.width;
		var fourth = width/4;
		var eighth = fourth/2;
		for (var i = 0; i < 4; i++){
		for (var j = 0; j < 4; j++){
			let x = j * fourth;
			let y = i * fourth;
			let number = grid[i][j];
			let color = colors[Math.floor((number-1) / 4)];
			context.fillStyle = color;
			context.fillRect(x, y, fourth, fourth);
			let text = number.toString();
			context.fillStyle = "#fff";
			context.fillText(text ,x + eighth, y + eighth);}}
	}	
	//---------------------------------------key event listener
	const key_function_map = {	
	'i': torus_up,		'k': torus_down,	'j': torus_left,
	'l': torus_right,	'w': mobius_up,		's': mobius_down,
	'a': mobius_left,	'd': mobius_right
	}

	window.addEventListener('keydown', (event) => {
		key_function_map[event.key]();
		grid_to_canvas();
	}, false); //TODO what does this false mean?
	//--------------------------------------resize event listener
	window.addEventListener("resize", draw_canvas);
	function draw_canvas(){
		var context = canvas.getContext('2d');
		let square_side = Math.min(window.innerWidth, window.innerHeight) - 30;
		square_side -= square_side%8; 
		canvas.setAttribute('width', square_side.toString()); 
		canvas.setAttribute('height',square_side.toString());
		canvas.width = canvas.width; canvas.height = canvas.height;
		let font_height_pix = Math.floor(canvas.width/12).toString();
		context.font = font_height_pix + "px Courier New";
		context.textAlign = "center";
		grid_to_canvas();
	}

	//TODO event listeners for touch events!
	
	draw_canvas();

});