村农

莫笑农家腊酒浑,丰年留客足鸡豚。


24点-js代码

TD-winter

###数组全排列 如[1,2,3,4] => [[1,1,1,1],[1,1,1,2]...[4,4,4,4]],代码如下:

    var rankAndComb = function(new_rank,array,flag,new_array){//new_rank为每次排序出来的序列,array为要排序的数组,flag为进入到第几个数字排序的标识,new_array为存储组合的数组。
        var len = array.length;
        for(var i = 0; i < len; i++){
            if(flag == len){
                if(i == 0){
                    new_array.push(new_rank);
                }else{
                    continue;
                }
            }else{
    rankAndComb(new_rank.concat(array[i]),array,flag+1,new_array);
//rankAndComb(new_rank.concat(array[i]),array.splice(i,1),flag+1,new_array);
                }
            }
            return new_array;
        }

###数组组合 如[1,2,3,4] => [[1,2,3,4],[1,2,4,3]...[4,3,2,1]]代码如下:

var rankAndCombSub = function(new_rank,array,new_array){
//new_rank每次生成的组合数组,array为要排序的数组,new_array为最终要返回的存储组合的数组
    var len = array.length;
    for(var i = 0;i < len;i++){
        if(len == 1){
            new_rank.push(array[0]);
            new_array.push(new_rank);
        }else{
            //console.log('%c '+ array+' i='+i, 'color:red');
            var new_rank_clone = objClone(new_rank);
            var array_clone = objClone(array);
            new_rank_clone.push(array_clone[i]);
            array_clone.splice(i,1);
            rankAndCombSub(new_rank_clone,array_clone,new_array);
        }
    }
    return new_array;
}
//示例
var rank24 = rankAndCombSub([],[1,3,2,4],[]);

###面向过程式完成24点 此方法无扩展性,只是为了完成任务。

var point24 = function(array){//限制了4个数字,需改动成任意数字
    //var len = array.length;
    for(var i = 0;i < 4;i++){
        var number_1 = operation(i,array[1],array[0]);
        for(var j = 0;j < 4;j++){
            var number_2 = operation(j,array[2],number_1);
            for(var k = 0;k < 4;k++){
                var number_3 = operation(k,array[3],number_2);
                if(number_3 == 24){
                    //console.log(array,opSign(i),opSign(j),opSign(k));
                }
            }
        }
    }
}

###排列运算 其实排列运算也是一种组合,如24点游戏中(四个数字),就是从['+','-','*','/']四个运算符中,选取三个进行排序,并于那四个数字进行运算而已。代码如下:

var point24Game = function(array,n,total,symbol_array){
    for(var i = 0;i < 4;i++){
        if(n != array.length){
            var temp_symbol_array = objClone(symbol_array);
            temp_symbol_array.push(i);
            point24Game(array,n+1,operation(i,array[n],total),temp_symbol_array);
        }else{
            if(total == 24){
                console.log(total,array,signToArray(symbol_array));
                break;
            }
        }
    }
}

###其它的一些辅助方法

var operation = function(op,number,total){//运算方式
    switch(op){
        case 0 :
            total = total + number;
            break;
        case 1 : 
            total = total - number;
            break;
        case 2 :
            total = total * number;
            break;
        case 3 : 
            total = total / number;
            break;
    }
    return total;
}
var opSign = function(op){//将[1,2,3,4]运算符代表的数字转化为运算符字符;如:1 => '+',2 => '-'
    switch(op){
        case 0 :
            return '+'
        case 1 : 
            return '-'
        case 2 :
            return '*'
        case 3 : 
            return '/'
    }
}
var signToArray = function(op_array){//将运算符代表的数组,转化成存储运算符符号的数组;如:如:[1,2,3,4] => ['+','-','*','/']
    return op_array.map(function(item){
        return opSign(item);
    })
}
var objClone = function(obj){//对象和数组实现深拷贝
    return JSON.parse(JSON.stringify(obj));
}

###总结 总的说来,这个实现发方式并不难,但在实现的时间却花了一天。实现过程中,也发现很多js有意思的事,如: 1.对象和数组的浅拷贝和容易影响结果和过程,且难以排查。 2.push、splice、concat等数组操作函数的正确使用。到底有没有改变原数组、有没有生成副本、返回值事什么等等。当这些问题和深浅拷贝纠缠在一起了,代码的复杂度一下子上升了几个层次,难以排查问题,切结果难以预料。 3.对于递归和迭代还有for循环的理解,break、continue、return等在何时何地准确的使用及打断的到底事什么。 4.要想代码理解度高,还是得函数式编程。只需关注传入值及返回值。且一定要控制变量的入口,最好禁止直接在函数中直接使用外部变量,而没通过参数传入的。 5.函数的传参没你想的那么简单,特别在自身被重复调用的时候,且,对象和数组作为参数应格外小心。