|
|
|
| Здравствуйте. Есть ли у кого нибудь пример морского боя на JavaScript, конкретней интересует расстановка кораблей?
Видел один сайтик, там реализовано расставление кораблей кликами на ячейки, то есть кликаешь 4 раза по рядом стоящим ячейкам и появляется кораблик четырёхпалубный.
Но у меня возникает вопрос, какой алгоритм этой расстановки, ведь человек может поставить сначало все однопалубные кораблики, а потом все двухпалубные у него не смогут поставиться так как в одну ячейку уже нет вариантов. Подскажите с алгоритмом | |
|
|
|
|
|
|
|
для: pazha
(01.08.2012 в 12:19)
| | Надо установить очерёдность расстановки:
-- сначалО ставится четырёхпалубный,
-- потомО - трёхпалубные,
-- затемО - двухпалубные,
-- ну и в концОВО - останется место и для однопалубных. | |
|
|
|
|
|
|
|
для: ЯСА
(01.08.2012 в 16:48)
| | Спасибо! ) | |
|
|
|
|
|
|
|
для: pazha
(01.08.2012 в 17:33)
| | ПожалуйстО.
Код дать?
Только он (код) без "костылей" будет, на чистом JS. | |
|
|
|
|
|
|
|
для: ЯСА
(01.08.2012 в 17:40)
| | Если не тяжело, я был бы очень признателен ) | |
|
|
|
|
|
|
|
для: 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. Если есть вопросы/пожелания по поводу функции создания игрового поля - спрашивайте сразу. Потом что-то менять я уже не буду. | |
|
|
|
|
|
|
|
для: ЯСА
(02.08.2012 в 18:07)
| | а) В) Д) | |
|
|
|
|
|
|
|
для: pazha
(03.08.2012 в 17:07)
| | Лады!
Сейчас и начну, скоро выложу. | |
|
|
|
|
|
|
|
для: ЯСА
(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);
}
}
}
}
}
|
| |
|
|
|
|
|
|
|
для: ЯСА
(04.08.2012 в 09:31)
| | Вы гений! Спасибо большое! Я парился неделю и не как не получалось!!!!!! | |
|
|
|
|
|
|
|
для: ЯСА
(04.08.2012 в 09:31)
| | Хорошая функция, если не возражаете то возьму к себе на заметку, может когда-нибудь дойдут руки доделать свой морской бой.
Единственный минус функция позволяет только расставлять, но не позволяет убрать хотя бы последний поставленный фрагмент корабля.
Когда я писал расстановку на РНР, то сделал автоматическую случайную расстановку, а так как хотел предоставить пользователю полный контроль над расстановкой, то сделал возможность редактировать и ручную и автоматическую расстановку в произвольном порядке, но так и не довел скрипт до ума (ума как раз и не хватило) и осталась возможность "обмануть" расстановку.
Естественно вариант реализации расстановки на JS во всех отношениях и удобнее и рациональнее. | |
|
|
|
|
|
|
|
для: Valick
(05.08.2012 в 14:57)
| | Полностью согласен. Я сделал что бы расстановка была при помощи JS, а сам PHP скрипт проверял её правильность. | |
|
|
|
|
|
|
|
для: Valick
(05.08.2012 в 14:57)
| | Функцию вполне можно ещё "причесать", упростив код.
По большому счёту все "проверки" можно расписать по всего четырём функциям ("верху"-"справа"-"снизу"-"слева") - код будет и короче, и читабельней.
Что до удаления (типа "передумал"), то вполне можно реализовать, причём на любом (кроме последней клетки) этапе "построения" очередного корабля - можно дополнительно навесить "клик" по любой из "синих" клеток, который приведёт к предыдущему состоянию. Это несложно.
Если очень надо, то можно и "причесать", и добавить удаление. | |
|
|
|
|
|
|
|
для: ЯСА
(05.08.2012 в 16:40)
| | Желательно, если это не сильно затруднит. | |
|
|
|
|
|
|
|
для: ЯСА
(05.08.2012 в 16:40)
| | Подскажите как отправить на сервер полученную расстановку для валидации? | |
|
|
|
|
|
|
|
для: Valick
(08.01.2013 в 15:06)
| | Тоже решил подумать над реализацией этой игры. На клиенте две таблицы в одной поле морского боя с айди номером столбца, в другой размеры кораблей. Клик по кораблю и далее клики по полю, если клик по следующему полю больше или меньше единицы или не равен соседним двум строкам, то ошибка, можно подсвечивать возможные клики. На сервере ключ это кол-во палуб, значение - номер ячейки. | |
|
|
|
|
|
|
|
для: Никчай
(09.01.2013 в 13:57)
| | :) Игра написана 3 года назад, 2 года назад переписана с использованием базы данных (но пока не выкладывал в сеть), просто расстановка реализована на РНР, а хотелось бы на JS | |
|
|
|
|
|
|
|
для: Valick
(09.01.2013 в 14:16)
| | У нас можно было делать корабль даже так: по номерам ячеек 1, 2, 12, 22. и рядом корабли могли быть. Может это не правильно, мало с этой игрой дружил.
А какие проблемы с js? Как отправлять данные? Так же как Вы делаете на php. Лучше сразу отправить, когда все будет готово. Можно сделать два глобальных массива, в одном хранить правила по кол-ву кораблей (pravila), а в другой помещать клики (dannie). Если правила не допускают слияние кораблей, то фунция будет в dannie, ячейки которого тоже будут массивами, переводить на следующий элемент. После каждого клика пробегаться по pravila, когда происходит переход на следующий элемент в dannie, удалять соответствующий корабль из pravila, если последний пуст отправлять на сервер.
Сама игра ajax-ом, все тоже самое что сейчас у Вас только без рисования. Всего два цикла по короблям и по ячейкам. | |
|
|
|
|
|
|
|
для: Никчай
(09.01.2013 в 16:28)
| | А какие проблемы с js?
самые что ни на есть серьезные, проще говоря я его не знаю, мне уже лет 5 его "некогда" выучить :) | |
|
|
|
|