Beispiel #1
0
  @Override
  public void showGame(
      Game game, Set<Location<Integer>> blockedLocations, Map<Room, Weapon> weaponLocations) {
    Board board = game.board;

    char[][] buffer = new char[2 * (board.width + 1)][2 * (board.height + 1)];
    for (char[] line : buffer) {
      Arrays.fill(line, ' ');
    }

    for (int x = 0; x < board.width; x++) {
      for (int y = 0; y < board.height; y++) {
        // The actual tile is at buffer[2x + 1][2y + 1]
        // Walls: above is [2x + 1][2y], left is [2x][2y + 1]

        if (board.hasWallBetween(
            new Location<>(x, y), new Location<>(x, y - 1))) { // if there's a wall above the tile.
          buffer[2 * x + 1][2 * y] = '-';
        }
        if (board.hasWallBetween(
            new Location<>(x, y),
            new Location<>(x - 1, y))) { // if there's a wall to the left of the tile.
          buffer[2 * x][2 * y + 1] = '|';
        }
      }
    }
    for (int x = 0; x < board.width; x++) {
      buffer[2 * x + 1][2 * board.height] = '-';
    }
    for (int y = 0; y < board.height; y++) {
      buffer[2 * board.width][2 * y + 1] = '|';
    }

    for (Room room : Room.values()) {
      Location<Float> centre = board.centreLocationForRoom(room);
      String name = room.shortName();

      int startX = 2 * centre.x.intValue() + 1 - name.length() / 2;
      int y = 2 * centre.y.intValue() + 1;

      for (int i = 0; i < +name.length(); i++) {
        buffer[startX + i][y] = name.charAt(i);
      }
    }

    for (Player player : game.allPlayers) {
      CluedoCharacter character = player.character;
      Location<Integer> location = player.location();
      buffer[2 * location.x + 1][2 * location.y + 1] = this.asciiIconForCharacter(character);
    }

    for (int y = 0; y < 2 * (board.height + 1); y++) {
      for (int x = 0; x < 2 * (board.width + 1); x++) {
        this.out.print(buffer[x][y]);
      }
      this.out.print('\n');
    }
  }
Beispiel #2
0
  @Override
  public Optional<Suggestion> requestPlayerAccusation(Player player) {
    char userWantsToMakeAccusation = '\0';

    while (userWantsToMakeAccusation != 'Y' && userWantsToMakeAccusation != 'N') {
      this.out.println("Do you want to make an accusation (Y/N)?");
      userWantsToMakeAccusation = this.scanner.next().charAt(0);
    }

    if (userWantsToMakeAccusation == 'Y') {
      this.out.println("Choose your suspect:");

      Stream<String> suspects =
          Arrays.stream(CluedoCharacter.values())
              .filter(e -> !player.cards.contains(e))
              .map(CluedoCharacter::toString);
      CluedoCharacter suspect = CluedoCharacter.values()[this.selectOptionFromList(suspects)];

      this.out.println("Choose your weapon:");

      Stream<String> weapons =
          Arrays.stream(Weapon.values())
              .filter(e -> !player.cards.contains(e))
              .map(Weapon::toString);
      Weapon weapon = Weapon.values()[this.selectOptionFromList(weapons)];

      this.out.println("Choose your room:");

      Stream<String> rooms =
          Arrays.stream(Room.values()).filter(e -> !player.cards.contains(e)).map(Room::toString);
      Room room = Room.values()[this.selectOptionFromList(rooms)];

      return Optional.of(new Suggestion(suspect, weapon, room));

    } else {
      return Optional.empty();
    }
  }
Beispiel #3
0
  @SuppressWarnings("SuspiciousNameCombination")
  // so we don't get warned about using 'WallWidth' in conjunction with height
  @Override
  protected void paintComponent(Graphics g) {

    double width = this.getWidth();
    double height = this.getHeight();

    Graphics2D graphics2D = (Graphics2D) g;

    graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    graphics2D.setRenderingHint(
        RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

    Board board = _gameState.board;

    double ratio = (double) board.width / board.height;

    width = Math.min(width, (height * ratio));
    height = Math.min(height, (width / ratio));

    double startX = this.getWidth() / 2 - width / 2;
    double startY = this.getHeight() / 2 - height / 2;

    g.setColor(Color.yellow);
    g.fillRect(round(startX), round(startY), round(width), round(height));

    // Draw the grid.

    g.setColor(Color.black);

    double step = width / board.width;

    for (double x = startX + step; x < startX + width; x += step) {
      g.drawLine(round(x), round(startY), round(x), round(startY + height));
    }
    for (double y = startY + step; y < startY + height; y += step) {
      g.drawLine(round(startX), round(y), round(startX + width), round(y));
    }

    // Draw the room tiles.

    int x = 0;
    for (Board.Tile[] column : board.tiles) {
      int y = 0;
      for (Board.Tile tile : column) {
        boolean hasRoom = tile.room.isPresent();
        boolean isUnaccessibleSpace = tile.connectedLocations.isEmpty();
        if (hasRoom || isUnaccessibleSpace) {
          g.setColor(hasRoom ? Color.lightGray : Color.cyan);
          g.fillRect(
              round(x * step + startX - 0.5),
              round(y * step + startY - 0.5),
              round(step + 1),
              round(step + 1));

          if (tile.isPassageway(board)) {
            g.setColor(Color.darkGray);
            for (int i = 0; i < step; i += 2) {
              g.fillRect(
                  round(x * step + startX - 0.5),
                  round(y * step + startY - 0.5 + i),
                  round(step + 1),
                  1);
            }
          }
        }

        y++;
      }

      x++;
    }

    // Draw the walls.
    // Loop again to draw over what we already have.

    g.setColor(Color.black);
    x = 0;
    for (Board.Tile[] column : board.tiles) {
      int y = 0;
      for (Board.Tile tile : column) {
        Location<Integer> location = new Location<>(x, y);

        if (board.hasWallBetween(location, new Location<>(x + 1, y))) {
          g.fillRect(
              round(startX + step * (x + 1) - WallWidth / 2),
              round(startY + step * y - 0.5),
              WallWidth,
              round(step + 1));
        }

        if (board.hasWallBetween(location, new Location<>(x, y + 1))) {
          g.fillRect(
              round(startX + step * x - 0.5),
              round(startY + step * (y + 1) - WallWidth / 2),
              round(step + 1),
              WallWidth);
        }

        y++;
      }

      x++;
    }

    // Draw the outer walls.

    g.fillRect(round(startX), round(startY), WallWidth, round(height));
    g.fillRect(round(startX), round(startY), round(width), WallWidth);
    g.fillRect(round(startX + width - WallWidth), round(startY), WallWidth, round(height));
    g.fillRect(round(startX), round(startY + height - WallWidth), round(width), WallWidth);

    // Draw the names for the rooms.

    g.setFont(GameFont);
    g.setColor(Color.black);
    FontMetrics fontMetrics = g.getFontMetrics(GameFont);

    for (Room room : Room.values()) {
      Location<Float> centre = board.centreLocationForRoom(room);
      double centreX = (centre.x + 0.5f) * step + startX;
      double centreY = (centre.y + 0.5f) * step + startY;

      String name = room.shortName().toUpperCase();

      Rectangle2D bounds = fontMetrics.getStringBounds(name, g);

      g.drawString(
          name, (int) (centreX - bounds.getCenterX()), (int) (centreY - bounds.getCenterY()));

      double stringBottom = bounds.getCenterY() + centreY;

      this.drawWeaponTokenForRoom(g, board, room, centreX, stringBottom, step);
    }

    // Draw the players.

    boolean shouldPlayMoveSequence = this.shouldPlayMoveSequence();
    for (Player player : _gameState.allPlayers) {
      boolean drawTransparent = false;
      Location<Float> playerLocation;
      if (shouldPlayMoveSequence
          && // We haven't finished animating the move
          player.character == _lastPlayerMoveCharacter) { // and the move is for this character
        // then we need to lerp between two values in the move sequence for the character's
        // position.

        int lowIndex = (int) Math.floor(_moveSequencePosition);
        int highIndex = (int) Math.ceil(_moveSequencePosition);
        double lerpValue = _moveSequencePosition - lowIndex;

        Location<Float> startLocation =
            this.centreForTileAtLocation(
                _lastPlayerMove.locations[lowIndex], board, startX, startY, step);
        Location<Float> endLocation =
            this.centreForTileAtLocation(
                _lastPlayerMove.locations[highIndex], board, startX, startY, step);
        if (Location.distance(startLocation, endLocation)
            > step * 1.5) { // if the tiles aren't adjacent, allowing for some error.
          drawTransparent = true;
        }
        playerLocation = Location.lerp(startLocation, endLocation, (float) lerpValue);
      } else {
        playerLocation =
            this.centreForTileAtLocation(player.location(), board, startX, startY, step);
      }

      this.drawPlayer(g, playerLocation, player.character, step, drawTransparent);
    }

    // If we're supposed to draw the overlay for the paths, do so. Don't draw the overlay while
    // we're animating.
    if (_accessibleTilePaths != null && !shouldPlayMoveSequence) {
      this.drawAccessibleTilesOverlay(g, _accessibleTilePaths, startX, startY, step);
    }
  }