Je n'ai rien à faire, j'ai donc aussi écrit un javascript pour Lianliankan. Les commentaires sont relativement complets. Les amis qui veulent apprendre devraient le lire.
La partie la plus difficile de Lian Lian Kan est probablement la recherche de chemin, qui consiste à voir s'il existe un chemin praticable entre les deux points cliqués par la souris. J'ai vu la méthode d'écriture récursive de quelqu'un et j'ai ressenti des démangeaisons, alors j'ai compris et j'ai découvert que ce n'était pas si difficile sans récursion.
La recherche de chemin est analysée du simple au difficile. Analysez d'abord si une ligne droite peut être connectée en ligne droite, puis analysez si deux points sur une ligne droite peuvent être connectés en tournant deux tours, et enfin analysez la situation lorsqu'ils ne le sont pas. sur une ligne droite.
Testé sous IE6, IE8, Firefox3.0.3.
Copiez le code comme suit :
<html>
<tête>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Code source JS Lianliankan version annotée parfaite</title>
</tête>
<style>
tableau{
border-collapse : effondrement ;
}
td{
bordure : solide #ccc 1px ;
hauteur : 36px ;
largeur : 36 px ;
curseur : pointeur ;
}
td img{
hauteur : 30px ;
largeur : 30 px ;
bordure : solide #fff 3px ;
/*
filtre : alpha (opacité = 80) ;
-moz-opacité : 0,8 ;
opacité : 0,8 ;
*/
}
</style>
<script>
//La partie suivante est la partie algorithme de recherche de chemin et n'a rien à voir avec la couche de présentation
//variables globales
var X = 16; //Nombre total de lignes
var Y = 14; //Nombre total de colonnes
var types = 15;//Types graphiques
//matrice de mise en page
//Pour la commodité de l'algorithme, la première ligne, la première colonne, la dernière ligne et la dernière colonne de la matrice sont toutes marquées par 0, ce qui est un chemin naturel.
var arr = nouveau tableau (Y);
var tbl;//Afficher l'élément table de la mise en page
var p1 = null;//Les coordonnées du premier point utilisé dans le chemin de recherche
var p2 = null;//Les coordonnées du deuxième point utilisé dans le chemin de recherche
var e1 = null;//L'élément correspondant au premier point
var e2 = null;//L'élément correspondant au deuxième point
// Recherche de chemin, étant donné deux points, recherche un chemin
//Le chemin est représenté par des points connectables
fonction getPath(p1, p2){
//Trier p1 et p2 avant de lancer la recherche afin que p2 soit le plus en bas à droite possible de p1.
//Cela peut simplifier l'algorithme
si(p1.x>p2.x){
var t = p1 ;
p1 = p2 ;
p2 = t;
}
sinon si(p1.x==p2.x){
si(p1.y>p2.y){
var t = p1 ;
p1 = p2 ;
p2 = t;
}
}
//En analysant la relation de position entre les deux points de Lianliankan, nous analysons progressivement chaque type du simple au difficile.
//Le premier type, si deux points sont sur une ligne droite et si les deux points peuvent être connectés par une ligne droite
if((onlineY(p1, p2)||onlineX(p1, p2)) && hasLine(p1, p2)){
statut = 'type 1' ;
retourner [p1,p2] ;
}
//Le deuxième type, si l'un des deux points est complètement entouré, cela ne fonctionnera pas.
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}) ){
statut = 'type 2' ;
renvoie null ;
}
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}) ){
statut = 'type 2' ;
renvoie null ;
}
//Le troisième type, deux points sont sur une ligne droite, mais ne peuvent pas être reliés par une ligne droite
varpt0, pt1, pt2, pt3 ;
//S'ils sont tous sur l'axe des x, scannez les chemins possibles de gauche à droite,
//Construisez 4 sommets pt0, pt1, pt2, pt3 à chaque fois, puis vérifiez s'ils sont connectés entre eux
si(en ligneX(p1, p2)){
pour(var i=0; i<Y; i++){
si(i==p1.y){
continuer;
}
pt0 = p1 ;
pt1 = {x : p1.x, y : je} ;
pt2 = {x : p2.x, y : je} ;
pt3 = p2 ;
//Si le sommet n'est pas vide, la route est bloquée.
si(!isEmpty(pt1) || !isEmpty(pt2)){
continuer;
}
si( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
statut = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')' ;
retourner [pt0, pt1, pt2, pt3] ;
}
}
}
//S'ils sont tous sur l'axe y, scannez les chemins possibles de haut en bas,
//Construisez 4 sommets pt0, pt1, pt2, pt3 à chaque fois, puis vérifiez s'ils sont connectés entre eux
si(en ligneY(p1, p2)){
pour(var j=0; j<X; j++){
si(j==p1.x){
continuer;
}
pt0 = p1 ;
pt1 = {x:j, y:p1.y} ;
pt2 = {x:j, y:p2.y} ;
pt3 = p2 ;
//Si le sommet n'est pas vide, la route est bloquée.
si(!isEmpty(pt1) || !isEmpty(pt2)){
continuer;
}
si( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
statut = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')' ;
retourner [pt0, pt1, pt2, pt3] ;
}
}
}
//Le quatrième type, les deux points ne sont pas sur une ligne droite.
//Scannez d'abord les chemins possibles verticalement
// De même, construisez 4 sommets à chaque fois pour voir s'il est praticable
pour(var k=0; k<Y; k++){
pt0 = p1 ;
pt1 = {x:p1.x, y:k} ;
pt2 = {x:p2.x, y:k} ;
pt3 = p2 ;
statut = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')' ;
//Cas particulier, si pt0 et pt1 coïncident
si (égal (pt0, pt1)) {
//Si pt2 n'est pas vide, ce chemin est bloqué
si(!isEmpty(pt2)){
continuer;
}
si( hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
retourner [pt1, pt2, pt3] ;
}
autre{
continuer;
}
}
//Cas particulier, si pt2 et pt3 se chevauchent
sinon si(égal(pt2,pt3)){
//Si pt1 n'est pas vide, ce chemin est bloqué
si(!isEmpty(pt1)){
continuer;
}
si( hasLine(pt0, pt1) && hasLine(pt1, pt2) ){
retourner [pt0, pt1, pt2] ;
}
autre{
continuer;
}
}
//Si ni pt1 ni pt2 ne sont vides, cela ne fonctionnera pas.
si(!isEmpty(pt1) || !isEmpty(pt2)){
continuer;
}
si( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
retourner [pt0, pt1, pt2, pt3] ;
}
}
//Scanner les chemins possibles horizontalement
pour(var k=0; k<X; k++){
pt0 = p1 ;
pt1 = {x:k, y:p1.y} ;
pt2 = {x:k, y:p2.y} ;
pt3 = p2 ;
statut = '(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 (égal (pt0, pt1)) {
si(!isEmpty(pt2)){
continuer;
}
si( hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
retourner [pt1, pt2, pt3] ;
}
}
si (égal (pt2, pt3)) {
si(!isEmpty(pt1)){
continuer;
}
si( hasLine(pt0, pt1) && hasLine(pt1, pt2) ){
retourner [pt0, pt1, pt2] ;
}
}
si(!isEmpty(pt1) || !isEmpty(pt2)){
continuer;
}
si( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
retourner [pt0, pt1, pt2, pt3] ;
}
}
//statut='type4';
renvoie null ;
/************ fin type 4 **************/
}
fonction égale(p1, p2){
return ((p1.x==p2.x)&&(p1.y==p2.y));
}
fonction en ligneX(p1, p2){
return p1.y==p2.y;
}
fonction en ligneY(p1, p2){
retourner p1.x==p2.x;
}
la fonction estEmpty(p){
return (arr[py][px]==0);
}
fonction hasLine(p1, p2){
si(p1.x==p2.x&&p1.y==p2.y){
renvoie vrai ;
}
si(en ligneY(p1, p2)){
var je = p1.y>p2.y?p2.y:p1.y;
je = je+1 ;
var max = p1.y>p2.y?p1.y:p2.y;
pour(; i<max; i++){
var p = {x : p1.x, y : je} ;
si(!isEmpty(p)){
casser
}
}
si(i==max){
renvoie vrai ;
}
renvoie faux ;
}
sinon if(onlineX(p1, p2)){
var j = p1.x>p2.x?p2.x:p1.x;
j = j+1 ;
var max = p1.x>p2.x?p1.x:p2.x;
pour(; j<max; j++){
var p = {x : j, y : p1.y} ;
si(!isEmpty(p)){
casser
}
}
si(j==max){
renvoie vrai ;
}
renvoie faux ;
}
}
//La partie suivante est la partie de la couche de présentation, comprenant le dessin, l'initialisation de la matrice, la liaison des événements de souris...
fonction $(id){retour document.getElementById(id)}
var t1, t2 ;//pour tester
//Chemin de base de l'image
var IMG_PATH = '//www.VeVB.COm';
//initialisation
fonction init(){
//Construire une bibliothèque d'images
var imgs = nouveau tableau (30);
pour(var i=1; i<=30; i++){
imgs[i] = 'r_' + i + '.gif';
}
tbl = $('tbl');
//Construire une table
pour(var ligne=0;ligne<Y-2;ligne++){
var tr=tbl.insertRow(-1);
pour(var col=0;col<X-2;col++) {
var td=tr.insertCell(-1);
}
}
//Construire une matrice
pour(var i=0; i<Y; i++){
arr[i] = nouveau tableau(X);
pour(var j=0; j<X; j++){
arr[i][j] = 0;
}
}
var total = (X-2)*(Y-2);
var tmp = new Array(total);//Utilisé pour générer des positions aléatoires
pour(var i=0; i<total; i++){
tmp[i] = 0;
}
pour(var i=0; i<total; i++){
si(tmp[i]==0){
var t = Math.floor(Math.random()*types) + 1;
tmp[je] = t;
tandis que(vrai){
var c = Math.floor(Math.random()*(total-i)) + i;
si(tmp[c]==0){
tmp[c] = t;
casser;
}
}
}
}
var c = 0 ;
pour(var i=1; i<Y-1; i++){
pour(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]] + '" />';
}
}
// Lier les événements de la souris
var img1, img2;
document.body.onclick = fonction(e){
var el = document.all?event.srcElement:e.target;
si(el.parentNode.tagName!='TD'){
retour;
}
si(!img1){
img1 = el;
}
autre{
img2 = el;
}
el.style.border = 'solide #3399FF 3px';
el = el.parentNode;
si(el.innerHTML==''){
p1 = p2 = e1 = e2 = nul ;
}
var r = el.parentNode.rowIndex +1;
var c = el.cellIndex +1;
si(p1==null){
//el.childNodes[0].style.border = 'solid #ccc 3px';
p1 = {x:c, y:r} ;
e1 = el;
}
autre{
p2 = {x:c, y:r} ;
e2 = el;
if(!equal(p1, p2)&&e1.innerHTML==el.innerHTML){
var chemin = getPath(p1, p2);
si(chemin!=null){
e1.innerHTML = e2.innerHTML = '';
arr[p1.y][p1.x] = arr[p2.y][p2.x] = 0;
}
}
si(t1){t1.style.backgroundColor = '';}
t1 = e1 ;
si (t2) {t2.style.backgroundColor = '';}
t2 = e2 ;
img1.style.border = 'solide #fff 3px';
img2.style.border = 'solide #fff 3px';
p1 = p2 = e1 = e2 = img1 = img2 = nul ;
t1.style.backgroundColor = t2.style.backgroundColor = 'rose clair';
}
}
}
</script>
<body onload="init();">
js Lianliankan version annotée parfaite<br />
<table id="tbl" cellpacing="0" cellpadding="0">
</table>
</corps>
</html>