예제 #1
0
파일: Game.java 프로젝트: FransM22/GipfGame
  /** By Dingding */
  private Set<Line.Segment> getRemovableLineSegments(
      Map<Position, Piece> pieceMap, PieceColor pieceColor) {
    Set<Line.Segment> removableLines = new HashSet<>();
    Set<Line> linesOnTheBoard =
        Line.getLinesOnTheBoard(
            this); // Get all the possible lines on the board. Positions don't need to be occupied.

    for (Line line : linesOnTheBoard) {
      Position currentPosition = line.getStartPosition();
      Position startOfSegment = null;
      Position endOfSegment = null;
      Direction direction = line.getDirection();
      int consecutivePieces =
          0; // We start at a dot position, so we can assume that we don't start in a set of
             // consecutive pieces
      boolean isInLineSegment = false;

      // Break the for-loop if an endOfSegment has been found (because the largest lines only have 7
      // positions on the board, there
      // can't be more than one set of four pieces of the same color (requiring at least 9
      // positions) on the board.
      for (;
          endOfSegment == null && isPositionOnPlayAreaOrOuterDots(currentPosition);
          currentPosition = currentPosition.next(direction)) {
        PieceColor currentPieceColor =
            pieceMap.containsKey(currentPosition)
                ? pieceMap.get(currentPosition).getPieceColor()
                : null;

        // Update the consecutivePieces
        if (currentPieceColor == pieceColor) consecutivePieces++;
        if (consecutivePieces == 4) isInLineSegment = true;
        if (currentPieceColor != pieceColor) consecutivePieces = 0;

        if (isInLineSegment) {
          if (isDotPosition(currentPosition) || currentPieceColor == null) {
            endOfSegment = currentPosition.previous(direction);
          }
        }

        // Update the startOfSegment if necessary
        if (startOfSegment == null) {
          if (currentPieceColor != null) {
            startOfSegment = currentPosition;
          }
        }
        if (currentPieceColor == null && endOfSegment == null) {
          startOfSegment = null;
        }

        // Add a line segment to the list if we have found one
        if (endOfSegment != null) {
          removableLines.add(new Line.Segment(this, startOfSegment, endOfSegment, direction));
        }
      }
    }

    return removableLines;
  }
예제 #2
0
파일: Game.java 프로젝트: FransM22/GipfGame
  // TODO: Refactor method
  private void removeLines(
      Map<Position, Piece> pieceMap,
      PieceColor pieceColor,
      Map<PieceColor, Set<Line.Segment>> linesTakenBy,
      Map<PieceColor, Set<Position>> piecesBackTo) {
    Set<Line.Segment> intersectingSegments;
    Set<Line.Segment> segmentsNotRemoved = new HashSet<>();

    do {
      intersectingSegments = new HashSet<>();
      Set<Line.Segment> removableSegmentsThisPlayer =
          getRemovableLineSegments(pieceMap, pieceColor);
      for (Line.Segment segment : removableSegmentsThisPlayer) {
        // Remove the line segments that are not intersecting with other line segments of the set
        boolean intersectionFound = false;

        for (Line.Segment otherSegment : removableSegmentsThisPlayer) {
          if (!segment.equals(otherSegment) && !segmentsNotRemoved.contains(otherSegment)) {
            if (segment.intersectsWith(otherSegment)) {
              if (!segmentsNotRemoved.contains(segment)) {
                intersectingSegments.add(segment);
                intersectionFound = true;
              }
            }
          }
        }

        if (!intersectionFound) {
          if (!segmentsNotRemoved.contains(segment)) {
            linesTakenBy.get(pieceColor).add(segment);
          }
        }
      }

      if (intersectingSegments.size() > 0) {
        Line.Segment segment = intersectingSegments.iterator().next();
        currentRemoveSelection = segment.getOccupiedPositions(pieceMap);

        int dialogResult =
            GipfBoardComponent.showConfirmDialog(
                gipfBoardState.players.current().pieceColor
                    + ", do you want to remove "
                    + segment
                        .getOccupiedPositions(pieceMap)
                        .stream()
                        .map(Position::getName)
                        .sorted()
                        .collect(toList())
                    + "?",
                "Remove line segment");
        if (dialogResult == JOptionPane.YES_OPTION) {
          // Remove the line
          linesTakenBy.get(pieceColor).add(segment);
        } else if (dialogResult == JOptionPane.NO_OPTION) {
          // Don't remove the line
          segmentsNotRemoved.add(segment);
        }
        currentRemoveSelection = new HashSet<>();
      }

      for (Line.Segment segment : linesTakenBy.get(pieceColor)) {
        Predicate<Map.Entry<Position, Piece>> isNormalPiece =
            entry -> entry.getValue().getPieceType() == NORMAL;
        Predicate<Map.Entry<Position, Piece>> isCurrentPlayersColor =
            entry -> entry.getValue().getPieceColor() == pieceColor;
        Predicate<Map.Entry<Position, Piece>> doesPlayerWantToRemoveGipf =
            entry -> {
              currentRemoveSelection.add(entry.getKey());
              int dialogResult =
                  GipfBoardComponent.showConfirmDialog(
                      gipfBoardState.players.current().pieceColor
                          + ", do you want to remove the Gipf at "
                          + entry.getKey().getName()
                          + "?",
                      "Remove Gipf");
              currentRemoveSelection = new HashSet<>();
              return dialogResult == JOptionPane.YES_OPTION;
            };

        Map<Position, Piece> piecesRemovedMap =
            segment.getOccupiedPositions(pieceMap).stream().collect(toMap(p -> p, pieceMap::get));

        piecesBackTo
            .get(pieceColor)
            .addAll(
                piecesRemovedMap
                    .entrySet()
                    .stream()
                    .filter(isCurrentPlayersColor.and(isNormalPiece.or(doesPlayerWantToRemoveGipf)))
                    .map(Map.Entry::getKey)
                    .collect(toSet()));

        piecesBackTo
            .get(null)
            .addAll(
                piecesRemovedMap
                    .entrySet()
                    .stream()
                    .filter(
                        isCurrentPlayersColor
                            .negate()
                            .and(isNormalPiece.or(doesPlayerWantToRemoveGipf)))
                    .map(Map.Entry::getKey)
                    .collect(toSet()));
      }

      piecesBackTo.values().forEach(positionSet -> removePiecesFromPieceMap(pieceMap, positionSet));
    } while (intersectingSegments.size() > 0);

    return;
  }
예제 #3
0
파일: Game.java 프로젝트: FransM22/GipfGame
  public Set<Move> getAllowedMoves() {
    // If there is already a winn
    if (gipfBoardState.players.winner() != null) {
      return Collections.emptySet();
    }

    // Create a set of incomplete moves containing the starting positions and directions for the
    // current piece
    Set<Move> potentialMoves = getPotentialStartMoves(getCurrentPiece());

    // If the current piece is a GIPF piece, the player is also allowed to place normal pieces.
    if (getCurrentPiece().getPieceType() == GIPF)
      potentialMoves.addAll(
          getPotentialStartMoves(Piece.of(NORMAL, getCurrentPiece().getPieceColor())));

    // These moves are marked as complete so a temporary game won't ask for user input.
    potentialMoves.stream().forEach(m -> m.isCompleteMove = true);

    Set<Move> potentialMovesIncludingLineSegmentRemoval = new HashSet<>();
    for (Move potentialMove : potentialMoves) {
      try {
        Map<Position, Piece> temporaryPieceMap = new HashMap<>(getGipfBoardState().getPieceMap());
        temporaryPieceMap.put(potentialMove.startPos, potentialMove.addedPiece);
        movePiecesTowards(
            temporaryPieceMap, potentialMove.getStartingPosition(), potentialMove.getDirection());

        Set<List<Pair<PieceColor, Line.Segment>>> RLineOrderingsSet =
            getRemovableLineOrderingsSetFromGipfBoard(
                temporaryPieceMap, getCurrentPiece().getPieceColor());
        if (RLineOrderingsSet.size() > 0) {
          for (List<Pair<PieceColor, Line.Segment>> RLineOrdering : RLineOrderingsSet) {
            Set<Position> piecesToWhite = new HashSet<>();
            Set<Position> piecesToBlack = new HashSet<>();
            Set<Position> piecesRemoved = new HashSet<>();

            for (Pair<PieceColor, Line.Segment> RLine : RLineOrdering) {
              Line.Segment removedSegment = RLine.getValue();

              // The color of the player who removed the line
              PieceColor colorRemoved = RLine.getKey();

              // Determine per segment to whom the pieces are given. Pieces can only be given to the
              // player
              // who removed the line, or deleted from the game.
              Set<Position> occupiedPositions =
                  removedSegment.getOccupiedPositions(temporaryPieceMap);
              Set<Position> piecesFromSegmentBackToReserve =
                  occupiedPositions
                      .stream()
                      .filter(
                          position ->
                              temporaryPieceMap.get(position).getPieceColor() == colorRemoved)
                      .collect(toSet());
              Set<Position> piecesFromSegmentRemoved =
                  occupiedPositions
                      .stream()
                      .filter(position -> !piecesFromSegmentBackToReserve.contains(position))
                      .collect(toSet());

              if (colorRemoved == WHITE) piecesToWhite.addAll(piecesFromSegmentBackToReserve);
              if (colorRemoved == BLACK) piecesToBlack.addAll(piecesFromSegmentBackToReserve);
              piecesRemoved.addAll(piecesFromSegmentRemoved);
            }

            // And finally add the move
            // the constructor will define this as a complete move, because all the parameters have
            // a value.
            potentialMovesIncludingLineSegmentRemoval.add(
                new Move(
                    potentialMove.addedPiece,
                    potentialMove.startPos,
                    potentialMove.direction,
                    piecesToWhite,
                    piecesToBlack,
                    piecesRemoved));
          }
        } else {
          // If no line segments can be removed, just add the original move
          potentialMovesIncludingLineSegmentRemoval.add(potentialMove);
        }
      } catch (InvalidMoveException e) {
        // We don't consider this move if it is invalid
      }
    }

    return potentialMovesIncludingLineSegmentRemoval;
  }