Files
yena_/task1/COMP2045-2324PA1/demo_source.java
louiscklaw 5fe1d532f2 update,
2025-02-01 02:11:33 +08:00

455 lines
16 KiB
Java

import java.io.File;
import java.util.Scanner;
/**
* @author: ______your name here (SID)_________
*
* For the instruction of the assignment please refer to the assignment
* GitHub.
*
* Plagiarism is a serious offense and can be easily detected. Please
* don't share your code to your classmate even if they are threatening
* you with your friendship. If they don't have the ability to work on
* something that can compile, they would not be able to change your
* code to a state that we can't detect the act of plagiarism. For the
* first commit of plagiarism, regardless you shared your code or
* copied code from others, you will receive 0 with an addition of 5
* mark penalty. If you commit plagiarism twice, your case will be
* presented in the exam board and you will receive a F directly.
*
* Terms about generative AI:
* You are not allowed to use any generative AI in this assignment.
* The reason is straight forward. If you use generative AI, you are
* unable to practice your coding skills. We would like you to get
* familiar with the syntax and the logic of the Java programming.
* We will examine your code using detection software as well as
* inspecting your code with our eyes. Using generative AI tool
* may fail your assignment.
*
* If you cannot work out the logic of the assignment, simply contact
* us on Discord. The teaching team is more the eager to provide
* you help. We can extend your submission due if it is really
* necessary. Just please, don't give up.
*/
public class l {
/**
* The following constants are variables that you can use in your code.
* Use them whenever possible. Try to avoid writing something like:
* if (input == 'W') ...
* instead
* if (input == UP) ...
*/
public static final char a = 'W';
public static final char b = 'S';
public static final char c = 'A';
public static final char d = 'D';
public static final char e = 'o';
public static final char f = '@';
public static final char g = '#';
public static final char h = '.';
public static final char i = '%';
/**
* Finished. You are not allowed to touch this method.
* The main method.
*/
public static void main(String[] arrstring) {
new l().a();
}
/**
* All coding of this method has been finished.
* You are not supposed to add or change any code in this method.
* However, you are required to add comments after every // to explain the code below.
*/
public void a() {
String string = "map1.txt";
char[][] arrc = this.b(string);
char[][] arrc2 = this.b(string);
if (arrc == null) {
System.out.println("Map file not found");
return;
}
int[] arrn = this.b(arrc);
if (arrn.length == 0) {
System.out.println("Player not found");
return;
}
int n2 = arrn[0];
int n3 = arrn[1];
while (!this.a(arrc)) {
this.c(arrc);
System.out.println("\nPlease enter a move (WASD): ");
char c2 = this.c();
if (c2 == 'q') break;
if (c2 == 'r') {
arrc = this.b(string);
n2 = arrn[0];
n3 = arrn[1];
continue;
}
if (c2 == 'h') {
this.b();
}
if (!this.c(arrc, n2, n3, c2)) continue;
this.b(arrc, n2, n3, c2);
this.a(arrc, arrc2);
int[] arrn2 = this.b(arrc);
n2 = arrn2[0];
n3 = arrn2[1];
}
System.out.println("Bye!");
}
/**
* Print the Help menu.
* TODO:
*
* Inspect the code in runApp() and find out the function of each characters.
* The first one has been done for you.
*/
public void b() {
System.out.println("Sokoban Help:");
System.out.println("Move up: W");
System.out.println("Move down: S");
System.out.println("Move left: A");
System.out.println("Move right: D");
System.out.println("Restart level: r");
System.out.println("Quit game: q");
System.out.println("Help: h");
}
/**
* Reading a valid input from the user.
*
* TODO
*
* This method will return a character that the user has entered. However, if a user enter an invalid character (e.g. 'x'),
* the method should keep prompting the user until a valid character is entered. Noted, there are all together 7 valid characters
* which you need to figure out yourself.
*/
public char c() {
char c2;
Scanner scanner = new Scanner(System.in);
while (true) {
String string;
if ((string = scanner.nextLine()).length() == 0) {
continue;
}
c2 = string.charAt(0);
if (c2 == 'W' || c2 == 'S' || c2 == 'A' || c2 == 'D' || c2 == 'q' || c2 == 'r' || c2 == 'h') break;
System.out.println("Invalid input, please enter again: ");
}
return c2;
}
/**
* Mysterious method.
*
* TODO
*
* We know this method is to "fix" the map. But we don't know how it does and why it is needed.
* You need to figure out the function of this method and implement it accordingly.
*
* You are given an additional demo program that does not implement this method.
* You can run them to see the difference between the two demo programs.
*/
// public void fixMap(_________________________) {
// }
public void a(char[][] arrc, char[][] arrc2) {
for (int i2 = 0; i2 < arrc.length; ++i2) {
for (int i3 = 0; i3 < arrc[i2].length; ++i3) {
if (arrc2[i2][i3] != '.' && arrc2[i2][i3] != '%' || arrc[i2][i3] != ' ') continue;
arrc[i2][i3] = 46;
}
}
}
/**
* To move a box in a map.
*
* TODO
*
* This method will move a box in the map. The box will be moved to the direction specified by the parameter "direction".
* You must call this method somewhere in movePlayer() method.
*
* After this method, a box should be moved to the new position from the coordinate [row, col] according to the direction.
* For example, if [row, col] is [2, 5] and the direction is 'S', the box should be moved to [3, 5].
*
* If a box is moved to a goal, the box should be marked as BOXONGOAL.
* If a box is moved to a non-goal, the box should be marked as BOX.
* You should set the original position of the box to ' ' in this method.
*
* Note, you may always assume that this method is called when the box can be moved to the direction.
* During grading, we will never call this method when the box cannot be moved to the direction.
*/
public void a(char[][] arrc, int n2, int n3, char c2) {
int n4;
int[] arrn = this.a(n2, n3, c2);
int n5 = arrn[0];
arrc[n5][n4] = arrc[n5][n4 = arrn[1]] == '.' ? 37 : 64;
arrc[n2][n3] = arrc[n2][n3] == '%' ? 46 : 32;
}
/**
* To move the player in the map.
*
* TODO
*
* This method will move the player in the map. The player will be moved to the direction specified by the parameter "direction".
*
* After this method, the player should be moved to the new position from the coordinate [row, col] according to the direction.
* At the same time, the original position of the player should be set to ' '.
*
* During the move of the player, it is also possible that a box is also moved.
*
* Note, you may always assume that this method is called when the player can be moved to the direction.
* During grading, we will never call this method when the player cannot be moved to the direction.
*/
public void b(char[][] arrc, int n2, int n3, char c2) {
int n4;
int[] arrn = this.a(n2, n3, c2);
int n5 = arrn[0];
if (arrc[n5][n4 = arrn[1]] == '@' || arrc[n5][n4] == '%') {
this.a(arrc, n5, n4, c2);
}
arrc[n5][n4] = 111;
arrc[n2][n3] = 32;
}
/**
* To check if the game is over.
*
* TODO
*
* This method should return true if the game is over, false otherwise.
* The condition for game over is that there is no goal left in the map that is not covered by a box.
*
* According to this definition, if the number of goal is actually more than the number of boxes,
* the game will never end even through all boxes are placed on the goals.
*/
public boolean a(char[][] arrc) {
for (int i2 = 0; i2 < arrc.length; ++i2) {
for (int i3 = 0; i3 < arrc[i2].length; ++i3) {
if (arrc[i2][i3] != '.') continue;
return false;
}
}
return true;
}
/**
* To count the number of rows in a file.
*
* TODO
*
* This method should return the number of rows in the file which filename is stated in the argument.
* If the file is not found, it should return -1.
*/
public int a(String string) {
try {
Scanner scanner = new Scanner(new File(string));
int n2 = 0;
while (scanner.hasNextLine()) {
++n2;
scanner.nextLine();
}
return n2;
}
catch (Exception exception) {
return -1;
}
}
/**
* To read a map from a file.
*
* TODO
*
* This method should return a 2D array of characters which represents the map.
* This 2D array should be read from the file which filename is stated in the argument.
* If the file is not found, it should return null.
*
* The number of columns in each row may be different. However, there is no restriction on
* the number of columns that is declared in the array. You can declare the number of columns
* in your array as you wish, as long as it is enough to store the map.
*
* That is, if the map is as follow,
* ####
* #.@o#
* # #
* ###
* your array may be declared as
* char[][] map = {{'#', '#', '#', '#'},
* {'#', '.', '@', 'o', '#'},
* {'#', ' ', ' ', '#'},
* {'#', '#', '#'} };
* or something like
* char[][] map = {{'#', '#', '#', '#', ' ', ' ', ' '},
* {'#', '.', '@', 'o', '#', ' ', ' '},
* {'#', ' ', ' ', '#', ' ', ' ', ' '},
* {'#', '#', '#', ' ', ' ', ' ', ' '} };
*/
public char[][] b(String string) {
int n2 = this.a(string);
if (n2 == -1) {
return null;
}
char[][] arrarrc = new char[n2][];
try (Scanner scanner = new Scanner(new File(string));){
int n3 = 0;
while (true) {
int n4;
String string2;
Object object;
if (scanner.hasNextLine()) {
object = scanner.nextLine();
string2 = "";
} else {
object = arrarrc;
return object;
}
for (n4 = ((String)object).length() - 1; n4 >= 0 && ((String)object).charAt(n4) == ' '; --n4) {
}
for (int i2 = 0; i2 <= n4; ++i2) {
string2 = string2 + ((String)object).charAt(i2);
}
arrarrc[n3] = string2.toCharArray();
++n3;
}
}
catch (Exception exception) {
return null;
}
}
/**
* To find the coordinate of player in the map.
*
* TODO
*
* This method should return a 2D array that stores the [row, col] of the player in the map.
* For example, if the map is as follow,
* ####
* #.@o#
* # #
* ###
* this method should return {1, 3}.
*
* In case there is no player in the map, this method should return null.
*/
public int[] b(char[][] arrc) {
for (int i2 = 0; i2 < arrc.length; ++i2) {
for (int i3 = 0; i3 < arrc[i2].length; ++i3) {
if (arrc[i2][i3] != 'o') continue;
int[] arrn = new int[]{i2, i3};
return arrn;
}
}
int[] arrn = new int[]{-1, -1};
return arrn;
}
/**
* To check if a move is valid.
*
* TODO
*
* This method should return true if the move is valid, false otherwise.
* The parameter "map" represents the map.
* The parameter "row" and "col" indicates where the player is.
* The parameter "direction" indicates the direction of the move.
* At the end of the method, this method should not change any content of the map.
*
* The physics of the game is as follow:
* 1. The player can only move to a position that is not occupied by a wall or a box.
* 2. If the player is moving to a position that is occupied by a box, the box can only be moved to a position that is not occupied by a wall or a box.
*
* Thus, in the following condition, the player can move to the right
* o # <-- there is a space
* o@ # <-- there is a space right to the box.
* In the following condition, the player cannot move to the right
* o# <-- there is a wall
* o@# <-- there is a wall right to the box.
* o@@ # <-- there is a box right to the box.
*/
public boolean c(char[][] arrc, int n2, int n3, char c2) {
return this.a(arrc, n2, n3, c2, true);
}
/**
* To print the map.
*
* TODO
*
* This method should print the map in the console.
* At the top row, it should print a space followed by the last digit of the column indexes.
* At the leftmost column, it should print the last two digits of row indexes, aligning to the left.
*/
public void c(char[][] arrc) {
int n2;
if (arrc == null) {
return;
}
int n3 = arrc[0].length;
for (n2 = 1; n2 < arrc.length; ++n2) {
if (n3 >= arrc[n2].length) continue;
n3 = arrc[n2].length;
}
System.out.print(" ");
for (n2 = 0; n2 < n3; ++n2) {
System.out.print(n2 % 10);
}
System.out.println();
for (n2 = 0; n2 < arrc.length; ++n2) {
System.out.printf("%-2d", n2 % 100);
for (int i2 = 0; i2 < arrc[n2].length; ++i2) {
System.out.print(arrc[n2][i2]);
}
System.out.println();
}
}
private int[] a(int n2, int n3, int n4) {
int[] arrn = new int[]{n2, n3};
switch (n4) {
case 87: {
arrn[0] = arrn[0] - 1;
break;
}
case 83: {
arrn[0] = arrn[0] + 1;
break;
}
case 65: {
arrn[1] = arrn[1] - 1;
break;
}
case 68: {
arrn[1] = arrn[1] + 1;
}
}
return arrn;
}
private boolean a(char[][] arrc, int n2, int n3, char c2, boolean bl) {
int[] arrn = this.a(n2, n3, c2);
int n4 = arrn[0];
int n5 = arrn[1];
if (n4 < 0 || n4 >= arrc.length || n5 < 0 || n5 >= arrc[n4].length) {
return false;
}
if (arrc[n4][n5] == '#') {
return false;
}
if (arrc[n4][n5] == '@' || arrc[n4][n5] == '%') {
if (bl) {
return this.a(arrc, n4, n5, c2, false);
}
return false;
}
return true;
}
}