首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在绕线连接6板上检查是否获胜

在绕线连接6板上检查是否获胜
EN

Code Review用户
提问于 2018-03-03 14:32:02
回答 1查看 231关注 0票数 2

我有一种方法,在"Torus“板上检查获胜条件,这是一个没有边界的董事会。这意味着如果你在左上角放置4个对角线石头,在右下角放置2个对角线石头,如果它们位于相同的对角线上,如果你忽略了边界,就会连接起来,这就会导致胜利。基本上这是一个连接6游戏。

size()返回板的大小,要么是18,要么是20。

currentPlayer是一个字符串,类似于"P1“或"P2”。

rc是刚刚移动的行和列。

代码语言:javascript
复制
public boolean checkTorusWinner(int r, int c){ 

    int count = 0;
    boolean hasWinner = false;
    String currentPlayer = board[r][c];
    int hSize = size();
    int vSize = size();

    /*
    Checks Horizontally for a Win.
     */
    for (int i = c; i < hSize; i++) {
        if (board[r][i] == currentPlayer) {
            count++;
        } else {
            count = 0;
        }
        if (i == size() - 1) {
            hSize = size() - 2;
            for (int j = 0; j < hSize; j++) {
                if (board[r][j] == currentPlayer) {
                    count++;
                } else {
                    count = 0;
                }
                if (count == 6) {

                    boardType = "none";
                    hasWinner = true;
                    break;
                }
            }
        }
        if (count == 6) {
            boardType = "none";
            hasWinner = true;
            break;
        }
    }
    /*
    Checks Vertically for a Win
     */
    for (int i = r; i < vSize; i++) {
        if (board[i][c] == currentPlayer) {
            count++;
        } else {
            count = 0;
        }
        if (i == size() - 1) {
            i = -1;
            vSize = size() - 2;
        }
        if (count == 6) {

            boardType = "none";
            hasWinner = true;
            break;
        }
    }

    /*
    Checks Diagonally from Top left to Bottom right
     */
    if (c - r >= 0) {
        int startingC;
        startingC = c - r;
        int size = size();
        for (int i = r, j = c; j < size; i++, j++) {
            if (board[i][j] == currentPlayer) {
                count++;
            } else {
                count = 0;
            }
            if (j == size() - 1) {
                j = startingC - 1;
                i = -1;
                size = size() - 2;

            }
            if (count == 6) {
                boardType = "none";
                hasWinner = true;
                break;
            }
        }
    } else {
        int size = size();
        int startingR;
        startingR = r - c;
        for (int i = r, j = c; i < size; i++, j++) {
            if (board[i][j] == currentPlayer) {
                count++;
            } else {
                count = 0;
            }
            if (i == size() - 1) {
                j = -1;
                i = startingR - 1;
                size = size() - 2;

            }

            if (count == 6) {
                boardType = "none";
                hasWinner = true;
                break;
            }

        }
    }

    /*
    Checks Diagonally from bottom left to top right;
     */
    if (r + c <= 17) {
        int loop = 0;
        int startingR;
        startingR = r + c;
        for (int i = r, j = c; i >= 0; i--, j++) {
            if (board[i][j] == currentPlayer) {
                count++;
            } else {
                count = 0;
            }

            if (i == 0 && loop == 0) {
                i = startingR + 1;
                j = -1;
                loop++;
            }

            if (count == 6) {
                boardType = "none";
                hasWinner = true;
                break;
            }

        }
    } else if (r + c > 17) {
        int loop = 0;
        int startingC;
        startingC = (r + c) - (size() - 1);
        for (int i = r, j = c; i >= startingC; i--, j++) {
            if (board[i][j] == currentPlayer) {
                count++;
            } else {
                count = 0;
            }
            if (i == startingC && loop == 0) {
                i = size();
                j = startingC - 1;
                loop++;
            }
            if (count == 6) {
                boardType = "none";
                hasWinner = true;
                break;
            }
        }
    }

    return hasWinner;
}

不幸的是,这种方法的长度不能满足我校的要求:它必须是最多80行。我不知道该如何缩短这段代码,这样它才能继续工作。

EN

回答 1

Code Review用户

发布于 2018-03-05 08:01:59

谢谢你分享你的代码。

您的代码是一种处理问题的过程方法。

一般来说,过程方法没有什么问题,但是Java是一种面向对象( oriented )编程语言,如果您想成为一名优秀的Java程序员,那么您应该开始以面向对象的方式解决问题。

但是OOP并不意味着将代码“拆分”成随机类。

OOP的最终目标是减少代码重复、提高可读性和支持重用以及扩展代码。

执行OOP意味着您遵循某些原则(除其他外):

  • 信息隐藏/封装
  • 单一责任
  • 分离关注点
  • 亲吻(保持简单)愚蠢。)
  • 干(不要重复自己)。
  • “告诉我!别问。”
  • 德米特定律(“不要和陌生人说话!”)

这对你的代码有什么帮助?

从OO的角度来看,您有当前的位置,您必须检查该位置是否是至少5个其他(不包括自身)相等元素行的一部分。

第一个含义是,您只需查看当前的位置邻居和没有必要扫描整个董事会。

最简单的方法是朝每个方向走,并计算属于当前玩家的连续邻居。然后,您添加存款指示,并检查和。

我使用一个技巧来安全地计算“环绕”数组中的索引:

代码语言:javascript
复制
(arrayLength + currentIndex + differece) % arrayLength 

其中%模数运算符。

以下是我将如何实现这一目标:

代码语言:javascript
复制
  class FiledPosition{
    final int r, c;
    FiledPosition(int r, int c){
        this.r=r;
        this.c=c;
    }
  }
  interface NeighborCalculator
    FiledPosition getFor(FiledPosition current);
  }

  enum Direction {NORTH,NORTH_EAST,EAST,SOUTH_EAST,SOUTH,SOUTH_WEST,WEST,NORTH_WEST}

上面的代码可能存在于不同的类中。下面的内容必须在您的解决方案类中

代码语言:javascript
复制
  private final Direction[][] opposits = new Direction[][]{
    {NORTH,SOUTH},    
    {NORTH_EAST,SOUTH_WEST},
    {NORTH_WEST,SOUTH_EAST},
    {EAST,WEST}
  }

  private final int WIN_COUNT_EXCLUDUNG_CURRENT = 5;
  Map<Direction, NeighborCalculator> neigborSelector = new HashMap<>();

public boolean checkTorusWinner(int r, int c){   

  neigborSelector.put(NORTH, new NeighborCalculator(){ // pre java8 anonymous inner class
       public  FiledPosition getFor(FiledPosition currentPoint ){
          return new Point((vSize+currentPoint.r-1)%vSize, currentPoint.c));
       }
  });
  neigborSelector.put(NORTH_EAST,currentPoint -> new Point((vSize+currentPoint.r-1)%vSize, (hSize+currentPoint.c+1)%hSize));  // java8 lambda
  neigborSelector.put(EAST,currentPoint -> new Point(currentPoint.r, (hSize+currentPoint.c+1)%hSize));
  neigborSelector.put(SOUTH_EAST,currentPoint -> new Point((vSize+currentPoint.r+1)%vSize, (hSize+currentPoint.c+1)%hSize)); 
  // similar for all directions, should be in the classes constructor.

  Map<Direction, Counter> lineSectionCounts = new HashMap<>();
  String currentPlayer = board[r][c];
  int hSize = size();
  int vSize = size();

  // count consecutive same in each direction without current
  for(Direction direction : Direction.values()){
     int consecutiveSame = 0;
     FiledPosition neigborPosition = neigborSelector.get(direction).getFor(new FiledPosition(r,c));
     while(currentPlayer.equals(board[neigborPosition.r][neigborPosition.c])){
        consecutiveSame++;
        neigborPosition = neigborSelector.get(direction).getFor(neigborPosition);
      }         
      lineSectionCounts.put(consecutiveSame); // auto boxed
   }

  // sum up opposit directions
  for(Direction[] opposit : opposits){
    if(WIN_COUNT_EXCLUDUNG_CURRENT < lineSectionCounts.get(oposit[0]) + lineSectionCounts.get(oposit[1])) // auto unbox
         return true; // current Player won.
  }
  return false; // no winner yet
}

这个完整的代码有57行(24行没有配置)。需要完整地配置neigborSelector映射(如果您使用jav8 lambdas),需要少4行。

这段代码使用了基本的Java概念,如类、接口和枚举,您应该已经听说过了。

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

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

复制
相关文章

相似问题

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