175 lines
5.5 KiB
JavaScript
175 lines
5.5 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import Board from './Board';
|
|
import './GameBoard.css';
|
|
|
|
function checkSunkShip(ships, hits) {
|
|
const sunkShipsArrays = ships.filter((ship) =>
|
|
ship.every((cell) =>
|
|
hits.some((hit) => hit.row === cell.row && hit.col === cell.col)
|
|
)
|
|
);
|
|
|
|
sunkShipsArrays.forEach((ship) => {
|
|
const size = ship.length;
|
|
if (size === 4) {
|
|
console.log('Battleship (4 cells) is sunk!');
|
|
} else if (size === 3) {
|
|
console.log('Cruiser (3 cells) is sunk!');
|
|
} else if (size === 2) {
|
|
console.log('Destroyer (2 cells) is sunk!');
|
|
} else if (size === 1) {
|
|
console.log('Submarine (1 cell) is sunk!');
|
|
}
|
|
});
|
|
|
|
return sunkShipsArrays.flat();
|
|
}
|
|
|
|
function GameBoard({ gameId, player1Name, player2Name, player1Ships, player2Ships, onNewGame }) {
|
|
const [currentPlayer, setCurrentPlayer] = useState(1);
|
|
const [hitsP1, setHitsP1] = useState([]);
|
|
const [missesP1, setMissesP1] = useState([]);
|
|
const [hitsP2, setHitsP2] = useState([]);
|
|
const [missesP2, setMissesP2] = useState([]);
|
|
const [sunkShipsP1, setSunkShipsP1] = useState([]);
|
|
const [sunkShipsP2, setSunkShipsP2] = useState([]);
|
|
const [winner, setWinner] = useState(null);
|
|
|
|
useEffect(() => {
|
|
console.log('player1Ships:', JSON.stringify(player1Ships, null, 2));
|
|
console.log('player2Ships:', JSON.stringify(player2Ships, null, 2));
|
|
}, []);
|
|
|
|
const saveGameResult = async (winnerName, loserName) => {
|
|
try {
|
|
const resp = await fetch('http://localhost:30000/api/save-result', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
gameId,
|
|
winner: winnerName,
|
|
loser: loserName,
|
|
moves: hitsP1.length + hitsP2.length
|
|
})
|
|
});
|
|
const data = await resp.json();
|
|
console.log('Game result saved:', data);
|
|
} catch (err) {
|
|
console.error('Error saving game result:', err);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
const totalCellsP1 = player1Ships.flat().length;
|
|
const totalCellsP2 = player2Ships.flat().length;
|
|
|
|
if (hitsP1.length === totalCellsP2) {
|
|
setWinner(player1Name);
|
|
saveGameResult(player1Name, player2Name);
|
|
} else if (hitsP2.length === totalCellsP1) {
|
|
setWinner(player2Name);
|
|
saveGameResult(player2Name, player1Name);
|
|
}
|
|
}, [hitsP1, hitsP2, player1Ships, player2Ships, player1Name, player2Name]);
|
|
|
|
useEffect(() => {
|
|
const sunkForP1 = checkSunkShip(player1Ships, hitsP2);
|
|
const sunkForP2 = checkSunkShip(player2Ships, hitsP1);
|
|
|
|
setSunkShipsP1(sunkForP1);
|
|
setSunkShipsP2(sunkForP2);
|
|
}, [hitsP1, hitsP2, player1Ships, player2Ships]);
|
|
|
|
const handleAttack = (row, col, opponent) => {
|
|
if (winner) return;
|
|
|
|
let alreadyAttacked;
|
|
if (opponent === 2) {
|
|
alreadyAttacked = [...hitsP1, ...missesP1].some(
|
|
(cell) => cell.row === row && cell.col === col
|
|
);
|
|
} else {
|
|
alreadyAttacked = [...hitsP2, ...missesP2].some(
|
|
(cell) => cell.row === row && cell.col === col
|
|
);
|
|
}
|
|
|
|
if (alreadyAttacked) {
|
|
alert('You have already attacked this cell!');
|
|
return;
|
|
}
|
|
|
|
let isHit = false;
|
|
if (opponent === 2) {
|
|
isHit = player2Ships.flat().some((cell) => cell.row === row && cell.col === col);
|
|
if (isHit) {
|
|
setHitsP1([...hitsP1, { row, col }]);
|
|
console.log(`Player1 hit a ship at [${row},${col}] on Player2's board`);
|
|
} else {
|
|
setMissesP1([...missesP1, { row, col }]);
|
|
console.log(`Player1 missed at [${row},${col}] on Player2's board`);
|
|
}
|
|
} else {
|
|
isHit = player1Ships.flat().some((cell) => cell.row === row && cell.col === col);
|
|
if (isHit) {
|
|
setHitsP2([...hitsP2, { row, col }]);
|
|
console.log(`Player2 hit a ship at [${row},${col}] on Player1's board`);
|
|
} else {
|
|
setMissesP2([...missesP2, { row, col }]);
|
|
console.log(`Player2 missed at [${row},${col}] on Player1's board`);
|
|
}
|
|
}
|
|
|
|
if (!isHit) {
|
|
setCurrentPlayer(currentPlayer === 1 ? 2 : 1);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="game-board">
|
|
{winner ? (
|
|
<div className="winner-section">
|
|
<h2>Winner: {winner}!</h2>
|
|
<button className="new-game-button" onClick={onNewGame}>Start New Game</button>
|
|
</div>
|
|
) : (
|
|
<h2 className="turn-title">Current turn: {currentPlayer === 1 ? player1Name : player2Name}</h2>
|
|
)}
|
|
|
|
<div className="boards-container">
|
|
<div className="board-wrapper">
|
|
<h3>{player1Name}'s Board</h3>
|
|
<Board
|
|
boardSize={10}
|
|
ships={player1Ships.flat()}
|
|
hits={hitsP2}
|
|
misses={missesP2}
|
|
sunkShips={sunkShipsP1}
|
|
onCellClick={
|
|
currentPlayer === 2 ? (r, c) => handleAttack(r, c, 1) : null
|
|
}
|
|
hideShips={true}
|
|
/>
|
|
</div>
|
|
|
|
<div className="board-wrapper">
|
|
<h3>{player2Name}'s Board</h3>
|
|
<Board
|
|
boardSize={10}
|
|
ships={player2Ships.flat()}
|
|
hits={hitsP1}
|
|
misses={missesP1}
|
|
sunkShips={sunkShipsP2}
|
|
onCellClick={
|
|
currentPlayer === 1 ? (r, c) => handleAttack(r, c, 2) : null
|
|
}
|
|
hideShips={true}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default GameBoard;
|