Reputation: 77
I am currently trying to refactor my code for a basic connect four game.
I have noticed that I have a lot of repetition in my play.java file, with regards to knowing which player creates a winning pattern either horizontally or vertically.
As the horizontal and vertical winning criteria remains constant, how would I go about creating an Abstract Class or Interface to minimise code duplication here?
play.java
public class play {
private Connect4Game connect;
public play(Connect4Game connect) {
this.connect=connect;
}
public void playGame() {
System.out.println("Welcome to Connect 4");
System.out.println("To play the game type in the number of the column you want to drop you counter in");
System.out.println("Player One = r Player 2 = y");
System.out.println("");
board boardObj = new board(connect);
boardObj.printBoard();
boolean win = false;
while(!win){
// player 1
String userInput = getUserInput();
int move = Integer.parseInt(userInput);
counter counterObj = new counter(connect);
counterObj.placeCounter('r', move);
boolean hasWon = false;
int count = 0;
// check horizontal
for(int i=0; i<connect.board.length; i++){
for(int j=0; j<connect.board[i].length; j++){
if(connect.board[i][j] == 'r'){
count = count + 1;
if(count == 4){
hasWon = true;
}
}
else{
count = 0;
}
}
}
// check vertical
count = 0;
for(int i=0; i<connect.board[0].length; i++){
for(int j=0; j<connect.board.length; j++){
if(connect.board[j][i] == 'r'){
count = count + 1;
if(count >= 4){
hasWon = true;
}
}
else{
count = 0;
}
}
}
boardObj.printBoard();
if(hasWon){
win = true;
System.out.println("You Have Won!!!");
}
else {
//player 2
userInput = getUserInput();
move = Integer.parseInt(userInput);
counterObj.placeCounter('y',move);
hasWon = false;
count = 0;
// check horizontal
for(int i=0; i<connect.board.length; i++){
for(int j=0; j<connect.board[i].length; j++){
if(connect.board[i][j] == 'y'){
count = count + 1;
if(count >= 4){
hasWon = true;
}
}
else{
count = 0;
}
}
}
// check vertical
count = 0;
for(int i=0; i<connect.board[0].length; i++){
for(int j=0; j<connect.board.length; j++){
if(connect.board[j][i] == 'y'){
count = count + 1;
if(count >= 4){
hasWon = true;
}
}
else{
count = 0;
}
}
}
boardObj.printBoard();
if(hasWon){
win = true;
System.out.println("You Have Won!!!");
}
}
}
}
public String getUserInput(){
String toReturn = null;
try{
toReturn = connect.input.readLine();
}
catch(Exception e){
}
return toReturn;
}
}
Upvotes: 1
Views: 118
Reputation: 40034
Neither would help in this instance. An abstract class would be used to establish the predetermined methods that would be supported by most subclasses. It would also include method signatures of methods that would be useful where implementations might be different, depending on how that class is be used. Even then, the predefined methods can be overridden as required.
An interface simply formalizes the required methods via signatures (abstract method declarations) for a class to implement to enforce a contract between the user and the class.
As you are not creating multiple classes there would be no benefit.
The best I could recommend would be to consolidate your horizontal and vertical checks into methods and to add other methods as needed to reduce duplicate code.
Upvotes: 4
Reputation: 10003
Start refactoring by using extract method. Your two sets of nested loops can be turned into a method. Maybe you can get it down to one set of nested loops on a method that you call four times.
Upvotes: 2