title: Nine-puzzle game breaks on tile alignment
body: <p>I'm currently doing a puzzle game just for fun. I'm sure everybody knows how this works, so I can probably skip the explanation.</p>
  
  <p>I can move a tile just fine the first two times. However, the board breaks after that.</p>
  
  <p>The <code>idx</code> property should point to the position in the grid. 0 for top left and 8 for bottom right. The <code>x</code> and <code>y</code> coordinates are basically the same thing, but I only use those for css positioning. </p>
  
  <p>A random tile is picked and is not rendered. My idea was that I'd swap the coordinates and <code>idx</code> of the tile you click on, with the hidden tile. However, it didn't quite work as expected and after hours of searching I think I need a pair of new eyes to help me spot my error.</p>
  
  <p>The problem is when you click on a tile to move it, so somewhere in <code>moveTile()</code>...</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="true">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>class NinePuzzle extends React.Component {
      constructor() {
      super();
      let q = [["0% 0%"], ["0% 50%"], ["0% 100%"], ["50% 0%"], ["50% 50%"], ["50% 100%"], ["100% 0%"], ["100% 50%"], ["100% 100%"]];
      this.removedTileIdx = Math.floor(Math.random() * 9);
      this.state = {
       bg: "https://media.wired.com/photos/595693e45992c54331ac2031/1:1/w_2400,c_limit/Porsche911_HP.jpg",
        tilesArr: [
         {idx: 0, bgPos: q.splice(Math.floor(Math.random()*9), 1)[0], x: 0, y: 0},
          {idx: 1, bgPos: q.splice(Math.floor(Math.random()*8), 1)[0], x: 33.333, y: 0},
          {idx: 2, bgPos: q.splice(Math.floor(Math.random()*7), 1)[0], x: 66.666, y: 0},
          {idx: 3, bgPos: q.splice(Math.floor(Math.random()*6), 1)[0], x: 0, y: 33.333},
          {idx: 4, bgPos: q.splice(Math.floor(Math.random()*5), 1)[0], x: 33.333, y: 33.333},
          {idx: 5, bgPos: q.splice(Math.floor(Math.random()*4), 1)[0], x: 66.666, y: 33.333},
          {idx: 6, bgPos: q.splice(Math.floor(Math.random()*3), 1)[0], x: 0, y: 66.666},
          {idx: 7, bgPos: q.splice(Math.floor(Math.random()*2), 1)[0], x: 33.333, y: 66.666},
          {idx: 8, bgPos: q.splice(Math.floor(Math.random()*1), 1)[0], x: 66.666, y: 66.666},
        ],
        noTileIdx: this.removedTileIdx,
      };
    }
    
    moveTile = (selectedIdx) =&gt; {
     let flag = false;
     let {noTileIdx} = this.state;
     let arr = this.state.tilesArr.slice();
      
      let selectedTile = Object.assign({}, arr[selectedIdx]);
      let hiddenTile = Object.assign({}, arr[noTileIdx]);
      
      let hX = hiddenTile.x;
      let hY = hiddenTile.y;
      
      if(noTileIdx+1 == selectedIdx || noTileIdx-1 == selectedIdx) {
       hiddenTile.x = selectedTile.x;
        selectedTile.x = hX;
        flag = true;
      } else if(noTileIdx+3 == selectedIdx || noTileIdx-3 == selectedIdx) {
       hiddenTile.y = selectedTile.y;
        selectedTile.y = hY;
        flag = true;
      }
      if(!flag) return;
      
      selectedTile.idx = noTileIdx;    
      hiddenTile.idx = selectedIdx;
  
      arr[selectedIdx] = selectedTile;    
      arr[noTileIdx] = hiddenTile;
      
      this.setState({tilesArr: arr, noTileIdx: selectedIdx});
    }
    
    render() {
     return(
       &lt;div className="board"&gt;
          {this.state.tilesArr.map(
           (item, i) =&gt; {
             if(i === this.removedTileIdx) return null;
             return (
               &lt;div
                  key={item.idx}
                  onClick={this.moveTile.bind(this, item.idx)}
                  style={{
                   backgroundImage: "url('"+ this.state.bg +"')",
                   backgroundPosition: item.bgPos,
                   left: item.x + "%",
                   top: item.y + "%"
                 }}
                /&gt;
              );
            }
          )}
       &lt;/div&gt;
      );
    }
  }
  
  ReactDOM.render(&lt;NinePuzzle /&gt;, document.getElementById("app"));</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>.board {
    width: 300px;
    height: 300px;
    border: 3px solid #5F5F22;
    border-radius: 5px;
    background-color: #FFFFC2;
    line-height: 0;
    position: relative;
  }
  
  .board div {
    width: 100px;
    height: 100px;
    display: inline-block;
    background-size: 300px;
    position: absolute;
    transition: top .25s, left .25s;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"&gt;&lt;/script&gt;
  &lt;div id="app"&gt;&lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>