#!/bin/bash
map=( {01..15} )
gx=0 gy=0
total_step=0
input(){
  echo -ne "\033[?25l"
  local aKey=(0 0 0 0)
  local cESC=`echo -ne "\033"`
  local index
  while ! check
  do
    read -s -n 1 key
    aKey=( "${aKey[@]:1}" "$key")
    if [[ $key${aKey[2]} == $cESC$cESC ]] ; then break
    elif [ "${aKey[@]:1:2}$key" = "${cESC} [A" -a $gy != 3 ] ; then # up
      (( ++gy ))         
      swap $(( gx + gy*4 )) $(( gx + gy*4 - 4 ))
    elif [ "${aKey[@]:1:2}$key" = "${cESC} [B" -a $gy != 0 ] ; then # down
      (( --gy ))
      swap $(( gx + gy*4 )) $(( gx + gy*4 + 4 ))
    elif [ "${aKey[@]:1:2}$key" = "${cESC} [C" -a $gx != 0 ] ; then # right
      (( --gx ))
      swap $(( gx + gy*4 )) $(( gx + gy*4 + 1 ))
    elif [ "${aKey[@]:1:2}$key" = "${cESC} [D" -a $gx != 3 ] ; then # left
      (( ++gx ))
      swap $(( gx + gy*4 )) $(( gx + gy*4 - 1 ))
    else continue
    fi
    draw
    (( total_step++ ))
  done
  echo -ne "\033[?25h"
}
draw(){
   tput cup 0 0
   printf "%2s %2s %2s %2s\n%2s %2s %2s %2s\n%2s %2s %2s %2s\n%2s %2s %2s %2s\n" "${map[@]}"
}
check(){
  local i j
  for (( i=1,j=2; j<16; i++,j++ ))
  do
     (( 1${map[$i]} > 1${map[$j]} )) && return 1
  done
  return 0
}
swap(){
   local tmp=${map[$1]}
   map[$1]=${map[$2]}
   map[$2]=$tmp
}
random(){
   map=( ' ' $(printf "%s\n" "${map[@]}" | sort -R))
}
clear
random
draw
input
echo finish. Total step is $total_step

