0

I am trying to create a FEN notation converter for chess. I've decided the best way to go about this is to remove any unnecessary values from the string that I don't need. Here is what it looks like.

rnbqkbnr/pppppppp/8/

These are all strings in my code. I've already found solutions for the end of each file which is represented by the / in the string. But my new problem is taking away the number values and adding back in blank squares to cover them.

When you see a number in FEN, that is essentially how many empty squares on the Chess table there are until another piece. My idea once again, to dumb it down for myself, was to convert these numbers like 8 into this 11111111 a series of numbers representing each square that would have to be empty.

While in practice, I assumed that I would just be able to splice the 8 out and just start filling up that index onwards with 1, this seems to be viable option, but unfortunately is quite buggy when moving the number around to different places.

Would anyone have a better option for this? Yes I know that there is already libraries that accomplish this, but what's the fun of coding if you don't attempt to reinvent the wheel a couple times.

correctFen function - maps over the string looking for any numbers

  const correctFen = () => {
    newFen.map((pos, index) => {
      if (Number(pos) && pos !== '/'){
        for (let i = 0; i < Number(pos); i++) {
          console.log('firing')
          setNewFen(addAfter(newFen, index + i, '1'))
        }
      }
    })
    console.log(newFen)
    figureOutPos()
  }

after looking at this, it's not really removing the index that I'm wanting, could be a problem here, it's adding the 1s after the last /

function addAfter(array, index, newItem) {
  return [
    ...array.slice(0, index),
    newItem,
    ...array.slice(index)
  ];
}
4156
  • 380
  • 4
  • 17
  • 1
    Your idea is good; if there are bugs, they're in the implementation, so please post the code. – Thomas Jul 06 '21 at 06:37
  • Welcome to Stack Overflow! Visit the [help], take the [tour] to see what and [ask].If you get stuck, post a [mcve] of your attempt, noting input and expected output using the [`[<>]`](https://meta.stackoverflow.com/questions/358992/ive-been-told-to-create-a-runnable-example-with-stack-snippets-how-do-i-do) snippet editor. – mplungjan Jul 06 '21 at 06:37
  • 1
    If you split the string into an array using `chessString.split('/')` you can then `.map()` it to a new array where the function replaces numbers with a string of ones of the indicated length: https://jsfiddle.net/po2c3dfv/ –  Jul 06 '21 at 06:39
  • @Thomas added some of my original code to it to help explain a bit more. I believe the problem is something small that I'm just not figuring out. – 4156 Jul 06 '21 at 06:43
  • @ChrisG checkout comment above - why can't I tag more than one person? – 4156 Jul 06 '21 at 06:44
  • 1
    That's how the comment system works :) Anyway, changing React state is asynchronous. You need to compose the complete new string first, and only then call `setNewFen` –  Jul 06 '21 at 06:47

1 Answers1

0

Looks like you're modifying newFen from the map callback. This would indeed mess up indices because everything after the current index shifts around.

Instead, return the new character(s) from the map callback. In most cases this will be the original character, but if it's a digit, you'll return a string of multiple characters. Then join the array together into a string again.

Something like this:

// Assuming newFen is a string in some outer scope.
const correctFen = () => {
  const correctedFen = newFen
    // Split the string into an array of single characters.
    .split('')
    // Apply a function to each character and gather the results in an array.
    .map((char, _index) => {
      // Try to parse `char` as an integer.
      const number = parseInt(char)
      if (isNaN(number)) {
        // `char` is not a digit. Return the character itself.
        return char
      } else {
        // `char` is a digit. Return a string of that many 1s.
        return '1'.repeat(number)
      }
    })
    // Join the array back into a string.
    .join('')
  setNewFen(correctedFen)
}
Thomas
  • 174,939
  • 50
  • 355
  • 478