import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
class Enemy {
String name;
double hp;
int dps;
int def;
double hitRate;
double critRate;
boolean alive;
Color themeColor;
public Enemy(String name, int hp, int dps, int def, double hitRate, double critRate, Color color) {
this.name = name;
this.hp = hp;
this.dps = dps;
this.def = def;
this.hitRate = hitRate;
this.critRate = critRate;
this.alive = true;
this.themeColor = color;
}
public double expectedDamage(int myDPS) {
int baseDamage = myDPS - this.def;
double d = Math.max(1, baseDamage);
return hitRate * d * (1 + critRate);
}
public int requiredRounds(int myDPS) {
double ed = expectedDamage(myDPS);
return (int) Math.ceil(hp / ed);
}
public double threatValue(int myDPS) {
return dps * requiredRounds(myDPS);
}
}
class BattleSimulator {
static final int MY_DPS = 1;
List<Enemy> enemies;
int totalDamageTaken;
StringBuilder battleLog = new StringBuilder();
public BattleSimulator(List<Enemy> enemies) {
this.enemies = new ArrayList<>(enemies);
this.totalDamageTaken = 0;
}
public String simulateSingleRound(int round) {
battleLog.setLength(0);
int roundDamage = 0;
for (Enemy e : enemies) {
if (e.alive) roundDamage += e.dps;
}
totalDamageTaken += roundDamage;
battleLog.append(String.format("第%d回合 敌方攻击 我方受到伤害:%d 总伤害:%d%n",
round, roundDamage, totalDamageTaken));
Enemy target = selectTarget();
if (target != null) {
double ed = target.expectedDamage(MY_DPS);
target.hp -= ed;
battleLog.append(String.format("我方攻击 %s 造成期望伤害 %.2f 剩余HP:%.2f%n",
target.name, ed, target.hp));
if (target.hp <= 1e-6) {
target.alive = false;
battleLog.append(target.name + " 被击败%n");
}
}
return battleLog.toString();
}
private Enemy selectTarget() {
return enemies.stream()
.filter(e -> e.alive)
.max(Comparator.comparingDouble(e -> e.threatValue(MY_DPS)))
.orElse(null);
}
public boolean isBattleEnded() {
return enemies.stream().noneMatch(e -> e.alive);
}
}
public class EnhancedBattleSimulator extends JFrame {
private static final Color BG_COLOR = new Color(45, 45, 48);
private static final Font TITLE_FONT = new Font("微软雅黑", Font.BOLD, 14);
private static final Font INFO_FONT = new Font("宋体", Font.PLAIN, 12);
private BattleSimulator simulator;
private JPanel enemyPanel;
private JTextArea logArea;
private JButton controlButton;
private JComboBox<String> speedCombo;
private Timer autoTimer;
private int currentRound = 1;
private boolean isAutoMode = false;
public EnhancedBattleSimulator(List<Enemy> enemies) {
simulator = new BattleSimulator(enemies);
initUI();
setupTimer();
}
private void initUI() {
setTitle("史诗级自动战斗模拟器");
setSize(900, 680);
setDefaultCloseOperation(EXIT_ON_CLOSE);
getContentPane().setBackground(BG_COLOR);
setLayout(new BorderLayout(10, 10));
JPanel controlPanel = createControlPanel();
add(controlPanel, BorderLayout.NORTH);
enemyPanel = new JPanel(new GridLayout(0, 3, 15, 15));
enemyPanel.setBorder(new EmptyBorder(15, 15, 15, 15));
enemyPanel.setBackground(BG_COLOR);
add(new JScrollPane(enemyPanel), BorderLayout.CENTER);
logArea = new JTextArea();
logArea.setFont(INFO_FONT);
logArea.setForeground(Color.WHITE);
logArea.setBackground(new Color(60, 60, 60));
logArea.setEditable(false);
add(new JScrollPane(logArea), BorderLayout.SOUTH);
updateEnemyDisplay();
}
private JPanel createControlPanel() {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
panel.setBackground(BG_COLOR);
controlButton = new JButton("开始史诗对决");
styleButton(controlButton, new Color(76, 175, 80));
controlButton.addActionListener(this::handleControlButton);
speedCombo = new JComboBox<>(new String[]{"慢动作", "正常速度", "闪电战"});
speedCombo.setRenderer(new StyledComboBoxRenderer());
speedCombo.setBackground(new Color(70, 70, 70));
speedCombo.setForeground(Color.WHITE);
speedCombo.setFont(INFO_FONT);
panel.add(createStyledLabel("战斗速度:"));
panel.add(speedCombo);
panel.add(Box.createHorizontalStrut(20));
panel.add(controlButton);
return panel;
}
private void styleButton(JButton button, Color bgColor) {
button.setFont(TITLE_FONT);
button.setBackground(bgColor);
button.setForeground(Color.WHITE);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(bgColor.darker(), 2),
BorderFactory.createEmptyBorder(8, 20, 8, 20)
));
}
private JLabel createStyledLabel(String text) {
JLabel label = new JLabel(text);
label.setFont(TITLE_FONT);
label.setForeground(new Color(200, 200, 200));
return label;
}
private void setupTimer() {
autoTimer = new Timer(1000, e -> {
if (!simulateNextRound()) {
stopAutoMode();
}
});
}
private void handleControlButton(ActionEvent e) {
if (isAutoMode) {
stopAutoMode();
} else {
startAutoMode();
}
}
private void startAutoMode() {
isAutoMode = true;
controlButton.setText("停止战斗");
speedCombo.setEnabled(false);
autoTimer.setDelay(getSpeedDelay());
autoTimer.start();
}
private void stopAutoMode() {
isAutoMode = false;
autoTimer.stop();
controlButton.setText("重新开始");
speedCombo.setEnabled(true);
}
private int getSpeedDelay() {
switch (speedCombo.getSelectedIndex()) {
case 0: return 1500;
case 1: return 800;
case 2: return 400;
default: return 1000;
}
}
private boolean simulateNextRound() {
if (simulator.isBattleEnded()) return false;
String log = simulator.simulateSingleRound(currentRound++);
SwingUtilities.invokeLater(() -> {
updateEnemyDisplay();
logArea.append(log + "--------------------\n");
logArea.setCaretPosition(logArea.getDocument().getLength());
});
return true;
}
private void updateEnemyDisplay() {
enemyPanel.removeAll();
for (Enemy e : simulator.enemies) {
enemyPanel.add(createEnemyCard(e));
}
enemyPanel.revalidate();
enemyPanel.repaint();
}
private JPanel createEnemyCard(Enemy enemy) {
JPanel card = new JPanel(new BorderLayout(10, 10));
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(enemy.themeColor, 3),
BorderFactory.createEmptyBorder(15, 15, 15, 15)
));
card.setBackground(new Color(55, 55, 58));
JProgressBar hpBar = new GradientProgressBar(enemy);
hpBar.setStringPainted(true);
JPanel infoPanel = new JPanel(new GridLayout(0, 1, 0, 5));
infoPanel.setOpaque(false);
addStyledLabel(infoPanel, "⚔ 攻击力: " + enemy.dps, new Color(255, 205, 210));
addStyledLabel(infoPanel, "�� 防御: " + enemy.def, new Color(179, 229, 252));
addStyledLabel(infoPanel, String.format("❤ 生命值: %.1f", enemy.hp), new Color(255, 138, 128));
card.add(hpBar, BorderLayout.NORTH);
card.add(infoPanel, BorderLayout.CENTER);
return card;
}
private void addStyledLabel(JPanel panel, String text, Color color) {
JLabel label = new JLabel(text);
label.setFont(INFO_FONT);
label.setForeground(color);
panel.add(label);
}
class GradientProgressBar extends JProgressBar {
private final Enemy enemy;
public GradientProgressBar(Enemy enemy) {
super(0, (int) enemy.hp);
this.enemy = enemy;
setValue((int) enemy.hp);
setString(String.format("%.1f / %d", enemy.hp, (int) enemy.hp));
setForeground(enemy.themeColor);
setBackground(new Color(70, 70, 70));
setFont(INFO_FONT);
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
double progress = getPercentComplete();
int width = (int) (getWidth() * progress);
GradientPaint gp = new GradientPaint(
0, 0, enemy.themeColor.brighter(),
width, 0, enemy.themeColor.darker()
);
g2d.setPaint(gp);
g2d.fillRect(0, 0, width, getHeight());
g2d.setColor(Color.WHITE);
FontMetrics fm = g2d.getFontMetrics();
String text = getString();
int x = (getWidth() - fm.stringWidth(text)) / 2;
int y = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();
g2d.drawString(text, x, y);
g2d.dispose();
}
}
class StyledComboBoxRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
label.setBackground(isSelected ? new Color(80, 80, 80) : BG_COLOR);
label.setForeground(isSelected ? Color.WHITE : new Color(180, 180, 180));
label.setBorder(new EmptyBorder(5, 15, 5, 15));
label.setFont(INFO_FONT);
return label;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
List<Enemy> enemies = new ArrayList<>();
enemies.add(new Enemy("森林巨魔", 35, 4, 2, 0.85, 0.15, new Color(106, 176, 76)));
enemies.add(new Enemy("暗影刺客", 28, 6, 1, 0.75, 0.25, new Color(148, 120, 221)));
enemies.add(new Enemy("熔岩巨人", 50, 3, 5, 0.95, 0.05, new Color(207, 102, 121)));
EnhancedBattleSimulator simulator = new EnhancedBattleSimulator(enemies);
simulator.setLocationRelativeTo(null);
simulator.setVisible(true);
});
}
}