单词搜索游戏:网格生成需要很长时间

时间:2018-02-28 10:16:11

标签: javascript algorithm performance

我正在开发一个Word Search益智游戏,我正在努力用字母生成网格。目前,我能够生成网格,但性能非常慢(对于正常使用而言太慢,在生成网格之前可能需要30-40秒)。

为了使单词适合网格,我使用的是递归函数,它试图拟合给定列表中的最后一个单词,然后是它之前的单词,等等,如果它不合适,则回溯到前一个单词并改变它的位置,然后再试一次。我想我做得不对,因为它一直来回走。

我尝试使用加权概率作为方向,因此生成是以“更聪明”的方式进行的,但我还没有得到任何结果。

我的问题: 如何优化此代码以使其更高效和可靠?我接受任何建议,即使它让我做了很多改变(例如,如果有一个迭代解决方案而不是递归的解决方案,或者我在函数中没有正确推理......)。

这是功能:

function tryWord(grid, wordList, index, gridLength){
    var valid = false;
    var clear = false;

    if(index==(wordList.length-1)){
        /* Clear grid for current index */
        for(var j=0; j<gridLength.x; j++){
            grid[index][j] = [];
            for (var k=0; k<gridLength.y; k++){
                grid[index][j][k] = '';
            }
        }
        var nbIterations = 0;
        // Try current word
        while(valid == false){
            // Impossible to resolve this grid
            if(nbIterations>500){
                return false;
            }
            nbIterations++;
            var initX = Math.floor(Math.random() * gridLength.x); // x coord of first letter of the word
            var initY = Math.floor(Math.random() * gridLength.y); // y coord of first letter of the word
            var direction = Math.floor(Math.random() * 8); // direction of the word (0=top-left; 1=top; 2=top-right; 3=right; 4=bottom-right; 5=bottom; 6=bottom-left; 7=left)

            valid = checkValidWord(wordList[index].length, initX, initY, direction, gridLength);
        }

        clear = checkClearWord(wordList[index], initX, initY, direction, grid[index]);
        if(!clear){
            return false;
        }

        var x = initX;
        var y = initY;
        for(var j=0; j<wordList[index].length; j++){

            grid[index][x][y] = wordList[index].charAt(j);
            switch(direction){
                case 0:
                    x--;
                    y--;
                    break;
                case 1:
                    y--;
                    break;
                case 2:
                    x++;
                    y--;
                    break;
                case 3:
                    x++;
                    break;
                case 4:
                    x++;
                    y++;
                    break;
                case 5:
                    y++;
                    break;
                case 6:
                    x--;
                    y++;
                    break;
                case 7:
                    x--;
                    break;
                default:
                    break;
            }
        }
        return grid;
    }
    else if(index!=(wordList.length-1)){
        var emptyGrid = true;
        for(var p=0; p<grid[index].length; p++){
            for(var q=0; q<grid[index][p].length; q++){
                if(grid[index][p][q]!=''){
                    emptyGrid = false;
                }
            }
        }
        if(emptyGrid || $scope.nbIterations>50){
            $scope.nbIterations=0;
            grid = tryWord(grid, wordList, index+1, gridLength);
        }
        /* Prepare grid for current index */
        grid[index] = grid[index+1];
        if(grid!=false){
            // Try current word
            while(valid == false){
                var initX = Math.floor(Math.random() * gridLength.x); // x coord of first letter of the word
                var initY = Math.floor(Math.random() * gridLength.y); // y coord of first letter of the word
                var direction = Math.floor(Math.random() * 8); // direction of the word (0=top-left; 1=top; 2=top-right; 3=right; 4=bottom-right; 5=bottom; 6=bottom-left; 7=left)

                valid = checkValidWord(wordList[index].length, initX, initY, direction, gridLength); // Check that word fits in the grid

            }

            clear = checkClearWord(wordList[index], initX, initY, direction, grid[index]);
            // If word is obstructed by other words
            if(!clear){
                $scope.nbIterations++;
                return tryWord(grid, wordList, index, gridLength); // Try again
            }
            else{
                var x = initX;
                var y = initY;
                for(var j=0; j<wordList[index].length; j++){                   

                    grid[index][x][y] = wordList[index].charAt(j);
                    switch(direction){
                        case 0:
                            x--;
                            y--;
                            break;
                        case 1:
                            y--;
                            break;
                        case 2:
                            x++;
                            y--;
                            break;
                        case 3:
                            x++;
                            break;
                        case 4:
                            x++;
                            y++;
                            break;
                        case 5:
                            y++;
                            break;
                        case 6:
                            x--;
                            y++;
                            break;
                        case 7:
                            x--;
                            break;
                        default:
                            break;
                    }
                }
                return grid;
            }
        }
        else{
            return false;
        }
    }
}

该功能的参数:

  • grid:在开头,只是一个填充''字符串的10x11x11数组。
  • wordList:要放入网格的一系列单词
  • index:0第一次调用函数时,它用于检查我们在wordList中的深度
  • gridLength:一个数组:{x:11,y:11},给出网格长度

关于该功能的更多准确性:

  • 函数checkValidWord检查到达给定方向的给定单词是否适合具有给定大小的网格。返回true或false。
  • 函数checkClearWord检查进入给定方向的给定单词是否适合网格中的其他单词(无阻塞等)。返回true或false。
  • 函数tryWord应该输出大小为[wordList.length; 11; 11]的三维数组。然后我使用grid [0]作为游戏的2维网格。

0 个答案:

没有答案