首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >2048 Java克隆

2048 Java克隆
EN

Code Review用户
提问于 2015-02-03 02:38:34
回答 1查看 3K关注 0票数 6

我正在做一个2048年的克隆,我的移动和合并瓷砖的方法真的很长。我听说过助手方法,但我有点不知道该如何使用它们。我觉得我的代码有点长,可以缩短,但我不知道怎么做。我能做些什么使它更短更干净?我也会接受任何建设性的批评,任何其他部分的方法。

代码语言:javascript
复制
 public boolean move(Direction direction)
{
boolean didMove = false;
int multiplier = 2;
if (direction == Direction.RIGHT) {

    //int i represents rows; int j represents columns
    for (int i = 0; i < GRID_SIZE; i++ ) {
    ArrayList<Integer> slideTile = new ArrayList<>();

    //Copying row w/o 0s  to ArrayList
    for (int j = 0; j < GRID_SIZE; j++) {
        if(grid[i][j] != 0) {
        slideTile.add(grid[i][j]);
        }
    }

    //Merging tiles that are next to each other if
    //they are equal and updating score.
    for (int j = slideTile.size()-1; j > 0; j--) {
        if (slideTile.get(j).equals(slideTile.get(j-1))) {
        slideTile.set(j, multiplier*slideTile.get(j-1));
        score = score + multiplier*slideTile.get(j-1);
        slideTile.set(j-1, 0);
        }
    }

    //Removing 0s that may have resulted from merging
    for (int j = 0; j < slideTile.size(); j++ ) {
        if (slideTile.get(j) == 0) {
            slideTile.remove(j);
        }
    }

    //Adding 0s to beginning of ArrayList to slide tiles right
    int size = slideTile.size();
    for (int j = 0; j < (GRID_SIZE - size); j++){
        slideTile.add(0, 0);
    }

    //Copying ArrayList row back to game grid.
    for (int j = 0; j < GRID_SIZE; j++) {
        this.grid[i][j] = slideTile.get(j);
    }
    }
    didMove = true;
    }

if (direction == Direction.LEFT) {

    //int i represents rows; int j represents columns
    for (int i = 0; i < GRID_SIZE; i++ ) {
    ArrayList<Integer> slideTile = new ArrayList<>();

    //Copying row w/o 0s  to ArrayList
    for (int j = 0; j < GRID_SIZE; j++) {
        if(grid[i][j] != 0) {
        slideTile.add(grid[i][j]);
        }
    }

    //Merging tiles that are next to each other if
    //they are equal and updating score.        
    for (int j = 0; j < slideTile.size()-1; j++) {
        if (slideTile.get(j).equals(slideTile.get(j+1))) {
        slideTile.set(j, multiplier*slideTile.get(j+1));
        score = score + multiplier*slideTile.get(j+1);
        slideTile.set(j+1, 0);
        }
    }

    //Removing 0s that may have resulted from merging
    for (int j = 0; j < slideTile.size(); j++ ) {
        if (slideTile.get(j) == 0) {
            slideTile.remove(j);
        }
    }

    //Adding 0s to end of ArrayList to slide tiles left
    int size = slideTile.size();
    for (int j = 0; j < (GRID_SIZE - size); j++){
        slideTile.add(0);
    }

    //Copying ArrayList row back to game grid.
    for (int j = 0; j < GRID_SIZE; j++) {
        this.grid[i][j] = slideTile.get(j);
    }
    }
    didMove = true;
    }

if (direction == Direction.UP) {

    //int i represents rows; int j represents columns
    for (int j = 0; j < GRID_SIZE; j++ ) {
    ArrayList<Integer> slideTile = new ArrayList<>();

    //Copying row w/o 0s  to ArrayList
    for (int i = 0; i < GRID_SIZE; i++) {
        if ( grid [i][j] != 0 )
        slideTile.add(grid[i][j]);

    }

    //Merging tiles that are next to each other if
    //they are equal and updating score.        
    for (int i = 0; i < slideTile.size()-1; i++) {
        if (slideTile.get(i).equals(slideTile.get(i+1))) {
        slideTile.set(i, multiplier*slideTile.get(i+1));
        System.out.println(slideTile.get(i));
        score = score + multiplier*slideTile.get(i+1);
        slideTile.set(i+1, 0);
        }
    }

    //Removing 0s that may have resulted from merging
    for (int i = 0; i < slideTile.size(); i++ ) {
        if (slideTile.get(i) == 0) {
            slideTile.remove(i);
        }
    }

    //Adding 0s to end of ArrayList to slide tiles up
    int size = slideTile.size();
    for (int i = 0; i < (GRID_SIZE - size); i++){
        slideTile.add(0);
    }

    //Copying ArrayList row back to game grid.
    for (int i = 0; i < GRID_SIZE; i++) {
        this.grid[i][j] = slideTile.get(i);
    }

    }
    didMove = true;
    }

if (direction == Direction.DOWN) {

    //int i represents rows; int j represents columns
    for (int j = 0; j < GRID_SIZE; j++ ) {
    ArrayList<Integer> slideTile = new ArrayList<>();


    //Copying row w/o 0s  to ArrayList
    for (int i = 0; i < GRID_SIZE; i++) {
        if(grid[i][j] != 0) {
        slideTile.add(grid[i][j]);
        }
    }

    //Merging tiles that are next to each other if
    //they are equal and updating score.    
    for (int i = slideTile.size()-1; i > 0; i--) {
        if (slideTile.get(i).equals(slideTile.get(i-1))) {
        slideTile.set(i, multiplier*slideTile.get(i-1));
        score = score + multiplier*slideTile.get(i-1);
        slideTile.set(i-1, 0);
        }
    }

    //Removing 0s that may have resulted from merging
    for (int i = 0; i <slideTile.size(); i++ ) {
        if (slideTile.get(i) == 0) {
            slideTile.remove(i);
        }
    }

    //Adding 0s to end of ArrayList to slide tiles up
    int size = slideTile.size();
    for (int i = 0; i < (GRID_SIZE - size); i++){
        slideTile.add(0, 0);
    }

    //Copying ArrayList row back to game grid.
    for (int i = 0; i < GRID_SIZE; i++) {
        this.grid[i][j] = slideTile.get(i);
    }
    }
    didMove = true;
    }          
return didMove;
}    
EN

回答 1

Code Review用户

发布于 2015-02-05 20:37:48

孟曼妮有很多好的建议。我不知道这个2048游戏是什么,但这里有一些建议,以改变结构,以消除重复的代码。

ETA:一个快速的变化是,您的注释是I是行,j是列。为什么不直接使用"row“和"col”作为变量名呢?

你有四个看起来非常相似的长箱子。一个“代码嗅觉”规则是,明确的案例分析几乎总是表明您做错了什么。

我首先看到的是计算分数的算法。无论您是通过slideTile列表还是向后前进,有两个变体。我将其分离成一个SlideDirection枚举:

代码语言:javascript
复制
public enum SlideDirection
{
    FORWARD {
        @Override public int slide(List<Integer> slideTile, int multiplier)
        {
            int score = 0;
            for (int idx = 0; idx < slideTile.size() - 1; idx++)
            {
                if (slideTile.get(idx).equals(slideTile.get(idx + 1)))
                {
                    slideTile.set(idx, multiplier * slideTile.get(idx + 1));
                    score += multiplier * slideTile.get(idx + 1);
                    slideTile.set(idx + 1, 0);
                }
            }
            return score;
        }
    },
    BACKWARD {
        @Override public int slide(List<Integer> slideTile, int multiplier)
        {
            int score = 0;
            for (int idx = slideTile.size() - 1; idx > 0; idx--)
            {
                if (slideTile.get(idx).equals(slideTile.get(idx - 1)))
                {
                    slideTile.set(idx, multiplier * slideTile.get(idx - 1));
                    score += multiplier * slideTile.get(idx - 1);
                    slideTile.set(idx - 1, 0);
                }
            }
            return score;
        }
    };
    public abstract int slide(List<Integer> slideTile, int multiplier);
}

我看到的第二件事是循环,不管你是水平的还是垂直的。我也把它放进了定向灯里。注意,move方法使用SlideDirection来执行任何版本的幻灯片()是合适的!

代码语言:javascript
复制
public enum Orientation
{
    Vertical {
        @Override public int move(SlideDirection direction, int[][]grid, int multiplier)
        {
            int score = 0;

            for (int col = 0; col < GRID_SIZE; col++)
            {
                ArrayList<Integer> slideTile = new ArrayList<>();

                // Copying col w/o 0s to ArrayList
                for (int row = 0; row < GRID_SIZE; row++)
                    if (grid[row][col] != 0)
                        slideTile.add(grid[row][col]);

                // Merging tiles that are next to each other if
                // they are equal and updating score.
                score += direction.slide(slideTile, multiplier);

                cleanUpSlideTile(slideTile);

                // Copying ArrayList col back to game grid.
                for (int row = 0; row < GRID_SIZE; row++)
                    grid[row][col] = slideTile.get(row);
            }
            return score;
        }
    },
    Horizontal {
        @Override public int move(SlideDirection direction, int[][]grid, int multiplier)
        {
            int score = 0;

            for (int row = 0; row < GRID_SIZE; row++)
            {
                List<Integer> slideTile = new ArrayList<>();

                // Copying row w/o 0s to ArrayList
                for (int col = 0; col < GRID_SIZE; col++)
                    if (grid[row][col] != 0)
                        slideTile.add(grid[row][col]);

                score += direction.slide(slideTile, multiplier);

                cleanUpSlideTile(slideTile);

                // Copying ArrayList row back to game grid.
                for (int col = 0; col < GRID_SIZE; col++)
                    grid[row][col] = slideTile.get(col);
            }
            return score;
        }
    };

    /**
     * Merging tiles that are next to each other if they are equal and
     * @param direction
     * @param grid
     * @param multiplier
     * @return
     */
    public abstract int move(SlideDirection direction, int[][]grid, int multiplier);

    private static void cleanUpSlideTile(List<Integer> slideTile)
    {
        // Removing 0s that may have resulted from merging
        for (int idx = 0; idx < slideTile.size(); idx++)
            if (slideTile.get(idx) == 0)
                slideTile.remove(idx);

        // Adding 0s to beginning of ArrayList to slideDirection tiles right
        int size = slideTile.size();
        for (int idx = 0; idx < (GRID_SIZE - size); idx++)
            slideTile.add(0, 0);
    }
}

现在你的方向灯将由这两个端点组成:

代码语言:javascript
复制
public enum Direction
{
    RIGHT(Orientation.Horizontal, SlideDirection.FORWARD),
    LEFT(Orientation.Horizontal, SlideDirection.BACKWARD),
    UP(Orientation.Vertical, SlideDirection.FORWARD),
    DOWN(Orientation.Vertical, SlideDirection.BACKWARD);

    private Orientation orientation;
    public Orientation getOrientation() { return orientation; }

    private SlideDirection slideDirection;
    public SlideDirection getSlideDirection() { return slideDirection; }

    Direction(Orientation orientation, SlideDirection slide)
    {
        this.orientation = orientation;
        this.slideDirection = slide;
    }
}

然后,您的移动函数看起来如下所示:

代码语言:javascript
复制
/**
* Return the score for the given direction.
* @param direction
* @return score
*/
public int move(Direction direction)
{
    int multiplier = 2;

    // TODO: Initialize the grid with values
    int[][] grid = new int[GRID_SIZE][];
    for (int i = 0; i < GRID_SIZE; i++)
        grid[i] = new int[GRID_SIZE];

    int score = direction.getOrientation().move(direction.getSlideDirection(), grid, multiplier);

    return score;
}

可能还有一些额外的清理可以完成,更好的名称,一些职责的改变,以及单元测试将有助于验证行为,但是最好能看到所有这些都在代码的其余部分中。

票数 5
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/79424

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档