考虑所有方案

时间:2014-05-16 03:53:47

标签: javascript if-statement

我目前有一个很长的脚本,可以解释每个场景。我写这篇文章是为了在棋盘上向上,向下,向左或向右移动AI。

包括所有评论,我的实际脚本长448行,非常混乱,因为大多数代码被复制到每个场景的帐户。 (如果感兴趣,可以找到here

所以你不必查看448行代码,我写了一些伪代码:

function ai() {
    var r = 0 or 1
    if condition

        if 0
            r = 0 or 1
            if 0
                if canDo c
                    do c
                else
                    if canDo d
                        do d
                    else
                        if canDo a
                            do a
                        else
                            if canDo b
                                do b
                            else
                                giveUp
            else if 1
                if canDo d
                    do d
                else
                    if canDo c
                        do c
                    else
                        if canDo a
                            do a
                        else
                            if canDo b
                                do b
                            else
                                giveUp
        else if 1
            r = 0 or 1
            if 0
                if canDo a
                    do a
                else
                    if canDo b
                        do b
                    else
                        if canDo c
                            do c
                        else
                            if canDo d
                                do d
                            else
                                giveUp
            else if 1
                if canDo b
                    do b
                else
                    if canDo a
                        do a
                    else
                        if canDo c
                            do c
                        else
                            if canDo d
                                do d
                            else
                                giveUp
    else

        if 0
            r = 0 or 1
            if 0
                if canDo c
                    do c
                else
                    if canDo d
                        do d
                    else
                        if canDo a
                            do a
                        else
                            if canDo b
                                do b
                            else
                                giveUp
            else if 1
                if canDo d
                    do d
                else
                    if canDo c
                        do c
                    else
                        if canDo a
                            do a
                        else
                            if canDo b
                                do b
                            else
                                giveUp
        else if 1
            r = 0 or 1
            if 0
                if canDo a
                    do a
                else
                    if canDo b
                        do b
                    else
                        if canDo c
                            do c
                        else
                            if canDo d
                                do d
                            else
                                giveUp
            else if 1
                if canDo b
                    do b
                else
                    if canDo a
                        do a
                    else
                        if canDo c
                            do c
                        else
                            if canDo d
                                do d
                            else
                                giveUp
}

是否有更简单的方法可以实现多种方案,因为您可以看到它变得非常快很长?

2 个答案:

答案 0 :(得分:1)

最重要的是要识别出重复代码的位置(并且你有很多代码)并将其分解为可重用的函数。然后,这通常会让您注意到更多重复的代码,您可以进一步考虑这些代码。然后您可能会注意到类似的代码,并且可以将其分解为更一般的情况。这就是我在你的代码上做到这一点时想出来的:

function ai(charPos) {
    var r = getRandomInt(0, 1);
    if (aiPos[0] - pos[0] > (aiPos[1] - pos[1]) * 2) {
        // Horizontal distance shorter than vertical distance
        if (!isInLine(charPos, aiPos, 'vertical')) {
            tryVerticalThenHorizontal();
        } else {
            tryHorizontalThenVertical();
        }
    } else {
        // Vertical distance shorter than horizontal distance
        if (!isInLine(charPos, aiPos, 'horizontal')) {
            tryHorizontalThenVertical();
        } else {
            tryVerticalThenHorizontal();
        }
    }
}

function Move(name, dx, dy) {
    this.name = name;
    this.dx = dx;
    this.dy = dy;
}

var verticalMoves = [new Move("up", 0, -1), new Move("down", 0, 1)];
var horizontalMoves = [new Move("left", -1, 0), new Move("right", 1, 0)];

function tryVerticalThenHorizontal() {
    if (!(pickAndTryMoves(verticalMoves) || pickandTryMoves(horizontalMoves))) {
        aiShoot();
    }
}

function tryHorizontalThenVertical() {
    if (!(pickAndTryMoves(horizontalMoves) || pickAndTryMoves(verticalMoves))) {
        aiShoot();
    }
}

// Returns true if a move succeeded, false if not
// moves should be an array with two items, each of which is a Move 
function pickAndTryMoves(moves) {
    var option = getRandomInt(0, 1;

    // Try moves[option], and moves[otherOption] if the first one fails
    return tryMove(moves[option]) || tryMove(moves[1 - option]);
}

// move is a Move object
function tryMove(move) {
    var canMove = canAiMove(move.name);
    if (canMove) {
        moveAi(move.dx, move.dy, move.name);
    }

    return canMove;
}

function moveAi(dx, dy, dirName) {
    var x = aiPos[0], y = aiPos[1],
        nextX = x + dx, nextY = y + dy;
    map[nextY] = map[nextY].replaceAt(nextX, '2');
    map[y] = map[y].replaceAt(x, wallChar);
    aiPos[0] = nextX;
    aiPos[1] = nextY;
    aiLastDir = dirName;
}

答案 1 :(得分:0)

您可以测试不可能的条件,几乎所有代码都只是复制/粘贴以前的代码。将这些转化为功能,并更好地组织它们。

你不可能的条件的例子:

if (r == 1) {
  do a
} else {
  if (r == 1) {
    do b
  } else {
    do c
  }
}

在这种情况下不可能做b,如果r不等于1,我们只能到else语句,为什么我们再次测试呢?

我将相同的代码格式化为40行。你将不得不经历它,但你可以看到这样的事情是多么容易维护和更新:

function ai(charPos) {
    var r = getRandomInt(0, 1);
    var arrUp = [0, -1, 'up'], arrDown = [0, 1, 'down'], 
        arrLeft = [-1, 0, 'left'], arrRight = [1, 0 'right'];

    if (r == 1) {
        var horizontalArray = [arrRight, arrLeft, arrDown, arrUp];
        var verticalArray    = [arrUp, arrDown, arrLeft, arrRight];
    } else {
        var horizontalArray = [arrLeft, arrRight, arrUp, arrDown];
        var verticalArray    = [arrDown, arrUp, arrRight, arrLeft];
    }

    if (aiPos[0] - pos[0] > (aiPos[1] - pos[1]) * 2) {
        // Horizontal distance shorter than vertical distance
        if (!isInLine(charPos, aiPos, 'vertical')) ? move(verticalArray) : move(horizontalArray);
    } else {
        // Vertical distance shorter than horizontal distance
        if (!isInLine(charPos, aiPos, 'horizontal')) ? move(horizontalArray) : move(verticalArray);
    }
}

function directionalMove(directions) {
    if (canAiMove(directions[0][0])) {
        mappos(directions[0][0], directions[0][1], directions[0][2]);
    } else if (canAiMove(directions[1][0])) {
        mappos(directions[1][0], directions[1][1], directions[1][2]);
    } else if (canAiMove(directions[2][0])) {
        mappos(directions[2][0], directions[2][1], directions[2][2]);
    } else if (canAiMove(directions[3][0])) {
        mappos(directions[3][0], directions[3][1], directions[3][2]);
    } else {
        aiShoot();
    }
}

function mappos(x, y, name) {
        map[aiPos[1] + y] = map[aiPos[1] + y].replaceAt(aiPos[0] + x, '2');
        map[aiPos[1]] = map[aiPos[1]].replaceAt(aiPos[0], wallChar);
        aiPos[0] = aiPos[0] + x;
        aiPos[1] = aiPos[1] + y;
        aiLastDir = name;
}