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
49 changed files with 3086 additions and 0 deletions

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<>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<>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<>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<>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<>todos:
//Invoca al m<>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<>todo helpText() de cada subclase de Command.
//Este m<>todo es invocado por el m<>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<>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<>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<>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<>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<>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<>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<>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<>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<>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<>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<>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<>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<>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<>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<>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<>ndez Torrubiano
*
*/
public class Controller {
//Atributos:
Scanner in;
//Constructor:
public Controller(Game game, Scanner in) {
this.in = new Scanner(System.in);
}
//M<>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<>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<>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<>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<>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;
}
}