No tengo nada que hacer, así que también escribí un javascript para Lianliankan. Los comentarios son relativamente completos. Los amigos que quieran aprender deberían leerlo.
La parte más difícil de Lian Lian Kan es probablemente la búsqueda de ruta, que consiste en ver si hay una ruta transitable entre los dos puntos en los que se hace clic con el mouse. Vi el método de escritura recursiva de alguien y sentí picazón, así que lo descubrí y descubrí que no es tan difícil sin recursividad.
La búsqueda de ruta se analiza de simple a difícil. Primero analice si una línea recta se puede conectar en línea recta, luego analice si dos puntos en una línea recta se pueden conectar dando dos vueltas y finalmente analice la situación cuando no lo están. en línea recta.
Probado bajo IE6, IE8, Firefox3.0.3.
Copie el código de código de la siguiente manera:
<html>
<cabeza>
<meta http-equiv="Tipo de contenido" content="text/html; charset=utf-8" />
<title>Código fuente JS Lianliankan versión anotada perfecta</title>
</cabeza>
<estilo>
mesa{
colapso fronterizo: colapso;
}
td{
borde: sólido #ccc 1px;
altura: 36px;
ancho: 36px;
cursor: puntero;
}
td img{
altura: 30 píxeles;
ancho: 30px;
borde: sólido #fff 3px;
/*
filtro: alfa(opacidad=80);
-moz-opacidad: 0,8;
opacidad: 0,8;
*/
}
</estilo>
<guión>
//La siguiente parte es la parte del algoritmo de búsqueda de ruta y no tiene nada que ver con la capa de presentación.
//variables globales
var X = 16; //Número total de filas
var Y = 14; //Número total de columnas
var tipos = 15;//Tipos gráficos
//matriz de diseño
// Para comodidad del algoritmo, la primera fila, la primera columna, la última fila y la última columna de la matriz están marcadas como 0, que es una ruta natural.
var arr = nueva matriz (Y);
var tbl;//Muestra el elemento de tabla del diseño
var p1 = null;//Las coordenadas del primer punto utilizado en la ruta de búsqueda
var p2 = null;//Las coordenadas del segundo punto utilizado en la ruta de búsqueda
var e1 = null;//El elemento correspondiente al primer punto
var e2 = null;//El elemento correspondiente al segundo punto
// Búsqueda de ruta, dados dos puntos, busca una ruta
//El camino está representado por puntos conectables
función obtenerRuta(p1, p2){
// Ordena p1 y p2 antes de comenzar la búsqueda para que p2 esté lo más abajo a la derecha posible de p1.
//Esto puede simplificar el algoritmo
si(p1.x>p2.x){
var t = p1;
p1 = p2;
p2 = t;
}
de lo contrario si(p1.x==p2.x){
si(p1.y>p2.y){
var t = p1;
p1 = p2;
p2 = t;
}
}
// Al analizar la relación posicional entre los dos puntos en Lianliankan, analizamos gradualmente cada tipo de simple a difícil.
// El primer tipo, si dos puntos están en línea recta y si los dos puntos se pueden conectar mediante una línea recta
if((en líneaY(p1, p2)||en líneaX(p1, p2)) && hasLine(p1, p2)){
estado = 'tipo 1';
devolver [p1,p2];
}
// El segundo tipo, si alguno de los dos puntos está completamente rodeado, no funcionará.
if( !isEmpty({x:p1.x, y:p1.y+1}) && !isEmpty({x:p1.x, y:p1.y-1}) && !isEmpty({x:p1. x-1, y:p1.y}) && !isEmpty({x:p1.x+1, y:p1.y}) ){
estado = 'tipo 2';
devolver nulo;
}
if( !isEmpty({x:p2.x, y:p2.y+1}) && !isEmpty({x:p2.x, y:p2.y-1}) && !isEmpty({x:p2. x-1, y:p2.y}) && !isEmpty({x:p2.x+1, y:p2.y}) ){
estado = 'tipo 2';
devolver nulo;
}
// El tercer tipo, dos puntos están en línea recta, pero no pueden estar conectados por una línea recta
var pt0, pt1, pt2, pt3;
//Si están todos en el eje x, escanea las posibles rutas de izquierda a derecha,
//Construye 4 vértices pt0, pt1, pt2, pt3 cada vez y luego verifica si están conectados entre sí
if(en líneaX(p1, p2)){
para(var i=0; i<Y; i++){
si(i==p1.y){
continuar;
}
pto0 = p1;
pt1 = {x: p1.x, y: i};
pt2 = {x: p2.x, y: i};
pto3 = p2;
//Si el vértice no está vacío, el camino está bloqueado.
si(!estávacío(pt1) || !estávacío(pt2)){
continuar;
}
if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
estado = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')' ;
devolver [pt0, pt1, pt2, pt3];
}
}
}
//Si están todos en el eje y, escanea las posibles rutas de arriba a abajo,
//Construye 4 vértices pt0, pt1, pt2, pt3 cada vez y luego verifica si están conectados entre sí
si(en líneaY(p1, p2)){
para(var j=0; j<X; j++){
si(j==p1.x){
continuar;
}
pto0 = p1;
pt1 = {x:j, y:p1.y};
pt2 = {x:j, y:p2.y};
pto3 = p2;
//Si el vértice no está vacío, el camino está bloqueado.
si(!estávacío(pt1) || !estávacío(pt2)){
continuar;
}
if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
estado = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')' ;
devolver [pt0, pt1, pt2, pt3];
}
}
}
// El cuarto tipo, los dos puntos no están en línea recta.
//Escanea las posibles rutas verticalmente primero
// De manera similar, construye 4 vértices cada vez para ver si es transitable
for(var k=0; k<Y; k++){
pto0 = p1;
pt1 = {x:p1.x, y:k};
pt2 = {x:p2.x, y:k};
pto3 = p2;
estado = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')' ;
//Caso especial, si pt0 y pt1 coinciden
si(igual(pt0,pt1)){
//Si pt2 no está vacío, esta ruta está bloqueada
si (! está vacío (pt2)) {
continuar;
}
if( hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
devolver [pt1, pt2, pt3];
}
demás{
continuar;
}
}
//Caso especial, si pt2 y pt3 se superponen
de lo contrario si (igual (pt2, pt3)) {
//Si pt1 no está vacío, esta ruta está bloqueada
si (! está vacío (pt1)) {
continuar;
}
if( hasLine(pt0, pt1) && hasLine(pt1, pt2) ){
devolver [pt0, pt1, pt2];
}
demás{
continuar;
}
}
//Si ni pt1 ni pt2 están vacíos, no funcionará.
si(!estávacío(pt1) || !estávacío(pt2)){
continuar;
}
if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
devolver [pt0, pt1, pt2, pt3];
}
}
//Escanea posibles rutas horizontalmente
para(var k=0; k<X; k++){
pto0 = p1;
pt1 = {x:k, y:p1.y};
pt2 = {x:k, y:p2.y};
pto3 = p2;
estado = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')' ;
si(igual(pt0,pt1)){
si (! está vacío (pt2)) {
continuar;
}
if( hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
devolver [pt1, pt2, pt3];
}
}
si(igual(pt2,pt3)){
si (! está vacío (pt1)) {
continuar;
}
if( hasLine(pt0, pt1) && hasLine(pt1, pt2) ){
devolver [pt0, pt1, pt2];
}
}
si(!estávacío(pt1) || !estávacío(pt2)){
continuar;
}
if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
devolver [pt0, pt1, pt2, pt3];
}
}
//estado='tipo4';
devolver nulo;
/************ tipo final 4 **************/
}
función igual(p1, p2){
retorno ((p1.x==p2.x)&&(p1.y==p2.y));
}
función en líneaX(p1, p2){
devolver p1.y==p2.y;
}
función en líneaY(p1, p2){
devolver p1.x==p2.x;
}
la función está vacía(p){
retorno (arr[py][px]==0);
}
función tieneLínea(p1, p2){
si(p1.x==p2.x&&p1.y==p2.y){
devolver verdadero;
}
si(en líneaY(p1, p2)){
var i = p1.y>p2.y?p2.y:p1.y;
yo = yo+1;
var máx = p1.y>p2.y?p1.y:p2.y;
para(; i<max; i++){
var p = {x: p1.x, y: i};
si (! está vacío (p)) {
romper
}
}
si(i==máximo){
devolver verdadero;
}
devolver falso;
}
else if(en líneaX(p1, p2)){
var j = p1.x>p2.x?p2.x:p1.x;
j = j+1;
var máx = p1.x>p2.x?p1.x:p2.x;
para(; j<max; j++){
var p = {x: j, y: p1.y};
si (! está vacío (p)) {
romper
}
}
si(j==máximo){
devolver verdadero;
}
devolver falso;
}
}
// La siguiente parte es la parte de la capa de presentación, que incluye dibujo, inicialización de matriz, vinculación de eventos del mouse...
función $(id){return document.getElementById(id)}
var t1, t2;//para probar
//Ruta base de la imagen
var IMG_PATH = '//www.VeVB.COm';
//inicialización
función inicio(){
//Construir biblioteca de imágenes
var imgs = nueva matriz (30);
para(var i=1; i<=30; i++){
imgs[i] = 'r_' + i + '.gif';
}
tbl = $('tbl');
//Construir tabla
for(var fila=0;fila<Y-2;fila++){
var tr=tbl.insertRow(-1);
para(var col=0;col<X-2;col++) {
var td=tr.insertCell(-1);
}
}
//Construir matriz
para(var i=0; i<Y; i++){
arr[i] = nueva matriz(X);
para(var j=0; j<X; j++){
arreglo[i][j] = 0;
}
}
var total = (X-2)*(Y-2);
var tmp = new Array(total);//Se utiliza para generar posiciones aleatorias
para(var i=0; i<total; i++){
tmp[yo] = 0;
}
para(var i=0; i<total; i++){
si(tmp[i]==0){
var t = Math.floor(Math.random()*tipos) + 1;
tmp[yo] = t;
mientras (verdadero) {
var c = Math.floor(Math.random()*(total-i)) + i;
si(tmp[c]==0){
tmp[c] = t;
romper;
}
}
}
}
var c = 0;
para(var i=1; i<Y-1; i++){
for(var j=1; j<X-1; j++){
arr[i][j] = tmp[c++];
tbl.rows[i-1].cells[j-1].innerHTML = '<img src="' + IMG_PATH + imgs[arr[i][j]] + '" />';
}
}
// Vincular eventos del mouse
var img1, img2;
documento.body.onclick = función(e){
var el = document.all?event.srcElement:e.target;
if(el.parentNode.tagName!='TD'){
devolver;
}
si(!img1){
img1 = el;
}
demás{
img2 = el;
}
el.style.border = 'sólido #3399FF 3px';
el = el.parentNode;
si(el.innerHTML==''){
p1 = p2 = e1 = e2 = nulo;
}
var r = el.parentNode.rowIndex +1;
var c = el.cellIndex +1;
si(p1==nulo){
//el.childNodes[0].style.border = 'sólido #ccc 3px';
p1 = {x:c, y:r};
e1 = el;
}
demás{
p2 = {x:c, y:r};
e2 = el;
if(!equal(p1, p2)&&e1.innerHTML==el.innerHTML){
var ruta = getPath(p1, p2);
si(ruta!=nulo){
e1.innerHTML = e2.innerHTML = '';
arreglo[p1.y][p1.x] = arreglo[p2.y][p2.x] = 0;
}
}
if(t1){t1.estilo.fondoColor = '';}
t1 = e1;
if(t2){t2.estilo.fondoColor = '';}
t2 = e2;
img1.style.border = 'sólido #fff 3px';
img2.style.border = 'sólido #fff 3px';
p1 = p2 = e1 = e2 = img1 = img2 = nulo;
t1.style.backgroundColor = t2.style.backgroundColor = 'rosa claro';
}
}
}
</script>
<cuerpo onload="init();">
js Lianliankan versión anotada perfecta<br />
<table id="tbl" cellspace="0" cellpadding="0">
</tabla>
</cuerpo>
</html>