feat: add Ship-Class Silhouettes and Red Sunk Markers
This commit is contained in:
+53
@@ -179,6 +179,58 @@
|
||||
return ['', 'Вода'];
|
||||
}
|
||||
|
||||
const fleetClasses = [
|
||||
{ length: 4, count: 1, symbol: 'ship-4-battleship', label: 'Линкор', className: 'battleship' },
|
||||
{ length: 3, count: 2, symbol: 'ship-3-cruiser', label: 'Крейсер', className: 'cruiser' },
|
||||
{ length: 2, count: 3, symbol: 'ship-2-destroyer', label: 'Эсминец', className: 'destroyer' },
|
||||
{ length: 1, count: 4, symbol: 'ship-1-cutter', label: 'Катер', className: 'cutter' },
|
||||
];
|
||||
|
||||
function sunkShipLengths(board) {
|
||||
const visited = new Set();
|
||||
const lengths = [];
|
||||
for (let start = 0; start < board.length; start += 1) {
|
||||
if (board[start] !== '4' || visited.has(start)) continue;
|
||||
let length = 0;
|
||||
const pending = [start]; visited.add(start);
|
||||
while (pending.length) {
|
||||
const index = pending.pop(); length += 1;
|
||||
const x = index % 10; const y = Math.floor(index / 10);
|
||||
[[x - 1, y], [x + 1, y], [x, y - 1], [x, y + 1]].forEach(([nextX, nextY]) => {
|
||||
const next = nextY * 10 + nextX;
|
||||
if (nextX >= 0 && nextX < 10 && nextY >= 0 && nextY < 10 && board[next] === '4' && !visited.has(next)) {
|
||||
visited.add(next); pending.push(next);
|
||||
}
|
||||
});
|
||||
}
|
||||
lengths.push(length);
|
||||
}
|
||||
return lengths;
|
||||
}
|
||||
|
||||
function fleetStatusElement(index, title) {
|
||||
const sunkLengths = sunkShipLengths(state.boards[index]);
|
||||
const fleet = document.createElement('section'); fleet.className = 'fleet-status'; fleet.setAttribute('aria-label', `Флот: ${title}`);
|
||||
fleetClasses.forEach(shipClass => {
|
||||
const row = document.createElement('div'); row.className = 'fleet-row';
|
||||
row.append(Object.assign(document.createElement('span'), { className: 'fleet-class', textContent: shipClass.label }));
|
||||
const ships = document.createElement('div'); ships.className = 'fleet-ships';
|
||||
for (let number = 0; number < shipClass.count; number += 1) {
|
||||
const sunkAt = sunkLengths.indexOf(shipClass.length);
|
||||
const sunk = sunkAt !== -1;
|
||||
if (sunk) sunkLengths.splice(sunkAt, 1);
|
||||
const ship = document.createElement('span');
|
||||
ship.className = `fleet-ship ${shipClass.className}${sunk ? ' sunk' : ''}`;
|
||||
ship.setAttribute('role', 'img'); ship.setAttribute('aria-label', `${shipClass.label} — ${sunk ? 'потоплен' : 'цел'}`);
|
||||
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.setAttribute('aria-hidden', 'true'); svg.setAttribute('focusable', 'false');
|
||||
const use = document.createElementNS('http://www.w3.org/2000/svg', 'use'); use.setAttribute('href', `/ship-sprite.svg#${shipClass.symbol}`);
|
||||
svg.append(use); ship.append(svg); ships.append(ship);
|
||||
}
|
||||
row.append(ships); fleet.append(row);
|
||||
});
|
||||
return fleet;
|
||||
}
|
||||
|
||||
function boardElement(index, title, targetable, result) {
|
||||
const board = document.createElement('section');
|
||||
board.className = 'board';
|
||||
@@ -223,6 +275,7 @@
|
||||
}
|
||||
}
|
||||
board.append(grid);
|
||||
board.append(fleetStatusElement(index, title));
|
||||
if (result) board.hidden = false;
|
||||
return board;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user