如何防止`嵌套`

How to prevent `nesting`

我编写了一个有效的代码,但我的老师告诉我我在“嵌套”,因为他看到了很多 if/else 语句,我尝试缩短我的代码,但我只是不知道如何才能得到删除这些 if/else 语句。

这是我的代码,一个简短的总结: 该代码是 nxn 块的网格,只能与 'blank' 块交换,因此我的代码如下所示:

    grd.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

            // This statement prevents the player from playing the game
            // if the timer is counting down.
            if (timer == true) {
                Toast.makeText(getApplicationContext(),
                        "The game has not started yet!", Toast.LENGTH_SHORT)
                        .show();

            } else {
                clickcounter++;

                // Because difficulty's are 0,1,2 the row/column dimensions
                // are difficulty + 3, here i create the texview of the moves
                // as well.
                size = (int) difficulty + 3;
                TextView movesText = (TextView) findViewById(R.id.textView2);

                // Checks if click is even or odd. Even is firstclick odd is
                // secondclick
                if (clickcounter % 2 == 1) {
                    firstimg = (ImageView) view;
                    firstclick = position;
                    firsttag = (int) firstimg.getTag();

                } else if (clickcounter % 2 == 0) {
                    ImageView secondimg = (ImageView) view;
                    scndtag = (int) secondimg.getTag();

                    // To prevent cheaters to press twice on the same tile
                    // we set this if statement
                    if (position == firstclick) {
                        clickcounter = 1;                       

                    // Next we check whether one of the clicked images
                    // is the blank one, if that's not the case do
                    // nothing!
                    } else if (firsttag != crops.size() - 1
                            && scndtag != crops.size() - 1) {

                    // This else statements checks what happens if one has clicked the
                    // blank tile
                    } else {

                        // This statement below is the same as an switch/case statement
                        // but because of the fact that the switch/case statement gave the
                        // following error i chose for this method:
                        // case expressions must be constant expressions
                        int i = firstclick - position;
                        if (i == -1) {
                            if(firstclick % size == size - 1){

                            } else {
                                swap(firstclick,position);
                                moves++;
                                movesText.setText("Moves: " + moves);
                                checkwin2();
                            }
                        } else if (i == 1) {
                            if(firstclick % size == 0){

                            } else {
                                swap(firstclick,position);
                                moves++;
                                movesText.setText("Moves: " + moves);
                                checkwin2();
                            }
                        } else if (i == size) {
                            swap(firstclick,position);
                            moves++;
                            movesText.setText("Moves: " + moves);
                            checkwin2();
                        } else if (i == -size) {
                            swap(firstclick,position);
                            moves++;
                            movesText.setText("Moves: " + moves);
                            checkwin2();
                        }
                    }
                }
            }
        }
    });
}

我试图做一个switch/case语句来防止这个if/else语句的总和,但是它说它不能将大小识别为常数(因为难度是玩家选择的变量), 所以如果我能做到这一点,也许 if/else 语句的重载就会消失。

有什么建议吗?我已经做了一些工作来使代码更具可读性,原始代码如下所示:

    grd.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
            if (timer == true) {
                Toast toast = new Toast(getApplicationContext());
                toast.makeText(getApplicationContext(),
                        "The game has not started yet!", Toast.LENGTH_SHORT)
                        .show();

            } else {
                clickcounter++;

                // Because difficulty's are 0,1,2 the row/column dimensions
                // are difficulty + 3
                size = (int) difficulty + 3;
                TextView movesText = (TextView) findViewById(R.id.textView2);

                // Checks if click is even or odd. Even is firstclick odd is
                // secondclick
                if (clickcounter % 2 == 1) {
                    firstimg = (ImageView) view;
                    firstclick = position;
                    firsttag = (int) firstimg.getTag();

                } else if (clickcounter % 2 == 0) {
                    ImageView secondimg = (ImageView) view;
                    Bitmap swapImage = crops.get(position);
                    Integer swapID = ID.get(position);
                    scndtag = (int) secondimg.getTag();

                    // To prevent cheaters to press twice on the same tile
                    // we set this if statement
                    if (position == firstclick) {
                        clickcounter = 1;

                    // These next if/else if statements are a summation
                    // of all kinds of
                    // rules that need to be implemented in the game!

                    // First we check whether one of the clicked images
                    // is the blank one
                    } else if (firsttag != crops.size() - 1
                            && scndtag != crops.size() - 1) {

                    // Here we check if the tiles are neighbors of each
                    // other
                    } else if ((position - 1 != firstclick)
                            && (position + 1 != firstclick)
                            && (position + size) != firstclick
                            && ((position - size) != firstclick)) {

                    // Check when secondclick on the right of firstclick
                    } else if (position - 1 == firstclick) {

                        // This prevents the game to swap tiles on the
                        // edges, like
                        // starting from 0, 2 with 3.
                        if (position % size != 0) {
                            crops.set(position, crops.get(firstclick));
                            ID.set(position, ID.get(firstclick));
                            crops.set(firstclick, swapImage);
                            ID.set(firstclick, swapID);
                            moves++;
                            movesText.setText("Moves: " + moves);
                            checkwin2();
                        }

                    // Check when secondclick on the left of firstclick
                    } else if (position + 1 == firstclick) {
                        if (position % size != (size - 1)) {
                            crops.set(position, crops.get(firstclick));
                            ID.set(position, ID.get(firstclick));
                            crops.set(firstclick, swapImage);
                            ID.set(firstclick, swapID);
                            moves++;
                            movesText.setText("Moves: " + moves);
                            checkwin2();
                        }

                    // Check when secondclick is above first
                    } else if ((position + size) == firstclick) {
                        crops.set(position, crops.get(firstclick));
                        ID.set(position, ID.get(firstclick));
                        crops.set(firstclick, swapImage);
                        ID.set(firstclick, swapID);
                        moves++;
                        movesText.setText("Moves: " + moves);
                        checkwin2();

                    // Check when secondclick is above first
                    } else if ((position - size) == firstclick) {
                        crops.set(position, crops.get(firstclick));
                        ID.set(position, ID.get(firstclick));
                        crops.set(firstclick, swapImage);
                        ID.set(firstclick, swapID);
                        moves++;
                        movesText.setText("Moves: " + moves);
                        checkwin2();
                    }

                    // This useful command rebuilds the imageviews
                    grd.invalidateViews();
                }
            }

        }
    });
}

谨致问候,

基斯蒂尔

首先,"too much nesting" 的内在问题是代码维护。所以,学习如何减少它是一个很好的做法。

当您有嵌套时 loops/if-else 可以采取一些措施来消除它。这里有一些提示:

  1. 如果您在代码中看到重复的模式,在您的情况下是这样的:

    交换(第一次点击,位置); 移动++; movesText.setText("Moves: " + 移动); checkwin2();

您应该创建一个方法。然后,如果由于任何原因它发生变化,它都在一个地方。此外,这允许您将 "logic" (if-else) 与过程分开。

  1. 您的代码非常"procedural",这有时是必要的,但却破坏了面向对象编程的好处。要改变这一点,请考虑创建一个对象来处理它。使 "logic variables" 像这样:

    int i = firstclick - position;

并使用此示例,将 "firstclick" 和 "position" 设为私有对象属性并创建 "getters" 和 "setters"。然后根据get/set执行逻辑。这将使您能够专注于“对象”是如何根据对它的更改而受到影响的。然后,如果您执行了第 1 步,则可以将这些方法合并到您的新对象中。

  1. 此外,您可以尝试采用最深的嵌套逻辑,将其变成 "object",然后尝试对下一个最深的嵌套逻辑执行相同的操作,依此类推。这可以揭示不明显的逻辑模式,同时还有助于使您的代码更易于阅读和维护。

  2. 检查您的 "flag" 变量。也许应该将它们归为一个或多个对象。您甚至可以将对象用作 "flag" - 但即使是标志也可以成为代码中的两个或多个变量,而不是正确地成为单个对象。

注意:不要"afraid"只有一种或两种方法的小或简单的对象。另外,不要犹豫使用单行方法。重要的是将动作(方法)和属性(变量)放在对象中,因为它们 相关