Food Chain Magnate 구현을위한 보드 생성기
코딩 기술을 연습하기 위해 Java로 보드 게임의 논리를 구현하고 있습니다. 저는 Food Chain Magnate를 선택했습니다. 왜냐하면 다른 데이터 구조가 필요한 상당히 복잡한 게임이기 때문입니다. 첫 번째 작업 중 하나는 게임 보드의 데이터 구조를 생성하는 것입니다. 게임에서 보드는 사용 가능한 20 개의 타일 중 일부 (플레이어 수에 따라 전체)를 사용하여 구성됩니다. 각 타일은 5 x 5 정사각형의 격자입니다. 각 타일의 정체성은 게임 중에 중요하지 않으며, 일부 사각형이 다른 타일과 다른 타일에있는 경우에만 중요합니다.
Board
기본적으로 계산을위한 추가 메서드가있는 2D Object 배열에 대한 래퍼 인 클래스를 BoardGenerator
만들고 Board
s 를 만들고 다른 타일의 내용으로 초기화 하는 클래스를 만들었습니다 .
Board.java
package com.lartkma.fcm.model.board;
public class Board {
public static final int TILE_SIZE = 5;
public static final Object OFF_LIMIT = new Object();
private Object[][] boardSquares;
public Board(int widthTiles, int heightTiles) {
this.boardSquares = new Object[widthTiles * TILE_SIZE][heightTiles * TILE_SIZE];
}
public Object get(int x, int y) {
if (x >= 0 && x < this.boardSquares.length && y >= 0 && y < this.boardSquares[0].length) {
return this.boardSquares[x][y];
} else {
return OFF_LIMIT;
}
}
public Object get(Point p) {
return get(p.x(), p.y());
}
public void set(int x, int y, Object obj) {
if (x >= 0 && x < this.boardSquares.length && y >= 0 && y < this.boardSquares[0].length) {
this.boardSquares[x][y] = obj;
} else {
throw new IndexOutOfBoundsException("Point " + new Point(x, y) + " is out of the board");
}
}
public void set(Point p, Object obj) {
set(p.x(), p.y(), obj);
}
public int getWidth() {
return this.boardSquares.length;
}
public int getHeight() {
return this.boardSquares[0].length;
}
/**
* Returns the tile where the square belongs, relative to this board. The value
* is not related to the original tile used to build the board, only allows to
* differentiate one tile from another.
* @param p
* @return
*/
public int getTileNumber(Point p) {
return (p.y() / TILE_SIZE) * (this.boardSquares.length / TILE_SIZE) + (p.x() / TILE_SIZE);
}
}
Point
클래스 생성자 간단한 불변 2D 포인트 클래스 Point(int x, int y)
, 메소드 x()
, y()
검색 대 및 add(int dx, int dy)
방법이 복귀 점 (x + DX, DY에 + Y). 나는 다른 수업에 초점을 맞추기 위해 여기에 쓰는 것이 아닙니다.
BoardGenerator.java
package com.lartkma.fcm.model.board;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Stream;
public class BoardGenerator {
public static Board fromRandom(int widthTiles, int heightTiles) {
Random rnd = new Random();
Map<Character, Object[][]> tileList = getTileList();
List<Character> randomTiles = new LinkedList<>(tileList.keySet());
Collections.shuffle(randomTiles);
Board board = new Board(widthTiles, heightTiles);
for (int i = 0; i < widthTiles; i++) {
for (int j = 0; j < heightTiles; j++) {
fillWithTile(board, tileList.get(randomTiles.get(i * heightTiles + j)), i * Board.TILE_SIZE,
j * Board.TILE_SIZE, rnd.nextInt(4));
}
}
return board;
}
/**
* Generates a board using the tiles and rotations indicated in the expression.
*
* The expression is composed of (# tiles tall) subexpressions separated by
* newlines or spaces, each subexpression made of (# tiles wide x 2) characters.
*
* Each 2 characters of a subexpression describe a tile and the rotation of such
* tile. The tile is indicated with one of the upper-case characters used in
* <a href="https://boardgamehelpers.com/FoodChainMagnate/MapTileKey.aspx">this page</a>.
* The rotation is described as a digit from 1 to 4, where 1 is the orientation shown in
* the page mentioned above (with the identified in the bottom left), 2 rotates the
* reference orientation rotated 90 degrees clockwise, and so on.
*
* @param expression
* @return
*/
public static Board fromExpression(String expression) {
String[] rows = expression.split("\n|\r\n| ");
int heightTiles = rows.length;
int widthTiles = Stream.of(rows).mapToInt(s -> s.length() / 2).max().orElse(0);
Board board = new Board(widthTiles, heightTiles);
Map<Character, Object[][]> tileList = getTileList();
for (int i = 0; i < widthTiles; i++) {
for (int j = 0; j < heightTiles; j++) {
if (2 * i + 1 < rows[rows.length - 1 - j].length()) {
char tileId = rows[rows.length - 1 - j].charAt(2 * i);
char tileRotationFactor = rows[rows.length - 1 - j].charAt(2 * i + 1);
if (tileList.containsKey(tileId) && tileRotationFactor >= '1' && tileRotationFactor <= '4') {
// Number of rotations goes from 0 to 3
fillWithTile(board, tileList.get(tileId), i * Board.TILE_SIZE, j * Board.TILE_SIZE,
tileRotationFactor - '1');
} else {
throw new IllegalArgumentException(
"Board tile expression \"" + tileId + tileRotationFactor + "\" cannot be read");
}
}
}
}
return board;
}
private static Map<Character, Object[][]> getTileList() {
Map<Character, Object[][]> outputMap = new HashMap<>();
try (BufferedReader stream = new BufferedReader(
new InputStreamReader(BoardGenerator.class.getResourceAsStream("tiles.txt")))) {
int lineCount = 1;
Object[][] currentTileContent = new Object[Board.TILE_SIZE][Board.TILE_SIZE];
char currentTileIdentifier = 'A';
String currentLine;
while ((currentLine = stream.readLine()) != null) {
for (int i = 0; i < Board.TILE_SIZE; i++) {
char lineChar = currentLine.charAt(i);
if (lineChar == 'O') {
currentTileContent[i][Board.TILE_SIZE - lineCount] = null;
} else if (lineChar == '-') {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(false, true, false, true);
} else if (lineChar == '|') {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(true, false, true, false);
} else if (lineChar == '/') {
// check the previous and next squares in the same line to check if this is
// a up-to-right turn or a right-to-up turn
char previous = (i == 0 ? 'O' : currentLine.charAt(i - 1));
char next = (i == Board.TILE_SIZE - 1 ? 'O' : currentLine.charAt(i + 1));
if ((isHorizontalRoad(previous) || i == 0) && !isHorizontalRoad(next)) {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(true, false, false,
true);
} else if (!isHorizontalRoad(previous)
&& (isHorizontalRoad(next) || i == Board.TILE_SIZE - 1)) {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(false, true, true,
false);
} else {
throw new IllegalStateException("Unknown combination on ( " + currentLine + ")");
}
} else if (lineChar == '\\') {
// check the previous and next squares in the same line to check if this is
// a up-to-left turn or a left-to-up turn
char previous = (i == 0 ? 'O' : currentLine.charAt(i - 1));
char next = (i == Board.TILE_SIZE - 1 ? 'O' : currentLine.charAt(i + 1));
if ((isHorizontalRoad(previous) || i == 0) && !isHorizontalRoad(next)) {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(false, false, true,
true);
} else if (!isHorizontalRoad(previous)
&& (isHorizontalRoad(next) || i == Board.TILE_SIZE - 1)) {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(true, true, false,
false);
} else {
throw new IllegalStateException("Unknown combination on ( " + currentLine + ")");
}
} else if (lineChar == '^') {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(true, true, false, true);
} else if (lineChar == '>') {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(true, true, true, false);
} else if (lineChar == 'V') {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(false, true, true, true);
} else if (lineChar == '<') {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(true, false, true, true);
} else if (lineChar == '+') {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(true, true, true, true);
} else if (lineChar == 'S') {
currentTileContent[i][Board.TILE_SIZE - lineCount] = GoodsSource.SODA;
} else if (lineChar == 'B') {
currentTileContent[i][Board.TILE_SIZE - lineCount] = GoodsSource.BEER;
} else if (lineChar == 'L') {
currentTileContent[i][Board.TILE_SIZE - lineCount] = GoodsSource.LEMONADE;
} else if (lineChar >= '0' && lineChar <= '9') {
Object previous = (i == 0 ? null : currentTileContent[i - 1][Board.TILE_SIZE - lineCount]);
if (previous instanceof House) {
// part of a two-digit house, same entity as left
currentTileContent[i][Board.TILE_SIZE
- lineCount] = currentTileContent[i - 1][Board.TILE_SIZE - lineCount];
} else {
int houseOrder = (lineChar - '0'); // classic
char next = (i == Board.TILE_SIZE - 1 ? 'O' : currentLine.charAt(i + 1));
if (next >= '0' && next <= '9') { // two digit id
houseOrder = houseOrder * 10 + (next - '0');
}
currentTileContent[i][Board.TILE_SIZE - lineCount] = new House(houseOrder);
}
} else if (lineChar == 'H') {
Object previous = (i == 0 ? null : currentTileContent[i - 1][Board.TILE_SIZE - lineCount]);
if (previous instanceof House) {
// same entity as left
currentTileContent[i][Board.TILE_SIZE - lineCount] = previous;
} else {
previous = (lineCount == 1 ? null
: currentTileContent[i][Board.TILE_SIZE - lineCount + 1]);
if (previous instanceof House) {
// same entity as up
currentTileContent[i][Board.TILE_SIZE - lineCount] = previous;
} else {
throw new IllegalStateException(
"Unknown combination on ( " + currentLine + "): no house defined near H");
}
}
} else {
throw new IllegalStateException("Unknown symbol: " + lineChar);
}
}
lineCount += 1;
if (lineCount > Board.TILE_SIZE) {
outputMap.put(currentTileIdentifier, currentTileContent);
lineCount = 1;
currentTileContent = new Object[Board.TILE_SIZE][Board.TILE_SIZE];
currentTileIdentifier += 1;
}
}
return outputMap;
} catch (IOException e) {
throw new Error("tiles.txt not available", e);
}
}
private static boolean isHorizontalRoad(char c) {
return c == '-' || c == '/' || c == '\\' || c == '^' || c == 'V' || c == '+';
}
private static void fillWithTile(Board board, Object[][] tileArray, int xStart, int yStart, int numRotations) {
for (int i = 0; i < Board.TILE_SIZE; i++) {
for (int j = 0; j < Board.TILE_SIZE; j++) {
Point boardPoint = new Point(xStart + i, yStart + j);
Point tileCoords = toTileCoords(i, j, numRotations);
Object inTile = tileArray[tileCoords.x()][tileCoords.y()];
if (inTile instanceof House) {
Object prevHouse;
if ((prevHouse = board.get(boardPoint.add(-1, 0))) instanceof House
&& ((House) prevHouse).getOrder() == ((House) inTile).getOrder()) {
// check house at the left
board.set(boardPoint, prevHouse);
} else if ((prevHouse = board.get(boardPoint.add(0, -1))) instanceof House
&& ((House) prevHouse).getOrder() == ((House) inTile).getOrder()) {
// check house below
board.set(boardPoint, prevHouse);
} else {
board.set(boardPoint, new House(((House) inTile).getOrder()));
}
} else if (inTile instanceof Road) {
board.set(boardPoint, ((Road) inTile).rotate(numRotations));
} else if (inTile instanceof GoodsSource || inTile == null) {
board.set(boardPoint, inTile);
} else {
throw new IllegalStateException("Unknown object: " + inTile.getClass());
}
}
}
}
private static Point toTileCoords(int x, int y, int rotations) {
switch (rotations) {
case 0:
return new Point(x, y);
case 1:
return new Point(Board.TILE_SIZE - 1 - y, x);
case 2:
return new Point(Board.TILE_SIZE - 1 - x, Board.TILE_SIZE - 1 - y);
case 3:
return new Point(y, Board.TILE_SIZE - 1 - x);
default:
throw new IllegalArgumentException("Should not happen");
}
}
}
tiles.txt
파일은 20 개 타일의 설명이 포함되어 있습니다. 각 타일의 내용은 여기에서 볼 수 있습니다.https://boardgamehelpers.com/FoodChainMagnate/MapTileKey.aspx(확장 타일은 포함되지 않음). 각 줄에 5 개의 문자로 구성된 일반 텍스트 파일입니다. 각 5 줄은 타일 (5 x 5)을 설명합니다. 각 타일에는 참조 링크에 표시된대로 처음 5 줄 타일 A, 다음 5 개 타일 B 등의 문자가 할당됩니다. 각 문자 (또는 문자 그룹)는 개체를 나타냅니다. 예를 들어, 타일 E는 다음과 같이 설명됩니다.
/-/OO
|BOOO
/O8H/
OOHH|
OO/-/
(문자 /
및 \
상황에 따라 가능한 두 가지 유형의 턴 중 하나를 나타낼 수 있음)
Road.java
package com.lartkma.fcm.model.board;
import java.util.Arrays;
import java.util.StringJoiner;
public class Road {
private boolean[] canMove;
public Road(boolean canGoUp, boolean canGoRight, boolean canGoDown, boolean canGoLeft) {
this.canMove = new boolean[] { canGoUp, canGoRight, canGoDown, canGoLeft };
}
public boolean canMove(Direction inDirection) {
return this.canMove[inDirection.ordinal()];
}
public Road rotate(int amountRotations) {
Road rotated = new Road(this.canMove[0], this.canMove[1], this.canMove[2], this.canMove[3]);
if (amountRotations < 0) {
// Java operator % returns a remainder, that is different from a mathematical
// modulus
// https://stackoverflow.com/questions/5385024/mod-in-java-produces-negative-numbers
// https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.3
amountRotations = amountRotations % rotated.canMove.length + rotated.canMove.length;
} else {
amountRotations = amountRotations % rotated.canMove.length;
}
boolean swapTemp;
for (int k = 0; k < amountRotations; k++) {
for (int i = 1; i < rotated.canMove.length; i++) { // it makes no sense for the first element
swapTemp = rotated.canMove[0];
rotated.canMove[0] = rotated.canMove[i];
rotated.canMove[i] = swapTemp;
}
}
return rotated;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Road) {
return Arrays.equals(this.canMove, ((Road) obj).canMove);
} else {
return false;
}
}
@Override
public String toString() {
StringJoiner name = new StringJoiner("-", "Road[", "]");
for (Direction d : Direction.values()) {
if (canMove(d)) {
name.add(d.name());
}
}
return name.toString();
}
}
Direction
값이있는 열거 형 UP, RIGHT, DOWN, LEFT
(순서대로)입니다. 속성 House
이있는 간단한 데이터 클래스 order
이지만 게임 중에 다른 속성을 변경합니다. GoodsSource
3 개의 가능한 인스턴스 만 가질 수있는 단순하고 변경 불가능한 클래스입니다.
BoardGeneratorTest.java (사용 방법에 대한 샘플)
package com.lartkma.fcm.model.board;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.junit.Assert.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import com.lartkma.fcm.model.board.Board;
import com.lartkma.fcm.model.board.GoodsSource;
import com.lartkma.fcm.model.board.House;
import com.lartkma.fcm.model.board.BoardGenerator;
import com.lartkma.fcm.model.board.Road;
public class BoardGeneratorTest {
@Test
@DisplayName("The board generator can receive specific tiles as parameters and should generate the correct amount of squares")
public void testBoardGeneratorSizeFromExpression() {
Board board = BoardGenerator.fromExpression("G1E2\nI3M4");
assertAll("The board should be of 2 x 2 tiles (10 x 10 squares)",
() -> assertEquals(10, board.getWidth(), "Board width"),
() -> assertEquals(10, board.getHeight(), "Board height"));
}
@Test
@DisplayName("The board generator can generate a random board and should generate the correct amount of squares")
public void testBoardGeneratorSizeFromRandom() {
Board board = BoardGenerator.fromRandom(3, 2);
assertAll("The board should be of 3 x 2 tiles (15 x 10 squares)",
() -> assertEquals(15, board.getWidth(), "Board width"),
() -> assertEquals(10, board.getHeight(), "Board height"));
}
@Test
@DisplayName("The board generator can create a 1-tile board with the correct contents")
public void testBoardGeneratorContent() {
Board board = BoardGenerator.fromExpression("E1");
assertAll("The board should have the following contents",
() -> assertThat("In 0, 0", board.get(0, 0), is(nullValue())),
() -> assertThat("In 1, 0", board.get(1, 0), is(nullValue())),
() -> assertThat("In 2, 0", board.get(2, 0), is(equalTo(new Road(false, true, true, false)))),
() -> assertThat("In 3, 0", board.get(3, 0), is(equalTo(new Road(false, true, false, true)))),
() -> assertThat("In 4, 0", board.get(4, 0), is(equalTo(new Road(true, false, false, true)))),
() -> assertThat("In 0, 1", board.get(0, 1), is(nullValue())),
() -> assertThat("In 1, 1", board.get(1, 1), is(nullValue())),
() -> assertThat("In 2, 1", board.get(2, 1), is(equalTo(new House(8)))),
() -> assertThat("In 3, 1", board.get(3, 1), is(sameInstance(board.get(2, 1)))),
() -> assertThat("In 4, 1", board.get(4, 1), is(equalTo(new Road(true, false, true, false)))),
() -> assertThat("In 0, 2", board.get(0, 2), is(equalTo(new Road(true, false, false, true)))),
() -> assertThat("In 1, 2", board.get(1, 2), is(nullValue())),
() -> assertThat("In 2, 2", board.get(2, 2), is(sameInstance(board.get(2, 1)))),
() -> assertThat("In 3, 2", board.get(3, 2), is(sameInstance(board.get(2, 1)))),
() -> assertThat("In 4, 2", board.get(4, 2), is(equalTo(new Road(false, true, true, false)))),
() -> assertThat("In 0, 3", board.get(0, 3), is(equalTo(new Road(true, false, true, false)))),
() -> assertThat("In 1, 3", board.get(1, 3), is(equalTo(GoodsSource.BEER))),
() -> assertThat("In 2, 3", board.get(2, 3), is(nullValue())),
() -> assertThat("In 3, 3", board.get(3, 3), is(nullValue())),
() -> assertThat("In 4, 3", board.get(4, 3), is(nullValue())),
() -> assertThat("In 0, 4", board.get(0, 4), is(equalTo(new Road(false, true, true, false)))),
() -> assertThat("In 1, 4", board.get(1, 4), is(equalTo(new Road(false, true, false, true)))),
() -> assertThat("In 2, 4", board.get(2, 4), is(equalTo(new Road(true, false, false, true)))),
() -> assertThat("In 3, 4", board.get(3, 4), is(nullValue())),
() -> assertThat("In 4, 4", board.get(4, 4), is(nullValue())));
}
@Test
@DisplayName("The board generator can create a rotated 1-tile board with the correct contents")
public void testBoardGeneratorContentRotated() {
Board board = BoardGenerator.fromExpression("E2");
assertAll("The board should have the following contents",
() -> assertThat("In 0, 0", board.get(0, 0), is(equalTo(new Road(true, true, false, false)))),
() -> assertThat("In 1, 0", board.get(1, 0), is(equalTo(new Road(false, true, false, true)))),
() -> assertThat("In 2, 0", board.get(2, 0), is(equalTo(new Road(false, false, true, true)))),
() -> assertThat("In 3, 0", board.get(3, 0), is(nullValue())),
() -> assertThat("In 4, 0", board.get(4, 0), is(nullValue())),
() -> assertThat("In 0, 1", board.get(0, 1), is(equalTo(new Road(true, false, true, false)))),
() -> assertThat("In 1, 1", board.get(1, 1), is(equalTo(new House(8)))),
() -> assertThat("In 2, 1", board.get(2, 1), is(sameInstance(board.get(1, 1)))),
() -> assertThat("In 3, 1", board.get(3, 1), is(nullValue())),
() -> assertThat("In 4, 1", board.get(4, 1), is(nullValue())),
() -> assertThat("In 0, 2", board.get(0, 2), is(equalTo(new Road(false, false, true, true)))),
() -> assertThat("In 1, 2", board.get(1, 2), is(sameInstance(board.get(1, 1)))),
() -> assertThat("In 2, 2", board.get(2, 2), is(sameInstance(board.get(1, 1)))),
() -> assertThat("In 3, 2", board.get(3, 2), is(nullValue())),
() -> assertThat("In 4, 2", board.get(4, 2), is(equalTo(new Road(true, true, false, false)))),
() -> assertThat("In 0, 3", board.get(0, 3), is(nullValue())),
() -> assertThat("In 1, 3", board.get(1, 3), is(nullValue())),
() -> assertThat("In 2, 3", board.get(2, 3), is(nullValue())),
() -> assertThat("In 3, 3", board.get(3, 3), is(equalTo(GoodsSource.BEER))),
() -> assertThat("In 4, 3", board.get(4, 3), is(equalTo(new Road(true, false, true, false)))),
() -> assertThat("In 0, 4", board.get(0, 4), is(nullValue())),
() -> assertThat("In 1, 4", board.get(1, 4), is(nullValue())),
() -> assertThat("In 2, 4", board.get(2, 4), is(equalTo(new Road(true, true, false, false)))),
() -> assertThat("In 3, 4", board.get(3, 4), is(equalTo(new Road(false, true, false, true)))),
() -> assertThat("In 4, 4", board.get(4, 4), is(equalTo(new Road(false, false, true, true)))));
}
}
답변
public static final int TILE_SIZE = 5;
TILE_EDGE_SIZE
타일이 5 개의 사각형을 포함하지 않기 때문에 이것을 또는 비슷한 것으로 부를 수 있습니다.
public Object get(int x, int y) {
이것을 제거하고 사용하십시오 get(Point p)
. 더 많은 작업이 아닙니다.
return OFF_LIMIT;
이 단일 마법 값 은 Array에 올바른 클래스를 사용하지 못하게합니다. 마법의 가치는 당신이 피하고 싶은 것입니다. 정말로 예외를 피하려면 Optional<Square>
. 그러나 개인적으로 예외를 던지고 Optional
반환 하는 대신 사용 합니다 null
.
throw new IndexOutOfBoundsException("Point " + new Point(x, y) + " is out of the board");
나는 당신이 그것을 할 수 있다는 것을 알았고, 이제 그들이 경계를 벗어난 것을 어떻게 처리하는지에 대해 대칭적인 방법을 만드십시오 .
public int getWidth() {
...
public int getHeight() {
완벽합니다. 응용 프로그램이 반환 될 이유가 없습니다 OFF_LIMIT
.
Map<Character, Object[][]> tileList = getTileList();
컬렉션과 배열을 혼합하는 것은 좋은 생각이 아닙니다. 컬렉션을 사용하십시오.
List<Character> randomTiles = new LinkedList<>(tileList.keySet());
정확히 말하면 ArrayList
여기서는 연결 목록이 아닌 사용 합니다.
Collections.shuffle(randomTiles);
임의의 인덱스를 찾은 다음 연결된 목록에서 이동하는 것은 좋은 생각이 아니기 때문입니다.
fillWithTile(board, tileList.get(randomTiles.get(i * heightTiles + j)), i * Board.TILE_SIZE, j * Board.TILE_SIZE, rnd.nextInt(4));
이 방법에서 너무 많은 일이 일어나고 있습니다. 왜 이런 일이 발생하고 무엇을하고 있습니까? 왜 거기에 마법 4
이 있습니까?
if (2 * i + 1 < rows[rows.length - 1 - j].length()) {
다시, 여기서 우리는 일이 어떻게 진행되고 있는지 볼 수 있지만 무엇이나 이유는 알 수 없습니다. 도움이되는 (불완전한 경우) JavaDoc은 다소 도움이되지만 의견을 주시면 감사하겠습니다.
private static Map<Character, Object[][]> getTileList() {
이 방법에서 너무 많은 작업이 수행되고 있으며 복잡성의 양은 놀랍습니다.
if (lineChar == 'O') { // ... endless else if's
여기서 스위치는 놀라운 일을 할 수 있지만 break;
진술을 잊지 마십시오 .
currentTileContent[i][Board.TILE_SIZE - lineCount] = null;
Object tileContent;
선언 은 어떻습니까? 그런 다음에서 설정 switch
하고 결국 currentTileContent[i][Board.TILE_SIZE - lineCount]
. 저에게 물어 보면 너무 많은 복사 / 붙여 넣기.
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(false, true, false, true);
아,가는 길 false, true, false, true
. 그것은 true
도로 가 아니며 enum
부울 매개 변수 대신 사용하십시오 . 그것은 당신이 읽어야 할 효과적인 Java에 있습니다.
EnumSet<Direction> possibleDirections = EnumSet.of(Direction.RIGHT, Direction.LEFT);
그저 soooo가 훨씬 더 좋네요, 동의하지 않습니까?
char previous = (i == 0 ? 'O' : currentLine.charAt(i - 1));
char next = (i == Board.TILE_SIZE - 1 ? 'O' : currentLine.charAt(i + 1));
if ((isHorizontalRoad(previous) || i == 0) && !isHorizontalRoad(next)) {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(true, false, false,
true);
} else if (!isHorizontalRoad(previous)
&& (isHorizontalRoad(next) || i == Board.TILE_SIZE - 1)) {
currentTileContent[i][Board.TILE_SIZE - lineCount] = new Road(false, true, true,
false);
} else {
throw new IllegalStateException("Unknown combination on ( " + currentLine + ")");
}
하나의 값이 반환됩니다. a Road
. 방법일까요? 너무 쉽게 구별 할 수 있습니다.
currentTileContent[i][Board.TILE_SIZE - lineCount] = GoodsSource.SODA;
아, 이제 알겠습니다. A Road
, GoodsSource
a House
또는 아무것도 예상되지 않습니다. 그래도 TileContent
최소한 과 같은 마커 인터페이스를 만들고 필요하지 않도록 구현 Road
하고 GoodsSource
구현하십시오 Object
. 너무 추하기 때문입니다.
throw new Error("tiles.txt not available", e);
완전히 읽을 수없는 것은 더 나은 예외 일 수 있습니다. 일반적으로 시스템 전체에서 복구 할 수없는 RuntimeException
것보다 선호되어야합니다 .Error
} else if ((prevHouse = board.get(boardPoint.add(0, -1))) instanceof House
&& ((House) prevHouse).getOrder() == ((House) inTile).getOrder()) {
// check house below
board.set(boardPoint, prevHouse);
좋아요, 당신은 더 큰 집을 만들고 있습니다. 나는 내가 비열하고 별도의 부분으로 구성된 집을 만들 수 있다고 생각합니다. 나는 당신의 집이 정사각형 이길 바랍니다. :) 그러나 정말로 다시 방법을 제공하십시오.
열거 형 값은 직접 비교할 수 있으며 order
같은지 비교할 필요가 없습니다 .
throw new IllegalArgumentException("Should not happen");
동의합니다. 그러한 예외는 허용되지 않습니다.
return this.canMove[inDirection.ordinal()];
또는 possibleDirections.contains(inDirection)
(위 참조?)