LBYCPEI Final Report 6
LBYCPEI Final Report 6
Laboratory Module 6
Abstraction, Inheritance, and Polymorphism
By
Luis Miguel IV G. Perez, LBYCPEI-EQ6
1
INTRODUCTION
Abstraction and polymorphism are two important concepts in object-oriented programming
(OOP). Abstraction refers to the act of representing essential features without including background
details or explanations. Polymorphism, on the other hand, is the ability of a single entity to take on
multiple forms. These concepts are often used together in OOP to create more flexible and reusable code.
In this article, we will explore the differences between abstract classes and interfaces, as well as the
differences between static and dynamic polymorphism. We will also learn how to create custom abstract
classes and use them in derived classes, and how to use dynamic polymorphism in OOP applications or
game programs.
Objectives
1. To understand and apply the concepts of abstraction and polymorphism.
2. To differentiate abstract classes and interfaces.
3. To compare static polymorphism and dynamic polymorphism.
4. To be able to write custom abstract classes and utilize it for multiple derived classes that have similar
behaviors.
5. To be able to use dynamic polymorphism and utilize it in an OOP application or game program.
Materials:
1. IntelliJ IDEA (Java IDE)
2. Java SE
3. cpei.jar (spl.jar)
4. ACM graphics documentation
2
PROCEDURES (Individual) / EXPERIMENTAL PLAN
I. Hangman Revisited
The goal of the first exercise is to create an interface in the IDE for the hangman activity from
previous modules. To do this, we need to add the methods from the hangman project to the interface. If
everything is done correctly, the methods in the interface should be able to reference the ones in the
hangman project.
The second exercise asked us to create a program that keeps track of a Pokémon card collection.
The starter code provided help for us to get started. The program uses an abstract class as its foundation,
which contains methods for getting information about the individual Pokémon in the collection. Our task
is to write the relevant information for each Pokémon by creating individual classes for each Pokémon,
with their corresponding stats. The starter code contains the necessary methods to make the program
work, so we need to fill in the missing code to make the methods function correctly. The program also
uses a canvas, similar to the one used in the hangman project in previous modules, to display the images
of the Pokémon.
The final exercise asked us to create a chess game using the acm graphics program. The provided
starter code included a Chess class that extends the GraphicsProgram class and creates a ChessDisplay
object and a ChessBoard object. The Chess class also implements a mousePressed method that is called
whenever a mouse button is pressed on the game board. This method checks which player's turn it is,
whether a piece is currently selected and whether the selected piece can move to the location that was
clicked on the board. If all of these conditions are met, the selected piece is moved to the clicked location,
the game board is updated, and it becomes the other player's turn. The code also makes use of different
classes for each of the individual chess pieces in the game.
3
RESULTS AND DISCUSSION
1. Hangman Revisited
4
Explanation:
This screenshot shows the successful implementation of the past hangman code to an interface class in
java. The interface allows the user to see the methods used in the hangman class and their corresponding
functions. This makes it easy to view all the methods that are used to make the program work.
Explanation:
This screenshot shows the removal of a pokemon with the user’s inputted number, particularly Bulbasaur,
and the bottom of the program shows that it cannot be found.
5
Explanation:
This screenshot shows the viewing of 1 random pokemon. In this screenshot, we also see an example of a
pokemon with two types, the first type being its main type and the second having its own color.
6
Explanation:
This screenshot shows the running of a slideshow of the different pokemon cards. 2 of 20 pokemon cards
is shown in the screenshots.
7
Explanation:
This screenshot shows the successful run of the search for a pokemon function. In this example, Pikachu
is searched in the ConsoleProgram then its corresponding card is shown in the GraphicsProgram on the
right.
8
3. Chess Program
9
Explanation:
The screenshots above show the various functions of the chess program. The first screenshot shows the
start of the game while the second shows that the chess pieces are movable. The program uses
polymorphism to create a chess program using the provided starter code. It includes multiple classes for
handling the game board, the main game, and the individual chess pieces. These classes manage the
movement and actions of the chess pieces.
10
CONCLUSION:
Did you achieve your objectives for this module? Describe your achievement in this module
one-by-one, objective by objective.
What have you learned? Both technically (focused on OOP), and in general (soft skills,
attitude-related, etc.)
Understanding the concept of polymorphism in OOP, and writing more efficient code with
polymorphism. I learned that these can be used to make the code more organized and easier to understand
which can be applied in real life when I can use different methods to solve different problems.
What are the common pitfalls, mistakes, and confusion that you have encountered? How did
you overcome them?
Common mistakes I had is relating the classes to each other and making sure that they were called
or are being used for the right logic. I overcame them by checking the errors given by the IDE and
double-checking the logic that I inputted into my code.
What are your recommendations for those who will try the activity for the first time and
what can you suggest to improve this module?
11
I recommend for those who will try this activity really understand how objects work and how they
can be modified to improve the program. This module can be improved if there were less time consumed
on adjusting the graphics.
12
choice = readInt("Choice: ");
switch (choice) {
case 1:
int num;
break;
case 5:
13
println("Thank you for using the Program");
break;
default:
println("Invalid Input");
break;
}
2.2 PokemonCards
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
14
// System.in reads from console while this reads from file
}
//Arrays.toString(pokemonStats);
} catch (FileNotFoundException e) {
15
System.out.println("File does not Exist");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
if (pokemonName.equalsIgnoreCase(names)){
return pokemonNum;
}
}
return -1;
}
2.3 PokemonCanvas
import acm.graphics.GCanvas;
import acm.graphics.*;
16
import java.awt.*;
System.out.println(pokemon.getName());
GImage pokemonPic = new GImage("assets/" + pokemon.getName() + ".png");
pokemonPic.sendToFront();
pokemonPic.setSize(200, 200);
add(pokemonPic, 200, 100);
names(pokemon);
add(pokemonName, x, 350);
}
rectOne.sendBackward();
if (pokemon.getType() == "Grass") {
rectOne.setColor(Color.GREEN);
rectOne.setFilled(true);
} else if (pokemon.getType() == "Fire") {
rectOne.setColor(Color.orange);
rectOne.setFilled(true);
} else if (pokemon.getType() == "Electric") {
rectOne.setColor(Color.yellow);
rectOne.setFilled(true);
} else if (pokemon.getType() == "Water") {
rectOne.setColor(Color.blue);
rectOne.setFilled(true);
}
else if (pokemon.getType() == "Psychic") {
rectOne.setColor(Color.MAGENTA);
rectOne.setFilled(true);
}
17
else if (pokemon.getType() == "Poison") {
rectOne.setColor(Color.getColor("Purple"));
rectOne.setFilled(true);
}
add(rectOne, 0, 430);
18
atkTxt.setFont("Times New Roman-Bold-30");
atkTxt.setColor(Color.WHITE);
add(atkTxt, 50, 575);
rectTwo.setColor(Color.MAGENTA);
rectTwo.setFilled(true);
} else if (firstType == "Grass" && secType == "Poison") {
rectOne.setColor(Color.GREEN);
rectOne.setFilled(true);
rectTwo.setColor(Color.MAGENTA);
rectTwo.setFilled(true);
} else if (firstType == "Water" && secType == "Psychic") {
19
rectOne.setColor(Color.blue);
rectOne.setFilled(true);
rectTwo.setColor(Color.MAGENTA);
rectTwo.setFilled(true);
}
else {
rectOne.setColor(Color.blue);
rectOne.setFilled(true);
rectTwo.setColor(Color.pink);
rectTwo.setFilled(true);
}
add(rectOne, 0, 430);
rectOne.sendForward();
rectOne.sendToFront();
add(rectTwo, 321, 430);
}
private void showMultiTypeStats(Pokemon pokemon) {
// Your CODE here
//rectOne.setColor(Color.green);
//add(rectOne,0, y + 170);
20
GLabel height = new GLabel("HEIGHT:"+ pokemon.getHeight());
height.setFont(fontWH);
height.setColor(Color.WHITE);
add(height,200,410);
21
protected String name;
protected String weight;
protected String height;
protected int atk;
protected int def;
protected int stamina;
protected String type;
22
public String getType(){
return type;
}
name = "Pikachu";
type = "Electric";
this.weight = stats[0];
this.height = stats[1];
this.atk = Integer.parseInt(stats[2].trim());
this.def = Integer.parseInt(stats[3].trim());
this.stamina = Integer.parseInt(stats[4].trim());
3.1 Chess.java
import java.awt.Color;
import java.awt.event.*;
/** The main class responsible for managing the chess game */
public class Chess extends GraphicsProgram {
/**
* Object responsible for handling the graphical display on the screen
*/
ChessDisplay display;
/**
* Object that keeps track of the locations of all pieces
23
*/
ChessBoard board;
ChessFrame frame;
ChessPiece lastPieceClicked;
boolean isWhiteTurn;
boolean isBlackTurn;
boolean isPieceClicked;
/**
* Method called before run responsible for initializing the ChessDisplay
and
* ChessBoard objects
*/
public void init() {
frame = new ChessFrame(this);
frame.init();
display = ChessDisplay.getInstance(this); // This line is required,
don't change it
board = new ChessBoard();
mouseListenerAdded();
/**
* The main method that runs the program
*/
public void run() {
// You fill this in.
display.draw(board);
}
//@Override
//public synchronized void addMouseListener(MouseListener l) {
//super.addMouseListener(l);
//}
24
isWhiteTurn = true;
isBlackTurn = false;
isPieceClicked = false;
}
if(isWhiteTurn){
if (!isPieceClicked){
if (board.pieceAt(place[0],place[1]).getColor() ==
ChessPiece.WHITE){
display.selectSquare(place[0],place[1], Color.blue);
lastPieceClicked = board.pieceAt(place[0],place[1]);
display.draw((board));
isPieceClicked = true;
} else {
println("not your piece");
}
} else {
if (lastPieceClicked.canMoveTo(place[0],place[1], board)){
board.removePiece(lastPieceClicked.getRow(),
lastPieceClicked.getCol());
lastPieceClicked.moveTo(place[0], place[1]);
board.addPiece(lastPieceClicked);
display.unselectAll();
display.draw(board);
isWhiteTurn = false;
isBlackTurn = true;
lastPieceClicked = null;
isPieceClicked = false;
System.out.println("Black's turn");
}
}
} else if (isBlackTurn){
if (!isPieceClicked){
if (board.pieceAt(place[0],place[1]).getColor() ==
ChessPiece.BLACK){
display.selectSquare(place[0],place[1], Color.blue);
lastPieceClicked = board.pieceAt(place[0],place[1]);
display.draw((board));
isPieceClicked = true;
} else {
println("not your piece");
}
} else {
if (lastPieceClicked.canMoveTo(place[0],place[1], board)){
board.removePiece(lastPieceClicked.getRow(),
lastPieceClicked.getCol());
lastPieceClicked.moveTo(place[0], place[1]);
board.addPiece(lastPieceClicked);
display.unselectAll();
display.draw(board);
isWhiteTurn = true;
isBlackTurn = false;
lastPieceClicked = null;
isPieceClicked = false;
25
System.out.println("White's turn");
}
}
}
}
@Override
public ChessFrame getChessFrame() {
return frame;
}
3.2 ChessBoard
/*
* Name:
* Section Leader:
* File: ChessBoard.java
* ------------------
* This class represents the ChessBoard. Its job is to keep track of where
all
* of the pieces are. Since we just learned about two-dimensional arrays,
it
* might be a good idea to use one here (just a hint). Currently, it
doesn't do
* anything, but it does have four methods for you to fill in. These are
the only
* required methods in this class. As long as these work, feel free to do
whatever
* else you want to get this class working.
*/
/** Constructor for the ChessBoard class (do whatever you want with this) */
public ChessBoard() {
// You fill this in.
// Note: In Java, each class variable, instance variable, or array
component is
//initialized with a default value when it is created
//For all reference types, the default value is null.
board = new ChessPiece[BOARD_SIZE][BOARD_SIZE];
26
for (int i = 0; i < 8; i++) {
addPiece(new Pawn(1,i,ChessPiece.BLACK));
addPiece(new Pawn(6,i,ChessPiece.WHITE));
}
//ROOK
addPiece(new Rook(0,0,ChessPiece.BLACK));
addPiece(new Rook(0,7,ChessPiece.BLACK));
addPiece(new Rook(7,0,ChessPiece.WHITE));
addPiece(new Rook(7,7,ChessPiece.WHITE));
//KNIGHT
addPiece(new Knight(0,1,ChessPiece.BLACK));
addPiece(new Knight(0,6,ChessPiece.BLACK));
addPiece(new Knight(7,1,ChessPiece.WHITE));
addPiece(new Knight(7,6,ChessPiece.WHITE));
//BISHOP
addPiece(new Bishop(0,2,ChessPiece.BLACK));
addPiece(new Bishop(0,5,ChessPiece.BLACK));
addPiece(new Bishop(7,2,ChessPiece.WHITE));
addPiece(new Bishop(7,5,ChessPiece.WHITE));
//QUEEN,KING
addPiece(new Queen(0,3,ChessPiece.BLACK));
addPiece(new King(0,4,ChessPiece.BLACK));
addPiece(new Queen(7,3,ChessPiece.WHITE));
addPiece(new King(7,4,ChessPiece.WHITE));
}
/** Returns the ChessPiece currently residing at the specified row and
* column. If no piece exists at the specified location, should return
* null.
*/
public ChessPiece pieceAt(int row, int col)
{
return board[row][col];
}
/** Adds the specified ChessPiece to the ChessBoard (hint: ChessPieces know
their
* own rows and columns. You can use this to figure out where to place the
piece)
*/
public void addPiece(ChessPiece piece)
{
// If the user attempts to add a piece to a location where one already
exists,
// addPiece should overwrite the old piece with the new one.
board[piece.getRow()][piece.getCol()] = piece;
}
/** Removes the piece at the specified location from the board.
*/
public void removePiece(int row, int col)
{
board[row][col] = null;
}
27
}
3.3 Bishop
/*
* Name:
* Section Leader:
* File: Bishop.java
* ------------------
* This class represents the Bishop type of chess piece. This piece can move and
capture
* pieces along diagonals. For more information visit:
http://en.wikipedia.org/wiki/Bishop_(chess)
*/
/** Method that returns a boolean indicating whether or not the bishop can
legally move
* to the specified location (you need to fill this one in).
*/
public boolean canMoveTo(int nextRow, int nextCol, ChessBoard board)
{
// Fill this in with your own code.
boolean canMoveBoolean = false;
int dx = Math.abs(this.row - nextRow);
int dy = Math.abs(this.col - nextCol);
int x = nextRow - this.row;
int y = nextCol - this.col;
int xDir = 0;
int yDir = 0;
if (dx != 0){
xDir = dx/x;
}
if (dy != 0){
yDir = dy/y;
}
if (this.color == WHITE){
if ((nextCol - this.col == nextRow - this.row) || (this.col - nextCol
== nextRow - this.row)) {
for (int i = 1; i <= Math.max(dx, dy); i++) {
if (board.pieceAt(this.row + xDir * i, this.col + yDir * i) !=
null) {
if (board.pieceAt(nextRow, nextCol).getColor() ==
ChessPiece.BLACK) {
28
canMoveBoolean = true;
} else {
canMoveBoolean = false;
break;
}
} else {
canMoveBoolean = !moveWouldCauseCheck(nextRow, nextCol,
board);
}
}
}
} else {
if ((nextCol - this.col == nextRow - this.row) || (this.col - nextCol
== nextRow - this.row)) {
for (int i = 1; i <= Math.max(dx, dy); i++) {
if (board.pieceAt(this.row + xDir * i, this.col + yDir * i) !=
null) {
if (board.pieceAt(nextRow, nextCol).getColor() ==
ChessPiece.WHITE) {
canMoveBoolean = true;
} else {
canMoveBoolean = false;
break;
}
} else {
canMoveBoolean = !moveWouldCauseCheck(nextRow, nextCol,
board);
}
}
}
}
return canMoveBoolean; // Eventually this line should not be here
}
/** Implementation of getType() method for the Bishop class. Provides a way
to identify
* the Bishop-type chess piece as such (you don't need to change anything
here)
*/
public PieceType getType()
{
return PieceType.BISHOP;
}
}
3.4 Rook
/*
* Name:
* Section Leader:
* File: Rook.java
* ------------------
* This class represents the Rook type of chess piece. This piece can move and
capture
* pieces along rows and columns. It is also known as a castle. For more
information visit:
* http://en.wikipedia.org/wiki/Rook_(chess)
29
*/
/** Method that returns a boolean indicating whether or not the bishop can
legally move
* to the specified location (you need to fill this one in).
*/
public boolean canMoveTo(int nextRow, int nextCol, ChessBoard board)
{
// Fill this in with your own code.
boolean canMoveBoolean = false;
int dx = Math.abs(this.row - nextRow);
int dy = Math.abs(this.col - nextCol);
int x = nextRow - this.row;
int y = nextCol - this.col;
int xDir = 0;
int yDir = 0;
if (dx != 0){
xDir = dx/x;
}
if (dy != 0){
yDir = dy/y;
}
if (this.color == WHITE){
if (this.col == nextCol || this.row == nextRow) {
for (int i = 1; i <= Math.max(dx, dy); i++) {
if (board.pieceAt(this.row + xDir * i, this.col + yDir * i) !=
null) {
if (board.pieceAt(nextRow, nextCol).getColor() ==
ChessPiece.BLACK) {
canMoveBoolean = true;
} else {
canMoveBoolean = false;
break;
}
} else {
canMoveBoolean = !moveWouldCauseCheck(nextRow, nextCol,
board);
}
}
}
} else {
if (this.col == nextCol || this.row == nextRow) {
for (int i = 1; i <= Math.max(dx, dy); i++) {
if (board.pieceAt(this.row + xDir * i, this.col + yDir * i) !=
null) {
30
if (board.pieceAt(nextRow, nextCol).getColor() ==
ChessPiece.WHITE) {
canMoveBoolean = true;
} else {
canMoveBoolean = false;
break;
}
} else {
canMoveBoolean = !moveWouldCauseCheck(nextRow, nextCol,
board);
}
}
}
}
return canMoveBoolean; // Eventually this line should not be here
}
/** Implementation of getType() method for the Rook class. Provides a way to
identify
* the Rook-type chess piece as such (you don't need to change anything
here)
*/
public PieceType getType()
{
return PieceType.ROOK;
}
31
3.5 King
/** Method that returns a boolean indicating whether or not the king can
legally move
* to the specified location (you need to fill this one in).
*/
public boolean canMoveTo(int nextRow, int nextCol, ChessBoard board)
{
// Fill this in with your own code.
boolean canMoveBoolean = false;
if (this.color == WHITE){
if ((this.col - nextCol)*(this.col - nextCol) + (this.row
-nextRow)*(this.row -nextRow) <= 2) {
if (board.pieceAt(nextRow, nextCol) != null){
if (board.pieceAt(nextRow, nextCol).getColor() ==
ChessPiece.BLACK) {
canMoveBoolean = true;
} else {
canMoveBoolean = false;
}
} else {
canMoveBoolean = !moveWouldCauseCheck(nextRow, nextCol, board);
}
}
} else {
if ((this.col - nextCol)*(this.col - nextCol) + (this.row
-nextRow)*(this.row -nextRow) <= 2) {
if (board.pieceAt(nextRow, nextCol) != null){
if (board.pieceAt(nextRow, nextCol).getColor() ==
ChessPiece.WHITE) {
canMoveBoolean = true;
} else {
canMoveBoolean = false;
}
} else {
canMoveBoolean = !moveWouldCauseCheck(nextRow, nextCol, board);
}
}
}
return canMoveBoolean; // Eventually this line should not be here
}
/** Implementation of getType() method for the King class. Provides a way to
identify
* the King-type chess piece as such (you don't need to change anything
here)
32
*/
public PieceType getType()
{
return PieceType.KING;
}
3.6 Knight
/*
* Name:
* Section Leader:
* File: Knight.java
* ------------------
* This class represents the Knight type of chess piece. This piece can move
only in
* L-shapes. That is it moves two spaces in one direction and one space in an
orthogonal
* direction. It is the only piece in chess that can jump over other pieces. For
* more information go here: http://en.wikipedia.org/wiki/Knight_(chess)
*/
/** Method that returns a boolean indicating whether or not the king can
legally move
* to the specified location (you need to fill this one in).
*/
public boolean canMoveTo(int nextRow, int nextCol, ChessBoard board)
{
// Fill this in with your own code.
boolean canMoveBoolean = false;
int dx = Math.abs(this.row - nextRow);
int dy = Math.abs(this.col - nextCol);
System.out.println(dx);
System.out.println(dy);
if (this.color == WHITE){
if ((dx == 2 && dy == 1) || (dx == 1 && dy == 2 )){
if (board.pieceAt(nextRow, nextCol) != null){
if (board.pieceAt(nextRow, nextCol).getColor() ==
ChessPiece.BLACK) {
canMoveBoolean = true;
} else {
canMoveBoolean = false;
}
33
}
else {
canMoveBoolean = !moveWouldCauseCheck(nextRow, nextCol, board);
}
}
} else {
if ((dx == 2 && dy == 1) || (dx == 1 && dy == 2 )){
if (board.pieceAt(nextRow, nextCol) != null){
if (board.pieceAt(nextRow, nextCol).getColor() ==
ChessPiece.WHITE) {
canMoveBoolean = true;
} else {
canMoveBoolean = false;
}
}
else {
canMoveBoolean = !moveWouldCauseCheck(nextRow, nextCol, board);
}
}
}
return canMoveBoolean; // Eventually this line should not be here
}
/** Implementation of getType() method for the Knight class. Provides a way
to identify
* the Knight-type chess piece as such (you don't need to change anything
here)
*/
public PieceType getType()
{
return PieceType.KNIGHT;
}
3.7 Pawn
/*
* Name:
* Section Leader:
* File: Pawn.java
* ------------------
* This class represents the Pawn type of chess piece. This piece can move only
straight
* forward (away from your side toward the other side). In can normally move
only one space
* at a time, except on the first move, when it has the option of moving two
spaces. The pawn,
* although it moves only forward, captures only diagonally forward. Turns out,
this makes it
* the most difficult to implement in code (fair warning). For more information
go
* here: http://en.wikipedia.org/wiki/Pawn_(chess)
*/
34
/** Constructor for the Pawn class */
public Pawn(int initialRow, int initialCol, int pieceColor)
{
this.row = initialRow;
this.col = initialCol;
this.color = pieceColor;
}
/** Method that returns a boolean indicating whether or not the pawn can
legally move
* to the specified location (you need to fill this one in).
*/
public boolean canMoveTo(int nextRow, int nextCol, ChessBoard board)
{
int dx = Math.abs(this.row - nextRow);
int dy = Math.abs(this.col - nextCol);
// Fill this in with your own code.
boolean canMoveBoolean = false;
if (this.color == WHITE){
if (board.pieceAt(nextRow, nextCol) == null){
if (this.row == 6){
if (dy == 0 && dx < 3){
canMoveBoolean = !moveWouldCauseCheck(nextRow, nextCol,
board);
}
} else if (dy == 0 && dx == 1){
canMoveBoolean = !moveWouldCauseCheck(nextRow, nextCol,
board);
}
} else if (board.pieceAt(nextRow, nextCol).getColor() ==
ChessPiece.BLACK){
if (dy == 1 && dx == 1){
canMoveBoolean = true;
}
}
} else {
if (board.pieceAt(nextRow, nextCol) == null){
if (this.row == 1){
if (dy == 0 && dx < 3){
canMoveBoolean = !moveWouldCauseCheck(nextRow, nextCol,
board);
}
} else if (dy == 0 && dx == 1){
canMoveBoolean = !moveWouldCauseCheck(nextRow, nextCol, board);
}
} else if (board.pieceAt(nextRow, nextCol).getColor() ==
ChessPiece.WHITE){
if (dy == 1 && dx == 1){
canMoveBoolean = true;
}
}
}
return canMoveBoolean; // Eventually this line should not be here
}
35
/** Implementation of getType() method for the Pawn class. Provides a way to
identify
* the Pawn-type chess piece as such (you don't need to change anything
here)
*/
public PieceType getType()
{
return PieceType.PAWN;
}
3.8 PieceType
36