我如何 Refactor/Extract 处理 java 中的这种气味代码?

How do i Refactor/Extract method on this smell codes in java?

我在重构这段代码时遇到了问题。我如何提取这个长方法? 我不知道这些代码中的气味代码在哪里,你们能帮我弄清楚这些气味代码以及如何重构这些代码吗?

private boolean placingFlag = false;
    protected Scanner scan = new Scanner(System.in);
    public void play() {
        clear();
        print();

        if(placingFlag) {
            System.out.println("currently your command is for placing/unplacing flag. Type 'switch' to start opening squares");
        } else {
            System.out.println("currently your command is for opening square. Type 'switch' to placing flag");
        }

        do {
            System.out.print("Input coordinate to command: ");
            String input = scan.nextLine().trim();
            if(input.equalsIgnoreCase("switch")) {
                placingFlag = !placingFlag;
                break;
            }
            if(input.length() != 2) {
                System.out.println("invalid coordinate");
                continue;
            }

            char c1 = input.charAt(0);
            char c2 = input.charAt(1);
            int x = c1 - 'A';
            int y = c2 - '1';

            if(x < 0 || x >= gameSetting.getWidth()) {
                System.out.println("invalid coordinate");
                continue;
            }
            if(y < 0 || y >= gameSetting.getHeight()) {
                System.out.println("invalid coordinate");
                continue;
            }

            if(!placingFlag) {
                if(board[y][x].flagged){
                    System.out.println("cannot open flagged square");
                    continue;
                }
                if(board[y][x].getType().equalsIgnoreCase("mine")) {
                    this.lose();
                    return;
                }

                open(x, y);

                if(isWin()) {
                    this.win();
                    return;
                }
            } else {
                if(board[y][x].getType().equalsIgnoreCase("number")) {
                    System.out.println("opened squared cannot be flagged");
                    continue;
                }
                board[y][x].flagged = !board[y][x].flagged;
            }
            break;
        }while(true);

        play();
    }

请大佬们指点一下这些代码如何提取这些长方法:)

还不错。你可以做一件事——根据输入将阅读输入与播放分开:

private static class GameMove {
  int x;
  int y;
  boolean switchFlagPlacingMode;
}

private GameMove readNextMove() { 
 // read in using the scanner
 // and validate the coordinates
}

另一件事 - while(true) 绝对是一种代码味道,你拥有的 continuebreakreturn 语句的数量也是如此 - 它们构成了代码很难追踪。考虑类似

boolean gameOver = false;

while(!gameOver) {

  boolean isMoveValid = false;
  GameMove nextMove = readNextMove();
  while(!isMoveValid) {
    // validate, set isMoveValid
    // if invalid: nextMove = readNextMove();
  }

  // process the move
  if (isWin()) {
    this.win();
    gameOver = true;
  }
  // similar for loss
}