umutcaner's picture
Upload 29 files
f11ab78 verified
import java.awt.*;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class MazeManager extends JPanel {
//Agens and queue
private Queue<Agent> agentQueue;
private Agent agent1;
private Agent agent2;
//variables
private final int cols, rows;
private final int cellSize = 20;
private final MazeTile[][] tiles;
private final boolean[][][] walls;
private final Random random = new Random();
private final int trapChance;
private final int powerUpChance;
//Game Mechanic
private boolean gameOver = false;
private int currRount = 0;
private Timer timer;
public MazeManager(int cols, int rows, int trapChance, int powerUpChance) {
//Create ways in maze
this.cols = cols;
this.rows = rows;
this.trapChance = trapChance;
this.powerUpChance = powerUpChance;
this.tiles = new MazeTile[cols][rows];
this.walls = new boolean[cols][rows][4];
for (int x = 0; x < cols; x++) {
for (int y = 0; y < rows; y++) {
tiles[x][y] = new MazeTile();
for (int d = 0; d < 4; d++) walls[x][y][d] = true;
}
}
boolean[][] visited = new boolean[cols][rows];
generateMaze(0, 0, visited);
placeEntities();
setPreferredSize(new Dimension(cols * cellSize, rows * cellSize));
agentQueue = new Queue(10);
agent1 = new Agent(0, 0, this, Color.BLUE, "Blue Agent",1);
agent2 = new Agent(cols - 1, rows - 1, this, Color.ORANGE, "Orange Agent",2);
agentQueue.enqueue(agent1);
agentQueue.enqueue(agent2);
timer = new Timer(300, e -> {
if (gameOver || agentQueue.isEmpty()) return;
if (currRount > 0 && currRount % 5 == 0) rotateCorridor();
repaint();
Agent currentAgent = agentQueue.dequeue();
currentAgent.moveTowardsGoal();
if (tiles[currentAgent.getX()][currentAgent.getY()].getEntity() == MazeTile.EntityType.GOAL) {
gameOver = true;
timer.stop();
Agent loser = currentAgent == agent1 ? agent2 : agent1;
GameLog(currentAgent, loser);
JOptionPane.showMessageDialog(this,
finalReport(agent1, agent2, currentAgent),
"Game over!",
JOptionPane.INFORMATION_MESSAGE);
return;
}
agentQueue.enqueue(currentAgent);
currRount++;
});
timer.start();
}
private void generateMaze(int x, int y, boolean[][] visited) {
visited[x][y] = true;
Integer[] dirs = {0, 1, 2, 3};
Collections.shuffle(Arrays.asList(dirs));
for (int dir : dirs) {
int nx = x, ny = y;
switch (dir) {
case 0:
ny--;
break;
case 1:
nx++;
break;
case 2:
ny++;
break;
case 3:
nx--;
break;
}
if (isInMaze(nx, ny) && !visited[nx][ny]) {
removeWall(x, y, dir);
generateMaze(nx, ny, visited);
}
}
}
public boolean hasWall(int x, int y, int dir) {
return walls[x][y][dir];
}
public void removeWall(int x, int y, int dir) {
walls[x][y][dir] = false;
int nx = x, ny = y;
int opp = (dir + 2) % 4;
switch (dir) {
case 0:
ny--;
break;
case 1:
nx++;
break;
case 2:
ny++;
break;
case 3:
nx--;
break;
}
if (isInMaze(nx, ny)) walls[nx][ny][opp] = false;
}
//-WİP-
private void placeEntities() {
int goalX = cols / 2;
int goalY = rows / 2;
tiles[goalX][goalY].setEntity(MazeTile.EntityType.GOAL);
int total = cols * rows;
int trapCount = total * trapChance / 100;
int powerCount = total * powerUpChance / 100;
for (int i = 0; i < trapCount; i++) {
int x, y;
do {
x = random.nextInt(cols);
y = random.nextInt(rows);
} while (tiles[x][y].getEntity() != MazeTile.EntityType.EMPTY || (x == goalX && y == goalY));
tiles[x][y].setEntity(MazeTile.EntityType.TRAP);
}
for (int i = 0; i < powerCount; i++) {
int x, y;
do {
x = random.nextInt(cols);
y = random.nextInt(rows);
} while (tiles[x][y].getEntity() != MazeTile.EntityType.EMPTY || (x == goalX && y == goalY));
tiles[x][y].setEntity(MazeTile.EntityType.POWER_UP);
}
}
private void rotateCorridor() {
boolean rotateRow = random.nextBoolean();
int index = rotateRow ? random.nextInt(rows) : random.nextInt(cols); //1=row, 2=col
int goalX = cols / 2, goalY = rows / 2; //coordinats of goal
/////////////////////////////////////////////
if (rotateRow && index == goalY)
{
return;
}
if (!rotateRow && index == goalX) {
return;
}
if (rotateRow && index == agent1.getY())
{
return;
}
//for not touching goal,agent1, agent2
if (!rotateRow && index == agent1.getX()) {
return;
}
if (!rotateRow && index == agent2.getX()) {
return;
}
if (rotateRow && index == agent2.getY()) {
return;
}
/////////////////////////////////////////////
if (rotateRow) {
CircularLinkedList<MazeTile.EntityType> entityList = new CircularLinkedList<>();
CircularLinkedList<Boolean> activePowerUp = new CircularLinkedList<>();
// taking data of every tile( entity type, is trap active, is powerup active)
//taking them to same circular linked list
CircularLinkedList<Boolean> activeTrap = new CircularLinkedList<>();
//rewrite every tiles
for (int x = 0; x < cols; x++) {
MazeTile tile = tiles[x][index];
entityList.add(tile.getEntity());
activeTrap.add( tile.isTrapActive());
activePowerUp.add(tile.isPowerUpActive());
}
entityList.rotateOneStep(1);
activeTrap.rotateOneStep(1);
activePowerUp.rotateOneStep(1);
for (int x = 0; x < cols; x++) {
tiles[x][index].setPowerUpActive(activePowerUp.get(x));
tiles[x][index].setEntity(entityList.get(x));
tiles[x][index].setTrapActive(activeTrap.get(x));
}
} else {
CircularLinkedList<Boolean> trapActiveList = new CircularLinkedList<>();
CircularLinkedList<Boolean> powerUpActiveList = new CircularLinkedList<>();
CircularLinkedList<MazeTile.EntityType> entityList = new CircularLinkedList<>();
for (int y = 0; y < rows; y++) {
MazeTile tile = tiles[index][y];
entityList.add(tile.getEntity());
trapActiveList.add(tile.isTrapActive());
powerUpActiveList.add(tile.isPowerUpActive());
}
entityList.rotateOneStep(1);
trapActiveList.rotateOneStep(1);
powerUpActiveList.rotateOneStep(1);
for (int y = 0; y < rows; y++) {
tiles[index][y].setEntity(entityList.get(y));
tiles[index][y].setTrapActive(trapActiveList.get(y));
tiles[index][y].setPowerUpActive(powerUpActiveList.get(y));
}
}
}
public boolean isInMaze(int x, int y) {
return x >= 0 && y >= 0 && x < cols && y < rows;
}
public MazeTile getTile(int x, int y) {
return tiles[x][y];
}
public int getCols() {
return cols;
}
public int getRows() {
return rows;
}
private String finalReport(Agent a1, Agent a2, Agent winner) {
StringBuilder sb = new StringBuilder();
sb.append(winner.getName()).append(" reached the target!\nnumber of rount played: ").append(currRount).append("\n\n");
for (Agent agent : new Agent[]{a1, a2}) {
sb.append(agent.getName()).append(":\n");
Stack<String> stack = agent.getMoveHistory();
for (int i = 0; i < stack.getSize(); i++) {
sb.append(stack.getElements()[i]).append("");
}
sb.append("\n");
}
return sb.toString();
}
private void GameLog(Agent winner, Agent loser) {
// preparing console screen before printing results
System.out.print("\033[H\033[2J");
System.out.flush();
//-----------
System.out.println("\n=== Game Over ===");
System.out.println("Winner Agent: " + winner.getName());
System.out.println("Number of rount played: " + currRount);
System.out.println("----------------------");
System.out.println(winner.getName() + " Statistics:");
System.out.println("- Step number: " + winner.getStepCount());
System.out.println("- Trap number: " + winner.getTrapHits());
System.out.println("- Power-Up usage: " + winner.getPowerUpUses());
System.out.println();
System.out.println(loser.getName() + " Statistics:");
System.out.println("- Step number: " + loser.getStepCount());
System.out.println("- Trap number: " + loser.getTrapHits());
System.out.println("- Power-Up usage: " + loser.getPowerUpUses());
try (FileWriter writer = new FileWriter("game_log.txt", true)) {
writer.write("=== Game Over ===\n");
writer.write("Winner Agent: " + winner.getName() + " (ID: " + winner.getId() + ")\n");
writer.write("Number of rount played: " + currRount + "\n\n");
for (Agent agent : new Agent[]{winner, loser}) {
writer.write(agent.getName() + " (ID: " + agent.getId() + ")\n");
writer.write("- Step number: " + agent.getStepCount() + "\n");
writer.write("- Trap number: " + agent.getTrapHits() + "\n");
writer.write("- Power-Up usage: " + agent.getPowerUpUses() + "\n");
writer.write("- Moves: ");
Stack<String> stack = agent.getMoveHistory();
for (int i = 0; i < stack.getSize(); i++) {
Object move = stack.getElements()[i];
writer.write(String.valueOf(move));
}
writer.write("\n--------------------------\n");
}
} catch (IOException e) {
System.out.println("Log file error: ");
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
for (int x = 0; x < cols; x++) {
for (int y = 0; y < rows; y++) {
int px = x * cellSize;
int py = y * cellSize;
if (walls[x][y][3]) g.drawLine(px, py, px, py + cellSize);
if (walls[x][y][1]) g.drawLine(px + cellSize, py, px + cellSize, py + cellSize);
if (walls[x][y][0]) g.drawLine(px, py, px + cellSize, py);
if (walls[x][y][2]) g.drawLine(px, py + cellSize, px + cellSize, py + cellSize);
switch (tiles[x][y].getEntity()) {
case GOAL -> {
g.setColor(Color.GREEN);
g.fillRect(px + 4, py + 4, cellSize - 8, cellSize - 8);
g.setColor(Color.BLACK);
}
case POWER_UP -> {
g.setColor(tiles[x][y].isPowerUpActive() ? Color.YELLOW : Color.GRAY);
g.fillRect(px + 4, py + 4, cellSize - 8, cellSize - 8);
g.setColor(Color.BLACK);
}
case TRAP -> {
g.setColor(tiles[x][y].isTrapActive() ? Color.RED : Color.GRAY);
g.fillRect(px + 4, py + 4, cellSize - 8, cellSize - 8);
g.setColor(Color.BLACK);
}
}
}
}
for (Agent agent : new Agent[]{agent1, agent2}) {
g.setColor(agent.passedWallThisTurn() ? Color.MAGENTA : agent.getColor());
g.fillOval(agent.getX() * cellSize + 5, agent.getY() * cellSize + 5, cellSize - 10, cellSize - 10);
}
g.setColor(Color.BLACK);
g.drawString("Curr Round: " + currRount, 10, 15);
}
}