Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

HTML+CSS+JavaScript

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Морской бой на JavaScript
 
 автор: pazha   (01.08.2012 в 12:19)   письмо автору
 
 

Здравствуйте. Есть ли у кого нибудь пример морского боя на JavaScript, конкретней интересует расстановка кораблей?

Видел один сайтик, там реализовано расставление кораблей кликами на ячейки, то есть кликаешь 4 раза по рядом стоящим ячейкам и появляется кораблик четырёхпалубный.

Но у меня возникает вопрос, какой алгоритм этой расстановки, ведь человек может поставить сначало все однопалубные кораблики, а потом все двухпалубные у него не смогут поставиться так как в одну ячейку уже нет вариантов. Подскажите с алгоритмом

  Ответить  
 
 автор: ЯСА   (01.08.2012 в 16:48)   письмо автору
 
   для: pazha   (01.08.2012 в 12:19)
 

Надо установить очерёдность расстановки:
-- сначалО ставится четырёхпалубный,
-- потомО - трёхпалубные,
-- затемО - двухпалубные,
-- ну и в концОВО - останется место и для однопалубных.

  Ответить  
 
 автор: pazha   (01.08.2012 в 17:33)   письмо автору
 
   для: ЯСА   (01.08.2012 в 16:48)
 

Спасибо! )

  Ответить  
 
 автор: ЯСА   (01.08.2012 в 17:40)   письмо автору
 
   для: pazha   (01.08.2012 в 17:33)
 

ПожалуйстО.

Код дать?
Только он (код) без "костылей" будет, на чистом JS.

  Ответить  
 
 автор: pazha   (01.08.2012 в 18:47)   письмо автору
 
   для: ЯСА   (01.08.2012 в 17:40)
 

Если не тяжело, я был бы очень признателен )

  Ответить  
 
 автор: ЯСА   (02.08.2012 в 18:07)   письмо автору
 
   для: pazha   (01.08.2012 в 18:47)
 

Ну давайте, попробуем.

Для начала даю HTML-код места под "своё" игровое поле и анонимную исполняемую функцию создания этого "своего" игрового поля.

Внутри функции на клик по "своему" игровому полю назначается функция SetShips (), коя и будет управлять расстановкой.
<center id="mb"></center>
<script>
function SetShips (ev) // расстановка кораблей
{
// код будет позже, см. Примечание
}

(function () // создание игрового поля
{
with (document) var o = getElementById ('mb'), t = createElement ('TABLE'), d = createElement ('DIV'), m = createElement ('H4'),
w = function (x, y) {with (document) {var a = createElement ('SPAN'); a.style.color = 'blue'; if (x) a.style.display = 'none';
a.appendChild (createTextNode (y)); getElementById ('mb').appendChild (a)}}
with (t) cellSpacing = cellPadding = 0, border = 1, style.borderCollapse = 'collapse';
d.style.cssText = 'width: 30px; height: 30px; cursor: pointer; background-color: #fff'; for (var j = 0; j < 10; j++)
for (var r = t.insertRow (-1), k = 0; k < 10; c.appendChild (d.cloneNode (1)), k++) var c = r.insertCell (-1);
t.onclick = SetShips; t.lang = '4332221111-0'; o.appendChild (t); m.appendChild (document.createTextNode ('Расставьте корабли:'));
o.appendChild (m); var a = 'четырёх', b = 'трёх', c = 'двух', d = 'одно', e = 'палубный', f = 'первый ', g = 'второй ',
h = 'третий ', i = 'четвёртый '; w (0, a + e); w (1, f + b + e); w (1, g + b + e); w (1, f + c + e); w (1, g + c + e);
w (1, h + c + e); w (1, f + d + e); w (1, g + d + e); w (1, h + d + e); w (1, i + d + e);
}) ();
</script>

Примечание: код функции SetShips () (где и будет интересующий вас алгоритм расстановки кораблей) я пока не написал. Ибо не только правила расстановки кораблей не стандартизированы, но и даже их форма (четырёхпалубные кто-то делает, например, как букву T, или как букву Г, а трёхпалубные - буквой Г; при этом разрешается любая ориентировка этих "букв", как в тетрисе).

Укажите здесь нужные вам параметры в виде строки из правильных ответов и тогда я напишу код расстановки с учётом ваших пожеланий.
-----
А) все корабли - в одну линию (горизонтальную или вертикальную)
Б) трёхпалубные и четырёхпалубные корабли могут иметь любую форму (и линия, и Г, и Т - с любой ориентировкой)

В) корабли могут соприкасаться с берегом
Г) корабли не могут соприкасаться с берегом

Д) корабли не могут соприкасаться друг с другом
Е) корабли могут соприкасаться по диагонали
-----

Я в детстве играл, в основном, по варианту А-В-Д ("корабли только в линию" - "корабли могут соприкасаться с берегом" - "корабли друг друга не касаются").
А как нужно вам?


PS. Если есть вопросы/пожелания по поводу функции создания игрового поля - спрашивайте сразу. Потом что-то менять я уже не буду.

  Ответить  
 
 автор: pazha   (03.08.2012 в 17:07)   письмо автору
 
   для: ЯСА   (02.08.2012 в 18:07)
 

а) В) Д)

  Ответить  
 
 автор: ЯСА   (04.08.2012 в 03:46)   письмо автору
 
   для: pazha   (03.08.2012 в 17:07)
 

Лады!
Сейчас и начну, скоро выложу.

  Ответить  
 
 автор: ЯСА   (04.08.2012 в 09:31)   письмо автору
 
   для: ЯСА   (04.08.2012 в 03:46)
 

function SetShips (ev)
{
var E = ev || window.event, D = E.srcElement || E.target; if (D.tagName != 'DIV' || D.lang) return;
var O = document.getElementById ('mb'), T = O.firstChild, K = O.getElementsByTagName ('DIV'),
fc = function (x) {var x = x.toString (); return ((x.length < 2) ? x : x.charAt (1)) * 1},
fr = function (x) {var x = x.toString (); return ((x.length < 2) ? 0 : x.charAt (0)) * 1},
fk = function (x, y) {with (x) lang = (y) ? 'p' : 't', style.backgroundColor = '#eee', style.cursor = 'default'},
c = D.parentNode.cellIndex, r = D.parentNode.parentNode.rowIndex, j = 10 * r + c, l = T.lang.split ('-'),
m = l [0].charAt (0) * 1, n = l [1] * 1 + 1; 
D.lang = 's'; with (D.style) {backgroundColor = 'blue'; cursor = 'default'}
for (var q = 0, lq = K.length; q < lq; q++) if (K [q].lang == 't')
   with (K [q]) lang = '', style.backgroundColor = '#fff', style.cursor = 'pointer';
if (r && c) fk (K [j - 11], 1); if (r && (c - 9)) fk (K [j - 9], 1); 
if ((r - 9) && c) fk (K [j + 9], 1); if ((r - 9) && (c - 9)) fk (K [j + 11], 1); 
if (m > n) {var v = '-'; if (n == 1)
   {var go = ve = 1; if (m == 3)
      {
      go = (((c && !(K [j - 1].lang)) && ((c - 1) && !(K [j - 2].lang))) || ((c && !(K [j - 1].lang)) && ((c - 9) && !(K [j + 1].lang)))
           || (((c - 9) && !(K [j + 1].lang)) && ((c - 8) && !(K [j +  2].lang)))) ? 1 : 0; 
      ve = (((r && !(K [j - 10].lang)) && ((r - 1) && !(K [j - 20].lang))) || ((r && !(K [j - 10].lang)) && ((r - 9) && !(K [j + 10].lang)))
           || (((r - 9) && !(K [j + 10].lang)) && ((r - 8) && !(K [j + 20].lang)))) ? 1 : 0; 
      }
   if (c && go) v += (j - 1) + '-'; if ((c - 9) && go) v += (j + 1) + '-';
   if (r && ve) v += (j - 10) + '-'; if ((r - 9) && ve) v += (j + 10) + '-';
   }
else
   {
   if ((c && (K [j - 1].lang == 's')) || ((c - 9) && (K [j + 1].lang == 's'))) 
      {
      if (c && (K [j - 1].lang == 's'))
         {if ((c - 9) && !(K [j + 1].lang)) v += (j + 1) + '-'; if (fc (j - n + 1) && !(K [j - n].lang)) v += (j - n) + '-'}
      else
         {if (c && !(K [j - 1].lang)) v += (j - 1) + '-'; if ((fc (j + n - 1) - 9) && !(K [j + n].lang)) v += (j + n) + '-'}
      }
   else
      {
      if (r && K [j - 10].lang == 's')
         {if (r - 9 && !(K [j + 10].lang)) v += (j + 10) + '-'; if (fr (j - 10 * n + 10) && !(K [j - 10 * n].lang)) v += (j - 10 * n) + '-'}
      else
         {if (r && !(K [j - 10].lang)) v += (j - 10) + '-'; if ((fr (j + 10 * n - 10) - 9) && !(K [j + 10 * n].lang)) v += (j + 10 * n) + '-'}
      }
   }      
for (var q = 0, lq = K.length; q < lq; q++) if (v.indexOf ('-' + q + '-') == -1 && !(K [q].lang)) fk (K [q], 0); T.lang = l [0] + '-' + n}
else
   {
   O.removeChild (O.getElementsByTagName ('SPAN') [0]); for (var q = 0, lq = K.length; q < lq; q++) 
      {
      if (K [q].lang == 's') 
         {
         K [q].style.backgroundColor = '#000';
         if ((fc (q) > 0) && (K [q - 1].lang != 's')) fk (K [q -  1], 1); if ((fc (q) - 9) && (K [q + 1].lang != 's')) fk (K [q +  1], 1);
         if ((q > 9) && (K [q - 10].lang != 's')) fk (K [q - 10], 1); if ((q < 90) && (K [q + 10].lang != 's')) fk (K [q + 10], 1);
         }
      }
   if (l [0].length == 1)
      {
      for (var q = 0, lq = K.length; q < lq; q++)
         if (K [q].lang != 's') with (K [q]) lang = '', style.backgroundColor = '#fff', style.cursor = 'default';
      O.getElementsByTagName ('H4') [0].innerHTML = 'Играйте!'; T.onclick = null; return;
      }
   T.lang = l [0].substr (1) + '-0'; O.getElementsByTagName ('SPAN') [0].style.display = '';
   var M = T.lang.charAt (0) - 1; if (M) for (var q = 0, lq = K.length; q < lq; q++)
      {
      if (!(K [q].lang))
         {
         var uL = ((fc (q) > 0) && !(K [q - 1].lang)), uR = ((fc (q) - 9) && !(K [q + 1].lang)),
         uU = ((q > 9) && !(K [q - 10].lang)), uD = ((q < 90) && !(K [q + 10].lang));
         if  (!(uL || uR || uU || uD)) fk (K [q], 0);
         else if (M > 1)
            {
            var uL2 = (uL && ((fc (q - 1) > 0) && !(K [q - 2].lang))), uR2 = (uR && ((fc (q + 1) - 9) && !(K [q + 2].lang))),
            uU2 = (uU && ((q > 19) && !(K [q - 20].lang))), uD2 = (uD && ((q < 80) && !(K [q + 20].lang)));
            if (!((uL && uR) || (uU && uD) || uL2 || uR2 || uU2 || uD2)) fk (K [q], 0);
            }
         }
      }
   }
}

  Ответить  
 
 автор: pazha   (05.08.2012 в 09:54)   письмо автору
 
   для: ЯСА   (04.08.2012 в 09:31)
 

Вы гений! Спасибо большое! Я парился неделю и не как не получалось!!!!!!

  Ответить  
 
 автор: Valick   (05.08.2012 в 14:57)   письмо автору
 
   для: ЯСА   (04.08.2012 в 09:31)
 

Хорошая функция, если не возражаете то возьму к себе на заметку, может когда-нибудь дойдут руки доделать свой морской бой.
Единственный минус функция позволяет только расставлять, но не позволяет убрать хотя бы последний поставленный фрагмент корабля.
Когда я писал расстановку на РНР, то сделал автоматическую случайную расстановку, а так как хотел предоставить пользователю полный контроль над расстановкой, то сделал возможность редактировать и ручную и автоматическую расстановку в произвольном порядке, но так и не довел скрипт до ума (ума как раз и не хватило) и осталась возможность "обмануть" расстановку.
Естественно вариант реализации расстановки на JS во всех отношениях и удобнее и рациональнее.

  Ответить  
 
 автор: pazha   (05.08.2012 в 15:00)   письмо автору
 
   для: Valick   (05.08.2012 в 14:57)
 

Полностью согласен. Я сделал что бы расстановка была при помощи JS, а сам PHP скрипт проверял её правильность.

  Ответить  
 
 автор: ЯСА   (05.08.2012 в 16:40)   письмо автору
 
   для: Valick   (05.08.2012 в 14:57)
 

Функцию вполне можно ещё "причесать", упростив код.
По большому счёту все "проверки" можно расписать по всего четырём функциям ("верху"-"справа"-"снизу"-"слева") - код будет и короче, и читабельней.

Что до удаления (типа "передумал"), то вполне можно реализовать, причём на любом (кроме последней клетки) этапе "построения" очередного корабля - можно дополнительно навесить "клик" по любой из "синих" клеток, который приведёт к предыдущему состоянию. Это несложно.

Если очень надо, то можно и "причесать", и добавить удаление.

  Ответить  
 
 автор: pazha   (05.08.2012 в 19:09)   письмо автору
 
   для: ЯСА   (05.08.2012 в 16:40)
 

Желательно, если это не сильно затруднит.

  Ответить  
 
 автор: Valick   (08.01.2013 в 15:06)   письмо автору
 
   для: ЯСА   (05.08.2012 в 16:40)
 

Подскажите как отправить на сервер полученную расстановку для валидации?

  Ответить  
 
 автор: Никчай   (09.01.2013 в 13:57)   письмо автору
 
   для: Valick   (08.01.2013 в 15:06)
 

Тоже решил подумать над реализацией этой игры. На клиенте две таблицы в одной поле морского боя с айди номером столбца, в другой размеры кораблей. Клик по кораблю и далее клики по полю, если клик по следующему полю больше или меньше единицы или не равен соседним двум строкам, то ошибка, можно подсвечивать возможные клики. На сервере ключ это кол-во палуб, значение - номер ячейки.

  Ответить  
 
 автор: Valick   (09.01.2013 в 14:16)   письмо автору
 
   для: Никчай   (09.01.2013 в 13:57)
 

:) Игра написана 3 года назад, 2 года назад переписана с использованием базы данных (но пока не выкладывал в сеть), просто расстановка реализована на РНР, а хотелось бы на JS

  Ответить  
 
 автор: Никчай   (09.01.2013 в 16:28)   письмо автору
 
   для: Valick   (09.01.2013 в 14:16)
 

У нас можно было делать корабль даже так: по номерам ячеек 1, 2, 12, 22. и рядом корабли могли быть. Может это не правильно, мало с этой игрой дружил.
А какие проблемы с js? Как отправлять данные? Так же как Вы делаете на php. Лучше сразу отправить, когда все будет готово. Можно сделать два глобальных массива, в одном хранить правила по кол-ву кораблей (pravila), а в другой помещать клики (dannie). Если правила не допускают слияние кораблей, то фунция будет в dannie, ячейки которого тоже будут массивами, переводить на следующий элемент. После каждого клика пробегаться по pravila, когда происходит переход на следующий элемент в dannie, удалять соответствующий корабль из pravila, если последний пуст отправлять на сервер.
Сама игра ajax-ом, все тоже самое что сейчас у Вас только без рисования. Всего два цикла по короблям и по ячейкам.

  Ответить  
 
 автор: Valick   (09.01.2013 в 17:03)   письмо автору
 
   для: Никчай   (09.01.2013 в 16:28)
 

А какие проблемы с js?
самые что ни на есть серьезные, проще говоря я его не знаю, мне уже лет 5 его "некогда" выучить :)

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования