// 15-Puzzle
   // Written by: Deepak Kumar
   // November 2019
   // Purpose: Program to play the 15-puzzle
   // It displays a 15-puzzle
   // Then the user can shuffle the tiles by pressing the 's' key.
   // Using the arrow keys, the user can move the "blank" tile up, down, left, or right
// This class models a 15-Puzzle board
   class Board {
 // Every board has 16 spaces, it is a 4x4 puzzle
   // One of which is a blank, represented by a 0
   int N = 4;  // NxN board
 // An initial board for testing purposes, no longer used
   int[][] example = {{1, 10, 15, 4}, 
   {13, 6, 3, 8}, 
   {2, 9, 12, 7}, 
   {14, 5, 0, 11}};
 int[][] board;  // The puzzle board
 // key codes of arrow keys, representing moves
   int left = 37;
   int right = 39;
   int up = 38;
   int down = 40; 
   int[] moves = {left, right, up, down};
 PFont font;    // display font
 Board() {  // Constructor, creates a fresh (solved) puzzle
   board = new int[N][N];
 int tile = 0;  // blank tile goes first
   for (int r = 0; r < N; r++) {
   for (int c = 0; c < N; c++) {
   board[r][c] = tile;
   tile++;
   }
   }
 // Also create the font that will be used
   font = loadFont("Arial-BoldMT-48.vlw");
   textFont(font);
   } // Board()
 void shuffle() {  // shuffles the puzzle using the moves() method
   // pick a random number of moves to shuffle
   int nMoves = int(random(20, 50));
   for (int i=0; i < nMoves; i++) {
   // do a random move (pick direction)
   int m = int(random(4));
   this.move(moves[m]);
   }
   this.display();
   } // shuffle()
 void move(int k) {    // Make a move represented by key, k (up, down,left, right
   // This involves moving the blank space up, left, down, or right
   // Find r, j of blank
   int r=0, c=0;
   for (int i=0; i < N; i++) {
   for (int j=0; j < N; j++) {
   if (board[i][j]==0) {
   r = i;
   c = j;
   }
   }
   }
 // Find out which key was pressed and then make the move
   // Does nothing if an incorrect key is pressed, or if there is
   // No move that can be made.
   if (k == up) {
   // Move blank up
   if (r > 0) {
   board[r][c] = board[r-1][c];
   board[r-1][c] = 0;
   }
   } else if (k == down) {
   // move blank down
   if (r < N-1) {
   board[r][c] = board[r+1][c];
   board[r+1][c] = 0;
   }
   } else if (k == left) {
   // move blank left
   if (c > 0) {
   board[r][c] = board[r][c-1];
   board[r][c-1] = 0;
   }
   } else if (k == right) {
   // move blank right
   if (c < N-1) {
   board[r][c] = board[r][c+1];
   board[r][c+1] = 0;
   }
   }
   } // move();
 void printBoard() {
   // prints the board in Console
   for (int i=0; i < N; i++) {
   for (int j=0; j < N; j++) {
   print(board[i][j] + "\t");
   }
   println();
   }
   } // print()
 void display() {
   // Displays the puzzle as it currently stands
 textSize(48);
   textAlign(CENTER);
   int w = height/5;
   int x = (width - N*w)/2;
   int y = (height - N*w)/2;
   pushMatrix();
   translate(x, y);
   for (int i=0; i < N; i++) {
   // Draw row i
   for (int j=0; j < N; j++) {
   // Draw all columns of row i
   noFill();
   rect(j*w, i*w, w, w);
   fill(0);
   text(board[i][j], j*w+w/2, i*w+w/2);
   if (board[i][j] == 0) {
   fill(0);
   rect(j*w, i*w, w, w);
   }
   }
   }
   popMatrix();
   } // display()
   } // class Board