const BOARD_SIZE = 10;
const SHIPS = [
{ name: 'Carrier', size: 5 },
{ name: 'Battleship', size: 4 },
{ name: 'Cruiser', size: 3 },
{ name: 'Submarine', size: 3 },
{ name: 'Destroyer', size: 2 }
];
let playerBoard = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(''));
let aiBoard = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(''));
let playerShips = [];
let aiShips = [];
let gamePhase = 'setup';
let aiTargetQueue = [];
let aiLastHit = null;
function generateAiShips() {
const board = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(''));
const ships = [];
for (const shipTemplate of SHIPS) {
let placed = false;
let attempts = 0;
while (!placed && attempts < 100) {
const direction = Math.random() < 0.5 ? 'horizontal' : 'vertical';
const row = Math.floor(Math.random() * BOARD_SIZE);
const col = Math.floor(Math.random() * BOARD_SIZE);
if (canPlaceShip(board, row, col, shipTemplate, direction)) {
const positions = [];
for (let i = 0; i < shipTemplate.size; i++) {
const newRow = direction === 'vertical' ? row + i : row;
const newCol = direction === 'horizontal' ? col + i : col;
board[newRow][newCol] = 'S';
positions.push({ row: newRow, col: newCol });
}
ships.push({
name: shipTemplate.name,
size: shipTemplate.size,
positions,
hits: Array(shipTemplate.size).fill(false)
});
placed = true;
}
attempts++;
}
}
aiShips = ships;
}
function canPlaceShip(board, row, col, ship, direction) {
for (let i = 0; i < ship.size; i++) {
const newRow = direction === 'vertical' ? row + i : row;
const newCol = direction === 'horizontal' ? col + i : col;
if (newRow >= BOARD_SIZE || newCol >= BOARD_SIZE || board[newRow][newCol] !== '') {
return false;
}
for (let dr = -1; dr <= 1; dr++) {
for (let dc = -1; dc <= 1; dc++) {
const checkRow = newRow + dr;
const checkCol = newCol + dc;
if (checkRow >= 0 && checkRow < BOARD_SIZE &&
checkCol >= 0 && checkCol < BOARD_SIZE &&
board[checkRow][checkCol] === 'S') {
return false;
}
}
}
}
return true;
}
function smartAiAttack() {
if (aiTargetQueue.length > 0) {
const target = aiTargetQueue.shift();
return target;
}
if (aiLastHit) {
const { row, col } = aiLastHit;
const directions = [
{ row: row - 1, col },
{ row: row + 1, col },
{ row, col: col - 1 },
{ row, col: col + 1 }
];
for (const dir of directions) {
if (dir.row >= 0 && dir.row < BOARD_SIZE &&
dir.col >= 0 && dir.col < BOARD_SIZE &&
playerBoard[dir.row][dir.col] !== 'H' &&
playerBoard[dir.row][dir.col] !== 'M') {
return dir;
}
}
aiLastHit = null;
}
const availableSquares = [];
for (let row = 0; row < BOARD_SIZE; row++) {
for (let col = 0; col < BOARD_SIZE; col++) {
if (playerBoard[row][col] !== 'H' && playerBoard[row][col] !== 'M') {
if ((row + col) % 2 === 0) {
availableSquares.push({ row, col });
}
}
}
}
if (availableSquares.length === 0) {
for (let row = 0; row < BOARD_SIZE; row++) {
for (let col = 0; col < BOARD_SIZE; col++) {
if (playerBoard[row][col] !== 'H' && playerBoard[row][col] !== 'M') {
availableSquares.push({ row, col });
}
}
}
}
return availableSquares[Math.floor(Math.random() * availableSquares.length)];
}
function aiAttack() {
const target = smartAiAttack();
if (!target) return;
const { row, col } = target;
let hit = false;
if (playerBoard[row][col] === 'S') {
hit = true;
playerBoard[row][col] = 'H';
aiLastHit = { row, col };
const directions = [
{ row: row - 1, col },
{ row: row + 1, col },
{ row, col: col - 1 },
{ row, col: col + 1 }
];
for (const dir of directions) {
if (dir.row >= 0 && dir.row < BOARD_SIZE &&
dir.col >= 0 && dir.col < BOARD_SIZE &&
playerBoard[dir.row][dir.col] !== 'H' &&
playerBoard[dir.row][dir.col] !== 'M') {
aiTargetQueue.push(dir);
}
}
for (const ship of playerShips) {
for (let i = 0; i < ship.positions.length; i++) {
if (ship.positions[i].row === row && ship.positions[i].col === col) {
ship.hits[i] = true;
if (ship.hits.every(hit => hit)) {
aiTargetQueue = [];
aiLastHit = null;
}
break;
}
}
}
} else {
playerBoard[row][col] = 'M';
}
const allPlayerShipsSunk = playerShips.every(ship => ship.hits.every(hit => hit));
if (allPlayerShipsSunk) {
alert('AI wins!');
resetGame();
}
}
function playerAttack(row, col) {
if (aiBoard[row][col] !== '' || gamePhase !== 'playing') return;
let hit = false;
for (const ship of aiShips) {
for (let i = 0; i < ship.positions.length; i++) {
if (ship.positions[i].row === row && ship.positions[i].col === col) {
ship.hits[i] = true;
hit = true;
break;
}
}
}
aiBoard[row][col] = hit ? 'H' : 'M';
const allAiShipsSunk = aiShips.every(ship => ship.hits.every(hit => hit));
if (allAiShipsSunk) {
alert('You win!');
resetGame();
return;
}
setTimeout(aiAttack, 1000);
}
function resetGame() {
playerBoard = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(''));
aiBoard = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(''));
playerShips = [];
aiShips = [];
gamePhase = 'setup';
aiTargetQueue = [];
aiLastHit = null;
}
generateAiShips();This code demonstrates the core game logic. The actual implementation may include additional features and optimizations.