유행 바이러스 전염 시뮬레이션 실험
모두 세 개의 자바 파일이 있으니 주석 알림에 따라 프로그램을 보충하고 모의 실험을 완성하십시오.
Epidemic.java (주 클래스)
/**
* Main class for simulating an epidemic. The simulation consists of a "world"
* (a square matrix of cells, or ints). Each cell can be empty or contains an
* individual. The state of a cell is denoted by its integer value in the array.
* The value {@code Config.EMPTY} (which is 0) indicates an empty cell.
* Each individual can be in one of the following states:
*
* - Uninfected. This individual has never been infected with the
* disease. This is indicated by the value {@code Config.UNINFECTED},
* which is -1.
*
- Recovered. This individual was infected with the disease but is
* no longer infected. This is indicated by the value
* {@code Config.RECOVERED}, which is. Once recovered, an individual can
* never again become infected.
*
- Infected. This individual currently has the disease. This is
* indicated by an integer value greater than 1. The higher this value,
* the longer the period will be before this individual switches to the
* RECOVERED state. If the value is less than or equal to
* {@code Config.CONTAGIOUS}, the individual is contagious and can
* spread their disease to others.
*
*
* Remember to use the constants from the {@code Config} class
* directly. DO NOT hard-code constant values from the Config class. You
* will lose points if you do this.
*/
public class Epidemic {
//
// A NOTE ON USING THIS SKELETON.
// We have provided many comments below to outline how your program
// should work. We do not, however, provide a comment describing
// every piece of code you will have to write. You may find that you
// need to add additional code to fully support the functionality
// required by the comments.
//
/**
* Application entry point. Runs an epidemic simulation to completion,
* displaying the results after each step using a {@code WorldViewer}
* object. Each step in the simulation consists of the following sub-steps:
*
* - Move individuals around in the world.
*
- Decrement infected individuals to represent the passage of time.
*
- Spread disease from contagious to uninfected individuals.
*
*
* At the end of each simulation step (that is, after each spread-disease
* substep), you should display the current simulation state by calling
* {@code Config.VIEWER.showWorld()} and passing the correct arguments.
* This will update the picture displayed on the window.
*
*
The simulation is complete once there are no more infected
* individuals.
*
* @param args Command-line arguments (ignored).
*/
public static void main(String[] args) {
// TODO
// Create a world as a 2-D array of ints. Use Config.WORLD_SIZE as
// the width and height of the world. The cells in the array will
// default to 0, which equals Config.EMPTY.
// Call the populateWorld method to populate the world with individuals.
// You may want to declare some variables to keep track of the
// simulation state. This will help you determine when the simulation is
// complete.
// Loop until there are no more infected individuals in the world.
// Call the move method to move individuals around in the world.
// Call the decrement method to advance the state of all infected
// individuals in the world.
// Call the spreadDisease method to spread disease from contagious
// to uninfected individuals.
// Update the viewer by calling Config.VIEWER.showWorld() and
// passing the appropriate information as arguments.
}
/**
* Populates the given world with uninfected and infected individuals, as
* specified by {@code Config.INITIAL_UNINFECTED_COUNT} and
* {@code Config.INITIAL_INFECTED_COUNT}.
*
* @param world World to populate.
*/
public static void populateWorld(int[][] world) {
//world = new int [89][89];
//INITIAL_UNINFECTED_COUNT {@code Config.INITIAL_UNINFECTED_COUNT}
//{@code Config.INITIAL_INFECTED_COUNT}
// TODO
// Populate the world with the correct number
// (Config.INITIAL_UNINFECTED_COUNT) of uninfected individuals. Use
// a loop to call the addIndividual method repeatedly to do this. The
// addIndividual method should be used to add each individual to the
// world.
// Populate world with the correct number
// (Config.INITIAL_INFECTED_COUNT) of infected individuals. Again,
// use a loop to repeatedly call the addInviddual method.
}
/**
* Adds an individual to the simulation world. This should be done by
* randomly selecting an EMPTY cell in the world. That cell's value should
* then be changed to the specified {@code newIndividual} value.
*
* @param world World to add an individual to.
* @param newIndividual The new value to put into the randomly selected
* cell.
*/
public static void addIndividual(int[][] world, int newIndividual) {
// TODO
}
/**
* Randomly moves individuals around in the world. This should be done by
* randomly selecting pairs of adjacent cells in the array. Each such pair
* should then have their values swapped. The number of pairs swapped should
* equal half the number of cells in the world.
*
* @param world The world array.
*/
public static void move(int[][] world) {
// TODO
// Repeatedly call the swapRandomIndividuals method. The number of times
// you call it should be equal to half (round down) of the total number
// of cells in the world.
}
/**
* Randomly swaps two adjacent individuals.
*
* @param world The world array.
*/
public static void swapRandomIndividuals(int[][] world) {
// TODO
// Pick a random cell in the world.
// Randomly pick one of the eight cells adjacent to this one. That is,
// if X was the cell picked earlier, randomly pick one of the A's from
// the diagram below:
// A A A
// A X A
// A A A
// Swap the values contained by the two selected cells.
}
/**
* Advances the disease state of all infected individuals. If an individual
* is infected, his or her state should be decremented by 1 to show the
* advancement of the disease towards the RECOVERED state. Individuals who
* are not infected should not be affected by the decrement method.
*
* @param world The world array.
*/
public static void decrement(int[][] world) {
// TODO
}
/**
* Spreads disease from contagious individuals to adjacent UNINFECTED
* individuals. For each pair of adjacent individuals, if one of them is
* contagious and the other is UNINFECTED, then there is a fixed chance
* ({@code Config.INFECTION_PROBABILITY}) that the UNINFECTED individual
* will become contagious.
*
* @param world The world array.
*/
public static void spreadDisease(int[][] world) {
// TODO
// Loop over all the cells in the world.
// If the cell does not contain a contagious individual (note
// that it could be EMPTY), do nothing.
// If the cell does contain a contagious individual, loop over
// all eight cells that are adjacent to this contagious
// individual. In this loop, you should check each adjacent cell
// to see if it is UNINFECTED. If it is, that cell should have a
// change (Config.INFECTION_PROBABILITY) of becoming
// infected right now. To mark the cell as infected, set its
// value to Config.INFECTED.
}
/**
* Wraps a world coordinate around. Using this on all coordinates means that
* our world has no boundaries--individuals and infections simply wrap
* around from top to bottom and from left to right. This is sometimes
* called a "toroidal world". See
* Wikipedia.
*
* You should call this method on any index before you use it to
* index into the world array. That way, even cells on the edges of the
* array will be considered to have eight adjacent cells. For example,
* consider the cell marked "X" below:
*
* A * A A
* A * A X
* A * A A
* * * * *
* The cell "X"is adjacent to the eight cells marked "A"because the world
* wraps around at the edges.
*
* @param size Size of the world.
* @param coord Coordinate to be wrapped.
* @return The wrapped version of the coordinate.
*/
public static int wrap(int size, int coord) {
//What you want to do here is take an input coord that is potentially
//outside the bounds of the world array and wrap it around so it falls
//within the bounds of the array. There are two ways that the coord can
//be outside the bounds of the world array:
// (1) it can be greater than or equal to size
// (2) it can be less than or equal to -1
//In the first case, we want to subtract the size from the coord to
//bring it within the legal range. In the second case, we want to add
//the size to the coord to bring it within the legal range. You can do
//this with loops and if statements, or you can do it much more
//elegantly using the modulus operator (%), which takes the remainder
//of its first argument after integer division by its second argument.
return 0;//TODO
}
}
2. WorldViewer.java import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.Arrays;
import java.util.concurrent.locks.*;
import javax.swing.*;
/**
* Provides a graphical user interface (GUI) for displaying a world in the
* epidemic simulation. The world is displayed
* as a grid of cells. Empty cells will show up as empty (black) in the grid.
* Uninfected individuals appear as small blue dots, infected individuals appear
* as large red dots, and recovered individuals appear as small pink dots.
* The viewer does not distinguish between contagious and non-contagious
* infected individuals; that is, it displays all infected individuals as large
* red dots.
*
* The viewer also shows the integer values passed to its {@link #showWorld}
* method:
*
* - The number of simulation steps executed so far.
*
- The current count of uninfected individuals.
*
- The current count of infected individuals.
*
- The current count of recovered individuals.
*
*
* DO NOT EDIT THIS FILE. You should put all your code for this
* assighnment in Epidemic.java.
*
* @author pollen
*/
public class WorldViewer {
private Snapshot current, previous, next;
private final JFrame frame;
private final JButton stepForwardButton;
private final JButton stepBackButton;
private final JLabel stepsLabel;
private final JLabel uninfectedLabel;
private final JLabel infectedLabel;
private final JLabel recoveredLabel;
/** Number of milliseconds to pause after each showWorld call. */
private final int frameDuration;
private final boolean enable;
private final Lock lock = new ReentrantLock();
private final Condition cond = lock.newCondition();
/**
* Creates a new WorldViewer for use in students' code. The window will not
* be shown until the showWorld method is called at least once.
*/
public WorldViewer() {
this(40, true);
}
/**
* Creates a new WorldViewer. The window will not be shown until the
* showWorld method is called at least once.
*
* Students' code should not call this constructor. It is for testing
* purposes only.
*
* @param frameDuration Number of milliseconds to pause after showing each
* frame.
*/
public WorldViewer(int frameDuration, boolean enable) {
this.frameDuration = frameDuration;
this.enable = enable;
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Epidemic Simulation");
frame.setSize(800, 600);
frame.setLocation(100, 100);
JPanel pane = new JPanel();
pane.setLayout(new BorderLayout());
frame.setContentPane(pane);
pane.add(new WorldPane(), BorderLayout.CENTER);
JPanel status = new JPanel();
status.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
status.setLayout(new GridLayout(1, 6));
pane.add(status, BorderLayout.SOUTH);
stepBackButton = new JButton("<< Step");
stepBackButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
stepBack();
}});
stepBackButton.setEnabled(false);
status.add(stepBackButton);
stepForwardButton = new JButton("Step >>");
stepForwardButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
stepForward();
}});
stepForwardButton.setEnabled(false);
status.add(stepForwardButton);
stepsLabel = new JLabel();
status.add(stepsLabel);
uninfectedLabel = new JLabel();
status.add(uninfectedLabel);
infectedLabel = new JLabel();
status.add(infectedLabel);
recoveredLabel = new JLabel();
status.add(recoveredLabel);
}
private void stepForward() {
if (next != null) {
showWorld(next, true, true);
} else {
runSimulation();
}
}
private void stepBack() {
showWorld(previous, true, false);
}
/** Wakens the sleeping simulation to run another step. */
private void runSimulation() {
lock.lock();
try {
cond.signalAll();
} finally {
lock.unlock();
}
}
/** Pauses the simulation. */
private void pauseSimulation(boolean await) {
if (await) {
lock.lock();
try {
cond.await();
} catch (InterruptedException e) {
// Empty.
} finally {
lock.unlock();
}
} else {
try {
Thread.sleep(frameDuration);
} catch (InterruptedException e) {
// Empty.
}
}
}
/**
* Displays the current state of the simulated world on the GUI window.
*
* @param world Matrix of tiles that make up the world.
* @param stepsTaken Number of steps that have been taken so far in this
* simulation.
* @param numUninfected Current number of uninfected individuals in the
* simulation.
* @param numInfected Current number of infected individuals in the
* simulation.
* @param numRecovered Current number of recovered individuals in the
* simulation.
* @param pause True to pause the simulation until the user hits the "Step"
* button. False to keep running without requiring the user to hit
* the "Step" button. Feel free to pass either {@code true} or {@code
* false} here. The * example video was generated with {@code pause} set to {@code
* false}.
*/
public void showWorld(
int[][] world,
int stepsTaken,
int numUninfected,
int numInfected,
int numRecovered,
boolean pause
) {
showWorld(new Snapshot(
world,
stepsTaken,
numUninfected,
numInfected,
numRecovered),
pause, true);
pauseSimulation(pause);
}
private void showWorld(
Snapshot newSnapshot,
boolean await,
boolean forward) {
if (forward) {
previous = current;
next = null;
} else {
previous = null;
next = current;
}
current = newSnapshot;
stepForwardButton.setEnabled(next != null || await);
stepBackButton.setEnabled(previous != null && await);
update();
}
/** Updates the painted display based on the current Snapshot. */
private void update() {
if (enable) {
stepsLabel.setText(String.format(
" Steps: %d", current.stepsTaken));
uninfectedLabel.setText(String.format(
" Uninfected: %d", current.numUninfected));
infectedLabel.setText(String.format(
" Infected: %d", current.numInfected));
recoveredLabel.setText(String.format(
" Recovered: %d", current.numRecovered));
frame.setVisible(true); // Make sure the window is shown.
frame.repaint();
}
}
/**
* Prints a representation of the current state of the world to System.out.
* While your program is not required to ever call this method, you may find
* it useful for debugging purposes.
*
* - Empty cells are represented by a space.
*
- Uninfected cells are represented by a period (.).
*
- Recovered cells are represented by a star (*).
*
- Infected cells are represented by an at-sign (@).
*
*
* @param world World array to print.
*/
public static void printWorld(int[][] world) {
for (int i = 0; i < world.length; i++) {
for (int j = 0; j < world[i].length; j++) {
char c;
switch (world[i][j]) {
case Config.EMPTY:
c = ' ';
break;
case Config.UNINFECTED:
c = '.';
break;
case Config.RECOVERED:
c = '*';
break;
default:
c = '@';
break;
}
System.out.print(c + " ");
}
System.out.println();
}
}
/**
* Gets the current number of uninfected individuals, based on the values
* that were passed into {@code showWorld}.
*
* Students' code should not call this method. It is for testing
* purposes only.
*/
public int getUninfectedCount() {
return current == null ? 0 : current.numUninfected;
}
/**
* Gets the current number of infected individuals, based on the values that
* were passed into {@code showWorld}.
*
* Students' code should not call this method. It is for testing
* purposes only.
*/
public int getInfectedCount() {
return current == null ? 0 : current.numInfected;
}
/**
* Gets the current number of recovered individuals, based on the values
* that were passed into {@code showWorld}.
*
* Students' code should not call this method. It is for testing
* purposes only.
*/
public int getRecoveredCount() {
return current == null ? 0 : current.numRecovered;
}
/**
* Gets the number of simulation steps executed so far, based on the values
* that were passed into {@code showWorld}.
*
* Students' code should not call this method. It is for testing
* purposes only.
*/
public int getStepCount() {
return current == null ? 0 : current.stepsTaken;
}
/** JPanel for painting a World on the screen. */
private class WorldPane extends JPanel {
private static final long serialVersionUID = 1L;
public WorldPane() {
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
}
@Override
public void paint(Graphics graphics) {
int[][] world = current.world;
Graphics2D g = (Graphics2D) graphics;
final Insets insets = getInsets();
final int width = getWidth();
final int height = getHeight();
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);
if (world == null) {
// Leave a blank screen.
} else {
// Paint each tile in the proper location.
int size = world.length;
double tileWidth = Math.min(
width - insets.left - insets.right,
height - insets.top - insets.bottom) / (double) size;
// First paint blue and pink individuals (and gray walls, for
// the extra credit portion of the assignment) at a normal size.
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
int tile = world[row][col];
if (tile == Config.EMPTY) {
// Paint nothing.
} else if (tile == Config.WALL) {
// Paint a gray square.
g.setColor(Color.GRAY);
g.fill(new Rectangle2D.Double(
col * tileWidth + insets.left,
row * tileWidth + insets.top,
tileWidth, tileWidth));
} else {
// Choose a color based on the individual's status.
if (tile == Config.UNINFECTED) {
g.setColor(Color.CYAN);
} else if (tile == Config.RECOVERED) {
g.setColor(Color.PINK);
} else { // Infected.
continue;
}
// Paint a circle to represent the individual.
g.fill(new Ellipse2D.Double(
(col + 0.1) * tileWidth + insets.left,
(row + 0.1) * tileWidth + insets.top,
tileWidth * 0.8, tileWidth * 0.8));
}
}
}
// Now paint red individuals at a larger size.
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
int tile = world[row][col];
if (tile == Config.EMPTY) {
// Paint nothing.
} else {
// Choose a color based on the individual's status.
if (tile == Config.UNINFECTED) {
continue;
} else if (tile == Config.RECOVERED) {
continue;
} else if (tile == Config.WALL){
continue;
} else { // Infected.
g.setColor(Color.RED);
}
// Paint a circle to represent the individual.
g.fill(new Ellipse2D.Double(
(col - 0.3) * tileWidth + insets.left,
(row - 0.3) * tileWidth + insets.top,
tileWidth * 1.6, tileWidth * 1.6));
}
}
}
}
}
}
private static class Snapshot {
public final int[][] world;
public final int stepsTaken;
public final int numUninfected;
public final int numInfected;
public final int numRecovered;
public Snapshot(
int[][] world,
int stepsTaken,
int numUninfected,
int numInfected,
int numRecovered) {
this.stepsTaken = stepsTaken;
this.numUninfected = numUninfected;
this.numInfected = numInfected;
this.numRecovered = numRecovered;
this.world = copy(world);
}
/** Creates a copy of a world. */
private static int[][] copy(int[][] world) {
int[][] copy = new int[world.length][];
for (int i = 0; i < world.length; i++) {
copy[i] = Arrays.copyOf(world[i], world[i].length);
}
return copy;
}
}
}
3. Config.java import java.util.Random;
/**
* Defines constant simulation configuration values. You should refer to these
* constants in your program. Do not put these magic numbers directly into your
* program's code. Instead, access them like this: {@code Config.RANDOM},
* {@code Config.INFECTED}, etc.
*
* DO NOT ADD, REMOVE, OR RENAME VARIABLES IN THIS FILE. You may
* change values in order to test your program for different configuration
* values.
*
* @author pollen
*/
public class Config {
private Config() {
// This private constructor prevents anyone from ever creating an
// instance of this class.
}
/**
* Random number generator to use for simulation. You may also create your
* own Random objects; we just provide this one for your convenience. In
* your Epidemic class, you may access it by typing {@code
* Config.RANDOM}.
*/
public static final Random RANDOM = new Random();
/**
* WorldViewer object to use for showing simulation results to the user in
* a GUI (Graphical User Interface) window. Do not create additional
* WorldViewer objects, as doing so will break our grading system. Use this
* WorldViewer object for displaying all stages of the simulation.
*/
public static final WorldViewer VIEWER = new WorldViewer();
/** Value to represent an empty tile in the world. */
public static final int EMPTY = 0;
/** Value to represent an uninfected individual in the world. */
public static final int UNINFECTED = -1;
/**
* Value representing a wall in the world. This is only used for the
* extra credit portion of the assignment. If you aren't doing extra
* credit, then you should ignore this constant.
*/
public static final int WALL = -2;
/**
* Value to represent an individual who has recovered from being infected.
*/
public static final int RECOVERED = 1;
/** Value to represent an individual who has just become infected. */
public static final int INFECTED = 9;
/**
* Value to represent an individual who is infected and contagious. Any
* value less than or equal to CONTAGIOUS and greater than RECOVERED is
* considered a contagious individual.
*/
public static final int CONTAGIOUS = 7;
/**
* Probability that infection is passed between any two adjacent
* individuals.
*/
public static final double INFECTION_PROBABILITY = 0.06;
/**
* Probability that an infected individual dies during any simulation step.
* This is only used for the extra credit portion of the assignment.
* If you aren't doing extra credit, then you should ignore this constant.
*/
public static final double DEATH_PROBABILITY = 0.05;
/** Width and height of the world, in cells. */
public static final int WORLD_SIZE = 90;
/** Initial count of uninfected individuals in the simulation. */
public static final int INITIAL_UNINFECTED_COUNT =
(int)(WORLD_SIZE * WORLD_SIZE * 0.8);
/** Initial count of infected individuals in the simulation. */
public static final int INITIAL_INFECTED_COUNT = 5;
/**
* Height of walls to create in the world. This is only used for the
* extra credit portion of the assignment. If you aren't doing extra
* credit, then you should ignore this constant.
*/
public static final int WALL_HEIGHT = (int)(WORLD_SIZE * 0.80);
/**
* Horizontal spacing of walls to create in the world. This is only used
* for the extra credit portion of the assignment. If you aren't doing
* extra credit, then you should ignore this constant.
*/
public static final int WALL_SPACING = 8;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
문자를 입력하여 해당 문자에 해당하는 ASCII 코드를 출력합니다.제목 설명 BoBo는 KiKi 문자의 상수나 문자 변수로 표시된 문자를 메모리에 ASCII 코드로 저장합니다.BoBo에서 키키에게 문제가 생겼습니다. 문자를 입력하고 해당 문자의 ASCII 코드를 출력하십시오.설명 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.