SoFunction
Updated on 2025-03-02

JS Lianlian's source code perfect annotation version (recommended)


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JS Lianlian's source code perfect annotation version</title>
</head>
<style>
 table{
  border-collapse: collapse;
 }
 td{
  border: solid #ccc 1px;
  height: 36px;
  width: 36px;
  cursor: pointer;
 }
 td img{
   height: 30px;
   width: 30px;
   border: solid #fff 3px;
   /*
   filter: alpha(opacity=80);
   -moz-opacity: 0.8;
   opacity: 0.8;
   */
 }

</style>
<script>
//The following part is the path search algorithm part and has nothing to do with the presentation layer

//Global variables
var X = 16;//Total number of rows
var Y = 14;//Total number of columns
var types = 15;//Graphic Type

//Layout matrix
//For the sake of algorithm convenience, the first row, first column, last row, and last column of the matrix are marked as 0, which is a natural path.
var arr = new Array(Y);
var tbl;//Display the table element of the layout

var p1 = null;//The coordinates of the first point used for searching the path
var p2 = null;//The coordinates of the second point used for searching the path
var e1 = null;//Element corresponding to the first point
var e2 = null;//Element corresponding to the second point

//Path search, give two points, search for the path
//The path is represented by a connected point
function getPath(p1, p2){
//Sort p1 and p2 before starting the search, so that p2 is as far as possible at the bottom right of p1.
// Doing so can simplify the algorithm
 if(>){
  var t = p1;
  p1 = p2;
  p2 = t; 
 }
 else if(==){
  if(>){
   var t = p1;
   p1 = p2;
   p2 = t; 
  }
 }
// By analyzing the positional relationship between two points, we gradually analyze each type from simple to difficult
//The first type, whether two points are on a straight line, and the two points can be connected in a straight line
 if((onlineY(p1, p2)||onlineX(p1, p2)) && hasLine(p1, p2)){
  status = 'type 1';
  return [p1,p2];
 }
//The second type, if any of the two points is completely surrounded, it will not work.
 if( !isEmpty({x:, y:+1}) && !isEmpty({x:, y:-1}) && !isEmpty({x:-1, y:}) && !isEmpty({x:+1, y:}) ){
  status = 'type 2';
  return null;
 }
 if( !isEmpty({x:, y:+1}) && !isEmpty({x:, y:-1}) && !isEmpty({x:-1, y:}) && !isEmpty({x:+1, y:}) ){
  status = 'type 2';
  return null;
 }
//The third type, two points are on a straight line, but cannot be connected in a straight line.
 var pt0, pt1, pt2, pt3;
//If all are on the x-axis, scan the possible paths from left to right.
//Construct 4 vertices pt0, pt1, pt2, pt3 each time, and then see if they are connected
 if(onlineX(p1, p2)){
  for(var i=0; i<Y; i++){
   if(i==){
    continue;
   }
   pt0 = p1;
   pt1 = {x: , y: i};
   pt2 = {x: , y: i};
   pt3 = p2;
//If the vertex is not empty, the path will not be opened.
   if(!isEmpty(pt1) || !isEmpty(pt2)){
    continue;
   }
   if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
    status = '(x:' + + ',y:' + + ')' + ', (x:' + + ',y:' + + ')' + ', (x:' + + ',y:' + + ')' + ', (x:' + + ',y:' + + ')';
    return [pt0, pt1, pt2, pt3];
   }
  }
 }
//If all are on the y-axis, scan the possible paths from top to bottom.
//Construct 4 vertices pt0, pt1, pt2, pt3 each time, and then see if they are connected
 if(onlineY(p1, p2)){
  for(var j=0; j<X; j++){
   if(j==){
    continue; 
   }
   pt0 = p1;
   pt1 = {x:j, y:};
   pt2 = {x:j, y:};
   pt3 = p2;
//If the vertex is not empty, the path will not be opened.
   if(!isEmpty(pt1) || !isEmpty(pt2)){
    continue;
   }
   if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
    status = '(x:' + + ',y:' + + ')' + ', (x:' + + ',y:' + + ')' + ', (x:' + + ',y:' + + ')' + ', (x:' + + ',y:' + + ')';
    return [pt0, pt1, pt2, pt3];
   }
  }
 }
//The fourth type, two points are not on a straight line.
//Scan the possible path vertically first
//Similarly, construct 4 vertices each time to see if they are accessible
 for(var k=0; k<Y; k++){
   pt0 = p1;
   pt1 = {x:, y:k};
   pt2 = {x:, y:k};
   pt3 = p2;
   status = '(x:' + + ',y:' + + ')' + ', (x:' + + ',y:' + + ')' + ', (x:' + + ',y:' + + ')' + ', (x:' + + ',y:' + + ')';
//Special case, if pt0 and pt1 overlap
   if(equal(pt0,pt1)){
//If pt2 is not empty, this path will not be opened
    if(!isEmpty(pt2)){
     continue;
    }
    if( hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
     return [pt1, pt2, pt3];
    }
    else{
     continue;
    }
   }
//Special case, if pt2 and pt3 overlap
   else if(equal(pt2,pt3)){
//If pt1 is not empty, this path will not be opened
    if(!isEmpty(pt1)){
     continue;
    }
    if( hasLine(pt0, pt1) && hasLine(pt1, pt2) ){
     return [pt0, pt1, pt2];
    }
    else{
     continue;
    }
   }
//If pt1 and pt2 are not empty, it will not work
   if(!isEmpty(pt1) || !isEmpty(pt2)){
    continue;
   }
   if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
    return [pt0, pt1, pt2, pt3];
   }
 }
//Landwise scan of possible paths
 for(var k=0; k<X; k++){
   pt0 = p1;
   pt1 = {x:k, y:};
   pt2 = {x:k, y:};
   pt3 = p2;
   status = '(x:' + + ',y:' + + ')' + ', (x:' + + ',y:' + + ')' + ', (x:' + + ',y:' + + ')' + ', (x:' + + ',y:' + + ')';
   if(equal(pt0,pt1)){
    if(!isEmpty(pt2)){
     continue;
    }
    if( hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
     return [pt1, pt2, pt3];
    }
   }
   if(equal(pt2,pt3)){
    if(!isEmpty(pt1)){
     continue;
    }
    if( hasLine(pt0, pt1) && hasLine(pt1, pt2) ){
     return [pt0, pt1, pt2];
    }
   }
   if(!isEmpty(pt1) || !isEmpty(pt2)){
    continue;
   }
   if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
    return [pt0, pt1, pt2, pt3];
   }
 }
 //status='type4';
 return null;
 /********** end type 4 **************/
}

function equal(p1, p2){
 return ((==)&&(==));
}

function onlineX(p1, p2){
 return ==;
}

function onlineY(p1, p2){
 return ==; 
}

function isEmpty(p){
 return (arr[][]==0); 
}

function hasLine(p1, p2){
 if(==&&==){
  return true; 
 }
 if(onlineY(p1, p2)){
  var i = >?:;
  i = i+1;
  var max = >?:;
  for(; i<max; i++){
   var p = {x: , y: i};
   if(!isEmpty(p)){
    break
   }
  }
  if(i==max){
   return true;
  }
  return false;
 }
 else if(onlineX(p1, p2)){
  var j = >?:;
  j = j+1;
  var max = >?:;
  for(; j<max; j++){
   var p = {x: j, y: };
   if(!isEmpty(p)){
    break
   }
  }
  if(j==max){
   return true;
  }
  return false;
 }
}
//The following parts are the presentation layer parts, including drawing, initialization matrix, and binding mouse events...
function $(id){return (id)}

var t1, t2;//For test
//Picture base path
var IMG_PATH = 'https://';
//initialization
function init(){
//Construct the picture library
 var imgs = new Array(30);
 for(var i=1; i<=30; i++){
  imgs[i] = 'r_' + i + '.gif';
 }
 tbl = $('tbl');
//Construct table
 for(var row=0;row<Y-2;row++){
  var tr=(-1);
  for(var col=0;col<X-2;col++) {
   var td=(-1);
  }
 }
//Construct the matrix
 for(var i=0; i<Y; i++){
  arr[i] = new Array(X);
  for(var j=0; j<X; j++){
   arr[i][j] = 0;
  }
 }
 var total = (X-2)*(Y-2);
var tmp = new Array(total);//For generating random positions
 for(var i=0; i<total; i++){
  tmp[i] = 0;
 }
 for(var i=0; i<total; i++){
  if(tmp[i]==0){
   var t = (()*types) + 1;
   tmp[i] = t;
   while(true){
    var c = (()*(total-i)) + i;
    if(tmp[c]==0){
     tmp[c] = t;
     break;
    }
   }
  }
 }
 var c = 0;
 for(var i=1; i<Y-1; i++){
  for(var j=1; j<X-1; j++){
   arr[i][j] = tmp[c++];
   [i-1].cells[j-1].innerHTML = '<img src="' + IMG_PATH + imgs[arr[i][j]] + '" />';
  } 
 }
//Bind mouse event
  var img1, img2;
  = function(e){
  var el = ?:;
  if(!='TD'){
   return;
  }
  if(!img1){
   img1 = el;
  }
  else{
   img2 = el;
  }
   = 'solid #3399FF 3px';
  el = ;
  if(==''){
   p1 = p2 = e1 = e2 = null;
  }
  var r = +1;
  var c = +1;
  if(p1==null){
   //[0]. = 'solid #ccc 3px';
   p1 = {x:c, y:r};
   e1 = el;
  }
  else{
   p2 = {x:c, y:r};
   e2 = el;
   if(!equal(p1, p2)&&==){
    var path = getPath(p1, p2);
    if(path!=null){
      = = '';
     arr[][] = arr[][] = 0;
    }
   }
   if(t1){ = '';}
   t1 = e1;
   if(t2){ = '';}
   t2 = e2;
    = 'solid #fff 3px';
    = 'solid #fff 3px';
   p1 = p2 = e1 = e2 = img1 = img2 = null;
    = = 'lightpink';
  }
 }
}
</script>
<body onload="init();">
JS Lianlian watch the perfect annotation version<br />
 <table cellspacing="0" cellpadding="0" border="1">
 </table>
</body>
</html>