Jump to content

Great Rash

Expert
  • Posts

    7,974
  • Joined

  • Last visited

  • Days Won

    144

Everything posted by Great Rash

  1. За вас скрипт чтоль написать? Ну так это в платные услуги.
  2. У меня все тоже летает... Правда фаербаг ошибку в скрипте нашел (radii is not defined - $(document).ready(radii); )
  3. Моно попробовать передать эту информацию GET'ом, а потом на другой странице распарсить url. Можно записать инфу в куки, а на другой странице прочитать её. (если юзер отключит куки, то ничего не будет работать) Как еще сделать без серверных скриптов не знаю...
  4. Ну так делайте, в чем проблема?
  5. Я вообще не очень хорошо знаю как ведут себя инлайн-блоки, но могу предположить что при задании паддинга смещается базовая линия, которая расположена чуть ниже элемента. Попробуйте убрать текст из спанов и вы, скорее всего, увидите, что все станет в порядке. P.S. Как уже сказал s0rr0w задание vertical-align: top; должно помочь.
  6. d0ublezer0, Погуглите по слову Hyphenator, и не нужно никаких "пасхалок для правильных пацанов"
  7. Чем вас так рассмешило решение, предложенное x-doggy???
  8. Ерунда полная... зайдите на страницу демо и попробуйте поизменять размер окна - все развалится. Это недоселекты - нет полного функционала настоящего селекта (поиск по регулярке, фокус по табу) У меня в Хроме не видно каретки на инпутах... Это я все к тому, что с украшением форм надо быть очень аккуратным. Украшать конечно хорошо и нужно (я не понимаю противников украшательства контролов), но все это делать надо не в ущерб функционалу.
  9. senistra, вообще пока не понятно почему не работает, но у вас изначально неверный подход к переключению табов. Давайте начнем писать вашу переключалку вместе: 1) все контейнеры для текста (tc1, tc2, tc3, ..., tcn) у вас должны лежать в общем контейнере (в принципе у вас это уже сделано - див с class="tabsCont2") 2) в скрипте находите этот контейнер 3) внутри этого контейнера находите всех потомков у которых tagName равен div 4) у вас получится массив со всеми дивами, расположенными в контейнере 5) проходитесь по нему циклом и прячете всё 6) потом показываете нужный При таком подходе вам не обязательно будет знать точное количество контейнеров (tc1, tc2, tc3, ..., tcn) и вы сможете абстрагироваться от определенного номера (i<=12). Начните писать скрипт по пунктам, которые я написал. Что не понятно спрашивайте, мы обязательно поможем. P.S. Если лень писать скрипт как я предложил: В вашем скрипте попробуйте написать цикл вот так (for (var i = 1; i < 12; i++)), есть мнение, что когда вы пишете <=, то скрипт ищет 13-ый элемент, не находит его и выдает ошибку, которую вы не видите по причине того, что не умеете пользоваться отладчиками.
  10. CSS3 типа волшебным образом заработал в недобраузерах?
  11. Возможно проблема и правда в самом браузере, у меня кстати после перезагрузки страницы тормоза пропали.
  12. из-за того, что каждый блок приходится верстать как резину, а верстка резины сама по себе сложнее верстки фикса, поэтому приходится тратить много времени на кроссбраузерность, опять же на продумывание уходит какое-то время - абсолютно все блоки универсальными сделать нельзя, так что надо продумать какие из них где и когда будут использоваться.
  13. Есть подозрение, что все тормоза из-за скрипта DD_roundies.js. Попробуйте его отключить.
  14. klierik, отличные статьи, спасибо! Именно к этому и стремлюсь когда верстаю. Правда сильно время работы увеличивает, поэтому если времени на верстку мало отведено, то этого идеала не удается достичь. Зато потом если менять структуру страницы время экономится в разы! Жаль начальство этого не понимает. Игорь Ермаков Ну я к примеру создаю специальные вспомогательные классы, которые стоят у меня в самом низу .css, они примерно такие: /* Helpers */ .fl {float: left;} .fr {float: right;} .text-center {text-align: center;} .text-right {text-align: right;} .overflow { overflow: hidden; //zoom: 1; /* это правило выношу через кандишнл камментс */ } /* end Helpers */ Это позволяет зафлоатить некоторые блоки если надо, не изменяя общий класс, или порулить расположением текста.
  15. Пример: хватит жеваться, код покажи!
  16. В JavaScript ничем, в других языках (например в PHP) отличаются. Это один из вариантов записи дефолтного значения. В JavaScript при записи значений переменной через || (ИЛИ) переменная примет первое значение равное true. Например: var f = false; var t = true; var x = f || t; alert(x); // true var a = 0; var b = 2; x = a || b; alert(x); // 2 (так как 0 приравнивается к false) Три знака равно это сравнение без приведения типов. Т.е. если я буду сравнивать вот так == программа сначала приведет данные к некоему общему типу, а потом их сравнит, а если написать ===, то приведения типов не будет. Это иногда очень полезно, попробуйте запустить следующий код: alert(0 == false); // выдаст true (т.к. произошло приведение к некоему общему типу данных) alert('' == false); // выдаст true alert('' == 0); // выдаст true alert(0 === false); // выдаст false (т.к. типы данных разные) alert('' === false); // выдаст false alert('' === 0); // выдаст false Кроме того, такая операция сравнения происходит вроде как быстрее (самолично не проверял, но читал где-то).
  17. Скрипт не существует, вот и гонево... http://red.dax.ru/black/Author.js - 404
  18. Задайте фиксированную ширину для ячеек leftoid и righttoid. Естественно что они смещаются, т.к. ширина у них в процентах стоит, а ширина руля всегда одинаковая.
  19. Доктайп стоит strict, а атрибуты у ссылок не закавычены... не верю чтоб валидатор это пропустил... <!-- плохо --> <a href=../index.htm> <!-- хорошо --> <a href="../index.htm">
  20. Ничего вы не сделали http://red.dax.ru/black/index2.html
  21. Для начала не засоряйте глобальную область видимости, определите все переменные внутри функции.
  22. Можно сделать так <img><!-- --><img>
  23. Обрабатываем клик по клетке Итак, у нас уже почти все готово для полноценной игры. Осталось только обработать клик по клетке на доске. Давайте создадим метод который назовем showInfo, внутри данного метода мы будем проверять проиграл ли уже пользователь, что отобразить на клетке и т.п. Метод будет принимать в качестве параметра элемент на котором кликнули: var MyMineSweeper = { init: function(o) { this.W = o ? o.W : 7; this.H = o ? o.H : 7; this.bombs = o ? o.bombs : Math.floor(this.W * this.H / 4); this.placedBombs = this.bombs; this.generateGUI(); }, generateGUI: function() { if (!this.game) { this.game = this.writeMainContainer(); this.gameCont = document.createElement('table'); this.gameCont.className = 'game-cont'; this.gameCont.insertRow(0); this.gameCont.insertRow(1); this.gameMenu = this.gameCont.rows[0].insertCell(0); this.gameMenu.rowSpan = 2; this.gameMenu.className = 'game-menu'; this.gameMenu.appendChild(document.createTextNode('Ширина поля:')); this.gameMenu.appendChild(document.createElement('br')); this.WInput = document.createElement('input'); this.WInput.type = 'text'; this.gameMenu.appendChild(this.WInput); this.gameMenu.appendChild(document.createTextNode('Высота поля:')); this.gameMenu.appendChild(document.createElement('br')); this.HInput = document.createElement('input'); this.HInput.type = 'text'; this.gameMenu.appendChild(this.HInput); this.gameMenu.appendChild(document.createTextNode('Кол-во мин:')); this.gameMenu.appendChild(document.createElement('br')); this.BInput = document.createElement('input'); this.BInput.type = 'text'; this.Init = document.createElement('input'); this.Init.type = 'button'; this.Init.value = 'Старт'; this.Init.className = 'game-start-button'; this.gameMenu.appendChild(this.BInput); this.gameMenu.appendChild(this.Init); this.gameStats = this.gameCont.rows[0].insertCell(1); this.gameField = this.gameCont.rows[1].insertCell(0); this.gameField.className = 'game-field'; this.game.appendChild(this.gameCont); } if (this.board) { this.board.parentNode.removeChild(this.board); this.board = null; } this.board = this.generateField(); this.board.cellSpacing = 0; this.board.className = 'game-board'; this.gameField.appendChild(this.board); this.gameStats.innerHTML = 'Новая игра: поле ' + this.W + 'x' + this.H + ', ' + this.bombs + 'мин'; this.setupEvents(); }, setupEvents: function() { var self = this; var buttonClick = function() { self.init({W: self.WInput.value, H: self.HInput.value, bombs: self.BInput.value}); } Event.add(this.Init, 'click', buttonClick); }, generateField: function() { var self = this; var table = document.createElement('table'); for (var i = 0; i < this.H; i++) { var r = table.insertRow(i); for (var j = 0; j < this.W; j++) { var c = r.insertCell(j); c.num = 0; c.index = [i, j]; c.clickHandler = function() { self.showInfo(this); } Event.add(c, 'click', c.clickHandler); } } do { var hNum = this.rand(0, this.H - 1); var wNum = this.rand(0, this.W - 1); if (!table.rows[hNum].cells[wNum].bomb) { table.rows[hNum].cells[wNum].num = null; table.rows[hNum].cells[wNum].bomb = true; this.placedBombs--; } } while (this.placedBombs > 0); for (var i = 0, len = table.rows.length; i < len; i++) { for (var j = 0, len2 = table.rows[i].cells.length; j < len2; j++) { if (table.rows[i].cells[j].bomb) { this.placeNumbers(table, j, i); } } } return table; }, placeNumbers: function(t, x, y) { if (x > 0) { t.rows[y].cells[x - 1].num++; } if (x < this.W - 1) { t.rows[y].cells[x + 1].num++; } if (x > 0 && y > 0) { t.rows[y - 1].cells[x - 1].num++; } if (y > 0) { t.rows[y - 1].cells[x].num++; } if (y > 0 && x < this.W - 1) { t.rows[y - 1].cells[x + 1].num++; } if (x > 0 && y < this.H - 1) { t.rows[y + 1].cells[x - 1].num++; } if (y < this.H - 1) { t.rows[y + 1].cells[x].num++; } if (x < this.W - 1 && y < this.H - 1) { t.rows[y + 1].cells[x + 1].num++; } }, showInfo: function(elem) { if (!elem.bomb) { this.openCell(elem); } else { this.openCell(elem); this.gameOver(); } }, openCell: function(elem) { if (!elem.bomb) { if (elem.num > 0) { elem.innerHTML = '<b>' + elem.num + '</b>'; } else { elem.innerHTML = ' '; } switch (elem.num) { case 1: elem.style.color = 'blue'; break; case 2: elem.style.color = 'green'; break; case 3: elem.style.color = 'red'; break; case 4: elem.style.color = 'dakrblue'; break; case 5: elem.style.color = 'pink'; break; case 6: elem.style.color = 'navy'; break; case 7: elem.style.color = 'brown'; break; case 8: elem.style.color = 'grey'; break; default: elem.style.color = 'black'; } } else { elem.innerHTML = '<b>M</b>'; } elem.style.background = '#d8e0ec'; }, writeMainContainer: function() { var html = '<div id="game" class="game"></div>'; document.writeln(html); return document.getElementById('game'); }, rand: function(min, max) { min = parseInt(min); max = parseInt(max); return Math.floor(Math.random() * (max - min + 1)) + min; } } Обрабатываем Game Over Теперь подумаем, что должно происходить когда юзер нарвался на мину: 1) нам нужно показать все мины на доске, 2) нам нужно снять все слушатели событий с клеток, чтобы пользователь не мог никуда больше кликнуть пока не начнет новую игру, 3) нам нужно уведомить пользователя о том что он проиграл. Реализуем все в коде: gameOver: function() { // пробегаемся циклом по доске for (var i = 0, len1 = this.board.rows.length; i < len1; i++) { // цикл по вертикали for (var j = 0, len2 = this.board.rows[i].cells.length; j < len2; j++) { // цикл по горизонтали if (this.board.rows[i].cells[j].bomb) { // если на клетке стоит мина // показываем мину this.openCell(this.board.rows[i].cells[j]); } // снимаем обработчик события "click" с каждой клетки Event.remove(this.board.rows[i].cells[j], 'click', this.board.rows[i].cells[j].clickHandler); } } // красим ячейку статистики в красный цвет this.gameStats.style.background = 'red'; // и говорим юзеру, что он подорвался this.gameStats.innerHTML = '<b>БАБАХ!!! GAME OVER!</b>'; } У нас все готово для полноценной игры. Ура! Однако радоваться рано. Если посмотреть на настоящего сапёра, то можно увидет одну особенность - если мы кликнем на клетку рядом с которой нет мин (т.е. номер на ней 0), то откроются все соседние пустые клетки, т.е. все клетки, граничащие с открытой, рядом к которыми тоже нет мин. То есть происходит так называемый каскад. Пожалуй это будет самая сложная функция в нашем сапёре. Итак... Реализуем каскад Вы себе даже не представляете как долго я бился на этим методом. Что я только не делал, где только не гуглил И вот, наконец я допер, что в нелегком деле каскадирования нам поможет рекурсия! Что такое рекурсия? Это когда функция вызывает сама себя. Что обязательно должно быть в рекурсивной функции? Первым делом в рекурсивной функции должен быть продуман выход из нее, чтобы не было бесконечного зацикливания. В принципе это все, что нужно знать о рекурсии, но без примера все равно сложно это понять, поэтому я вам приведу пример простейшей рекурсии: // функция принимает в качестве параметра начальное число и конечное число function myRecursion(num, maxNum) { /* * первым делом продумываем * выход из бесконечной рекурсии */ if (num > maxNum) { // если начальное число больше конечного // выходим из функции return; } // пишем в документ текущую цифру document.write(num + ', '); // увеличиваем число на 1 num++; // вызываем саму себя (рекурсивный вызов) myRecursion(num, maxNum); } myRecursion(0, 5); // выведет 0, 1, 2, 3, 4, 5 Ну вот, теперь вы должны представлять что такое рекурсия и мы можем начать писать наш метод-каскад, назовем его roll, метод будет принимать в качестве параметров координаты клетки на доске: roll: function(x, y) { /* * первым делом продумываем * выход из бесконечной рекурсии */ // если x или y выходят за границы доски if (x < 0 || y < 0 || x >= this.W || y >= this.H) { // выходим return; } // открываем клетку this.openCell(this.board.rows[y].cells[x]); // если рядом с клеткой есть бомба (т.е. номер в ней больше 0) if (this.board.rows[y].cells[x].num > 0) { // вставляем в клетку цифру this.board.rows[y].cells[x].innerHTML = '<b>' + this.board.rows[y].cells[x].num + '</b>'; // выходим return; } // если мы уже эту клетку проверяли if (this.board.rows[y].cells[x].check) { // выходим return; } // отмечаем, что эту ячейку мы уже проверяли this.board.rows[y].cells[x].check = true; // далее пошла рекурсия this.roll(x + 1, y); // делаем шаг вправо this.roll(x - 1, y); // делаем шаг влево this.roll(x, y + 1); // делаем шаг вниз this.roll(x, y - 1); // делаем шаг вверх this.roll(x - 1, y - 1); // делаем шаг вверх влево this.roll(x + 1, y - 1); // делаем шаг вверх вправо this.roll(x - 1, y + 1); // делаем шаг вниз влево this.roll(x + 1, y + 1); // делаем шаг вниз вправо } Вызывать наш каскад будем в методе showInfo, для этого нам его надо будет немного изменить, добавив дополнительные проверки: showInfo: function(elem) { if (!elem.bomb) { // если в клетке нет мины if (elem.num > 0) { // если рядом есть мины (номер больше 0) // открываем клетку this.openCell(elem); } else { // если рядом нет ни одной мины /* * запускаем каскад * тут нам и пригодилось дополнительное * свойство хранимое в клетке (index), * в котором храняться в виде массива * координаты клетки на доске */ this.roll(elem.index[1], elem.index[0]); } } else { // если в клетке мина // открываем клетку this.openCell(elem); // завершаем игру this.gameOver(); } } Вот и все. Теперь у нас готов полноценный сапер. Он конечно не совсем похож на того сапера который присутствует в винде. В нем нельзя отмечать места с предполагаемой миной и нет счетчика времени, зато в нем можно варьировать уровень сложности и размер доски по своему усмотрению, а все недостатки легко доделать. Главное вы теперь знаете устройство такой замечательной логической игры как сапёр! Ах да, вот полный код нашего сапера: var MyMineSweeper = { init: function(o) { this.W = o ? o.W : 7; this.H = o ? o.H : 7; this.bombs = o ? o.bombs : Math.floor(this.W * this.H / 4); this.placedBombs = this.bombs; this.generateGUI(); }, generateGUI: function() { if (!this.game) { this.game = this.writeMainContainer(); this.gameCont = document.createElement('table'); this.gameCont.className = 'game-cont'; this.gameCont.insertRow(0); this.gameCont.insertRow(1); this.gameMenu = this.gameCont.rows[0].insertCell(0); this.gameMenu.rowSpan = 2; this.gameMenu.className = 'game-menu'; this.gameMenu.appendChild(document.createTextNode('Ширина поля:')); this.gameMenu.appendChild(document.createElement('br')); this.WInput = document.createElement('input'); this.WInput.type = 'text'; this.gameMenu.appendChild(this.WInput); this.gameMenu.appendChild(document.createTextNode('Высота поля:')); this.gameMenu.appendChild(document.createElement('br')); this.HInput = document.createElement('input'); this.HInput.type = 'text'; this.gameMenu.appendChild(this.HInput); this.gameMenu.appendChild(document.createTextNode('Кол-во мин:')); this.gameMenu.appendChild(document.createElement('br')); this.BInput = document.createElement('input'); this.BInput.type = 'text'; this.Init = document.createElement('input'); this.Init.type = 'button'; this.Init.value = 'Старт'; this.Init.className = 'game-start-button'; this.gameMenu.appendChild(this.BInput); this.gameMenu.appendChild(this.Init); this.gameStats = this.gameCont.rows[0].insertCell(1); this.gameField = this.gameCont.rows[1].insertCell(0); this.gameField.className = 'game-field'; this.game.appendChild(this.gameCont); } if (this.board) { this.board.parentNode.removeChild(this.board); this.board = null; } this.board = this.generateField(); this.board.cellSpacing = 0; this.board.className = 'game-board'; this.gameField.appendChild(this.board); this.gameStats.innerHTML = 'Новая игра: поле ' + this.W + 'x' + this.H + ', ' + this.bombs + 'мин'; this.WInput.value = this.W; this.HInput.value = this.H; this.BInput.value = this.bombs; this.gameStats.style.background = '#bfd3ed'; this.setupEvents(); }, setupEvents: function() { var self = this; var buttonClick = function() { self.init({W: self.WInput.value, H: self.HInput.value, bombs: self.BInput.value}); } Event.add(this.Init, 'click', buttonClick); }, generateField: function() { var self = this; var table = document.createElement('table'); for (var i = 0; i < this.H; i++) { var r = table.insertRow(i); for (var j = 0; j < this.W; j++) { var c = r.insertCell(j); c.num = 0; c.index = [i, j]; c.clickHandler = function() { self.showInfo(this); } Event.add(c, 'click', c.clickHandler); } } do { var hNum = this.rand(0, this.H - 1); var wNum = this.rand(0, this.W - 1); if (!table.rows[hNum].cells[wNum].bomb) { table.rows[hNum].cells[wNum].num = null; table.rows[hNum].cells[wNum].bomb = true; this.placedBombs--; } } while (this.placedBombs > 0); for (var i = 0, len = table.rows.length; i < len; i++) { for (var j = 0, len2 = table.rows[i].cells.length; j < len2; j++) { if (table.rows[i].cells[j].bomb) { this.placeNumbers(table, j, i); } } } return table; }, placeNumbers: function(t, x, y) { if (x > 0) { t.rows[y].cells[x - 1].num++; } if (x < this.W - 1) { t.rows[y].cells[x + 1].num++; } if (x > 0 && y > 0) { t.rows[y - 1].cells[x - 1].num++; } if (y > 0) { t.rows[y - 1].cells[x].num++; } if (y > 0 && x < this.W - 1) { t.rows[y - 1].cells[x + 1].num++; } if (x > 0 && y < this.H - 1) { t.rows[y + 1].cells[x - 1].num++; } if (y < this.H - 1) { t.rows[y + 1].cells[x].num++; } if (x < this.W - 1 && y < this.H - 1) { t.rows[y + 1].cells[x + 1].num++; } }, showInfo: function(elem) { if (!elem.bomb) { if (elem.num > 0) { this.openCell(elem); } else { this.roll(elem.index[1], elem.index[0]); } } else { this.openCell(elem); this.gameOver(); } }, openCell: function(elem) { if (!elem.bomb) { if (elem.num > 0) { elem.innerHTML = '<b>' + elem.num + '</b>'; } else { elem.innerHTML = ' '; } switch (elem.num) { case 1: elem.style.color = 'blue'; break; case 2: elem.style.color = 'green'; break; case 3: elem.style.color = 'red'; break; case 4: elem.style.color = 'dakrblue'; break; case 5: elem.style.color = 'pink'; break; case 6: elem.style.color = 'navy'; break; case 7: elem.style.color = 'brown'; break; case 8: elem.style.color = 'grey'; break; default: elem.style.color = 'black'; } } else { elem.innerHTML = '<b>M</b>'; } elem.style.background = '#d8e0ec'; }, gameOver: function() { for (var i = 0, len1 = this.board.rows.length; i < len1; i++) { for (var j = 0, len2 = this.board.rows[i].cells.length; j < len2; j++) { if (this.board.rows[i].cells[j].bomb) { this.openCell(this.board.rows[i].cells[j]); } Event.remove(this.board.rows[i].cells[j], 'click', this.board.rows[i].cells[j].clickHandler); } } this.gameStats.style.background = 'red'; this.gameStats.innerHTML = '<b>БАБАХ!!! GAME OVER!</b>'; }, roll: function(x, y) { if (x < 0 || y < 0 || x >= this.W || y >= this.H) { return; } this.openCell(this.board.rows[y].cells[x]); if (this.board.rows[y].cells[x].num > 0) { this.board.rows[y].cells[x].innerHTML = '<b>' + this.board.rows[y].cells[x].num + '</b>'; return; } if (this.board.rows[y].cells[x].check) { return; } this.board.rows[y].cells[x].check = true; this.roll(x + 1, y); this.roll(x - 1, y); this.roll(x, y + 1); this.roll(x, y - 1); this.roll(x - 1, y - 1); this.roll(x + 1, y - 1); this.roll(x - 1, y + 1); this.roll(x + 1, y + 1); }, writeMainContainer: function() { var html = '<div id="game" class="game"></div>'; document.writeln(html); return document.getElementById('game'); }, rand: function(min, max) { min = parseInt(min); max = parseInt(max); return Math.floor(Math.random() * (max - min + 1)) + min; } } Всем спасибо за внимание, надеюсь урок был вам полезен. Предложения, замечания и т.п. пишите в личку.
  24. Серверную часть не я разрабатывал, и ко мне это мало относилось, так что работал с тем что есть. Да и формы были пипец какие сложные, не уверен что их все можно было генерить сразу на сервере, там были банковские операции и многое зависело от того какой счет выбрал пользователь, да и вообще там много факторов было - я в структуру не вникал просто делал что скажут.
  25. А совсем хорошо будет сделать как описано тут
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy