유행 바이러스 전염 시뮬레이션 실험

유행 바이러스 전염 시뮬레이션 실험
모두 세 개의 자바 파일이 있으니 주석 알림에 따라 프로그램을 보충하고 모의 실험을 완성하십시오.
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: *
    *
  1. Move individuals around in the world. *
  2. Decrement infected individuals to represent the passage of time. *
  3. 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: *

    *
  1. The number of simulation steps executed so far. *
  2. The current count of uninfected individuals. *
  3. The current count of infected individuals. *
  4. 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; }

좋은 웹페이지 즐겨찾기