How to create a simple Prompt BattleShip Game in Javascript

Viewed 1182

I need to make a battleship game in JS with Prompt and I cant for the life of Me figure it out. Example is attached: https://www.youtube.com/watch?v=xSpJLx72PQY Quality isnt very good Here is some code

// BattleShip Grid
let grid = ["0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"];
// Ship Locations
let shipLocations = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19"];
// Hit Locations
let hit = ["3", "9", "15"];
let enterNumber = "Enter a Number Between 0-19";
// Prompts First Guess
let guess = prompt(grid + '\n' + (enterNumber));
// Checks if there is a HIT
if(hit.indexOf(guess) !== -1){
        grid[guess] = "1";
        prompt(grid + '\n' + (enterNumber));
//Checks for Miss
    } else{
        grid[guess] = "X";
        prompt(grid + '\n' + (enterNumber));
    }

Needs to be

0 0 0 0 0 
0 0 0 0 0 
0 0 0 0 0 
0 0 0 0 0 

Every time a hit happens the 0 where the hit happens becomes a 1 and if a miss it becomes an X and needs to update in the prompt. Hope someone can help. Was using an array. If someone could give me the answer so I can look it over and understand it would be great. Im very new

Hit

0 0 0 1 0 
0 0 0 0 0 
0 0 0 0 0 
0 0 0 0 0 

Miss

0 0 0 0 0 
0 X 0 0 0 
0 0 0 0 0 
0 0 0 0 0 

Updates

0 0 0 1 0 
0 X 0 0 0 
0 0 0 0 0 
0 0 0 0 0 

UPDATE credit to julien.giband

New code, how do I get it to show a grid of 20 so 5 x 4?

const GRID_SIZE = 5;


const grid = ["0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"];
// Ship Locations
const shipLocations = ["3", "9", "15"];
let guess; //Entered value
let count = 0; //counter for rounds
do { //We'll loop indefintely until the user clicks cancel on prompt

  //Construct prompt using string template (multiline)
  const prpt = `Round #${++count}
${printGrid()}
Enter a Number Between 0-19`;
  guess = prompt(prpt);
  if (!guess && guess !== 0)
    break; //Stop when cancel was clicked
  
  const hit = shipLocations.indexOf(guess) >= 0;
  console.log(`At round ${count}, cell ${guess} is a ${hit ? 'hit': 'miss'}`);
  grid[guess] = hit ? '1' : 'X';
} while (guess || guess === 0); //Must have an exit condition

/** Pretty-print the grid **/
function printGrid() {
  let res = "";
  for (let r = 0; r < GRID_SIZE; r++) {
    let srow = "";
    for (let c = 0; c < GRID_SIZE; c++) {
      srow += " " + grid[r * GRID_SIZE + c];
    }
    res += srow.substr(1) + '\n';
  }
  return res;
}
2 Answers

//Grid size: result will be n*n cells
const GRID_SIZE = 5;

// BattleShip Grid (filled with 0s)
const grid = new Array(GRID_SIZE * GRID_SIZE);
grid.fill('0');
// Ship Locations
const shipLocations = [];
//Set test ship locations to first 3 rows fully filled
for (let i = 0; i < GRID_SIZE * 3; i++) {
  shipLocations.push("" + i);
}

let guess; //Entered value
let count = 0; //counter for rounds
do { //We'll loop indefintely until the user clicks cancel on prompt

  //Construct prompt using string templates
  guess = prompt( `Round #${++count}\n` +
                  `${printGrid()}\n` +
                  `Enter a Number Between 0-${GRID_SIZE * GRID_SIZE - 1}`);
  if (!guess && guess !== 0)
    break; //Stop when cancel was clicked
  
  const hit = shipLocations.indexOf(guess) >= 0;
  console.log(`At round ${count}, cell ${guess} is a ${hit ? 'hit': 'miss'}`);
  grid[guess] = hit ? '1' : 'X';
} while (guess || guess === 0); //Must have an exit condition

/** Pretty-print the grid **/
function printGrid() {
  let res = "";
  for (let r = 0; r < GRID_SIZE; r++) {
    let srow = "";
    for (let c = 0; c < GRID_SIZE; c++) {
      srow += " " + grid[r * GRID_SIZE + c];
    }
    res += srow.substr(1) + '\n';
  }
  return res;
}

I made an engine like class of my own. It sports a scalable map, ships of different orientations and sizes, as well as random ship positioning.

//////////////////////
// GLOBAL VARIABLES //
//////////////////////

let game = new Battleship(6, 5) //Change map size here
let theShips={
    A: 3, // ID:size
    B: 2, // feel free to add more ships
    C: 4,
    D: 1
  }

let map = []
let round = 0
let note = ''
let moves = []

///////////////
// FUNCTIONS //
///////////////

function newmap() {
  let size = game.size
  map = []
  moves = []
  round = 0
  game.newmap()
  while (size--) {
    map.push(' _ ')
  }
}

function show(msg, arr) {
  let display = `${msg} \n`
  for (let y = 0; y < game.y; y++) {
    for (let x = 0; x < game.x; x++)
      display += `${arr[ x + (game.x*y) ]} `
    display += '\n'
  }
  return display
}

function watch(bool, msg) {
  if (bool) console.log(msg, 'successful!')
  else console.log(msg, 'failed!')
  return bool
}

function makeGuess(guess) {
  let ret = false
  let valid
  if (guess.toLowerCase().trim() == 'exit') ret = true
  guess = parseInt(guess)
  valid = 0 < guess < game.size
  if (valid && !moves.includes(guess)) {
    moves.push(guess)
    if (game.checkPosition(guess)) ret = hit(guess)
    else miss(guess)
    round++
  }
  return ret
}

function hit(position) {
  let sunk = game.hitShip(position)
  map[position] = ' O ' // When a ship is hit it will appear as an 'O'
  note = "It's a HIT!!!"
  return !game.checkShip(sunk) ? sunkShip(sunk) : false
}

function miss(position) {
  map[position] = ' X ' // When a ship is missed guess will appear as an 'X'
  note = "It's a miss!"
  return false
}

function sunkShip(id) {
  note = 'You sunk a ship'
  game.ships.splice(game.ships.indexOf(id), 1)
  return game.ships.length < 1
}

function newRandomMap(battleships) {
  for (let ships in battleships)
    while (true)
      if (watch(game.placeShip(ships, random(game.size), battleships[ships], random(2) ? 'horizontal' : 'vertical'), `Ship '${ships}' placement`)) break;
}

function random(num) {
  return Math.floor(Math.random() * num)
}

function init() {
  newmap() // make a map
  newRandomMap(theShips)
}

function startGame() {
  while (true) {
    if (makeGuess(prompt(promptMSG()))) break;
  }
  if (game.ships.length < 1) alert('You successfully sunk all the ships!!!')
}

function promptMSG() {
  return `note:Type 'exit' to stop\nRound#${round} ${show(note,map)}Pick a number from 0 to ${game.size-1}`
}

////////////////
// INITIALIZE //
////////////////

init()
//console.log(game.ships)
//console.log(show('Hidden',game.map))
//console.log(show('Make the first move',map))
startGame()
<script>
////////////
// ENGINE //
////////////

class Battleship { // engine by StepPen-codes
  constructor(x, y) {
    this.x = x
    this.y = y
    this.size = x * y
    this.map = []
    this.ships = []

    this.newmap()
  }
  newmap() {
    let i = this.size
    this.ships = [] // reset ships array
    while (i--)
      this.map[i] = "0" //resets map array
  }
  hitShip(position) {
    let id = this.map[position]
    this.map[position] = "0"
    return id
  }
  checkShip(id) {
    return this.map.includes(id)
  }
  checkPosition(position) {
    return this.map[position] != "0"
  }
  placeShip(id, position, size, orientation = 'horizontal') {
    let posY = Math.floor(position / this.x)
    let posX = position % this.x
    let placed = false

    if (!this.ships.includes(id)) {
      switch (orientation) {
        case 'horizontal':
          if (size + posX <= this.x) {
            placed = this.setShip(id, position, size, 1)
          }
          break;
        case 'vertical':
          if (size + posY <= this.y) {
            placed = this.setShip(id, position, size, this.x)
          }
          break;
      }
      if (placed) this.ships.push(id) // setting ship is successful include ship in ships
    }
    return placed
  }
  setShip(id, position, size, adjustment) {
    let ship = [],
      ret = true
    for (let i = 0; i < size; i++) {
      let pos = position + (i * adjustment)
      if (!this.checkPosition(pos)) ship.push(pos)
      else {
        ret = false
        break;
      }
    }
    if (ret)
      for (let i of ship) this.map[i] = id
    return ret
  }
}
</script>

Here it is:

Related