0

I made the following code to allocate words in a array of arrays. Like a word game.

var board = [
  ["m","t","h","v","g","y","m","w","n","q"],
  ["q","e","v","f","a","k","n","c","c","k"],
  ["x","s","r","e","r","c","m","c","h","a"],
  ["j","z","f","w","g","i","o","t","b","l"],
  ["x","v","j","m","x","q","s","s","v","c"],
  ["m","i","i","a","e","u","t","t","j","m"],
  ["t","n","j","w","h","j","e","m","b","d"],
  ["v","n","t","f","r","y","b","q","v","a"],
  ["k","q","x","b","q","w","c","i","v","g"],
  ["s","o","m","e","t","h","i","n","g","t"]
];

const directions = [
  'horizontal',
  'vertical'
];

function chooseRandomPlace() {
  return [Math.floor(Math.random() * 10),
          Math.floor(Math.random() * 10)];
}

let i = 0;
function horizontal(word) {
  i++;
  console.log(i);
  let wordLength = word.length;
  let [x, y] = chooseRandomPlace();
  if (9 - y < wordLength) return horizontal(word);

  for (let i = 0; i < wordLength; i++) {
    if (typeof board[x][y + i] !== 'string') {
      return horizontal(word)
    }
  }

  for (let i = 0; i < wordLength; i++) {
    board[x][y + i] = {value: word[i]};
  }
}

function vertical(word) {
  i++;
  console.log(i);
  let wordLength = word.length;
  let [x, y] = chooseRandomPlace();
  if (9 - x < wordLength) return vertical(word);


  for (let i = 0; i < wordLength; i++) {
    if (typeof board[x + i][y] !== 'string') {
      return vertical(word);
    }
  }

  for (let i = 0; i < wordLength; i++) {
    board[x + i][y] = {value: word[i]};
  }
}

function alocate(word) {
  let direction = directions[Math.floor(Math.random() * directions.length)];
  if (direction === 'horizontal') {
    horizontal(word)
  } else {
    vertical(word);
  }
  console.log(JSON.stringify(board));
}

const words = ['SOMETHIN', 'SOMETHIN', 'SOMETHIN', 'SOMETHIN', 'SOMETHIN'];
for (let word of words) {
  let location = alocate(word);
}

And is working, but it can cause a Maximum call stack size exceeded error error depending on the number of words (max of 10) and the length of each word. Is there any type of improvement to do to avoid this... and if not, is there some sort of mathematic algorithm to set a secure limit of words with max length?

Thank you.

2
  • 1
    You currently place words successively at random positions without overlap. As soon as no such position is available, you descend into an endless loop. Ideally, you would recognise this and perform backtracking. Commented Apr 18, 2017 at 3:27
  • Why did you delete previous Question? Commented Apr 18, 2017 at 3:37

1 Answer 1

1

Convert string representing word to an array. Create two variables reflecting starting index of array within array of arrays and index within array of arrays which current index of string should be set at to re-form the word.

Post increment vertical index to, which corresponds to adjacent array within array of arrays. Set each adjacent array at index where, which corresponds to the index of current array, to value of index of string. To set letter horizontally, post increment from variable.

You can create a function which accepts an optional object where values can be set at indexes of board array reflecting horizontal and diagonal coordinates to generate a crossword board having words in horizontal, vertical and diagonal lines on the board.

There are at least nine words at crossword board at stacksnippets, where .color of .textContent of element is changed at click where the letter is part of a word.

let board = [["m","t","h","v","g","y","m","w","n","q"],
            ["q","e","v","f","a","k","n","c","c","k"],
            ["x","s","r","e","r","c","m","c","h","a"],
            ["j","z","f","w","g","i","o","t","b","l"],
            ["x","v","j","m","x","q","s","s","v","c"],
            ["m","i","i","a","e","u","t","t","j","m"],
            ["t","n","j","w","h","j","e","m","b","d"],
            ["v","n","t","f","r","y","b","q","v","a"],
            ["k","q","x","b","q","w","c","i","v","g"],
            ["a","d","r","j","m","n","r","e","n","t"]];

const div = document.querySelector("div");

const settings = {list:void 0, diagonal:false, horizontal:false, from:0, to:0};

const setWord = (coords) => {

  div.innerHTML = "";
  
  let {list, from, to, diagonal, horizontal} = Object.assign({}, settings, coords);
  
  if (!list || list.length && list.length === 0) 
    throw new Error("list is not defined");
  
  for (let letter of list) {
    let [x, y] = [horizontal ? to : to++
                 , diagonal || horizontal ? from++ : from];
    board[x][y] = `<span onclick="this.className='letter'">${letter}</span>`;
  }

  for (let arr of board) {
    div.innerHTML += `${arr.map(letter =>
      /^</.test(letter) ? letter : `<span>${letter}</span>`).join(" ")}<br>`;
  }

}

setWord({list:"su", diagonal:false, from:4, to:2});
setWord({list:"ha", diagonal:false, from:2, to:0});
setWord({list:"lemur", diagonal:true, from:2, to:2});
setWord({list:"f", diagonal:false, from:2, to:3});
setWord({list:"d", diagonal:false, from:5, to:3});
setWord({list:"a", diagonal:false, from:6, to:3});
setWord({list:"l", diagonal:false, from:7, to:3});
setWord({list:"l", diagonal:false, from:7, to:3});
setWord({list:"p", diagonal:false, from:5, to:6});
setWord({list:"pa", horizontal:true, from:0, to:2});
setWord({list:"m", horizontal:true, from:3, to:2});
setWord({list:"clone", diagonal:false, from:7, to:2});
.letter {
  color: green;
}

div {
  background: #000;
  width: 180px;
  margin: 4px;
  padding: 4px;
  border: 4px solid goldenrod;
}

div span {
  color: red;
  white-space: pre;
  position: relative;
  display: inline-block;
  width: 14px;
}
<div></div>

Sign up to request clarification or add additional context in comments.

1 Comment

@zer00ne May never know. High science or common chatter.

Your Answer

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