├── README.md ├── app.js ├── index.html └── style.css /README.md: -------------------------------------------------------------------------------- 1 | # battleships 2 | pure JavasScript game of BattleShips against the computer 3 | 4 | Work In Progress 5 | 6 | The computer will take a random go on the user grid after the game start button is pressed and the user has taken their first go. 7 | 8 | - Computers BattleShips are currently visible 9 | - Users Grid is blue 10 | - Computers grid is green and the battleships are randomly generated 11 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', () => { 2 | const userGrid = document.querySelector('.grid-user') 3 | const computerGrid = document.querySelector('.grid-computer') 4 | const displayGrid = document.querySelector('.grid-display') 5 | const ships = document.querySelectorAll('.ship') 6 | const destroyer = document.querySelector('.destroyer-container') 7 | const submarine = document.querySelector('.submarine-container') 8 | const cruiser = document.querySelector('.cruiser-container') 9 | const battleship = document.querySelector('.battleship-container') 10 | const carrier = document.querySelector('.carrier-container') 11 | const startButton = document.querySelector('#start') 12 | const rotateButton = document.querySelector('#rotate') 13 | const turnDisplay = document.querySelector('#whose-go') 14 | const infoDisplay = document.querySelector('#info') 15 | const userSquares = [] 16 | const computerSquares = [] 17 | const width = 10 18 | let isGameOver = false 19 | let currentPlayer = 'user' 20 | let isHorizontal = true 21 | 22 | // Create Boards 23 | function createBoard(grid, squares, width) { 24 | for (let i = 0; i < width*width; i++) { 25 | const square = document.createElement('div') 26 | square.setAttribute('id', i) 27 | grid.appendChild(square) 28 | squares.push(square) 29 | } 30 | } 31 | createBoard(userGrid, userSquares, width) 32 | createBoard(computerGrid, computerSquares, width) 33 | 34 | // Ships 35 | const shipArray = [ 36 | { 37 | name: 'destroyer', 38 | directions: [ 39 | [0, 1], 40 | [0, width] 41 | ] 42 | }, 43 | { 44 | name: 'submarine', 45 | directions: [ 46 | [0, 1, 2], 47 | [0, width, width*2] 48 | ] 49 | }, 50 | { 51 | name: 'cruiser', 52 | directions: [ 53 | [0, 1, 2], 54 | [0, width, width*2] 55 | ] 56 | }, 57 | { 58 | name: 'battleship', 59 | directions: [ 60 | [0, 1, 2, 3], 61 | [0, width, width*2, width*3] 62 | ] 63 | }, 64 | { 65 | name: 'carrier', 66 | directions: [ 67 | [0, 1, 2, 3, 4], 68 | [0, width, width*2, width*3, width*4] 69 | ] 70 | } 71 | ] 72 | 73 | 74 | // Draw the computers ships in random locations 75 | function generate(ship) { 76 | let randomDirection = Math.floor(Math.random() * ship.directions.length) 77 | let current = ship.directions[randomDirection] 78 | if (randomDirection === 0 ) direction = 1 79 | if (randomDirection === 1) direction = 10 80 | let randomStart = Math.abs(Math.floor(Math.random() * computerSquares.length - (ship.directions[0].length * direction))) 81 | 82 | const isTaken = current.some(index => computerSquares[randomStart + index].classList.contains('taken')) 83 | const isAtRightEdge = current.some(index => (randomStart + index) % width === width - 1) 84 | const isAtLeftEdge = current.some(index => (randomStart + index) % width === 0) 85 | 86 | if (!isTaken && !isAtRightEdge && !isAtLeftEdge) current.forEach(index => computerSquares[randomStart + index].classList.add('taken', ship.name)) 87 | 88 | else generate(ship) 89 | } 90 | generate(shipArray[0]) 91 | generate(shipArray[1]) 92 | generate(shipArray[2]) 93 | generate(shipArray[3]) 94 | generate(shipArray[4]) 95 | 96 | //Rotate the Ships 97 | function rotate() { 98 | if (isHorizontal) { 99 | destroyer.classList.toggle('destroyer-container-vertical') 100 | submarine.classList.toggle('submarine-container-vertical') 101 | cruiser.classList.toggle('cruiser-container-vertical') 102 | battleship.classList.toggle('battleship-container-vertical') 103 | carrier.classList.toggle('carrier-container-vertical') 104 | isHorizontal = false 105 | return 106 | } 107 | if (!isHorizontal) { 108 | destroyer.classList.toggle('destroyer-container-vertical') 109 | submarine.classList.toggle('submarine-container-vertical') 110 | cruiser.classList.toggle('cruiser-container-vertical') 111 | battleship.classList.toggle('battleship-container-vertical') 112 | carrier.classList.toggle('carrier-container-vertical') 113 | isHorizontal = true 114 | return 115 | } 116 | } 117 | rotateButton.addEventListener('click', rotate) 118 | 119 | // Move around user ship options 120 | ships.forEach(ship => ship.addEventListener('dragstart', dragStart)) 121 | userSquares.forEach(square => square.addEventListener('dragstart', dragStart)) 122 | userSquares.forEach(square => square.addEventListener('dragover', dragOver)) 123 | userSquares.forEach(square => square.addEventListener('dragenter', dragEnter)) 124 | userSquares.forEach(square => square.addEventListener('drageleave', dragLeave)) 125 | userSquares.forEach(square => square.addEventListener('drop', dragDrop)) 126 | userSquares.forEach(square => square.addEventListener('dragend', dragEnd)) 127 | 128 | let selectedShipIndex 129 | let draggedShip 130 | let draggedShipLength 131 | 132 | ships.forEach(ship => ship.addEventListener('mousedown', (e) => { 133 | selectedShipIndex = e.target.id 134 | })) 135 | 136 | function dragStart(e){ 137 | draggedShipNode = this.childNodes.item(e.target) 138 | draggedShip = this 139 | draggedShipLength = this.childNodes.length 140 | } 141 | 142 | function dragOver(e) { 143 | e.preventDefault() 144 | } 145 | 146 | function dragEnter(e) { 147 | e.preventDefault() 148 | } 149 | 150 | function dragLeave() { 151 | console.log('dragLeave',this) 152 | } 153 | 154 | function dragDrop() { 155 | shipId = draggedShip.firstChild.id 156 | shipClass = shipId.slice(0, -2) 157 | 158 | if (selectedShipIndex === draggedShip.firstChild.id) { 159 | for (let i = 0; i < draggedShipLength; i++) { 160 | if (isHorizontal) { 161 | userSquares[parseInt(this.id) + i].classList.add('taken', shipClass) 162 | } else userSquares[parseInt(this.id) + width*i].classList.add('taken', shipClass) 163 | } 164 | } 165 | if (draggedShip.childNodes[1] && selectedShipIndex === draggedShip.childNodes[1].id) { 166 | for (let i = 0; i < draggedShipLength; i++) { 167 | if (isHorizontal) { 168 | userSquares[parseInt(this.id) -1 + i].classList.add('taken', shipClass) 169 | } else userSquares[parseInt(this.id) -1 + width*i].classList.add('taken', shipClass) 170 | } 171 | } 172 | if (draggedShip.childNodes[2] && selectedShipIndex === draggedShip.childNodes[2].id) { 173 | for (let i = 0; i < draggedShipLength; i++) { 174 | if (isHorizontal) { 175 | userSquares[parseInt(this.id) -2 + i].classList.add('taken', shipClass) 176 | } else userSquares[parseInt(this.id) -2 + width*i].classList.add('taken', shipClass) 177 | } 178 | } 179 | if (draggedShip.childNodes[3] && selectedShipIndex === draggedShip.childNodes[3].id) { 180 | for (let i = 0; i < draggedShipLength; i++) { 181 | if (isHorizontal) { 182 | userSquares[parseInt(this.id) -3 + i].classList.add('taken', shipClass) 183 | } else userSquares[parseInt(this.id) -3 + width*i].classList.add('taken', shipClass) 184 | } 185 | } 186 | if (draggedShip.childNodes[4] && selectedShipIndex === draggedShip.childNodes[4].id) { 187 | for (let i = 0; i < draggedShipLength; i++) { 188 | if (isHorizontal) { 189 | userSquares[parseInt(this.id) -4 + i].classList.add('taken', shipClass) 190 | } else userSquares[parseInt(this.id) -4 + width*i].classList.add('taken', shipClass) 191 | } 192 | } 193 | displayGrid.removeChild(draggedShip) 194 | } 195 | 196 | function dragEnd() { 197 | console.log('dragEnd',this ) 198 | } 199 | 200 | 201 | // Game logic 202 | function playGame() { 203 | if (isGameOver) return 204 | if (currentPlayer === 'user') { 205 | turnDisplay.innerHTML = 'Your Go' 206 | computerSquares.forEach(square => square.addEventListener('click', function(e) { 207 | revealSquare(square) 208 | })) 209 | } 210 | if (currentPlayer === 'computer') { 211 | turnDisplay.innerHTML = 'Computers Go' 212 | setTimeout (computerGo, 1000) 213 | } 214 | } 215 | startButton.addEventListener('click', playGame) 216 | 217 | // Notify user of users wins 218 | let destroyerCount = 0 219 | let submarineCount = 0 220 | let cruiserCount = 0 221 | let battleshipCount = 0 222 | let carrierCount = 0 223 | 224 | function revealSquare(square) { 225 | if (!square.classList.contains('boom')) { 226 | if (!square.classList.contains('boom') && square.classList.contains('destroyer')) destroyerCount++ 227 | if (!square.classList.contains('boom') && square.classList.contains('submarine')) submarineCount++ 228 | if (!square.classList.contains('boom') && square.classList.contains('cruiser')) cruiserCount++ 229 | if (!square.classList.contains('boom') && square.classList.contains('battleship')) battleshipCount++ 230 | if (!square.classList.contains('boom') && square.classList.contains('carrier')) carrierCount++ 231 | 232 | if (square.classList.contains('taken')) { 233 | square.classList.add('boom') 234 | } 235 | checkForWins() 236 | currentPlayer = 'computer' 237 | playGame() 238 | } 239 | 240 | } 241 | 242 | // Notify user of computers wins 243 | let cpuDestroyerCount = 0 244 | let cpuSubmarineCount = 0 245 | let cpuCruiserCount = 0 246 | let cpuBattleshipCount = 0 247 | let cpuCarrierCount = 0 248 | 249 | function computerGo() { 250 | let random = Math.floor(Math.random() * userSquares.length) 251 | if (!userSquares[random].classList.contains('boom')) { 252 | userSquares[random].classList.add('boom') 253 | if (userSquares[random].classList.contains('destroyer')) cpuDestroyerCount++ 254 | if (userSquares[random].classList.contains('submarine')) cpuSubmarineCount++ 255 | if (userSquares[random].classList.contains('cruiser')) cpuCruiserCount++ 256 | if (userSquares[random].classList.contains('battleship')) cpuBattleshipCount++ 257 | if (userSquares[random].classList.contains('carrier')) cpuCarrierCount++ 258 | checkForWins() 259 | } else computerGo() 260 | currentPlayer = 'user' 261 | turnDisplay.innerHTML = 'Your Go' 262 | } 263 | 264 | 265 | // Check for wins 266 | function checkForWins() { 267 | if (destroyerCount === 2) { 268 | infoDisplay.innerHTML = 'You sunk the computers destroyer' 269 | destroyerCount = 10 270 | } 271 | if (submarineCount === 3) { 272 | infoDisplay.innerHTML = 'You sunk the computers submarine' 273 | submarineCount = 10 274 | } 275 | if (cruiserCount === 3) { 276 | infoDisplay.innerHTML = 'You sunk the computers cruiser' 277 | cruiserCount = 10 278 | } 279 | if (battleshipCount === 4) { 280 | infoDisplay.innerHTML = 'You sunk the computers battleship' 281 | battleshipCount = 10 282 | } 283 | if (carrierCount === 5) { 284 | infoDisplay.innerHTML = 'You sunk the computers carrier' 285 | carrierCount = 10 286 | } 287 | if (cpuDestroyerCount === 2) { 288 | infoDisplay.innerHTML = 'Computer sunk the your destroyer' 289 | cpuDestroyerCount = 10 290 | } 291 | if (cpuSubmarineCount === 3) { 292 | infoDisplay.innerHTML = 'Computer sunk the your submarine' 293 | cpuSubmarineCount = 10 294 | } 295 | if (cpuCruiserCount === 3) { 296 | infoDisplay.innerHTML = 'Computer sunk the your cruiser' 297 | cpuCruiserCount = 10 298 | } 299 | if (cpuBattleshipCount === 4) { 300 | infoDisplay.innerHTML = 'Computer sunk the your battleship' 301 | cpuBattleshipCount = 10 302 | } 303 | if (cpuCarrierCount === 5) { 304 | infoDisplay.innerHTML = 'Computer sunk the your carrier' 305 | cpuCarrierCount = 10 306 | } 307 | if ((destroyerCount + submarineCount + cruiserCount + battleshipCount + carrierCount) === 50) { 308 | infoDisplay.innerHTML = 'YOU WIN!' 309 | isGameOver = true 310 | } 311 | if ((cpuDestroyerCount + cpuSubmarineCount + cpuCruiserCount + cpuBattleshipCount + cpuCarrierCount) === 50) { 312 | infoDisplay.innerHTML = 'COMPUTER WINS!' 313 | isGameOver = true 314 | } 315 | } 316 | 317 | }) 318 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Battle Ships 6 | 7 | 8 | 9 | 10 | 11 |

12 | 13 |
14 |
15 |
16 |
17 | 18 |
19 | 20 | 21 |

Your Go

22 |

23 |
24 | 25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | .grid-user { 2 | width: 400px; 3 | height: 400px; 4 | display: flex; 5 | flex-wrap: wrap; 6 | margin: 20px; 7 | background-color: blue; 8 | } 9 | 10 | .grid-computer { 11 | width: 400px; 12 | height: 400px; 13 | display: flex; 14 | flex-wrap: wrap; 15 | margin: 20px; 16 | background-color: lightgreen; 17 | } 18 | 19 | .grid-display { 20 | width: 400px; 21 | height: 400px; 22 | margin: 20px; 23 | background-color: yellow; 24 | } 25 | 26 | .grid div { 27 | width: 40px; 28 | height: 40px; 29 | } 30 | 31 | .container { 32 | display: flex; 33 | } 34 | 35 | .taken { 36 | background-color: black 37 | } 38 | 39 | .destroyer-container { 40 | width: 80px; 41 | height: 40px; 42 | background-color: orange; 43 | margin: 10px; 44 | } 45 | 46 | .destroyer-container-vertical { 47 | width: 40px; 48 | height: 80px; 49 | display: flex; 50 | flex-wrap: wrap; 51 | background-color: orange; 52 | margin: 10px; 53 | } 54 | 55 | .submarine-container { 56 | width: 120px; 57 | height: 40px; 58 | background-color: pink; 59 | margin: 10px; 60 | } 61 | 62 | .submarine-container-vertical { 63 | width: 40px; 64 | height: 120px; 65 | display: flex; 66 | flex-wrap: wrap; 67 | background-color: pink; 68 | margin: 10px; 69 | } 70 | 71 | .cruiser-container { 72 | width: 120px; 73 | height: 40px; 74 | background-color: purple; 75 | margin: 10px; 76 | } 77 | 78 | .cruiser-container-vertical { 79 | width: 40px; 80 | height: 120px; 81 | display: flex; 82 | flex-wrap: wrap; 83 | background-color: purple; 84 | margin: 10px; 85 | } 86 | 87 | .battleship-container { 88 | width: 160px; 89 | height: 40px; 90 | background-color: aqua; 91 | margin: 10px; 92 | } 93 | 94 | .battleship-container-vertical { 95 | width: 40px; 96 | height: 160px; 97 | display: flex; 98 | flex-wrap: wrap; 99 | background-color: aqua; 100 | margin: 10px; 101 | } 102 | 103 | .carrier-container { 104 | width: 200px; 105 | height: 40px; 106 | background-color: green; 107 | margin: 10px; 108 | } 109 | 110 | .carrier-container-vertical { 111 | width: 40px; 112 | height: 200px; 113 | display: flex; 114 | flex-wrap: wrap; 115 | background-color: green; 116 | margin: 10px; 117 | } 118 | 119 | .destroyer { 120 | background-color: orange; 121 | } 122 | 123 | .submarine { 124 | background-color: pink; 125 | } 126 | 127 | .cruiser { 128 | background-color: purple; 129 | } 130 | 131 | .battleship { 132 | background-color: aqua; 133 | } 134 | 135 | .carrier { 136 | background-color: green; 137 | } 138 | 139 | 140 | .ship div { 141 | width: 40px; 142 | height: 40px; 143 | display: inline-block; 144 | } 145 | 146 | 147 | .boom { 148 | background-color: red; 149 | } 150 | --------------------------------------------------------------------------------