battleship-oldschool / index.html
MikePfunk28's picture
and doesnt seem like attacking works - Follow Up Deployment
87f9229 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Battleship Game</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
.cell {
width: 40px;
height: 40px;
transition: all 0.2s ease;
}
.cell:hover:not(.hit):not(.miss) {
transform: scale(1.1);
box-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
}
.ship {
background-color: #4b5563;
}
.hit {
background-color: #ef4444;
position: relative;
}
.hit::after {
content: "✖";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 20px;
}
.miss {
background-color: #60a5fa;
position: relative;
}
.miss::after {
content: "•";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 20px;
}
@media (max-width: 768px) {
.cell {
width: 30px;
height: 30px;
}
}
@media (max-width: 480px) {
.cell {
width: 25px;
height: 25px;
}
}
.ship-preview {
opacity: 0.7;
}
.ship-placing {
background-color: #10b981;
}
.ship-invalid {
background-color: #f59e0b;
}
.ship-sunk {
background-color: #991b1b;
}
.ship-sunk::after {
content: "☠";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 20px;
}
</style>
</head>
<body class="bg-gray-900 text-white min-h-screen flex flex-col items-center justify-center p-4">
<div class="container mx-auto max-w-6xl">
<h1 class="text-4xl font-bold text-center mb-8 text-blue-400">Battleship Game</h1>
<div id="setup-screen" class="text-center mb-8">
<h2 class="text-2xl font-semibold mb-4">Place Your Ships</h2>
<div class="flex flex-wrap justify-center gap-4 mb-6">
<div id="carrier" class="flex items-center bg-gray-800 p-2 rounded cursor-move" draggable="true" data-size="5">
<div class="flex">
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
</div>
<span class="ml-2">Carrier (5)</span>
</div>
<div id="battleship" class="flex items-center bg-gray-800 p-2 rounded cursor-move" draggable="true" data-size="4">
<div class="flex">
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
</div>
<span class="ml-2">Battleship (4)</span>
</div>
<div id="cruiser" class="flex items-center bg-gray-800 p-2 rounded cursor-move" draggable="true" data-size="3">
<div class="flex">
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
</div>
<span class="ml-2">Cruiser (3)</span>
</div>
<div id="submarine" class="flex items-center bg-gray-800 p-2 rounded cursor-move" draggable="true" data-size="3">
<div class="flex">
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
</div>
<span class="ml-2">Submarine (3)</span>
</div>
<div id="destroyer" class="flex items-center bg-gray-800 p-2 rounded cursor-move" draggable="true" data-size="2">
<div class="flex">
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
<div class="cell ship-preview bg-gray-600 border border-gray-400"></div>
</div>
<span class="ml-2">Destroyer (2)</span>
</div>
</div>
<div class="flex flex-col md:flex-row justify-center gap-8 mb-6">
<div>
<h3 class="text-xl font-medium mb-2">Your Board</h3>
<div id="player-board" class="grid grid-cols-10 gap-0 border-2 border-blue-400 bg-blue-900 bg-opacity-20">
<!-- Player board will be generated here -->
</div>
</div>
<div class="mt-8 md:mt-0">
<div class="flex items-center justify-between mb-2">
<h3 class="text-xl font-medium">Orientation</h3>
<button id="rotate-btn" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded">
Horizontal ↔
</button>
</div>
<div id="instructions" class="bg-gray-800 p-4 rounded-lg mb-4">
<p class="mb-2">Drag and drop ships onto your board.</p>
<p>Click the button above to change ship orientation.</p>
</div>
<button id="start-game-btn" class="bg-green-600 hover:bg-green-700 text-white px-6 py-3 rounded-lg text-lg font-semibold hidden">
Start Game
</button>
<button id="randomize-btn" class="bg-purple-600 hover:bg-purple-700 text-white px-4 py-2 rounded-lg mr-2">
Randomize
</button>
<button id="reset-btn" class="bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-lg">
Reset
</button>
</div>
</div>
</div>
<div id="game-screen" class="hidden">
<div class="flex flex-col md:flex-row justify-center gap-8 mb-8">
<div>
<h3 class="text-xl font-medium mb-2">Your Board</h3>
<div id="player-game-board" class="grid grid-cols-10 gap-0 border-2 border-blue-400 bg-blue-900 bg-opacity-20">
<!-- Player game board will be generated here -->
</div>
</div>
<div>
<h3 class="text-xl font-medium mb-2">Enemy Board</h3>
<div id="enemy-board" class="grid grid-cols-10 gap-0 border-2 border-red-400 bg-red-900 bg-opacity-20">
<!-- Enemy board will be generated here -->
</div>
</div>
</div>
<div class="text-center mt-6">
<div id="game-status" class="text-2xl font-semibold mb-4 text-yellow-400"></div>
<div class="flex justify-center gap-4">
<button id="new-game-btn" class="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-lg">
New Game
</button>
<button id="show-ships-btn" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg">
Show Enemy Ships
</button>
</div>
</div>
</div>
<div id="game-over-screen" class="hidden text-center mt-8">
<h2 id="game-result" class="text-3xl font-bold mb-6"></h2>
<div class="flex justify-center gap-4">
<button id="play-again-btn" class="bg-green-600 hover:bg-green-700 text-white px-6 py-3 rounded-lg text-lg font-semibold">
Play Again
</button>
<button id="main-menu-btn" class="bg-blue-600 hover:bg-blue-700 text-white px-6 py-3 rounded-lg text-lg font-semibold">
Main Menu
</button>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Game state
const gameState = {
playerBoard: [],
enemyBoard: [],
playerShips: [],
enemyShips: [],
currentShip: null,
currentShipSize: 0,
currentOrientation: 'horizontal',
gamePhase: 'setup', // 'setup', 'playing', 'gameOver'
playerTurn: true,
enemyBoardAttacks: [],
shipsToPlace: [
{ id: 'carrier', name: 'Carrier', size: 5 },
{ id: 'battleship', name: 'Battleship', size: 4 },
{ id: 'cruiser', name: 'Cruiser', size: 3 },
{ id: 'submarine', name: 'Submarine', size: 3 },
{ id: 'destroyer', name: 'Destroyer', size: 2 }
],
placedShips: 0
};
// DOM elements
const setupScreen = document.getElementById('setup-screen');
const gameScreen = document.getElementById('game-screen');
const gameOverScreen = document.getElementById('game-over-screen');
const playerBoard = document.getElementById('player-board');
const playerGameBoard = document.getElementById('player-game-board');
const enemyBoard = document.getElementById('enemy-board');
const rotateBtn = document.getElementById('rotate-btn');
const startGameBtn = document.getElementById('start-game-btn');
const randomizeBtn = document.getElementById('randomize-btn');
const resetBtn = document.getElementById('reset-btn');
const newGameBtn = document.getElementById('new-game-btn');
const showShipsBtn = document.getElementById('show-ships-btn');
const playAgainBtn = document.getElementById('play-again-btn');
const mainMenuBtn = document.getElementById('main-menu-btn');
const gameStatus = document.getElementById('game-status');
const gameResult = document.getElementById('game-result');
// Initialize boards
function initializeBoards() {
// Clear boards
playerBoard.innerHTML = '';
playerGameBoard.innerHTML = '';
enemyBoard.innerHTML = '';
// Initialize game state arrays
gameState.playerBoard = Array(10).fill().map(() => Array(10).fill(0));
gameState.enemyBoard = Array(10).fill().map(() => Array(10).fill(0));
gameState.playerShips = [];
gameState.enemyShips = [];
gameState.placedShips = 0;
// Create player board cells for setup
for (let row = 0; row < 10; row++) {
for (let col = 0; col < 10; col++) {
const cell = document.createElement('div');
cell.className = 'cell border border-gray-400 bg-blue-900 bg-opacity-30';
cell.dataset.row = row;
cell.dataset.col = col;
cell.addEventListener('dragover', handleDragOver);
cell.addEventListener('drop', handleDrop);
cell.addEventListener('dragenter', handleDragEnter);
cell.addEventListener('dragleave', handleDragLeave);
playerBoard.appendChild(cell);
}
}
// Create player game board cells
for (let row = 0; row < 10; row++) {
for (let col = 0; col < 10; col++) {
const cell = document.createElement('div');
cell.className = 'cell border border-gray-400 bg-blue-900 bg-opacity-30';
cell.dataset.row = row;
cell.dataset.col = col;
playerGameBoard.appendChild(cell);
}
}
// Create enemy board cells
for (let row = 0; row < 10; row++) {
for (let col = 0; col < 10; col++) {
const cell = document.createElement('div');
cell.className = 'cell border border-gray-400 bg-red-900 bg-opacity-30';
cell.dataset.row = row;
cell.dataset.col = col;
cell.addEventListener('click', handleEnemyCellClick);
enemyBoard.appendChild(cell);
}
}
}
// Setup drag and drop for ships
function setupDragAndDrop() {
const ships = document.querySelectorAll('[draggable="true"]');
ships.forEach(ship => {
ship.addEventListener('dragstart', handleDragStart);
});
}
// Handle drag start
function handleDragStart(e) {
gameState.currentShip = e.target.id;
gameState.currentShipSize = parseInt(e.target.dataset.size);
e.dataTransfer.setData('text/plain', e.target.id);
e.dataTransfer.effectAllowed = 'copy';
}
// Handle drag over
function handleDragOver(e) {
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
}
// Handle drag enter
function handleDragEnter(e) {
if (gameState.currentShip) {
const row = parseInt(e.target.dataset.row);
const col = parseInt(e.target.dataset.col);
// Highlight potential ship placement
highlightShipPlacement(row, col, gameState.currentShipSize, gameState.currentOrientation);
}
}
// Handle drag leave
function handleDragLeave(e) {
// Remove all temporary placement classes
const cells = playerBoard.querySelectorAll('.cell');
cells.forEach(cell => {
cell.classList.remove('ship-placing', 'ship-invalid');
});
}
// Handle drop
function handleDrop(e) {
e.preventDefault();
const row = parseInt(e.target.dataset.row);
const col = parseInt(e.target.dataset.col);
const shipId = e.dataTransfer.getData('text/plain');
const shipSize = gameState.currentShipSize;
// Check if placement is valid
if (canPlaceShip(row, col, shipSize, gameState.currentOrientation)) {
// Place the ship
placeShip(row, col, shipSize, gameState.currentOrientation, shipId);
// Remove the ship from the available ships
const shipElement = document.getElementById(shipId);
shipElement.style.display = 'none';
// Increment placed ships counter
gameState.placedShips++;
// Check if all ships are placed
if (gameState.placedShips === gameState.shipsToPlace.length) {
startGameBtn.classList.remove('hidden');
}
}
// Remove all temporary placement classes
const cells = playerBoard.querySelectorAll('.cell');
cells.forEach(cell => {
cell.classList.remove('ship-placing', 'ship-invalid');
});
gameState.currentShip = null;
}
// Highlight potential ship placement
function highlightShipPlacement(row, col, size, orientation) {
// First remove all highlights
const cells = playerBoard.querySelectorAll('.cell');
cells.forEach(cell => {
cell.classList.remove('ship-placing', 'ship-invalid');
});
// Calculate cells that would be occupied
const cellsToHighlight = [];
let isValid = true;
if (orientation === 'horizontal') {
for (let i = 0; i < size; i++) {
const newCol = col + i;
if (newCol >= 10) {
isValid = false;
break;
}
// Check if cell is already occupied
if (gameState.playerBoard[row][newCol] !== 0) {
isValid = false;
}
cellsToHighlight.push({row, col: newCol});
}
} else { // vertical
for (let i = 0; i < size; i++) {
const newRow = row + i;
if (newRow >= 10) {
isValid = false;
break;
}
// Check if cell is already occupied
if (gameState.playerBoard[newRow][col] !== 0) {
isValid = false;
}
cellsToHighlight.push({row: newRow, col});
}
}
// Apply highlighting
cellsToHighlight.forEach(({row, col}) => {
const index = row * 10 + col;
const cell = playerBoard.children[index];
if (isValid) {
cell.classList.add('ship-placing');
} else {
cell.classList.add('ship-invalid');
}
});
}
// Check if ship can be placed
function canPlaceShip(row, col, size, orientation) {
if (orientation === 'horizontal') {
// Check if ship goes out of bounds
if (col + size > 10) return false;
// Check if any cell is already occupied
for (let i = 0; i < size; i++) {
if (gameState.playerBoard[row][col + i] !== 0) {
return false;
}
}
} else { // vertical
// Check if ship goes out of bounds
if (row + size > 10) return false;
// Check if any cell is already occupied
for (let i = 0; i < size; i++) {
if (gameState.playerBoard[row + i][col] !== 0) {
return false;
}
}
}
return true;
}
// Place a ship on the board
function placeShip(row, col, size, orientation, shipId) {
const shipCells = [];
if (orientation === 'horizontal') {
for (let i = 0; i < size; i++) {
const newCol = col + i;
if (newCol < 10) {
gameState.playerBoard[row][newCol] = shipId;
shipCells.push({row, col: newCol});
}
}
} else { // vertical
for (let i = 0; i < size; i++) {
const newRow = row + i;
if (newRow < 10) {
gameState.playerBoard[newRow][col] = shipId;
shipCells.push({row: newRow, col});
}
}
}
// Add to player ships
gameState.playerShips.push({
id: shipId,
size: size,
hits: 0,
cells: shipCells
});
// Update the board display
updatePlayerBoard();
}
// Update player board display
function updatePlayerBoard() {
for (let row = 0; row < 10; row++) {
for (let col = 0; col < 10; col++) {
const index = row * 10 + col;
const cell = playerBoard.children[index];
const gameCell = playerGameBoard.children[index];
// Clear any ship classes
cell.classList.remove('ship');
gameCell.classList.remove('ship');
// If cell has a ship, add ship class
if (gameState.playerBoard[row][col] !== 0) {
cell.classList.add('ship');
gameCell.classList.add('ship');
}
}
}
}
// Randomize ship placement
function randomizeShips() {
// Reset player board
gameState.playerBoard = Array(10).fill().map(() => Array(10).fill(0));
gameState.playerShips = [];
gameState.placedShips = 0;
// Show all ship elements
gameState.shipsToPlace.forEach(ship => {
document.getElementById(ship.id).style.display = 'flex';
});
// Place each ship randomly
gameState.shipsToPlace.forEach(ship => {
let placed = false;
let attempts = 0;
const maxAttempts = 100;
while (!placed && attempts < maxAttempts) {
const orientation = Math.random() < 0.5 ? 'horizontal' : 'vertical';
const row = Math.floor(Math.random() * 10);
const col = Math.floor(Math.random() * 10);
if (canPlaceShip(row, col, ship.size, orientation)) {
placeShip(row, col, ship.size, orientation, ship.id);
placed = true;
gameState.placedShips++;
}
attempts++;
}
if (!placed) {
console.error(`Could not place ${ship.name} after ${maxAttempts} attempts`);
}
});
// Update the board display
updatePlayerBoard();
// Show start button if all ships placed
if (gameState.placedShips === gameState.shipsToPlace.length) {
startGameBtn.classList.remove('hidden');
}
}
// Reset the game
function resetGame() {
// Reset game state
gameState.playerBoard = Array(10).fill().map(() => Array(10).fill(0));
gameState.playerShips = [];
gameState.placedShips = 0;
gameState.currentShip = null;
gameState.currentShipSize = 0;
gameState.currentOrientation = 'horizontal';
// Show all ship elements
gameState.shipsToPlace.forEach(ship => {
document.getElementById(ship.id).style.display = 'flex';
});
// Hide start button
startGameBtn.classList.add('hidden');
// Update the board display
updatePlayerBoard();
// Reset orientation button text
rotateBtn.textContent = 'Horizontal ↔';
}
// Start the game
function startGame() {
// Setup enemy ships randomly
setupEnemyShips();
// Switch to game screen
setupScreen.classList.add('hidden');
gameScreen.classList.remove('hidden');
// Update game status
gameStatus.textContent = "Your turn - Attack the enemy!";
gameState.playerTurn = true;
gameState.gamePhase = 'playing';
// Update player game board
updatePlayerGameBoard();
// Initialize enemy board attack tracking
gameState.enemyBoardAttacks = Array(10).fill().map(() => Array(10).fill(false));
}
// Setup enemy ships randomly
function setupEnemyShips() {
gameState.enemyBoard = Array(10).fill().map(() => Array(10).fill(0));
gameState.enemyShips = [];
// Place each ship randomly
gameState.shipsToPlace.forEach(ship => {
let placed = false;
let attempts = 0;
const maxAttempts = 500; // Increased attempts for better placement
while (!placed && attempts < maxAttempts) {
const orientation = Math.random() < 0.5 ? 'horizontal' : 'vertical';
// Ensure ships are placed within bounds
const row = orientation === 'vertical' ?
Math.floor(Math.random() * (10 - ship.size)) :
Math.floor(Math.random() * 10);
const col = orientation === 'horizontal' ?
Math.floor(Math.random() * (10 - ship.size)) :
Math.floor(Math.random() * 10);
if (canPlaceEnemyShip(row, col, ship.size, orientation)) {
placeEnemyShip(row, col, ship.size, orientation, ship.id);
placed = true;
}
attempts++;
}
if (!placed) {
console.error(`Could not place enemy ${ship.name} after ${maxAttempts} attempts`);
// Force placement by clearing board and trying again
gameState.enemyBoard = Array(10).fill().map(() => Array(10).fill(0));
gameState.enemyShips = [];
setupEnemyShips();
return;
}
});
console.log("Enemy ships placed:", gameState.enemyShips);
}
// Check if enemy ship can be placed
function canPlaceEnemyShip(row, col, size, orientation) {
if (orientation === 'horizontal') {
// Check if ship goes out of bounds
if (col + size > 10) return false;
// Check if any cell is already occupied
for (let i = 0; i < size; i++) {
if (gameState.enemyBoard[row][col + i] !== 0) {
return false;
}
}
} else { // vertical
// Check if ship goes out of bounds
if (row + size > 10) return false;
// Check if any cell is already occupied
for (let i = 0; i < size; i++) {
if (gameState.enemyBoard[row + i][col] !== 0) {
return false;
}
}
}
return true;
}
// Place an enemy ship
function placeEnemyShip(row, col, size, orientation, shipId) {
const shipCells = [];
if (orientation === 'horizontal') {
for (let i = 0; i < size; i++) {
const newCol = col + i;
if (newCol < 10) {
gameState.enemyBoard[row][newCol] = shipId;
shipCells.push({row, col: newCol});
}
}
} else { // vertical
for (let i = 0; i < size; i++) {
const newRow = row + i;
if (newRow < 10) {
gameState.enemyBoard[newRow][col] = shipId;
shipCells.push({row: newRow, col});
}
}
}
// Verify all cells were placed
if (shipCells.length === size) {
// Add to enemy ships
gameState.enemyShips.push({
id: shipId,
name: gameState.shipsToPlace.find(s => s.id === shipId).name,
size: size,
hits: 0,
cells: shipCells
});
return true;
}
return false;
}
// Update player game board
function updatePlayerGameBoard() {
for (let row = 0; row < 10; row++) {
for (let col = 0; col < 10; col++) {
const index = row * 10 + col;
const cell = playerGameBoard.children[index];
// Clear any classes
cell.className = 'cell border border-gray-400 bg-blue-900 bg-opacity-30';
// If cell has a ship, add ship class (only if hit)
if (gameState.playerBoard[row][col] !== 0) {
// Check if this cell has been hit by enemy
const cellHit = cell.classList.contains('hit');
if (cellHit) {
cell.classList.add('ship');
}
}
}
}
}
// Handle enemy cell click (player's attack)
function handleEnemyCellClick(e) {
if (!gameState.playerTurn || gameState.gamePhase !== 'playing') return;
const row = parseInt(e.target.dataset.row);
const col = parseInt(e.target.dataset.col);
// Check if cell was already attacked
if (e.target.classList.contains('hit') || e.target.classList.contains('miss')) {
return;
}
// Process attack
const hit = gameState.enemyBoard[row][col] !== 0;
gameState.enemyBoardAttacks[row][col] = true;
if (hit) {
// It's a hit!
e.target.classList.add('hit');
// Find which ship was hit
const shipId = gameState.enemyBoard[row][col];
const ship = gameState.enemyShips.find(s => s.id === shipId);
// Increment hit count
ship.hits++;
// Check if ship is sunk
if (ship.hits === ship.size) {
// Mark all ship cells as sunk
ship.cells.forEach(({row, col}) => {
const index = row * 10 + col;
const cell = enemyBoard.children[index];
cell.classList.add('ship-sunk');
});
gameStatus.textContent = `You sunk the enemy ${shipId}!`;
// Check if all enemy ships are sunk
if (gameState.enemyShips.every(ship => ship.hits === ship.size)) {
endGame(true);
return;
}
} else {
gameStatus.textContent = "Hit! Attack again!";
}
} else {
// It's a miss
e.target.classList.add('miss');
gameStatus.textContent = "Miss! Enemy's turn.";
gameState.playerTurn = false;
// Enemy's turn after a short delay
setTimeout(enemyTurn, 1000);
}
}
// Enemy's turn
function enemyTurn() {
// Simple AI - random attacks with some intelligence
let row, col, index, cell;
let validAttack = false;
let attempts = 0;
const maxAttempts = 100;
// Try to find a cell that hasn't been attacked yet
while (!validAttack && attempts < maxAttempts) {
row = Math.floor(Math.random() * 10);
col = Math.floor(Math.random() * 10);
index = row * 10 + col;
cell = playerGameBoard.children[index];
if (!cell.classList.contains('hit') && !cell.classList.contains('miss')) {
validAttack = true;
}
attempts++;
}
// If we couldn't find a valid cell (shouldn't happen in normal game)
if (!validAttack) {
console.error("Couldn't find valid attack cell");
gameState.playerTurn = true;
gameStatus.textContent = "Your turn - Attack the enemy!";
return;
}
// Process attack
const hit = gameState.playerBoard[row][col] !== 0;
if (hit) {
// Enemy hit our ship
cell.classList.add('hit');
// Find which ship was hit
const shipId = gameState.playerBoard[row][col];
const ship = gameState.playerShips.find(s => s.id === shipId);
// Increment hit count
ship.hits++;
// Check if ship is sunk
if (ship.hits === ship.size) {
// Mark all ship cells as sunk
ship.cells.forEach(({row, col}) => {
const index = row * 10 + col;
const cell = playerGameBoard.children[index];
cell.classList.add('ship-sunk');
});
gameStatus.textContent = `Enemy sunk your ${shipId}!`;
// Check if all our ships are sunk
if (gameState.playerShips.every(ship => ship.hits === ship.size)) {
endGame(false);
return;
}
} else {
gameStatus.textContent = "Enemy hit your ship! Their turn continues.";
}
// Enemy gets another turn after hitting
setTimeout(enemyTurn, 1000);
} else {
// Enemy missed
cell.classList.add('miss');
gameStatus.textContent = "Enemy missed! Your turn.";
gameState.playerTurn = true;
}
}
// End the game
function endGame(playerWon) {
gameState.gamePhase = 'gameOver';
gameScreen.classList.add('hidden');
gameOverScreen.classList.remove('hidden');
if (playerWon) {
gameResult.textContent = "Congratulations! You won!";
gameResult.className = "text-3xl font-bold mb-6 text-green-400";
} else {
gameResult.textContent = "Game Over! You lost!";
gameResult.className = "text-3xl font-bold mb-6 text-red-400";
}
// Show all enemy ships
showEnemyShips();
}
// Show enemy ships
function showEnemyShips() {
for (let row = 0; row < 10; row++) {
for (let col = 0; col < 10; col++) {
const index = row * 10 + col;
const cell = enemyBoard.children[index];
if (gameState.enemyBoard[row][col] !== 0) {
cell.classList.add('ship');
}
}
}
}
// Toggle showing enemy ships
function toggleShowEnemyShips() {
const cells = enemyBoard.querySelectorAll('.cell');
let showing = false;
// Check if ships are currently shown
cells.forEach(cell => {
if (cell.classList.contains('ship')) {
showing = true;
}
});
// Toggle based on current state
cells.forEach(cell => {
if (gameState.enemyBoard[cell.dataset.row][cell.dataset.col] !== 0) {
if (showing) {
cell.classList.remove('ship');
showShipsBtn.textContent = 'Show Enemy Ships';
} else {
cell.classList.add('ship');
showShipsBtn.textContent = 'Hide Enemy Ships';
}
}
});
}
// New game
function newGame() {
// Reset game state
gameState.gamePhase = 'setup';
gameState.playerTurn = true;
// Switch to setup screen
gameScreen.classList.add('hidden');
gameOverScreen.classList.add('hidden');
setupScreen.classList.remove('hidden');
// Reset boards
initializeBoards();
resetGame();
}
// Play again
function playAgain() {
// Reset game state
gameState.gamePhase = 'setup';
gameState.playerTurn = true;
// Switch to setup screen
gameOverScreen.classList.add('hidden');
setupScreen.classList.remove('hidden');
// Reset boards
initializeBoards();
resetGame();
}
// Return to main menu
function mainMenu() {
// Reset game state
gameState.gamePhase = 'setup';
gameState.playerTurn = true;
// Switch to setup screen
gameOverScreen.classList.add('hidden');
setupScreen.classList.remove('hidden');
// Reset boards
initializeBoards();
resetGame();
}
// Event listeners
rotateBtn.addEventListener('click', () => {
gameState.currentOrientation = gameState.currentOrientation === 'horizontal' ? 'vertical' : 'horizontal';
rotateBtn.textContent = gameState.currentOrientation === 'horizontal' ? 'Horizontal ↔' : 'Vertical ↕';
});
startGameBtn.addEventListener('click', startGame);
randomizeBtn.addEventListener('click', randomizeShips);
resetBtn.addEventListener('click', resetGame);
newGameBtn.addEventListener('click', newGame);
showShipsBtn.addEventListener('click', toggleShowEnemyShips);
playAgainBtn.addEventListener('click', playAgain);
mainMenuBtn.addEventListener('click', mainMenu);
// Initialize the game
initializeBoards();
setupDragAndDrop();
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://deepsite.hf.co/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://deepsite.hf.co" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://deepsite.hf.co?remix=MikePfunk28/battleship-oldschool" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>