0

New to OO, I am making a game and I have this as my initialState :

let initialState = {
  grid : null,
  player : {
    coordinates : null,
    health : 100 ,
    weapon : "Stick",
    expLevel : 1
  },
  enemies : [],
  weapons : [],
  items : []
}

when DOM is loaded, I am able to initialize weapons and items corretly. However, both of these properties share the exact functionality except the object literal that is initialized :

initialState.weapons = placeWeapons(3);
initialState.items = placeItems(2);

where placeWeapons

function placeWeapons(numberofWeapons){
  let weapons = [];
  let availableSpots = [];
  let placementWeapons = []; //list of coordinates that will place weapons
  let grid = initialState.grid;

  //collect whats available of coords that are not taken in initialState.occupiedCoordinates
  grid.forEach( (row, rowIndex) => (
    row.forEach( (cell, colIndex) => {
      if (cell === 1){
        availableSpots.push([rowIndex,colIndex])
      }
    })
  ))

  //lets place the weapons. When placed, it will update initialState.occupiedCoordinates
  while( placementWeapons.length < numberofWeapons ){
    let randCoords = availableSpots[Math.floor(Math.random() * availableSpots.length)];
    if (grid[randCoords[0]][randCoords[1]] === 1){
      placementWeapons.push(randCoords);
      grid[randCoords[0]][randCoords[1]] = 0
    }
  }
  placementWeapons.forEach( coord => {
    let weapon = {
      name : "Weapon Name",
      coords : coord,
      damage : 3
    }
    weapons.push(weapon)
  })
  return weapons;
}

placeItems

function placeItems(numberofItems){
  let items = [];
  let availableSpots = [];
  let placementItems = []; //list of coordinates that will place items
  let grid = initialState.grid;

  //collect whats available of coords that are not taken in initialState.occupiedCoordinates
  grid.forEach( (row, rowIndex) => (
    row.forEach( (cell, colIndex) => {
      if (cell === 1){
        availableSpots.push([rowIndex,colIndex])
      }
    })
  ))

  //lets place the items. When placed, it will update initialState.occupiedCoordinates
  while( placementItems.length < numberofItems ){
    let randCoords = availableSpots[Math.floor(Math.random() * availableSpots.length)];
    if (grid[randCoords[0]][randCoords[1]] === 1){
      placementItems.push(randCoords);
      grid[randCoords[0]][randCoords[1]] = 0
    }
  }
  placementItems.forEach( coord => {
    let item = {
      name : "Item Name",
      coords : coord,
      health : 3
    }
    items.push(item)
  })
  return items;
}

How can I DRY this pattern?

1
  • Make it easier by writing a function that returns an array of possible placements. Commented Nov 2, 2016 at 2:56

1 Answer 1

2

The only significant difference I see is the thing being placed. So the logical thing to do is extract that and pass it in as an argument:

// WARNING: Untested code:
function placeThings(thing, numberofThings){
  let things = [];
  let availableSpots = [];
  let placementItems = []; //list of coordinates that will place things
  let grid = initialState.grid;

  //collect whats available of coords that are not taken in initialState.occupiedCoordinates
  grid.forEach( (row, rowIndex) => (
    row.forEach( (cell, colIndex) => {
      if (cell === 1){
        availableSpots.push([rowIndex,colIndex])
      }
    })
  ))

  //lets place the items. When placed, it will update initialState.occupiedCoordinates
  while( placementItems.length < numberofThings ){
    let randCoords = availableSpots[Math.floor(Math.random() * availableSpots.length)];
    if (grid[randCoords[0]][randCoords[1]] === 1){
      placementItems.push(randCoords);
      grid[randCoords[0]][randCoords[1]] = 0
    }
  }
  placementItems.forEach( coord => {
    things.push(Object.create(thing))
  })
  return things;
}

Now you can do:

// Weapons:
placeThings({
  name : "Weapon Name",
  coords : coord,
  damage : 3
},50);

// Items:
placeThings({
  name : "Item Name",
  coords : coord,
  health : 3
},100);

If you want to make the things being placed random you can just pass a function instead of an object:

// WARNING: Untested code:
function placeThings(thingGenerator, numberofThings){
  let things = [];

  /*
   * bla bla..
   */

  placementItems.forEach( coord => {
    things.push(thingGenerator())
  })
  return things;
}

So you'd do something like:

placeThings(makeWeapon, 50);
placeThings(makeItem, 100);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.