Java Swing 可视化素数筛:动态演示 1~120 质数筛选【附完整源码】

动态演示 1~120 质数筛选

项目简介

本项目基于Java Swing图形界面开发,实现可视化质数筛选工具PrimeNumberSieve。程序在10行×12列网格中摆放1~120全部数字,通过延时动画逐个校验数值是否为素数,素数格子变红,合数填充随机配色,同时右侧文本框实时累加所有找到的质数,把抽象的素数判断算法转化为直观的动态画面。

项目用到技术:Swing窗口布局、GridLayout网格布局、SwingWorker子线程动画延时、高效素数判定算法、随机配色工具方法。

素数判定算法原理(分小点)

  1. 素数规则
    (1)小于等于 1:非素数;
    (2)2、3:是素数;
    (3)能被 2、3 整除:非素数;
    (4)从 i=5 开始,步长 + 6,校验i和i+2能否整除目标数,直到√n。
  2. 核心 isPrime 算法思路
    区别暴力循环,该判定方式减少循环次数,优化大数判断效率,下文代码对应本逻辑

完整源码:

java 复制代码
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class PrimeNumberSieve extends JFrame {

    private static final int ROWS = 10;
    private static final int COLS = 12;
    private static final int TOTAL = ROWS * COLS; // 120
    private static final int DELAY = 50; // 每个格子遍历延迟(毫秒)

    private JPanel gridPanel;
    private JPanel primeListPanel;
    private JLabel[] numberLabels = new JLabel[TOTAL];
    private JTextArea primeTextArea;
    private List<Integer> primesFound = new ArrayList<>();
    private Random random = new Random();

    public PrimeNumberSieve() {
        setTitle("Prime Numbers Visual Sieve");
        setSize(900, 650);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setLayout(new BorderLayout(10, 10));

        // 初始化网格面板 (10行12列)
        gridPanel = new JPanel(new GridLayout(ROWS, COLS, 3, 3));
        gridPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        gridPanel.setBackground(Color.WHITE);

        // 创建120个格子,初始灰色
        for (int i = 1; i <= TOTAL; i++) {
            JLabel label = new JLabel(String.valueOf(i), SwingConstants.CENTER);
            label.setOpaque(true);
            label.setBackground(Color.GRAY);
            label.setForeground(Color.BLACK);
            label.setFont(new Font("Arial", Font.BOLD, 14));
            label.setPreferredSize(new Dimension(60, 45));

            Border border = BorderFactory.createLineBorder(Color.DARK_GRAY, 1);
            label.setBorder(border);

            numberLabels[i - 1] = label;
            gridPanel.add(label);
        }

        // 右侧素数列表面板
        primeListPanel = new JPanel(new BorderLayout());
        primeListPanel.setBorder(BorderFactory.createTitledBorder("Prime numbers"));
        primeListPanel.setBackground(Color.WHITE);
        primeListPanel.setPreferredSize(new Dimension(200, 0));

        primeTextArea = new JTextArea();
        primeTextArea.setEditable(false);
        primeTextArea.setFont(new Font("Monospaced", Font.PLAIN, 14));
        primeTextArea.setBackground(Color.WHITE);
        primeTextArea.setLineWrap(true);
        primeTextArea.setWrapStyleWord(true);

        JScrollPane scrollPane = new JScrollPane(primeTextArea);
        scrollPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        primeListPanel.add(scrollPane, BorderLayout.CENTER);

        // 添加到主窗口
        add(gridPanel, BorderLayout.CENTER);
        add(primeListPanel, BorderLayout.EAST);

        // 开始遍历动画
        startSieveAnimation();
    }

    private void startSieveAnimation() {
        SwingWorker<Void, Integer> worker = new SwingWorker<>() {
            @Override
            protected Void doInBackground() throws Exception {
                for (int i = 1; i <= TOTAL; i++) {
                    Thread.sleep(DELAY);
                    publish(i);
                }
                return null;
            }

            @Override
            protected void process(List<Integer> chunks) {
                for (int num : chunks) {
                    checkAndColorNumber(num);
                }
            }

            @Override
            protected void done() {
                // 动画结束后,在控制台打印所有素数
                System.out.println("=== 遍历完成 ===");
                System.out.println("找到的素数总数: " + primesFound.size());
                System.out.println("所有素数: " + primesFound);

                // 也可以在 GUI 中弹窗提示
                JOptionPane.showMessageDialog(
                        PrimeNumberSieve.this,
                        "筛法完成!共找到 " + primesFound.size() + " 个素数。\n请在控制台查看完整列表。",
                        "完成",
                        JOptionPane.INFORMATION_MESSAGE
                );
            }
        };
        worker.execute();
    }

    private void checkAndColorNumber(int num) {
        JLabel label = numberLabels[num - 1];

        if (isPrime(num)) {
            // 素数 -> 红色
            label.setBackground(Color.RED);
            label.setForeground(Color.WHITE);
            primesFound.add(num);

            // 更新右侧素数列表显示
            updatePrimeDisplay();
        } else {
            // 非素数 -> 随机颜色(排除红色和灰色,避免混淆)
            Color randomColor = getRandomColor();
            label.setBackground(randomColor);
            label.setForeground(Color.BLACK);
        }
    }

    private boolean isPrime(int n) {
        if (n <= 1) return false;
        if (n <= 3) return true;
        if (n % 2 == 0 || n % 3 == 0) return false;
        for (int i = 5; i * i <= n; i += 6) {
            if (n % i == 0 || n % (i + 2) == 0) return false;
        }
        return true;
    }

    private Color getRandomColor() {
        // 生成鲜艳的随机颜色,排除红色(素数专用)和灰色(初始色)
        int r, g, b;
        do {
            r = random.nextInt(200) + 55; // 55-255
            g = random.nextInt(200) + 55;
            b = random.nextInt(200) + 55;
        } while ((r > 200 && g < 100 && b < 100) || (r == g && g == b)); // 排除红色和灰色

        return new Color(r, g, b);
    }

    private void updatePrimeDisplay() {
        StringBuilder sb = new StringBuilder();
        int count = 0;
        for (int p : primesFound) {
            sb.append(String.format("%4d", p));
            count++;
            if (count % 4 == 0) {
                sb.append("\n");
            } else {
                sb.append(" ");
            }
        }
        primeTextArea.setText(sb.toString());
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new PrimeNumberSieve().setVisible(true);
        });
    }
}
相关推荐
青山木5 分钟前
一把 Redis 分布式锁,踩透四个坑:锁争抢、僵尸锁、锁过期、锁丢失
java·数据库·redis·后端
Java内核笔记28 分钟前
万字避坑!Spring Boot 3.x 升 4.0 最全升级指南(附 Migration Checklist,建议收藏⭐)
java·后端
从零开始的代码生活_30 分钟前
C++ list 原理与实践:双向链表、迭代器与简化实现
开发语言·c++·后端·学习·算法·链表·list
cfm_29141 小时前
SpringBoot启动原理
java·spring boot·spring
ttod_qzstudio2 小时前
【软考算法】软件设计师下午第四题之动态规划:0-1 背包与最长公共子序列的“填表艺术“
算法·动态规划·软考
柒和远方2 小时前
LeetCode 139. 单词拆分 —— 从暴力回溯到 DP 完全背包
javascript·python·算法
漫随流水2 小时前
Java——springboot web案例
java·开发语言·spring boot
从此以后自律2 小时前
Java Object 类常用方法全讲解
java·开发语言
念何架构之路2 小时前
Docker 容器状态机 学习
java·学习·docker
你有我备注吗2 小时前
SQL学习之查询
java·sql·学习