首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Java 优化技术(4)

Java 优化技术(4)

Board 类在实现         Board 类之前,需要处理两个有趣的问题。首先,我们必须确定数据结构。Meteor 拼图板基本上是 5 乘 10 格的正六边形,我们可以将它表示为 50 个         Cell 对象的数组。我们将使用         BoardCell 子类(如清单 5 所示),而不直接使用         Cell 类,BoardCell 子类跟踪占用单元的块:      
清单 5. BoardCell 子类
1
2
3
4
5
6
7
8
9
public class BoardCell extends Cell {
  private Piece piece = null;
  public Piece getPiece() {
    return piece;
  }
  public void setPiece(Piece piece) {
    this.piece = piece;
  }
}




如果在一个数组中存储图板的所有 50 个图板单元,我们将必须编写某些冗长乏味的初始化代码。该初始化代码为图板上的每个单元标识相邻的图板单元,如图 3 所示。例如,单元 0 有两个邻居:右面的单元 1 和右下的单元 5。  显示了         initializeBoardCell() 方法,从         Board 类的构造器调用该方法以完成这个初始化。      
图 3. 表示成单元数组的图板既然我们已经实现了图板的数据结构,则转向下一个问题:编写将块放入图板的         placePiece() 方法。编写该方法的最难部分是确定块是否适合图板上的给定位置。确定块是否适合的一种方法是:首先,找出所有这样的图板单元,如果将块放入图板,则这些图板单元就可能会被块单元占用。获得这组图板单元后,我们可以容易地确定新的块是否合适:所有相应的块单元都需要是空的并且块要完全适合图板。这个过程是由显示在清单 6 中的         findOccupiedBoardCells() 方法和         placePiece() 方法实现的。注:我们使用         PieceCell 对象的         processed 字段以避免         findOccupiedBoardCells() 方法中的无限递归。      
清单 6. Board 类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
public class Board {
  public static final int NUMBEROFCELLS = 50;
  public static final int NUMBEROFCELLSINROW = 5;
  private BoardCell[] boardCells = new BoardCell[NUMBEROFCELLS];
  public Board() {
    for (int i = 0; i < NUMBEROFCELLS; i++) {
      boardCells = new BoardCell();
    }
    for (int i = 0; i < NUMBEROFCELLS; i++) {
      initializeBoardCell(boardCells, i);
    }
  }
  /**
   * Initialize the neighbours of the given boardCell at the given
   * index on the board
   */
  private void initializeBoardCell(BoardCell boardCell, int index) {
    int row = index/NUMBEROFCELLSINROW;
    // Check if cell is in last or first column
    boolean isFirst = (index%NUMBEROFCELLSINROW == 0);
    boolean isLast = ((index+1)%NUMBEROFCELLSINROW == 0);
    if (row%2 == 0) { // Even rows
      if (row != 0) {
        // Northern neighbours
        if (!isFirst) {
          boardCell.setNeighbour(Cell.NORTHWEST, boardCells[index-6]);
        }
        boardCell.setNeighbour(Cell.NORTHEAST, boardCells[index-5]);
      }
      if (row != ((NUMBEROFCELLS/NUMBEROFCELLSINROW)-1)) {
        // Southern neighbours
        if (!isFirst) {
          boardCell.setNeighbour(Cell.SOUTHWEST, boardCells[index+4]);
        }
        boardCell.setNeighbour(Cell.SOUTHEAST, boardCells[index+5]);
      }
    }
    else { // Uneven rows
      // Northern neighbours
      if (!isLast) {
        boardCell.setNeighbour(Cell.NORTHEAST, boardCells[index-4]);
      }
      boardCell.setNeighbour(Cell.NORTHWEST, boardCells[index-5]);
      // Southern neighbours
      if (row != ((NUMBEROFCELLS/NUMBEROFCELLSINROW)-1)) {
        if (!isLast) {
          boardCell.setNeighbour(Cell.SOUTHEAST, boardCells[index+6]);
        }
        boardCell.setNeighbour(Cell.SOUTHWEST, boardCells[index+5]);
      }
    }
    // Set the east and west neighbours
    if (!isFirst) {
      boardCell.setNeighbour(Cell.WEST, boardCells[index-1]);
    }
    if (!isLast) {
      boardCell.setNeighbour(Cell.EAST, boardCells[index+1]);
    }
  }
  public void findOccupiedBoardCells(
    ArrayList occupiedCells, PieceCell pieceCell, BoardCell boardCell) {
    if (pieceCell != null && boardCell != null && !pieceCell.isProcessed()) {
      occupiedCells.add(boardCell);
      
      /* Neighbouring cells can form loops, which would lead to an
         infinite recursion. Avoid this by marking the processed
         cells. */
      
      pieceCell.setProcessed(true);
      // Repeat for each neighbour of the piece cell
      for (int i = 0; i < Cell.NUMBEROFSIDES; i++) {
        findOccupiedBoardCells(occupiedCells,
                               (PieceCell)pieceCell.getNeighbour(i),
                               (BoardCell)boardCell.getNeighbour(i));
      }
    }
  }
  public boolean placePiece(Piece piece, int boardCellIdx) {
    // We will manipulate the piece using its first cell
    return placePiece(piece, 0, boardCellIdx);
  }
  public boolean
    placePiece(Piece piece, int pieceCellIdx, int boardCellIdx) {
    // We're going to process the piece
    piece.resetProcessed();
    // Get all the boardCells that this piece would occupy
    ArrayList occupiedBoardCells = new ArrayList();
    findOccupiedBoardCells(occupiedBoardCells,
                           piece.getPieceCell(pieceCellIdx),
                           boardCells[boardCellIdx]);
    if (occupiedBoardCells.size() != Piece.NUMBEROFCELLS) {
      // Some cells of the piece don't fall on the board
      return false;
    }
    for (int i = 0; i < occupiedBoardCells.size(); i++) {
      if (((BoardCell)occupiedBoardCells.get(i)).getPiece() != null)
        // The board cell is already occupied by another piece
        return false;
    }
    // Occupy the board cells with the piece
    for (int i = 0; i < occupiedBoardCells.size(); i++) {
      ((BoardCell)occupiedBoardCells.get(i)).setPiece(piece);
    }
    return true; // The piece fits on the board
  }
  public void removePiece(Piece piece) {
    for (int i = 0; i < NUMBEROFCELLS; i++) {
      // Piece objects are unique, so use reference equality
      if (boardCells.getPiece() == piece) {
        boardCells.setPiece(null);
      }
    }
  }
}




这完成了我们的初始解决方案的实现。让我们对它进行测试吧。
返回列表