From 07067303b3c95a56f68b7bd14237e40669d932ca Mon Sep 17 00:00:00 2001 From: tjsus <tjsus@172.20.148.137> Date: Thu, 29 Aug 2024 11:10:05 -0700 Subject: [PATCH] Assignment 3 code added. --- .../ExampleSimulationProgramBattleShip.java | 241 ++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgramBattleShip.java diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgramBattleShip.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgramBattleShip.java new file mode 100644 index 0000000000..dd9344676f --- /dev/null +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgramBattleShip.java @@ -0,0 +1,241 @@ +package MV3500Cohort2024JulySeptember.homework3.Smith; + +import edu.nps.moves.dis7.pdus.*; +import edu.nps.moves.dis7.utilities.DisChannel; +import edu.nps.moves.dis7.utilities.PduFactory; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** The purpose of this inheritable class is to provide an easily modifiable + * example simulation program that includes DIS-capable entities performing + * tasks of interest, and then reporting activity via PDUs to the network. + * Default program initialization includes PDU recording turned on by default. + */ +public class ExampleSimulationProgramBattleShip { + + // Constants for the Battleship game + private static final int GRID_SIZE = 10; // 10x10 grid for Battleship + private static final int MAX_TURNS = 100; // Limit turns to avoid infinite games + + // Grids for each player + private char[][] player1Grid = new char[GRID_SIZE][GRID_SIZE]; + private char[][] player2Grid = new char[GRID_SIZE][GRID_SIZE]; + + // To track whose turn it is + private boolean isPlayer1Turn = true; + + // Ship positions (simple example positions for each player's ships) + private final int[][] player1Ships = {{0, 0}, {0, 1}, {0, 2}}; // Positions for player 1's ships + private final int[][] player2Ships = {{5, 5}, {5, 6}, {5, 7}}; // Positions for player 2's ships + + // DIS utilities + private String descriptor = this.getClass().getSimpleName(); + protected DisChannel disChannel; + protected PduFactory pduFactory; + protected FirePdu firePduPlayer1; + protected FirePdu firePduPlayer2; + protected MunitionDescriptor munitionDescriptor1 = new MunitionDescriptor(); + + // Simulation time settings + private double simulationTimeStepDuration = 1.0; // seconds + private double simulationTimeSeconds = 0.0; + + // Tracking indices for Player 1's systematic search + private int player1SearchRow = 0; + private int player1SearchCol = 0; + + /** + * Constructor to create an instance of this class. + * Design goal: additional built-in initialization conveniences can go here + * to keep your efforts focused on the runSimulation() method. + */ + public ExampleSimulationProgramBattleShip() { + initialize(); + } + + /** + * Initialize the simulation program, setting up the DIS channel, + * PDUs, and the Battleship game grids. + */ + private void initialize() { + initializeDisChannel(); + initializeSimulationEntities(); + setupGrids(); + disChannel.join(); + } + + /** + * Initialize the DIS channel for communication, setting verbose output + * for debugging and creating the PduFactory. + */ + private void initializeDisChannel() { + disChannel = new DisChannel(); + pduFactory = disChannel.getPduFactory(); + disChannel.setDescriptor(this.getClass().getSimpleName()); + disChannel.setUpNetworkInterface(); + disChannel.getDisNetworkInterface().setVerbose(true); // sending and receipt + disChannel.getPduRecorder().setVerbose(true); + } + + /** + * Initialize simulation entities by creating PDUs for firing events. + */ + private void initializeSimulationEntities() { + firePduPlayer1 = pduFactory.makeFirePdu(); + firePduPlayer2 = pduFactory.makeFirePdu(); + } + + /** + * Set up the game grids for each player, marking empty water and ship positions. + */ + private void setupGrids() { + // Initialize grids with empty water '~' + for (int i = 0; i < GRID_SIZE; i++) { + for (int j = 0; j < GRID_SIZE; j++) { + player1Grid[i][j] = '~'; + player2Grid[i][j] = '~'; + } + } + + // Place ships on the grids ('P' denotes a ship) + for (int[] ship : player1Ships) { + player1Grid[ship[0]][ship[1]] = 'P'; + } + for (int[] ship : player2Ships) { + player2Grid[ship[0]][ship[1]] = 'P'; + } + } + + /** + * This runSimulationLoops() method is for you, a customizable programmer-modifiable + * code block for defining and running a new simulation of interest. + */ + public void runSimulationLoops() { + int turnCount = 0; + while (turnCount < MAX_TURNS) { + if (isPlayer1Turn) { + // Player 1 systematically searches Player 2's grid + int[] target = selectNextTargetForPlayer1(); + handleFire(firePduPlayer1, player2Grid, target, "Player 1"); + } else { + // Player 2 fires at Player 1 randomly + int[] target = selectRandomTarget(); + handleFire(firePduPlayer2, player1Grid, target, "Player 2"); + } + + // Switch turns and increment turn counter + isPlayer1Turn = !isPlayer1Turn; + turnCount++; + + // Check for win conditions + if (checkWinCondition(player1Grid)) { + System.out.println("Player 2 wins!"); + break; + } else if (checkWinCondition(player2Grid)) { + System.out.println("Player 1 wins!"); + break; + } + + // Wait for the next simulation step + try { + Thread.sleep((long) (simulationTimeStepDuration * 1000)); // units of seconds * (1000 msec/sec) = milliseconds + } catch (InterruptedException iex) { + Logger.getLogger(ExampleSimulationProgram.class.getSimpleName()).log(Level.SEVERE, null, iex); + } + + // Increment simulation time + simulationTimeSeconds += simulationTimeStepDuration; + } + } + + /** + * Systematically select the next target for Player 1 in a row-by-row manner. + * @return the coordinates of the next target cell. + */ + private int[] selectNextTargetForPlayer1() { + // Systematically select the next target in a row-by-row manner + int[] target = {player1SearchRow, player1SearchCol}; + + // Move to the next column + player1SearchCol++; + // If end of row is reached, move to the next row and reset column + if (player1SearchCol >= GRID_SIZE) { + player1SearchCol = 0; + player1SearchRow++; + } + + // Ensure search stays within grid bounds + if (player1SearchRow >= GRID_SIZE) { + player1SearchRow = 0; // Reset search if bounds are exceeded + } + + return target; + } + + /** + * Randomly select a target on the grid for Player 2's turn. + * @return the coordinates of the randomly selected target cell. + */ + private int[] selectRandomTarget() { + int x = (int) (Math.random() * GRID_SIZE); + int y = (int) (Math.random() * GRID_SIZE); + return new int[]{x, y}; + } + + /** + * Handles the firing action, checking if the target is a hit or miss, + * updating the grid, and sending the appropriate PDU. + * @param firePdu the FirePdu object to use for the shot. + * @param grid the grid of the player being fired at. + * @param target the coordinates of the target cell. + * @param player the name of the player firing the shot. + */ + private void handleFire(FirePdu firePdu, char[][] grid, int[] target, String player) { + int x = target[0]; + int y = target[1]; + + // Fire at the target position + firePdu.setDescriptor(munitionDescriptor1).setRange(100.0f); // Example fire properties + + if (grid[x][y] == 'P') { + grid[x][y] = 'H'; // Hit + System.out.println(player + " hits a ship at (" + x + ", " + y + ")!"); + } else if (grid[x][y] == '~') { + grid[x][y] = 'M'; // Miss + System.out.println(player + " misses at (" + x + ", " + y + ")."); + } else { + System.out.println(player + " fires at (" + x + ", " + y + ") but it's already hit/missed."); + } + + // Send the fire PDU to reflect the shot + disChannel.sendSinglePdu(simulationTimeSeconds, firePdu); + } + + /** + * Checks the win condition by verifying if all ships on the grid have been hit. + * @param grid the grid to check. + * @return true if all ships are hit; false otherwise. + */ + private boolean checkWinCondition(char[][] grid) { + // Check if all ships have been hit + for (int i = 0; i < GRID_SIZE; i++) { + for (int j = 0; j < GRID_SIZE; j++) { + if (grid[i][j] == 'P') { + return false; // There are still ships left + } + } + } + return true; // All ships have been hit + } + + /** + * Main method is first executed when a program instance is loaded. + * @param args command-line parameters: network address and port. + * Command-line arguments are an array of optional String parameters that are passed from execution environment during invocation + */ + public static void main(String[] args) { + ExampleSimulationProgramBattleShip game = new ExampleSimulationProgramBattleShip(); + game.runSimulationLoops(); + System.out.println("Game Over"); + } +} -- GitLab