Space Invaders

The classic game Space Invaders, without GUI.
This commit is contained in:
Fernando Méndez 2020-09-17 20:06:49 +02:00 committed by GitHub
parent 08097b1ba0
commit 1d271afe24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 3086 additions and 0 deletions

View File

@ -0,0 +1,79 @@
package tp.p2;
/**
* @author Fernando Méndez Torrubiano; DNI: 02723009Q
* @clase TP1, GRUPO D.
*
*/
public enum Level {
EASY(4, 2, 0.2, 3, 0.5, 1),
HARD(8, 4, 0.3, 2, 0.2, 2),
INSANE(12, 4, 0.5, 1, 0.1, 3);
private int numRegularAliens;
private int numDestroyerAliens;
private int numCyclesToMoveOneCell;
private double ovniFrequency;
private double shootFrequency;
private int numRowsOfRegularAliens;
private double turnExplodeFrequency = 0.05; // actualmente no depende del nivel
private Level(
int numRegularAliens,
int numDestroyerAliens,
double shootFrequency,
int numCyclesToMoveOneCell,
double ovniFrequency,
int numRowsOfRegularAliens)
{
this.numRegularAliens = numRegularAliens;
this.numDestroyerAliens = numDestroyerAliens;
this.shootFrequency = shootFrequency;
this.numCyclesToMoveOneCell = numCyclesToMoveOneCell;
this.ovniFrequency = ovniFrequency;
this.numRowsOfRegularAliens = numRowsOfRegularAliens;
}
public int getNumRegularAliens() {
return numRegularAliens;
}
public int getNumDestroyerAliens() {
return numDestroyerAliens;
}
public double getShootFrequency() {
return shootFrequency;
}
public int getNumCyclesToMoveOneCell() {
return numCyclesToMoveOneCell;
}
public double getOvniFrequency() {
return ovniFrequency;
}
public int getNumRowsOfRegularAliens() {
return numRowsOfRegularAliens;
}
public int getNumRegularAliensPerRow() {
return numRegularAliens / numRowsOfRegularAliens;
}
public int getNumDestroyerAliensPerRow() {
return getNumDestroyerAliens();
}
public static Level parse(String cadenaEntrada) {
for (Level level : Level.values())
if (level.name().equalsIgnoreCase(cadenaEntrada))
return level;
return EASY;
}
public double getTurnExplodeFrequency(){
return turnExplodeFrequency;
}
}

View File

@ -0,0 +1,71 @@
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
package tp.p2;
import java.util.Random;
import java.util.Scanner;
import java.lang.NumberFormatException;
import tp.p2.Level;
import tp.p2.controller.Controller;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano; DNI: 02723009Q
* @clase TP1, GRUPO D.
*
*/
public class Main {
public static void main(String[] args) {
Game game;
Level level = null;
Scanner in = null;
int seed = 0;
Random rnd = null;
//Selecci<EFBFBD>n de nivel:
if(args.length >= 1) {
level = Level.parse(args[0]);
}
else {
level = Level.EASY;
}
//Selecci<EFBFBD>n de semilla:
if(args.length == 2) {
try {
seed = Integer.parseInt(args[1]);
}
catch (NumberFormatException ex){
System.err.format(ex.getMessage() + " %n %n");
}
finally {
rnd = new Random(seed);
}
}
else {
rnd = new Random(System.currentTimeMillis());
}
game = new Game(level, rnd);
Controller controlador = new Controller(game, in);
controlador.run(game);
}
}
/*
//Selecci<EFBFBD>n de nivel:
if(args[0].contentEquals("EASY")) {
nivel = Level.EASY;
} else if(args[0].contentEquals("HARD")){
nivel = Level.HARD;
} else if(args[0].contentEquals("INSANE")) {
nivel = Level.INSANE;
}else {
nivel = Level.EASY;
}
*/

View File

@ -0,0 +1,40 @@
package tp.p2.controller.Commands;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class BuySuperMissileCommand extends Command {
public BuySuperMissileCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
}
@Override
public boolean execute(Game game) throws CommandExecuteException {
boolean exe = true;
if(!game.buySuperMissile()) {
System.err.println("Error, you can't buy a Super Missile right now.");
exe = false;
}
return exe;
}
@Override
public Command parse(String[] commandWords) {
Command cmd = null;
if(commandWords[0].equals("buy") || commandWords[0].equals("b")) {
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,40 @@
package tp.p2.controller.Commands;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.controller.Exceptions.CommandParseException;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public abstract class Command {
//Atributos:
protected final String name;
protected final String shortcut;
private final String details;
private final String help;
protected static final String incorrectNumArgsMsg = "Incorrect number of arguments";
protected static final String incorrectArgsMSg = "Incorrect argument format";
//Constructor:
public Command(String name, String shortcut, String details, String help) {
this.name = name;
this.shortcut = shortcut;
this.details = details;
this.help = help;
}
//M<EFBFBD>todos:
public abstract boolean execute(Game game) throws CommandExecuteException;
public abstract Command parse(String[] commandWords) throws CommandParseException;
protected boolean matchCommandName(String name) {
return this.shortcut.equalsIgnoreCase(name) || this.name.equalsIgnoreCase(name);
}
public String helpText() {
return this.details + ": " + this.help + "\n";
}
}

View File

@ -0,0 +1,63 @@
package tp.p2.controller.Commands;
import tp.p2.controller.Exceptions.CommandParseException;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class CommandGenerator {
//Atributos:
private static final int MAXCOMMANDS = 14;
private static Command[] avaliableCommands = {
new MoveCommand("move", "m", "Move <left|right><1|2>", "Moves UCM-Ship to the indicated direction."),
new ShotCommand("shoot", "s", "Shoot", "UCM-Ship launches a missile."),
new ShockwaveCommand("shockwave", "w", "ShockWave", "UCM-Ship releases a shock wave."),
new ListCommand("list", "l", "List", "Prints the list of available ships."),
new ResetCommand("reset", "r", "Reset", "Starts a new game."),
new HelpCommand("help", "h", "Help", "Prints this help message."),
new ExitCommand("exit", "e", "Exit", "Terminates the program."),
new UpdateCommand("none", "", "[none]", "Skips one cycle."),
new BuySuperMissileCommand("buy", "b", "Buy", "Buy a Super Missile."),
new StringifyCommand("stringify", "sf", "Stringify", "Serialize the board."),
new ListPrintersCommand("listPrinters", "lp", "ListPrinters", "Prints the list of available printers."),
new SuperShootCommand("supermissile", "sm", "SuperMissile", "UCM-Ship launches a super-missile."),
new SaveCommand("save", "g", "Save", "Save the game on a file."),
new LoadCommand("load", "c", "Load", "Load the game of a file.")
};
//M<EFBFBD>todos:
//Invoca al m<EFBFBD>todo "parse" de cada subclase de Command.
public static Command parseCommand(String[] commandWords) throws CommandParseException {
boolean encontrado = false;
int i = 0;
Command cmd = null;
while(!encontrado && i < MAXCOMMANDS) {
if(avaliableCommands[i].parse(commandWords) != null) {
cmd = avaliableCommands[i];
encontrado = true;
}
else {
i++;
}
}
if(cmd == null) { throw new CommandParseException(Command.incorrectArgsMSg); }
return cmd;
}
//Invoca al m<EFBFBD>todo helpText() de cada subclase de Command.
//Este m<EFBFBD>todo es invocado por el m<EFBFBD>todo "execute" de la clase HelpCommand.
public static String commandHelp(){
String help = "";
for (int i = 0; i < avaliableCommands.length; i++) {
help += avaliableCommands[i].helpText();
}
return help;
}
}

View File

@ -0,0 +1,33 @@
package tp.p2.controller.Commands;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class ExitCommand extends Command {
public ExitCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
// TODO Auto-generated constructor stub
}
@Override
public boolean execute(Game game) {
game.exit();
return true;
}
@Override
public Command parse(String[] commandWords) {
Command cmd = null;
if(commandWords[0].equals("exit") || commandWords[0].equals("e")) {
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,43 @@
package tp.p2.controller.Commands;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class HelpCommand extends Command {
public HelpCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
// TODO Auto-generated constructor stub
}
@Override
public boolean execute(Game game) throws CommandExecuteException {
String help = CommandGenerator.commandHelp();
if(help != "") {
System.out.println(help);
}
else {
throw new CommandExecuteException("No description available.");
}
return false;
}
@Override
public Command parse(String[] commandWords) {
Command cmd = null;
if(commandWords[0].equals("help") || commandWords[0].equals("h")) {
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,39 @@
package tp.p2.controller.Commands;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class ListCommand extends Command {
public ListCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
// TODO Auto-generated constructor stub
}
@Override
public boolean execute(Game game) {
System.out.println(
"[R]egular ship: Points: 5 - Harm: 0 - Shield: 2 \n" +
"[D]estroyer ship: Points: 10 - Harm: 1 - Shield: 1 \n" +
"[E]xplosive destroyer ship: Points: 10 - Harm: 1 - Shield: 1 \n" +
"[O]vni: Points: 25 - Harm: 0 - Shield: 1 \n" +
"^__^: Harm: 1 - Shield: 3\n");
return false;
}
@Override
public Command parse(String[] commandWords) {
Command cmd = null;
if(commandWords[0].equals("list") || commandWords[0].equals("l")) {
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,39 @@
package tp.p2.controller.Commands;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.game.Game;
import tp.p2.game.PrinterTypes;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class ListPrintersCommand extends Command {
public ListPrintersCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
// TODO Auto-generated constructor stub
}
@Override
public boolean execute(Game game) throws CommandExecuteException {
System.out.println(PrinterTypes.printerHelp(game));
if(PrinterTypes.printerHelp(game) == "") {
throw new CommandExecuteException("No printers avaliable.");
}
return false;
}
@Override
public Command parse(String[] commandWords) {
Command cmd = null;
if(commandWords[0].equals("listPrinters") || commandWords[0].equals("lp")) {
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,99 @@
package tp.p2.controller.Commands;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Scanner;
import tp.p2.Level;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.controller.Exceptions.CommandParseException;
import tp.p2.controller.Exceptions.FileContentsException;
import tp.p2.game.FileContentsVerifier;
import tp.p2.game.Game;
import tp.p2.game.GameObjects.AlienShip;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class LoadCommand extends Command {
private Scanner in;
public LoadCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
this.in = new Scanner(System.in);
}
@Override
public boolean execute(Game game) throws CommandExecuteException {
BufferedReader inStream = null;
FileContentsVerifier verifier = new FileContentsVerifier();
String gameString = "";
int restCycles = 0;
System.out.println("File name > ");
String fileName = in.nextLine() + ".dat";
try {
inStream = new BufferedReader(
new InputStreamReader(
new FileInputStream(fileName), "UTF-8"));
try {
//Read from the archive until we find the game line:
do {
gameString = inStream.readLine().trim();
} while(!verifier.verifyGameString(gameString));
String[] words = gameString.split(FileContentsVerifier.separator1);
restCycles = Integer.parseInt(words[1]);
//Read the level:
String levelString = inStream.readLine().trim();
verifier.verifyLevelString(levelString);
Level level = Level.parse(levelString);
//Load the game information:
game.load(inStream);
AlienShip.setNumAliens(level.getNumRegularAliens()+level.getNumDestroyerAliens());
game = new Game(level, restCycles);
System.out.println("Game successfully loaded from file " + fileName + "\n");
}
catch (FileContentsException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
inStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return true;
}
@Override
public Command parse(String[] commandWords) throws CommandParseException {
Command cmd = null;
if(commandWords[0].equals("load") || commandWords[0].equals("c")) {
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,59 @@
package tp.p2.controller.Commands;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.controller.Exceptions.CommandParseException;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class MoveCommand extends Command{
//Atributos:
private String moveDir;
private int nCasillas;
//Constructor:
public MoveCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
}
//M<EFBFBD>todos:
public boolean execute(Game game) throws CommandExecuteException{
boolean exe = false;
if(game.move(this.moveDir, this.nCasillas)) {
exe = true;
}
return exe;
}
public Command parse(String[] commandWords) throws CommandParseException {
Command cmd = null;
if(commandWords.length > 3) {
throw new CommandParseException(Command.incorrectNumArgsMsg);
}
if(commandWords[0].equals("move") || commandWords[0].equals("m")) {
cmd = this;
if(commandWords[1].equals("left") || commandWords[1].equals("right")) {
this.moveDir = commandWords[1];
if(Integer.parseInt(commandWords[2]) > 0 && Integer.parseInt(commandWords[2]) <= 2) {
this.nCasillas = Integer.parseInt(commandWords[2]);
}
else {
throw new CommandParseException("The number of cells is not correct.");
}
}
else {
throw new CommandParseException("Error reading the direction.");
}
}
return cmd;
}
}

View File

@ -0,0 +1,33 @@
package tp.p2.controller.Commands;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class ResetCommand extends Command {
public ResetCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
// TODO Auto-generated constructor stub
}
@Override
public boolean execute(Game game) {
game.reset();
return true;
}
@Override
public Command parse(String[] commandWords) {
Command cmd = null;
if(commandWords[0].equals("reset") || commandWords[0].equals("r")) {
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,63 @@
package tp.p2.controller.Commands;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.controller.Exceptions.CommandParseException;
import tp.p2.game.Game;
import tp.p2.game.GamePrinter;
import tp.p2.game.Stringifier;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class SaveCommand extends Command {
private Scanner in;
public SaveCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
this.in = new Scanner(System.in);
}
@Override
public boolean execute(Game game) throws CommandExecuteException {
GamePrinter printer = new Stringifier();
System.out.println("File name > ");
String fileName = in.nextLine() + ".dat";
BufferedWriter outChars = null;
try {
outChars = new BufferedWriter(new FileWriter(fileName));
outChars.write(printer.toString(game));
outChars.close();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if(outChars == null) { throw new CommandExecuteException("No se pudo guardar el juego."); }
else { System.out.println("Game successfully saved in file " + fileName + ". Use the 'load' command to reload it.\n"); }
}
return false;
}
@Override
public Command parse(String[] commandWords) throws CommandParseException {
Command cmd = null;
if(commandWords[0].equals("save") || commandWords[0].equals("g")) {
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,39 @@
package tp.p2.controller.Commands;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class ShockwaveCommand extends Command {
//Atributos:
public ShockwaveCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
}
public boolean execute(Game game) throws CommandExecuteException {
boolean exe = true;
if(!game.shockWave()) {
exe = false;
throw new CommandExecuteException("El ShockWave no est<73> disponible.");
}
return exe;
}
public Command parse(String[] commandWords) {
Command cmd = null;
if(commandWords[0].equals("shockwave") || commandWords[0].equals("w")) {
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,41 @@
package tp.p2.controller.Commands;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class ShotCommand extends Command {
//Atributos:
//Constructor:
public ShotCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
}
//M<EFBFBD>todos:
public boolean execute(Game game) throws CommandExecuteException {
boolean exe = true;
if(!game.shootLaser()) {
exe = false;
throw new CommandExecuteException("You can't launch two missiles at once.");
}
return exe;
}
public Command parse(String[] commandWords) {
Command cmd = null;
if(commandWords[0].equals("shot") || commandWords[0].equals("s")) {
//cmd = new ShotCommand(commandWords[0], "m", "Realiza un disparo", null);
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,47 @@
package tp.p2.controller.Commands;
import tp.p2.controller.Commands.Command;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.game.Game;
import tp.p2.game.GamePrinter;
import tp.p2.game.Stringifier;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class StringifyCommand extends Command{
public StringifyCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
// TODO Auto-generated constructor stub
}
@Override
public boolean execute(Game game) throws CommandExecuteException {
GamePrinter printer = new Stringifier();
if(printer != null) {
System.out.println(printer.toString(game));
}
/*
else {
throw new CommandExecuteException("The board could not be serializable.");
}*/
return false;
}
@Override
public Command parse(String[] commandWords) {
Command cmd = null;
if (commandWords[0].equals("stringify") || commandWords[0].equals("sf")) {
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,41 @@
package tp.p2.controller.Commands;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class SuperShootCommand extends Command {
public SuperShootCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
}
public boolean execute(Game game) throws CommandExecuteException {
boolean exe = true;
if(!game.shootSuperLaser()) {
exe = false;
throw new CommandExecuteException("You don't have super-missiles.");
}
return exe;
}
public Command parse(String[] commandWords) {
Command cmd = null;
if(commandWords[0].equals("supermissile") || commandWords[0].equals("sm")) {
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,31 @@
package tp.p2.controller.Commands;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class UpdateCommand extends Command {
public UpdateCommand(String name, String shortcut, String details, String help) {
super(name, shortcut, details, help);
// TODO Auto-generated constructor stub
}
@Override
public boolean execute(Game game) {
return true;
}
@Override
public Command parse(String[] commandWords) {
Command cmd = null;
if(commandWords[0].equals("none") || commandWords[0].equals("n") || commandWords[0].equals("")) {
cmd = this;
}
return cmd;
}
}

View File

@ -0,0 +1,97 @@
/**
*
*/
package tp.p2.controller;
import java.util.Scanner;
import tp.p2.controller.Commands.Command;
import tp.p2.controller.Commands.CommandGenerator;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.controller.Exceptions.CommandParseException;
import tp.p2.game.BoardPrinter;
import tp.p2.game.Game;
import tp.p2.game.GamePrinter;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class Controller {
//Atributos:
Scanner in;
//Constructor:
public Controller(Game game, Scanner in) {
this.in = new Scanner(System.in);
}
//M<EFBFBD>todos:
//Ejecuta el bucle del juego hasta que termina:
public void run(Game game) {
GamePrinter printer = new BoardPrinter(Game.MAXFIL, Game.MAXCOL);
System.out.println(game + printer.toString(game));
do {
System.out.println("Command > ");
String[] words = in.nextLine().toLowerCase().trim().split("\\s+");
try {
Command command = CommandGenerator.parseCommand(words);
if (command != null) {
if (command.execute(game)) {
game.update();
System.out.println(game + printer.toString(game));
}
}
else {
System.out.format("Command " + words[0] + " not found. \n");
}
}
catch (CommandParseException | CommandExecuteException ex) {
System.out.format(ex.getMessage() + " %n %n");
}
} while (!game.isFinished());
game.update();
System.out.println(game + printer.toString(game));
System.out.println(game.getWinnerMessage());
}
}
//TPpr2v2:
/*
public class Controller {
//Atributos:
Scanner in;
//Constructor:
public Controller(Game game, Scanner in) {
this.in = new Scanner(System.in);
}
//M<EFBFBD>todos:
//Ejecuta el bucle del juego hasta que termina:
public void run(Game game) {
System.out.println(game);
do {
System.out.println("Command > ");
String[] words = in.nextLine().toLowerCase().trim().split("\\s+");
Command command = CommandGenerator.parseCommand(words);
if (command != null) {
if (command.execute(game)) {
game.update();
System.out.println(game);
}
}
else {
System.out.format("Command " + words[0] + " not found. \n");
}
} while (!game.isFinished());
}
}
*/

View File

@ -0,0 +1,21 @@
package tp.p2.controller.Exceptions;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class CommandExecuteException extends Exception {
private static final long serialVersionUID = 1L;
private String message;
public CommandExecuteException(String string) {
this.message = "Failed to run command.\n"
+ "Cause of exception: \n"
+ this + ": " + string;
}
public String getMessage() {
return this.message;
}
}

View File

@ -0,0 +1,22 @@
package tp.p2.controller.Exceptions;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class CommandParseException extends Exception {
private static final long serialVersionUID = 1L;
private String message;
public CommandParseException(String string) {
this.message = "Command can<61>t be parse.\n"
+ "Cause of exception: \n"
+ this + ": " + string;
}
public String getMessage() {
return this.message;
}
}

View File

@ -0,0 +1,24 @@
package tp.p2.controller.Exceptions;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class FileContentsException extends Exception {
public static final String wrongPrefixMsg = "unknown game attribute: ";
public static final String lineTooLongMsg = "too many words on line commencing: ";
public static final String lineTooShortMsg = "missing data on line commencing: ";
private static final long serialVersionUID = 1L;
private String string;
public FileContentsException(String string) {
this.string = "Contend not found.\n"
+ "Cause of exception: \n"
+ this + ": " + string;
}
public String toString() {
return this.string;
}
}

View File

@ -0,0 +1,76 @@
package tp.p2.game;
import tp.p2.util.MyStringUtils;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class BoardPrinter implements GamePrinter {
private int numRows;
private int numCols;
private String[][] board;
private final String space = " ";
public BoardPrinter(int maxfil, int maxcol) {
this.numRows = maxfil;
this.numCols = maxcol;
}
@Override
public String toString(Game game) {
encodeGame(game);
int cellSize = 7;
int marginSize = 2;
String vDelimiter = "|";
String hDelimiter = "-";
String rowDelimiter = MyStringUtils.repeat(hDelimiter, (numCols * (cellSize + 1)) - 1);
String margin = MyStringUtils.repeat(space, marginSize);
String lineDelimiter = String.format("%n%s%s%n", margin + space, rowDelimiter);
StringBuilder str = new StringBuilder();
str.append(lineDelimiter);
for(int i=0; i<numRows; i++) {
str.append(margin).append(vDelimiter);
for (int j=0; j<numCols; j++) {
str.append(MyStringUtils.centre(board[i][j], cellSize)).append(vDelimiter);
}
str.append(lineDelimiter);
}
return str.toString();
}
private void encodeGame(Game game) {
this.board = new String[numRows][numCols];
for(int i = 0; i < numRows; i++) {
for(int j = 0; j < numCols; j++) {
board[i][j] = game.board.toString(i, j);
}
}
}
@Override
public GamePrinter parse(String name) {
GamePrinter tablero = null;
if(name.equals("boardprinter") || name.equals("board")) {
tablero = this;
}
return tablero;
}
@Override
public String helpText() {
return "prints the game formatted as a board of dimension: " + Game.MAXFIL + "," + Game.MAXCOL;
}
@Override
public void setGame(Game game) {
//
}
}

View File

@ -0,0 +1,224 @@
package tp.p2.game;
import tp.p2.Level;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class FileContentsVerifier{
public static final String separator1 = ";";
public static final String separator2 = ",";
public static final String labelRefSeparator = " - ";
private String foundInFileString = "";
private void appendToFoundInFileString(String linePrefix) {
foundInFileString += linePrefix;
}
// Don't catch NumberFormatException.
public boolean verifyCycleString(String cycleString) {
String[] words = cycleString.split(separator1);
appendToFoundInFileString(words[0]);
if (words.length != 2
|| !verifyCurrentCycle(Integer.parseInt(words[1])))
return false;
return true;
}
public boolean verifyLevelString(String levelString) {
String[] words = levelString.split(separator1);
appendToFoundInFileString(words[0]);
if (words.length != 2
|| !verifyLevel(Level.parse(words[1])))
return false;
return true;
}
// Don't catch NumberFormatException.
public boolean verifyOvniString(String lineFromFile, Game game, int armour) {
String[] words = lineFromFile.split(separator1);
appendToFoundInFileString(words[0]);
if (words.length != 3) return false;
String[] coords = words[1].split(separator2);
if ( !verifyCoords(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), game)
|| !verifyLives(Integer.parseInt(words[2]), armour) )
return false;
return true;
}
// Don't catch NumberFormatException.
public boolean verifyPlayerString(String lineFromFile, Game game, int armour) {
String[] words = lineFromFile.split(separator1);
appendToFoundInFileString(words[0]);
if (words.length != 6) return false;
String[] coords = words[1].split(separator2);
if ( !verifyCoords(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), game)
|| !verifyLives(Integer.parseInt(words[2]), armour)
|| !verifyPoints(Integer.parseInt(words[3]))
|| !verifyBool(words[4]) )
return false;
return true;
}
// Don't catch NumberFormatException.
/*
public boolean verifyAlienShipString(String lineFromFile, Game game, int armour) {
String[] words = lineFromFile.split(separator1);
appendToFoundInFileString(words[0]);
if (words.length != 5) return false;
String[] coords = words[1].split(separator2);
if ( !verifyCoords(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), game)
|| !verifyLives(Integer.parseInt(words[2]), armour)
|| !verifyCycleToNextAlienMove(Integer.parseInt(words[3]), game.getLevel())
|| !verifyDir(words[4]) ) {
return false;
}
return true;
}
*/
//DestroyerAlien
public boolean verifyDestroyerShipString(String lineFromFile, Game game, int armour) {
String[] words = lineFromFile.split(separator1);
appendToFoundInFileString(words[0]);
if (words.length != 5) return false;
if(!words[0].equals("D")) return false;
String[] coords = words[1].split(separator2);
if ( !verifyCoords(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), game)
|| !verifyLives(Integer.parseInt(words[2]), armour)
|| !verifyCycleToNextAlienMove(Integer.parseInt(words[3]), game.getLevel())
|| !verifyDir(words[4]) ) {
return false;
}
return true;
}
//RegularAlien
public boolean verifyRegularShipString(String lineFromFile, Game game, int armour) {
String[] words = lineFromFile.split(separator1);
appendToFoundInFileString(words[0]);
if (words.length != 5) return false;
if(!words[0].equals("R")) return false;
String[] coords = words[1].split(separator2);
if ( !verifyCoords(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), game)
|| !verifyLives(Integer.parseInt(words[2]), armour)
|| !verifyCycleToNextAlienMove(Integer.parseInt(words[3]), game.getLevel())
|| !verifyDir(words[4]) ) {
return false;
}
return true;
}
//ExplosiveAlien
public boolean verifyExplosiveShipString(String lineFromFile, Game game, int armour) {
String[] words = lineFromFile.split(separator1);
appendToFoundInFileString(words[0]);
if (words.length != 5) return false;
if(!words[0].equals("E")) return false;
String[] coords = words[1].split(separator2);
if ( !verifyCoords(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), game)
|| !verifyLives(Integer.parseInt(words[2]), armour)
|| !verifyCycleToNextAlienMove(Integer.parseInt(words[3]), game.getLevel())
|| !verifyDir(words[4]) ) {
return false;
}
return true;
}
// Don't catch NumberFormatException.
public boolean verifyWeaponString(String lineFromFile, Game game) {
String[] words = lineFromFile.split(separator1);
if (words.length != 2) return false;
appendToFoundInFileString(words[0]);
String[] coords = words[1].split(separator2);
if ( !verifyCoords(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), game) )
return false;
return true;
}
public boolean verifyRefString(String lineFromFile) {
String[] words = lineFromFile.split(labelRefSeparator);
if (words.length != 2 || !verifyLabel(words[1])) return false;
return true;
}
public static boolean verifyLabel(String label) {
return Integer.parseInt(label) > 0;
}
public static boolean verifyCoords(int x, int y, Game game) {
return game.isOnBoard(x, y);
}
public static boolean verifyCurrentCycle(int currentCycle) {
return currentCycle >= 0;
}
public static boolean verifyLevel(Level level) {
return level != null;
}
public static boolean verifyDir(String dir) {
return dir != null;
}
public static boolean verifyLives(int live, int armour) {
return 0 < live && live <= armour;
}
public static boolean verifyPoints(int points) {
return points >= 0;
}
public static boolean verifyCycleToNextAlienMove(int cycle, Level level) {
return 0 <= cycle && cycle <= level.getNumCyclesToMoveOneCell();
}
// parseBoolean converts any string different from "true" to false.
public static boolean verifyBool(String boolString) {
return boolString.equals("true") || boolString.equals("false");
}
public boolean isMissileOnLoadedBoard() {
return foundInFileString.toUpperCase().contains("M");
}
// Use a regular expression to verify the string of concatenated prefixes found
public boolean verifyLines() {
// TO DO: compare foundInFileString with a regular expression
return true;
}
// text explaining allowed concatenated prefixes
public String toString() {
// TO DO
return "";
}
public boolean verifyGameString(String gameString) {
String[] words = gameString.split(";");
appendToFoundInFileString(words[0]);
if (words.length != 2)
return false;
return true;
}
}

View File

@ -0,0 +1,265 @@
package tp.p2.game;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Random;
import tp.p2.Level;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.controller.Exceptions.FileContentsException;
import tp.p2.game.GameObjects.BoardInitializer;
import tp.p2.game.GameObjects.GameObject;
import tp.p2.game.GameObjects.Ovni;
import tp.p2.game.GameObjects.AlienShip;
import tp.p2.game.GameObjects.Shockwave;
import tp.p2.game.GameObjects.SuperMissile;
import tp.p2.game.GameObjects.UCMMissile;
import tp.p2.game.GameObjects.UCMShip;
import tp.p2.game.GameObjects.Interfaces.IPlayerController;
import tp.p2.game.GameObjects.Lists.GameObjectBoard;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class Game implements IPlayerController{
//Constantes:
public final static int MAXFIL = 9;
public final static int MAXCOL = 8;
public final static int DAMAGE = 1;
public final static int COSTSUPERMISSILE = 20;
//Atributos
private int currentCycle;
private Random rand;
private Level level;
private int restCycles;
GameObjectBoard board;
private UCMShip player;
private boolean doExit;
private BoardInitializer initializer;
//Constructor:
public Game (Level level, Random random){
this.rand = random;
this.level = level;
this.restCycles = this.level.getNumCyclesToMoveOneCell();
initializer = new BoardInitializer();
initGame();
}
public Game (Level level, int restCycles){
this.rand = new Random(System.currentTimeMillis());
this.level = level;
this.restCycles = restCycles;
this.currentCycle = restCycles;
initializer = null;
}
//M<EFBFBD>todos:
public void initGame () {
currentCycle = 0;
board = initializer.initialize(this, level);
player = new UCMShip(this, MAXFIL - 1, MAXCOL / 2);
board.add(player);
}
public Random getRandom() {
return rand;
}
public Level getLevel() {
return level;
}
public int getCurrentCycle() {
return this.currentCycle;
}
public void reset() {
initGame();
}
public void addObject(GameObject object) {
board.add(object);
}
public String positionToString(int fila, int columna) {
return board.toString(fila, columna);
}
public boolean isFinished() {
return playerWin() || aliensWin() || doExit;
}
public boolean aliensWin() {
return !player.isAlive() || AlienShip.haveLanded();
}
private boolean playerWin () {
return AlienShip.allDead();
}
public void update() {
board.computerAction();
board.update();
currentCycle += 1;
if(this.restCycles == 0) {
this.restCycles = this.level.getNumCyclesToMoveOneCell();
}
else {
restCycles--;
}
}
public boolean isOnBoard(int fila, int columna) {
return MAXFIL > fila && MAXCOL > columna;
}
public void exit() {
doExit = true;
}
public String infoToString() {
return "Life: " + this.player.getLive() + "\n"
+ "Number of cycles: " + this.currentCycle + "\n"
+ "Points: " + this.player.getPoints() + "\n"
+ "Remaining aliens: " + AlienShip.numAliens() + "\n"
+ "ShockWave: " + this.player.getShockWave() + "\n"
+ "Number of SuperMissiles: " + this.player.getNumSuperMissiles() + "\n";
}
public String toString() {
//BoardPrinter gp = new BoardPrinter(MAXFIL, MAXCOL);
//String tablero = this.infoToString() + gp.toString(this);
//return tablero;
return this.infoToString();
}
public String serialize() {
return "--SPACE INVADERS v2.0--\n\n"
+ "G;" + this.restCycles + "\n"
+ "L;" + this.level + "\n"
+ this.board.serialize() + "\n";
}
public String getWinnerMessage () {
if (playerWin()) return "Player win!";
else if (aliensWin()) return "Aliens win!";
else if (doExit) return "Player exits the game";
else return "This should not happen";
}
@Override
public boolean move(String dir, int numCells) throws CommandExecuteException{
boolean move = false;
if(this.player.move(dir, numCells)) {
move = true;
}
return move;
}
@Override
public boolean shootLaser() {
boolean shoot = false;
if(this.player.getMisile()) {
this.enableMissile();
shoot = true;
}
return shoot;
}
@Override
public boolean shockWave() {
boolean sw = false;
if(this.player.getShockWave()) {
sw = true;
this.board.swAttack();
this.player.deleteSW();
GameObject ovni = new Ovni(this, 0, Game.MAXCOL, 1);
this.board.add(ovni);
}
return sw;
}
@Override
public boolean shootSuperLaser() {
boolean shoot = false;
if(this.player.getSuperMisile() || this.player.getMisile()) {
this.enableSuperMissile();
shoot = true;
}
return shoot;
}
@Override
public void receivePoints(int points) {
this.player.addPoints(points);
}
@Override
public void enableShockWave() {
Shockwave sw = new Shockwave(this, this.player.getFila(), this.player.getColumna(), 1);
this.player.activeSW(sw);
this.board.add(sw);
}
@Override
public void enableMissile() {
UCMMissile misil = new UCMMissile(this, this.player.getFila(), this.player.getColumna(), 1);
this.player.activeMisile(misil);
this.board.add(misil);
}
@Override
public void enableSuperMissile() {
SuperMissile misil = new SuperMissile(this, this.player.getFila(), this.player.getColumna(), 1);
this.player.activeSuperMisile(misil);
this.board.add(misil);
}
public boolean buySuperMissile() throws CommandExecuteException {
boolean buy = false;
if (this.player.getPoints() >= COSTSUPERMISSILE) {
this.player.subtractPoints(COSTSUPERMISSILE);
this.player.getSuperMissile();
buy = true;
}
if(!buy) {
throw new CommandExecuteException("You don't have enough points.");
}
return buy;
}
public int getRestCycles() {
return this.restCycles;
}
public void load(BufferedReader inStream) throws IOException, FileContentsException {
this.board.setCurrentObjects(0);
String line = inStream.readLine().trim();
while (line != null && !line.isEmpty()) {
FileContentsVerifier verifier = new FileContentsVerifier();
GameObject gameObject = GameObjectGenerator.parse(line, this, verifier);
if(gameObject == null) {
throw new FileContentsException("invalid file, unrecognised line prefix");
}
board.add(gameObject);
line = inStream.readLine().trim();
}
}
}

View File

@ -0,0 +1,46 @@
package tp.p2.game;
import java.util.Random;
import tp.p2.Level;
import tp.p2.controller.Exceptions.FileContentsException;
import tp.p2.game.GameObjects.Bomb;
import tp.p2.game.GameObjects.DestroyerAlien;
import tp.p2.game.GameObjects.GameObject;
import tp.p2.game.GameObjects.Ovni;
import tp.p2.game.GameObjects.RegularAlien;
import tp.p2.game.GameObjects.Shockwave;
import tp.p2.game.GameObjects.SuperMissile;
import tp.p2.game.GameObjects.UCMMissile;
import tp.p2.game.GameObjects.UCMShip;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class GameObjectGenerator {
private static Game otherGame = new Game(Level.EASY, new Random(System.currentTimeMillis()));
private static GameObject[] availableGameObjects = {
new UCMShip(otherGame, 0, 0),
new Ovni(otherGame, 0, 0, 0),
new RegularAlien(otherGame, 0, 0, 0),
new DestroyerAlien(otherGame, 0, 0, 0),
new Shockwave(otherGame, 0, 0, 0),
new Bomb(otherGame, 0, 0, 0),
new UCMMissile(otherGame, 0, 0, 0),
new SuperMissile(otherGame, 0, 0, 0)
};
public static GameObject parse(String stringFromFile, Game game, FileContentsVerifier verifier) throws FileContentsException {
GameObject gameObject = null;
for (GameObject go: availableGameObjects) {
gameObject = go.parse(stringFromFile, game, verifier);
if (gameObject != null) break;
}
return gameObject;
}
}
/*
*/

View File

@ -0,0 +1,130 @@
package tp.p2.game.GameObjects;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public abstract class AlienShip extends EnemyShip {
//Atributos est<EFBFBD>ticos:
protected static boolean down = false; //Variable est<EFBFBD>tica booleana para indicar si los Aliens tienen que bajar o no.
protected static String direction = "left"; //Variable est<EFBFBD>tica que indica la direcci<EFBFBD>n en la que se mueve los aliens.
protected static boolean isLanded = false;
protected static boolean allDead = false;
protected static int numAliens = 0; //Variable est<EFBFBD>tica que indica el n<EFBFBD>mero de Aliens que hay en el tablero actualmente.
protected static int contAliens = 0; //Variable est<EFBFBD>tica que ind<EFBFBD>ca (si down == true), cu<EFBFBD>ntos aliens han bajado.
//Constructor:
public AlienShip(Game game, int fila, int col, int live) {
super(game, fila, col, live);
}
//M<EFBFBD>todos:
public static boolean haveLanded() {
return isLanded;
}
public static boolean allDead() {
return allDead;
}
public static int numAliens() {
return numAliens;
}
public static void setNumAliens(int aliens) {
numAliens = aliens;
}
public void move() {
if(this.game.getRestCycles() == 0) {
if(direction == "left") {
this.columna--;
if(this.columna == 0) {
down = true;
}
}
else if(direction == "right") {
this.columna++;
if(this.columna == Game.MAXCOL-1) {
down = true;
}
}
}
if(down && this.game.getRestCycles() == this.level.getNumCyclesToMoveOneCell()) {
this.fila++;
if(this.fila == Game.MAXFIL-1) { isLanded = true; }
contAliens++;
if(contAliens >= numAliens) {
contAliens = 0;
down = false;
if(direction == "left") {
direction = "right";
}
else {
direction = "left";
}
}
}
}
public boolean receiveMissileAttack(int damage) {
this.getDamage(damage);
return true;
}
public boolean receiveShockWaveAttack(int damage) {
this.getDamage(damage);
return true;
}
public boolean recibeExplodeAttack(int damage) { //Para recibir da<EFBFBD>o de una nave explosiva.
this.getDamage(damage);
return true;
}
public abstract void computerAction();
public abstract void onDelete();
public abstract String toString();
}
/*
public void move() {
if(this.game.getCurrentCycle() % this.level.getNumCyclesToMoveOneCell() == 0) {
if(direction == "left") {
this.columna--;
if(this.columna == 0) {
down = true;
}
}
else if(direction == "right") {
this.columna++;
if(this.columna == Game.MAXCOL-1) {
down = true;
}
}
}
if(down == true && this.game.getCurrentCycle() % this.level.getNumCyclesToMoveOneCell() != 0) {
this.fila++;
if(this.fila == Game.MAXFIL-1) { isLanded = true; }
contAliens++;
if(contAliens == numAliens) {
contAliens = 0;
down = false;
if(direction == "left") {
direction = "right";
}
else {
direction = "left";
}
}
}
}
*/

View File

@ -0,0 +1,61 @@
package tp.p2.game.GameObjects;
import tp.p2.Level;
import tp.p2.game.Game;
import tp.p2.game.GameObjects.Lists.GameObjectBoard;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class BoardInitializer {
private Level level;
private GameObjectBoard board;
private Game game;
public GameObjectBoard initialize(Game game, Level level) {
this.level = level;
this.game = game;
board = new GameObjectBoard(Game.MAXFIL, Game.MAXCOL);
initializeOvni();
initializeRegularAliens();
initializeDestroyerAliens();
return board;
}
private void initializeOvni () {
GameObject ovni = new Ovni(game, 0, Game.MAXCOL, 1);
board.add(ovni);
}
private void initializeRegularAliens () {
int fila=2, col=3;
for (int i = 0; i < this.level.getNumRowsOfRegularAliens(); i++) {
for (int j = 0; j < this.level.getNumRegularAliensPerRow(); j++) {
GameObject regular = new RegularAlien(this.game, fila, col, 2);
board.add(regular);
col++;
}
fila++;
col = 3;
}
}
private void initializeDestroyerAliens() {
int fila, col;
switch (level) {
case EASY: fila = 3; col = 4; break;
case HARD: fila = 4; col = 3; break;
default: fila = 5; col = 3; break;
}
for (int i = 0; i < this.level.getNumDestroyerAliensPerRow(); i++) {
GameObject destroyer = new DestroyerAlien(this.game, fila, col, 1);
board.add(destroyer);
col++;
}
}
}

View File

@ -0,0 +1,74 @@
package tp.p2.game.GameObjects;
import tp.p2.game.FileContentsVerifier;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class Bomb extends Weapon{
//Atributos:
private String letra;
//Constructor:
public Bomb(Game game, int fila, int col, int live) {
super(game, fila, col, live);
this.letra = "oo";
}
public Bomb() {
super(null, 0, 0, 0);
this.letra = "oo";
}
public void weaponAttack(GameObject other) {
other.receiveBombAttack(Game.DAMAGE);
//this.live--;
this.getDamage(Game.DAMAGE);
}
public boolean recibeMissileAttack(int damage) {
//this.live--;
this.getDamage(damage);
return true;
}
@Override
public void computerAction() {}
@Override
public void onDelete() {
if(this.getLive() <= 0 || this.getFila() > Game.MAXFIL-1) { //
this.isAlive = false;
}
}
@Override
public void move() {
this.fila++;
}
@Override
public String toString() {
return this.letra;
}
@Override
public String serializer() {
return "B;"
+ this.fila + ","
+ this.columna + ","
+ this.live;
}
@Override
public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) {
String[] words = stringFromFile.split(FileContentsVerifier.separator1);
String[] coords = words[1].split(FileContentsVerifier.separator2);
return verifier.verifyWeaponString(stringFromFile, game2) ?
new Bomb(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2])):null;
}
}

View File

@ -0,0 +1,86 @@
package tp.p2.game.GameObjects;
import tp.p2.game.FileContentsVerifier;
import tp.p2.game.Game;
import tp.p2.game.GameObjects.Interfaces.IExecuteRandomActions;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class DestroyerAlien extends AlienShip implements IExecuteRandomActions{
//Atributos:
private Bomb bomb;
private String letra;
//Constructor:
public DestroyerAlien(Game game, int fila, int col, int live) {
super(game, fila, col, live);
this.bomb = null;
this.letra = "D";
numAliens++;
}
public DestroyerAlien() {
super(null, 0, 0, 1);
this.bomb = null;
this.letra = "D";
numAliens++;
}
//M<EFBFBD>todos:
public void deleteBomb() {
this.bomb = null;
}
public boolean getBomb() {
return this.bomb != null ? true : false;
}
@Override
public void computerAction() {
if(this.bomb == null && IExecuteRandomActions.canGenerateRandomBomb(game)) {
this.bomb = new Bomb(game, this.fila, this.columna, 1);
this.game.addObject(this.bomb);
}
}
@Override
public void onDelete() {
if(this.bomb != null && !this.bomb.isAlive) {
this.deleteBomb();
}
if(this.live <= 0) {
this.isAlive = false;
numAliens--;
this.game.receivePoints(10);
if(numAliens == 0) { allDead = true; }
}
}
@Override
public String toString() {
return this.letra + "[" + this.live + "]";
}
@Override
public String serializer() {
return "D;"
+ this.fila + ","
+ this.columna + ";"
+ this.live + ";"
//+ this.getBomb() + ";"
+ this.game.getRestCycles() + ";"
+ this.direction;
}
@Override
public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) {
String[] words = stringFromFile.split(FileContentsVerifier.separator1);
String[] coords = words[1].split(FileContentsVerifier.separator2);
return verifier.verifyDestroyerShipString(stringFromFile, game2, 2) ?
new DestroyerAlien(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2])):null;
}
}

View File

@ -0,0 +1,23 @@
package tp.p2.game.GameObjects;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public abstract class EnemyShip extends Ship {
//Constructor:
public EnemyShip(Game game, int fila, int col, int live) {
super(game, fila, col, live);
// TODO Auto-generated constructor stub
}
//M<EFBFBD>todos:
public abstract void computerAction();
public abstract void onDelete();
public abstract void move();
public abstract String toString();
}

View File

@ -0,0 +1,73 @@
package tp.p2.game.GameObjects;
import tp.p2.Level;
import tp.p2.game.FileContentsVerifier;
import tp.p2.game.Game;
import tp.p2.game.GameObjects.Interfaces.IAttack;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public abstract class GameObject implements IAttack {
//Atributos est<EFBFBD>ticos:
protected int fila, columna;
protected int live;
protected boolean isAlive;
protected Game game;
protected Level level;
//Constrcutor:
public GameObject(Game game, int fila, int col, /*Coordenadas iniciales*/ int live) {
this.fila = fila;
this.columna = col;
this.game = game;
this.level = this.game.getLevel();
this.live = live;
this.isAlive = true;
}
//M<EFBFBD>todos:
public int getFila() {
return this.fila;
}
public int getColumna() {
return this.columna;
}
public boolean isAlive() {
return this.isAlive;
}
public int getLive() {
return this.live;
}
public boolean isOnPosition(int x, int y) {
return this.fila == x && this.columna == y;
}
public void getDamage (int damage) {
this.live = damage >= this.live ? 0 : this.live - damage;
}
public boolean isOut() {
return !game.isOnBoard(this.fila, this.columna);
}
public void update() {
this.move();
if(this.isAlive != false) { this.onDelete(); }
}
public abstract void computerAction();
public abstract void onDelete();
public abstract void move();
public abstract String toString();
public abstract String serializer();
public abstract GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier);
}

View File

@ -0,0 +1,16 @@
package tp.p2.game.GameObjects.Interfaces;
import tp.p2.game.GameObjects.GameObject;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public interface IAttack {
default boolean performAttack(GameObject other) {return false;};
default boolean receiveMissileAttack(int damage) {return false;};
default boolean receiveBombAttack(int damage) {return false;};
default boolean receiveShockWaveAttack(int damage) {return false;};
default boolean recibeExplodeAttack(int damage) {return false;};
}

View File

@ -0,0 +1,18 @@
package tp.p2.game.GameObjects.Interfaces;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public interface IExecuteRandomActions {
static boolean canGenerateRandomOvni(Game game){
return game.getRandom().nextDouble() < game.getLevel().getOvniFrequency();
}
static boolean canGenerateRandomBomb(Game game){
return game.getRandom().nextDouble() < game.getLevel().getShootFrequency();
}
}

View File

@ -0,0 +1,20 @@
package tp.p2.game.GameObjects.Interfaces;
import tp.p2.controller.Exceptions.CommandExecuteException;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public interface IPlayerController {
// PLAYER ACTIONS
public boolean move (String dir, int numCells) throws CommandExecuteException;
public boolean shootLaser();
public boolean shockWave();
public boolean shootSuperLaser();
// CALLBACKS
public void receivePoints(int points);
public void enableShockWave();
public void enableMissile();
public void enableSuperMissile();
}

View File

@ -0,0 +1,129 @@
package tp.p2.game.GameObjects.Lists;
import tp.p2.game.Game;
//import tp.p2.game.Game;
import tp.p2.game.GameObjects.GameObject;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class GameObjectBoard {
//Atributos:
private GameObject[] objects;
private int currentObjects;
//Constructor:
public GameObjectBoard (int width, int height) {
this.objects = new GameObject[width * height];
this.currentObjects = 0;
}
//M<EFBFBD>todos:
private int getCurrentObjects() {
return this.currentObjects;
}
public void setCurrentObjects(int currentObjects) {
this.currentObjects = currentObjects;
}
public void add (GameObject object) {
this.objects[this.currentObjects] = object;
this.currentObjects++;
}
/*
private GameObject getObjectInPosition(int fila, int columna) {
int pos = getIndex(fila, columna);
return this.objects[pos];
}
*/
private int getIndex(int fila, int columna) {
boolean encontrado = false;
int i = this.getCurrentObjects()-1;
while(!encontrado && i >= 0) {
if(this.objects[i].getFila() == fila && this.objects[i].getColumna() == columna) {
encontrado = true;
}
else {
i--;
}
}
return i;
}
private void remove(GameObject object) {
int pos = getIndex(object.getFila(), object.getColumna());
this.objects[pos] = null;
for (int i = pos; i < this.getCurrentObjects(); i++) {
this.objects[i] = this.objects[i+1];
}
this.currentObjects--;
}
public void update() {
for (int i = 0; i < this.getCurrentObjects(); i++) {
this.objects[i].update();
this.checkAttacks(this.objects[i]);
}
this.removeDead();
}
private void checkAttacks(GameObject object) {
for (int i = 0; i < this.getCurrentObjects(); i++) {
if (object != this.objects[i]) {
if(object.performAttack(this.objects[i])) {
object.onDelete();
this.objects[i].onDelete();
}
}
}
}
public void computerAction() {
for (int i = 0; i < this.getCurrentObjects(); i++) {
this.objects[i].computerAction();
}
}
private void removeDead() {
for (int i = 0; i < this.getCurrentObjects(); i++) {
if(!this.objects[i].isAlive()) {
remove(this.objects[i]);
}
}
}
public void swAttack() {
for (int i = 0; i < this.getCurrentObjects(); i++) {
this.objects[i].receiveShockWaveAttack(Game.DAMAGE);
}
}
public String toString(int fila, int columna) {
String print = "";
for (int i = 0; i < this.getCurrentObjects(); i++) {
if(this.objects[i].getFila() == fila && this.objects[i].getColumna() == columna) {
print += this.objects[i].toString();
}
}
return print;
}
public String serialize() {
String serialize = "";
for (int i = 0; i < this.getCurrentObjects(); i++) {
serialize += this.objects[i].serializer() + "\n";
}
return serialize;
}
}

View File

@ -0,0 +1,88 @@
package tp.p2.game.GameObjects;
import tp.p2.game.FileContentsVerifier;
import tp.p2.game.Game;
import tp.p2.game.GameObjects.Interfaces.IExecuteRandomActions;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class Ovni extends EnemyShip{
//Atributos:
private String letra;
private boolean enabble;
//Constructor:
public Ovni(Game game, int fila, int col, int live) {
super(game, fila, col, live);
this.letra = "O";
this.enabble = false;
}
public Ovni() {
super(null, 0, 0, 1);
this.letra = "O";
this.enabble = false;
}
//M<EFBFBD>todos:
public String toString() {
return this.letra + "[" + this.live + "]";
}
@Override
public void computerAction() {
if(IExecuteRandomActions.canGenerateRandomOvni(game)) {
this.enabble = true;
}
}
public boolean receiveMissileAttack(int damage) {
this.live -= damage;
this.game.enableShockWave();
this.game.receivePoints(25);
return true;
}
public boolean receiveShockWaveAttack(int damage) {
this.live -= damage;
return true;
}
@Override
public void onDelete() {
if(this.columna < 0) {
this.enabble = false;
this.columna = Game.MAXCOL;
}
else if(this.live <= 0) {
this.isAlive = false;
}
}
@Override
public void move() {
if(this.enabble) { //QUITAR LA CONDICI<EFBFBD>N DE LA COLUMNA, ES S<EFBFBD>LO PARA PRUEBAS. && this.columna >= Game.MAXCOL
this.columna--;
}
}
@Override
public String serializer() {
return "O;"
+ this.fila + ","
+ this.columna + ";"
+ this.live;
}
@Override
public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) {
String[] words = stringFromFile.split(FileContentsVerifier.separator1);
String[] coords = words[1].split(FileContentsVerifier.separator2);
return verifier.verifyOvniString(stringFromFile, game2, 1) ?
new Ovni(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2])):null;
}
}

View File

@ -0,0 +1,115 @@
package tp.p2.game.GameObjects;
import tp.p2.game.FileContentsVerifier;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class RegularAlien extends AlienShip {
//Atributos:
private String letra;
private boolean explosive;
//Constructor:
public RegularAlien(Game game, int fila, int col, int live) {
super(game, fila, col, live);
this.letra = "C";
this.explosive = false;
numAliens++;
}
public RegularAlien() {
super(null, 0, 0, 2);
this.letra = "C";
this.explosive = false;
numAliens++;
}
public RegularAlien(Game game, int fila, int col, int live, String letra) {
super(game, fila, col, live);
this.letra = letra;
this.explosive = false;
numAliens++;
}
public int getLive() {
return this.live;
}
public boolean isDead() {
return this.getLive() > 0;
}
@Override
public void computerAction() {
if((!this.explosive) && (this.game.getRandom().nextDouble() < this.level.getTurnExplodeFrequency())) {
this.explosive = true;
this.letra = "E";
}
}
@Override
public void onDelete() {
if(this.live == 0) {
if(!this.explosive) { this.isAlive = false; }
numAliens--;
if(numAliens == 0) { allDead = true; }
this.game.receivePoints(5);
}
}
@Override
public String toString() {
return this.letra + "[" + this.live + "]";
}
@Override
public String serializer() {
String letra = "R";
if(explosive) {letra = this.letra;}
return letra + ";"
+ this.fila + ","
+ this.columna + ";"
+ this.live + ";"
+ this.game.getRestCycles() + ";"
+ this.direction;
}
//M<EFBFBD>todos si la nave es explosiva:
public void explodeAttack(GameObject other) {
other.recibeExplodeAttack(Game.DAMAGE);
}
public boolean performAttack(GameObject other) {
boolean attack = false;
if(this.explosive && this.live == 0) {
if(other.isAlive()) {
if(other.isOnPosition(fila-1, columna) || other.isOnPosition(fila+1, columna) || other.isOnPosition(fila, columna-1) || other.isOnPosition(fila, columna+1)) {
this.explodeAttack(other); //restar vida
attack = true;
}
}
this.isAlive = false;
}
return attack;
}
@Override
public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) {
String[] words = stringFromFile.split(FileContentsVerifier.separator1);
String[] coords = words[1].split(FileContentsVerifier.separator2);
if(words[0].equals("R")) {
return verifier.verifyRegularShipString(stringFromFile, game2, 2) ?
new RegularAlien(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2])):null;
}
else {
return verifier.verifyExplosiveShipString(stringFromFile, game2, 2) ?
new RegularAlien(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2]), words[0]):null;
}
}
}

View File

@ -0,0 +1,22 @@
package tp.p2.game.GameObjects;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public abstract class Ship extends GameObject {
//Constructor:
public Ship(Game game, int fila, int col, int live) {
super(game, fila, col, live);
}
//M<EFBFBD>todos:
public abstract void computerAction();
public abstract void onDelete();
public abstract void move();
public abstract String toString();
}

View File

@ -0,0 +1,55 @@
package tp.p2.game.GameObjects;
import tp.p2.game.FileContentsVerifier;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class Shockwave extends Weapon {
public Shockwave(Game game, int fila, int col, int live) {
super(game, fila, col, live);
}
public Shockwave() {
super(null, 0, 0, 1);
}
@Override
protected void weaponAttack(GameObject other) {
other.receiveShockWaveAttack(Game.DAMAGE);
this.getDamage(Game.DAMAGE);
}
@Override
public void computerAction() {}
@Override
public void onDelete() {
if(this.live == 0) {
this.isAlive = false;
}
}
@Override
public void move() {}
@Override
public String toString() {
return "";
}
@Override
public String serializer() {
return "";
}
@Override
public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) {
return verifier.verifyWeaponString(stringFromFile, game2) ? new Shockwave(game2, 0, 0, 1):null;
}
}

View File

@ -0,0 +1,69 @@
package tp.p2.game.GameObjects;
import tp.p2.game.FileContentsVerifier;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class SuperMissile extends Weapon {
//Atributos:
private String letra;
//Constructor:
public SuperMissile(Game game, int fila, int col, int live) {
super(game, fila, col, live);
this.letra = "||";
}
public SuperMissile() {
super(null, 0, 0, 1);
this.letra = "||";
}
//M<EFBFBD>todos:
@Override
protected void weaponAttack(GameObject other) {
other.receiveMissileAttack(Game.DAMAGE*2);
this.getDamage(Game.DAMAGE);
}
@Override
public void computerAction() {}
@Override
public void onDelete() {
if(this.live <= 0 || this.fila < 0) {
this.isAlive = false;
}
}
@Override
public void move() {
this.fila--;
}
@Override
public String toString() {
return this.letra;
}
@Override
public String serializer() {
return "M;"
+ this.fila + ","
+ this.columna;
}
@Override
public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) {
String[] words = stringFromFile.split(FileContentsVerifier.separator1);
String[] coords = words[1].split(FileContentsVerifier.separator2);
return verifier.verifyWeaponString(stringFromFile, game2) ?
new SuperMissile(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2])):null;
}
}

View File

@ -0,0 +1,67 @@
package tp.p2.game.GameObjects;
import tp.p2.game.FileContentsVerifier;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class UCMMissile extends Weapon{
//Atributos:
private String letra;
//Constructor:
public UCMMissile(Game game, int fila, int col, int live) {
super(game, fila, col, live);
this.letra = "|";
}
public UCMMissile() {
super(null, 0, 0, 1);
this.letra = "|";
}
@Override
protected void weaponAttack(GameObject other) {
other.receiveMissileAttack(Game.DAMAGE);
//this.live--;
this.getDamage(Game.DAMAGE);
}
@Override
public void computerAction() {}
@Override
public void onDelete() {
if(this.live <= 0 || this.fila < 0) {
this.isAlive = false;
}
}
@Override
public void move() {
this.fila--;
}
@Override
public String toString() {
return this.letra;
}
@Override
public String serializer() {
return "M;"
+ this.fila + ","
+ this.columna;
}
@Override
public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) {
String[] words = stringFromFile.split(FileContentsVerifier.separator1);
String[] coords = words[1].split(FileContentsVerifier.separator2);
return verifier.verifyWeaponString(stringFromFile, game2) ?
new UCMMissile(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2])):null;
}
}

View File

@ -0,0 +1,186 @@
package tp.p2.game.GameObjects;
import tp.p2.controller.Exceptions.CommandExecuteException;
import tp.p2.game.FileContentsVerifier;
//import tp.p2.controller.ShockwaveCommand;
import tp.p2.game.Game;
//import tp.p2.util.MyStringUtils;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class UCMShip extends Ship {
//Atributos:
private Weapon misil;
private Shockwave shockwave;
private String letra;
private int points;
private int numSuperMissiles;
//Constructor:
public UCMShip(Game game, int fila, int col) {
super(game, fila, col, 3);
this.misil = null;
this.shockwave = null;
this.letra = "^__^";
this.points = 0;
this.numSuperMissiles = 0;
}
public UCMShip() {
super(null, Game.MAXFIL-1, 4, 3);
this.misil = null;
this.shockwave = null;
this.letra = "^__^";
this.points = 0;
this.numSuperMissiles = 0;
}
public void activeMisile(UCMMissile misil) {
this.misil = misil;
}
public void activeSW(Shockwave sw) {
this.shockwave = sw;
}
public void activeSuperMisile(SuperMissile supermisil) {
if(this.numSuperMissiles > 0) { this.misil = supermisil; }
}
public void deleteMisil() {
if(this.getSuperMisile()) { this.numSuperMissiles--; }
this.misil = null;
}
public void deleteSW() {
this.shockwave = null;
}
public boolean receiveBombAttack(int damage) {
this.live -= damage;
return true;
}
@Override
public void computerAction() {}
@Override
public void onDelete() {
if((this.misil != null) && (!this.misil.isAlive)) { //(this.misil.getLive() == 0 || this.misil.getFila() < 0)
this.deleteMisil();
}
if(this.live <= 0) {
this.isAlive = false;
}
}
public boolean move(String dir, int nCasillas) throws CommandExecuteException{
boolean move = false;
switch(dir) {
case "right":
if(this.columna + nCasillas < Game.MAXCOL) {
switch(nCasillas) {
case 1: this.columna++; move = true; break;
case 2: this.columna += 2; move = true; break;
default: break;
}
}
break;
case "left":
if(this.columna - nCasillas >= 0) {
switch(nCasillas) {
case 1: this.columna--; move = true; break;
case 2: this.columna -= 2; move = true; break;
default: this.columna += 0; move = false; break;
}
}
break;
}
if(!move) {
throw new CommandExecuteException("You'd come out of the limits of the board.");
}
return move;
}
public void addPoints(int points) {
this.points += points;
}
public void subtractPoints(int points) {
this.points -= points;
}
public int getPoints() {
return this.points;
}
public boolean getMisile() {
boolean misilEnable = false;
if(this.misil == null) {
misilEnable = true;
}
return misilEnable;
}
public boolean getShockWave() {
boolean sw = false;
if(this.shockwave != null) {
sw = true;
}
return sw;
}
public boolean getSuperMisile() {
boolean smEnable = false;
if(this.numSuperMissiles > 0) {
smEnable = true;
}
return smEnable;
}
public void getSuperMissile() {
this.numSuperMissiles++;
}
public int getNumSuperMissiles() {
return this.numSuperMissiles;
}
@Override
public void move() {}
@Override
public String toString() {
return this.letra /*+ "[" + this.live + "]"*/;
}
@Override
public String serializer() {
return "P;"
+ this.fila + ","
+ this.columna + ";"
+ this.live + ";"
+ this.points + ";"
+ this.getShockWave() + ";"
+ this.numSuperMissiles;
}
@Override
public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) {
String[] words = stringFromFile.split(FileContentsVerifier.separator1);
String[] coords = words[1].split(FileContentsVerifier.separator2);
return verifier.verifyPlayerString(stringFromFile, game2, 3) ?
new UCMShip(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1])):null;
}
}

View File

@ -0,0 +1,36 @@
package tp.p2.game.GameObjects;
import tp.p2.game.Game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public abstract class Weapon extends GameObject {
public Weapon(Game game, int fila, int col, int live) {
super(game, fila, col, live);
// TODO Auto-generated constructor stub
}
public boolean performAttack(GameObject other) {
boolean attack = false;
if(isAlive() && other.isAlive()) {
if(other.isOnPosition(this.fila, this.columna)) { //x, y de weapon
this.weaponAttack(other); //restar vida
attack = true;
}
}
return attack;
}
protected abstract void weaponAttack(GameObject other);
public abstract void computerAction();
public abstract void onDelete();
public abstract void move();
public abstract String toString();
}

View File

@ -0,0 +1,11 @@
package tp.p2.game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public interface GamePrinter {
String toString(Game game);
public GamePrinter parse(String name);
public String helpText();
void setGame(Game game); //A<EFBFBD>adido en la versi<EFBFBD>n 3.
}

View File

@ -0,0 +1,29 @@
package tp.p2.game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class PrinterGenerator {
private static GamePrinter[] availablePrinters = {
new BoardPrinter(Game.MAXFIL, Game.MAXCOL),
new Stringifier(),
};
public static GamePrinter parse(String name) {
GamePrinter printer = null;
for (GamePrinter p: availablePrinters) {
printer = p.parse(name);
if (printer != null) break;
}
return printer;
}
public static String printerHelp() {
StringBuilder printers = new StringBuilder();
for (GamePrinter p: availablePrinters)
printers.append(p.helpText());
return printers.toString();
}
}

View File

@ -0,0 +1,45 @@
package tp.p2.game;
import tp.p2.controller.Exceptions.CommandExecuteException;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public enum PrinterTypes {
BOARDPRINTER("boardprinter",
"prints the game formatted as a board of dimension: ",
new BoardPrinter(Game.MAXFIL, Game.MAXCOL)),
STRINGIFIER("stringifier",
"prints the game as plain text",
new Stringifier());
private String printerName;
private String helpText;
private GamePrinter printerObject;
private PrinterTypes(String name, String text, GamePrinter printer) {
printerName = name;
helpText = text;
printerObject = printer;
}
public static String printerHelp(Game game) throws CommandExecuteException {
String helpString = "";
for (PrinterTypes printer : PrinterTypes.values())
helpString += String.format("%s : %s%s%n", printer.printerName, printer.helpText,
(printer == BOARDPRINTER ? Game.MAXFIL + " x " + Game.MAXCOL : "") );
if(helpString == "") {throw new CommandExecuteException("No hay tableros disponibles.");}
return helpString;
}
// Assumes a max of one object of each printer type is needed (otherwise return copy)
public GamePrinter getObject(Game game) {
printerObject.setGame(game);
return printerObject;
}
}

View File

@ -0,0 +1,34 @@
package tp.p2.game;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class Stringifier implements GamePrinter{
@Override
public String toString(Game game) {
return game.serialize();
}
@Override
public GamePrinter parse(String name) {
GamePrinter tablero = null;
if(name.equals("serializer") || name.equals("stringifier")) {
tablero = this;
}
return tablero;
}
@Override
public String helpText() {
return "prints the game as plain text";
}
@Override
public void setGame(Game game) {
// TODO Auto-generated method stub
}
}

View File

@ -0,0 +1,24 @@
package tp.p2.util;
/**
* @author Fernando M<EFBFBD>ndez Torrubiano
*
*/
public class MyStringUtils {
public static String repeat(String elmnt, int length) {
String result = "";
for (int i = 0; i < length; i++) {
result += elmnt;
}
return result;
}
public static String centre(String text, int len){
String out = String.format(" %"+len+"s %s %"+len+"s", "",text,"");
float mid = (out.length()/2);
float start = mid - (len/2);
float end = start + len;
return out.substring((int)start, (int)end);
}
}