Мне делать нечего, поэтому я еще написал javascript для Lianliankan. Комментарии относительно полные. Друзья, которые хотят научиться, должны это прочитать.
Самая сложная часть Lian Lian Kan, вероятно, — это поиск пути, который заключается в том, чтобы увидеть, есть ли проходимый путь между двумя точками, на которые щелкает мышь. Я увидел чей-то метод рекурсивного письма, и мне захотелось, поэтому я разобрался и обнаружил, что без рекурсии не так уж и сложно.
Поиск пути анализируется от простого к сложному. Сначала анализируйте, можно ли соединить прямую линию в прямую, затем анализируйте, можно ли соединить две точки на прямой, повернув два поворота, и, наконец, анализируйте ситуацию, когда это не так. по прямой.
Протестировано под IE6, IE8, Firefox3.0.3.
Скопируйте код кода следующим образом:
<html>
<голова>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Исходный код JS Lianliankan идеальная аннотированная версия</title>
</голова>
<стиль>
стол{
граница-коллапс: коллапс;
}
тд {
граница: сплошная #ccc 1px;
высота: 36 пикселей;
ширина: 36 пикселей;
курсор: указатель;
}
тд изображение {
высота: 30 пикселей;
ширина: 30 пикселей;
граница: сплошная #fff 3px;
/*
фильтр: альфа (непрозрачность = 80);
-moz-непрозрачность: 0,8;
непрозрачность: 0,8;
*/
}
</стиль>
<скрипт>
//Следующая часть представляет собой часть алгоритма поиска пути и не имеет ничего общего с уровнем представления
//глобальные переменные
var X = 16 //Общее количество строк
var Y = 14 //Общее количество столбцов
var типы = 15;//Графические типы
//матрица макета
//Для удобства алгоритма первая строка, первый столбец, последняя строка и последний столбец матрицы помечены как 0, что является естественным путем.
вар arr = новый массив (Y);
var tbl;//Отображение табличного элемента макета
var p1 = null;//Координаты первой точки, используемой в пути поиска
var p2 = null;//Координаты второй точки, используемой в пути поиска
var e1 = null;//Элемент, соответствующий первой точке
var e2 = null;//Элемент, соответствующий второй точке
//Поиск пути по двум точкам, ищем путь
//Путь представлен соединяемыми точками
функция getPath(p1, p2){
//Сортируем p1 и p2 перед началом поиска так, чтобы p2 находился как можно дальше в правом нижнем углу от p1.
//Это может упростить алгоритм
если(p1.x>p2.x){
вар т = р1;
р1 = р2;
р2 = т;
}
иначе, если(p1.x==p2.x){
если(p1.y>p2.y){
вар т = р1;
р1 = р2;
р2 = т;
}
}
//Анализируя позиционные взаимоотношения между двумя точками в Ляньлянькане, мы постепенно анализируем каждый тип от простого к сложному.
//Первый тип: находятся ли две точки на прямой линии и можно ли соединить две точки прямой линией
if((onlineY(p1, p2)||onlineX(p1, p2)) && hasLine(p1, p2)){
статус = 'тип 1';
вернуть [p1,p2];
}
//Второй тип, если какая-либо из двух точек полностью окружена, работать не будет.
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}) ){
статус = 'тип 2';
вернуть ноль;
}
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}) ){
статус = 'тип 2';
вернуть ноль;
}
//Третий тип, две точки находятся на прямой, но не могут быть соединены прямой линией
вар пт0, пт1, пт2, пт3;
//Если все они находятся на оси X, сканируем возможные пути слева направо,
//Каждый раз строим 4 вершины pt0, pt1, pt2, pt3, а затем проверяем, связаны ли они между собой
если(онлайнX(p1, p2)){
for(var i=0; i<Y; i++){
если (я == p1.y) {
продолжать;
}
пт0 = р1;
pt1 = {x: p1.x, y: i};
pt2 = {x: p2.x, y: i};
пт3 = р2;
//Если вершина не пуста, дорога заблокирована.
if(!isEmpty(pt1) || !isEmpty(pt2)){
продолжать;
}
if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
status = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')' ;
вернуть [pt0, pt1, pt2, pt3];
}
}
}
//Если они все находятся на оси Y, сканируем возможные пути сверху вниз,
//Каждый раз строим 4 вершины pt0, pt1, pt2, pt3, а затем проверяем, связаны ли они между собой
если(онлайнY(p1, p2)){
for(var j=0; j<X; j++){
если(j==p1.x){
продолжать;
}
пт0 = р1;
pt1 = {x:j, y:p1.y};
pt2 = {x:j, y:p2.y};
пт3 = р2;
//Если вершина не пуста, дорога заблокирована.
if(!isEmpty(pt1) || !isEmpty(pt2)){
продолжать;
}
if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
status = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')' ;
вернуть [pt0, pt1, pt2, pt3];
}
}
}
//Четвертый тип: две точки не лежат на прямой линии.
//Сначала сканируем возможные пути вертикально
//Аналогично каждый раз строим 4 вершины, чтобы проверить, проходимость ли она
for(var k=0; k<Y; k++){
пт0 = р1;
pt1 = {x:p1.x, y:k};
pt2 = {x:p2.x, y:k};
пт3 = р2;
status = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')' ;
//Особый случай, если pt0 и pt1 совпадают
если (равно (pt0, pt1)) {
//Если pt2 не пуст, этот путь заблокирован
если(!isEmpty(pt2)){
продолжать;
}
if( hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
вернуть [пт1, пт2, пт3];
}
еще{
продолжать;
}
}
//Особый случай, если pt2 и pt3 перекрываются
иначе если(равно(pt2,pt3)){
//Если pt1 не пуст, этот путь заблокирован
если(!isEmpty(pt1)){
продолжать;
}
if( hasLine(pt0, pt1) && hasLine(pt1, pt2) ){
вернуть [pt0, pt1, pt2];
}
еще{
продолжать;
}
}
//Если ни pt1, ни pt2 не пусты, это не сработает.
if(!isEmpty(pt1) || !isEmpty(pt2)){
продолжать;
}
if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
вернуть [pt0, pt1, pt2, pt3];
}
}
//Сканируем возможные пути по горизонтали
for(var k=0; k<X; k++){
пт0 = р1;
pt1 = {x:k, y:p1.y};
pt2 = {x:k, y:p2.y};
пт3 = р2;
status = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')' ;
если (равно (pt0, pt1)) {
если(!isEmpty(pt2)){
продолжать;
}
if( hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
вернуть [пт1, пт2, пт3];
}
}
если (равно (pt2, pt3)) {
если(!isEmpty(pt1)){
продолжать;
}
if( hasLine(pt0, pt1) && hasLine(pt1, pt2) ){
вернуть [pt0, pt1, pt2];
}
}
if(!isEmpty(pt1) || !isEmpty(pt2)){
продолжать;
}
if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){
вернуть [pt0, pt1, pt2, pt3];
}
}
//статус='тип4';
вернуть ноль;
/************ тип окончания 4 **************/
}
функция равна(p1, p2){
return ((p1.x==p2.x)&&(p1.y==p2.y));
}
функция онлайнX(p1, p2){
вернуть p1.y==p2.y;
}
функция онлайнY(p1, p2){
вернуть p1.x==p2.x;
}
функция isEmpty(p){
возврат (arr[py][px]==0);
}
функция hasLine(p1, p2){
если(p1.x==p2.x&&p1.y==p2.y){
вернуть истину;
}
если(онлайнY(p1, p2)){
вар я = p1.y>p2.y?p2.y:p1.y;
я = я+1;
вар макс = p1.y>p2.y?p1.y:p2.y;
for(; я<max; я++){
вар p = {x: p1.x, y: i};
если(!isEmpty(p)){
перерыв
}
}
если (я == макс) {
вернуть истину;
}
вернуть ложь;
}
иначе, если(онлайнX(p1, p2)){
вар j = p1.x>p2.x?p2.x:p1.x;
j = j+1;
вар Макс = p1.x>p2.x?p1.x:p2.x;
for(; j<max; j++){
вар p = {x: j, y: p1.y};
если(!isEmpty(p)){
перерыв
}
}
если (j==макс){
вернуть истину;
}
вернуть ложь;
}
}
//Следующая часть — это часть уровня представления, включая рисование, инициализацию матрицы, привязку событий мыши...
функция $(id){return document.getElementById(id)}
var t1, t2;//для тестирования
//Базовый путь к изображению
вар IMG_PATH = '//www.VeVB.COM';
//инициализация
функция инициализации(){
//Создаем библиотеку изображений
вар imgs = новый массив (30);
for(var i=1; i<=30; я++){
imgs[i] = 'r_' + я + '.gif';
}
таблица = $('таблица');
//Создаем таблицу
for(var row=0;row<Y-2;row++){
вар tr=tbl.insertRow(-1);
for(var col=0;col<X-2;col++) {
вар td=tr.insertCell(-1);
}
}
//Создаем матрицу
for(var i=0; i<Y; i++){
arr[i] = новый массив (X);
for(var j=0; j<X; j++){
arr[i][j] = 0;
}
}
вар всего = (X-2)*(Y-2);
var tmp = new Array(total);//Используется для генерации случайных позиций
for(var i=0; i<total; i++){
тмп[я] = 0;
}
for(var i=0; i<total; i++){
если(tmp[i]==0){
var t = Math.floor(Math.random()*types) + 1;
тмп[я] = т;
в то время как (правда) {
var c = Math.floor(Math.random()*(total-i)) + i;
если(tmp[c]==0){
тмп[с] = т;
перерыв;
}
}
}
}
вар с = 0;
for(var i=1; i<Y-1; я++){
for(var j=1; j<X-1; j++){
arr[i][j] = tmp[С++];
tbl.rows[i-1].cells[j-1].innerHTML = '<img src="' + IMG_PATH + imgs[arr[i][j]] + '" />';
}
}
//Привязываем события мыши
вар img1, img2;
document.body.onclick = функция (e) {
var el = document.all?event.srcElement:e.target;
if(el.parentNode.tagName!='TD'){
возвращаться;
}
если(!img1){
img1 = эл;
}
еще{
img2 = эл;
}
el.style.border = 'сплошной #3399FF 3 пикселя';
эль = el.parentNode;
если(el.innerHTML==''){
p1 = p2 = e1 = e2 = ноль;
}
вар r = el.parentNode.rowIndex +1;
вар c = el.cellIndex +1;
если (p1 == ноль) {
//el.childNodes[0].style.border = 'solid #ccc 3px';
p1 = {x:c, y:r};
е1 = эл;
}
еще{
p2 = {x:c, y:r};
е2 = эл;
if(!equal(p1, p2)&&e1.innerHTML==el.innerHTML){
вар путь = getPath (p1, p2);
если (путь! = ноль) {
e1.innerHTML = e2.innerHTML = '';
arr[p1.y][p1.x] = arr[p2.y][p2.x] = 0;
}
}
if(t1){t1.style.backgroundColor = '';}
т1 = е1;
if(t2){t2.style.backgroundColor = '';}
т2 = е2;
img1.style.border = 'сплошной #fff 3px';
img2.style.border = 'сплошной #fff 3px';
p1 = p2 = e1 = e2 = img1 = img2 = ноль;
t1.style.backgroundColor = t2.style.backgroundColor = 'светло-розовый';
}
}
}
</скрипт>
<body onload="init();">
js Lianliankan идеальная аннотированная версия<br />
<table id="tbl" cellpacing="0" cellpadding="0">
</таблица>
</тело>
</html>