我正在编写一个程序,使用蒙特卡洛方法近似 π 的值。
我的计划是让它直观地绘制 X 个点,并根据该图计算结果。
到目前为止的设计是这样的:
快速警告:我是 Java 的新手 - 请原谅任何可怕的代码设置或愚蠢的问题。
运行程序时,根据输入速度会发生以下两种情况之一:
a.) 对于慢速或中速,在计时器启动之前绘制两个点,并绘制第一个“真实”点。
b.) 对于快速或非常快的速度,第一个点会绘制两次。
由于某种原因,这也可能发生在第二点而不是第一点。
我不知道为什么会发生这种情况。以下是我尝试过的一些事情:
public class Main {
public static void main(String[] args) {
SimSetup simSetup = new SimSetup();
simSetup.simSetup();
SimFrame frame = new SimFrame();
SimDrawing d = new SimDrawing();
frame.add(d);
frame.setVisible(true);
}
}
public class SimSetup {
private final UserInput userInput = new UserInput();
public void simSetup() {
title.displayTitle();
boolean startupSuccess = false;
while (!startupSuccess) {
userInput.setPoints();
userInput.setPlotSpeed();
if ((userInput.setVerification(userInput.getPoints(),
userInput.getPlotSpeed()))) {
break;
}
}
SimDrawing.setPoints(userInput.getPoints());
SimDrawing.setSpeed(userInput.getPlotSpeed());
}
}
import java.util.InputMismatchException;
import java.util.Objects;
import java.util.Scanner;
public class UserInput {
private int numPoints;
private short plotSpeed;
private String verification;
public int getPoints() {
return numPoints;
}
public short getPlotSpeed() {
return plotSpeed;
}
public String getVerification() {
return verification;
}
public int setPoints() {
System.out.print("Enter the number of points to be plotted using a positive integer between 1 and 100,000: ");
try {
Scanner scanner = new Scanner(System.in);
numPoints = scanner.nextInt();
if (numPoints < 0) {
System.out.println("\nNumber of points must be a positive integer. Please try again.\n");
setPoints();
} else if (numPoints == 0) {
System.out.println("\nCan't generate a plot using zero points! Please try again.\n");
setPoints();
} else if (numPoints > 100000) {
System.out.println("\nNumber of points is too large. Please try again.\n");
setPoints();
}
} catch (InputMismatchException e) {
System.out.println("\nThe number of points must be an integer between 1 and 100,000. Please try again.\n");
setPoints();
}
return numPoints;
}
public short setPlotSpeed() {
System.out.print("\nSelect a plotting animation speed from the choices below:");
System.out.println("\n0 -- Slow\n1 -- Medium\n2 -- Fast\n3 -- Very Fast\n");
try {
Scanner scanner = new Scanner(System.in);
short speedChoice = scanner.nextShort();
if (speedChoice == 0) {
plotSpeed = 100;
} else if (speedChoice == 1) {
plotSpeed = 50;
} else if (speedChoice == 2) {
plotSpeed = 10;
} else if (speedChoice == 3) {
plotSpeed = 1;
}
} catch (InputMismatchException e) {
System.out.println("Speed must be an integer between 0 to 3. Please try again.");
}
return plotSpeed;
}
public boolean setVerification(long numPoints, short plotSpeed) {
if (numPoints > 50000 && (plotSpeed == 100 || plotSpeed == 50)) {
System.out.println("This combination of points and animation speed will result in long completion time.");
System.out.println("Are you sure? (Y to continue, N to re-enter choices.)");
try {
Scanner scanner = new Scanner(System.in);
verification = scanner.nextLine();
verification = verification.toLowerCase();
if (Objects.equals(verification, "n")) {
System.out.println("\nProcess aborted.\n");
return false;
} else if (!Objects.equals(verification, "n") && !Objects.equals(verification, "y")) {
System.out.println("\nVerification input not recognized. Please try again.");
setVerification(numPoints, plotSpeed);
return false;
}
} catch (Exception e) {
System.out.println("Exception: " + e);
}
}
return true;
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SimDrawing extends JPanel implements ActionListener {
int count = 0;
int max = 525;
int min = 75;
int circleRadius = 450;
int x = min + (int) (Math.random() * (max - min + 1));
int y = min + (int) (Math.random() * (max - min + 1));
private static int points;
private static short speed;
private int circlePoints;
private int outsidePoints;
Timer t = new Timer(speed, this);
public static void setPoints(int numPoints) {
points = numPoints;
}
public static void setSpeed(short plotSpeed) {
speed = plotSpeed;
}
public SimDrawing() {
t.start();
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("\nCount: " + count);
x = min + (int) (Math.random() * (max - min + 1));
y = min + (int) (Math.random() * (max - min + 1));
System.out.println("\nPoint generated: " + "(" + x + "," + y + ")");
repaint();
if (count == points) {
t.stop();
pointCheck();
}
count++;
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
double distanceFromCenter = (Math.sqrt(Math.pow((x - 75), 2) + Math.pow((y - 525), 2)));
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(2));
g2d.drawLine(74, 74, 526, 74);
g2d.drawLine(74, 74, 74, 526);
g2d.drawLine(74, 526, 526, 526);
g2d.drawLine(526, 74, 526, 526);
g2d.setStroke(new BasicStroke(3));
if (distanceFromCenter <= circleRadius) {
g2d.setColor(Color.BLACK);
g2d.drawLine(x, y, x, y);
System.out.println("Plotting inside point: " + "(" + x + "," + y + ")");
circlePoints++;
}
if (distanceFromCenter > circleRadius) {
g2d.setColor(Color.RED);
g2d.drawLine(x, y, x, y);
System.out.println("Plotting outside point: " + "(" + x + "," + y + ")");
outsidePoints++;
}
}
public void pointCheck() {
System.out.println("\nThe number of points inside the circle is: " + circlePoints);
System.out.println("The number of points outside the circle is: " + outsidePoints);
int totalMappedPoints = circlePoints + outsidePoints;
System.out.println("The total number of points is: " + totalMappedPoints);
}
}
import javax.swing.*;
import java.awt.*;
public class SimFrame extends JFrame {
public SimFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setAlwaysOnTop(true);
setTitle("Monte Carlo Method of Approximating π");
setSize(616, 639);
setResizable(false);
setLayout(new GridLayout());
setLocationRelativeTo(null);
}
}
我想你可能错过了
Component#paint()
的作用,这意味着在代码中,您将需要 SimDrawing 中的一个变量,称为
/**Vector2 is a base java class, i think, if not find one online*/
List<Vector2> plottedPoints = new ArrayList<>();
然后,在paint函数中绘制这些点
for (Vector2 point : plottedPoints) {
g2d.setColor(getColorOfPoint(point));
g2d.drawOval(point.x-5, point.y-5, 10, 10);
}
课堂上的其他地方:
public static Color getColorOfPoint(Vector2 point) {
return SimDrawing.isInsideCircle(point) ? Color.Red : Color.Blue;
}
另外还有
SimDrawing#actionPerformed(ActionEvent)
方法
points.add(new Vector2(x, y));
//Also add to the points in or outside
if (isInsideCircle(point))
pointsInside++;
else
pointsOutside++;
同班的其他地方:
public static Color isInsideCircle(Vector2 point) {
..The code you used earlier
}