将代码拆分为不同的类时,为什么会出现堆栈溢出错误?

时间:2019-04-28 15:59:14

标签: java

我最近做了一个Connect 4游戏。但是,我将所有代码都放在一个Java文件/类中。我现在正在尝试重构代码,以便将不同的代码操作分成不同的类。例如玩,玩和玩游戏。

有人可以向我解释为什么我收到以下错误吗?

Exception in thread "main" java.lang.StackOverflowError
at java.nio.Buffer.<init>(Buffer.java:201)
at java.nio.ByteBuffer.<init>(ByteBuffer.java:281)
at java.nio.HeapByteBuffer.<init>(HeapByteBuffer.java:57)
at java.nio.ByteBuffer.allocate(ByteBuffer.java:335)
at sun.nio.cs.StreamDecoder.<init>(StreamDecoder.java:251)
at sun.nio.cs.StreamDecoder.<init>(StreamDecoder.java:231)
at sun.nio.cs.StreamDecoder.forInputStreamReader(StreamDecoder.java:69)
at java.io.InputStreamReader.<init>(InputStreamReader.java:74)
at Connect4Game.<init>(Connect4Game.java:19)
at play.<init>(play.java:2)
at Connect4Game.<init>(Connect4Game.java:21)
at play.<init>(play.java:2)
at Connect4Game.<init>(Connect4Game.java:21)
at play.<init>(play.java:2)
at Connect4Game.<init>(Connect4Game.java:21)
at play.<init>(play.java:2)
at Connect4Game.<init>(Connect4Game.java:21)
at play.<init>(play.java:2)
at Connect4Game.<init>(Connect4Game.java:21)
at play.<init>(play.java:2)
at Connect4Game.<init>(Connect4Game.java:21)
at play.<init>(play.java:2)
at Connect4Game.<init>(Connect4Game.java:21)
at play.<init>(play.java:2)

如果将方向正确指向我会非常感激,因为这是我第一次将工作代码重构为多个类。

这是我的代码:

Connect4Game.java

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Connect4Game {

final int boardWidth=7;
final int boardHeight=7;
int totalMovesPlayed;

public BufferedReader input;
public char[][] board;

public static void main(String[] args){
    new Connect4Game();
}

public Connect4Game(){
    board = new char[6][7];
    input = new BufferedReader(new InputStreamReader(System.in));

    play PlayObj = new play();
    PlayObj.playGame();

    }
}

play.java

public class play extends Connect4Game {

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();
    boardObj.printBoard();


    boolean win = false;
    while(!win){

        // player 1
        String userInput = getUserInput();
        int move = Integer.parseInt(userInput);

        counter counterObj = new counter();
        counterObj.placeCounter('r', move);


        boolean hasWon = false;
        int count = 0;

        // check horizontal
        for(int i=0; i<board.length; i++){
            for(int j=0; j<board[i].length; j++){
                if(board[i][j] == 'r'){
                    count = count + 1;
                    if(count == 4){
                        hasWon = true;
                        System.out.println("You Have Won!!!");
                    }
                }
                else{
                    count = 0;
                }
            }

        }

        // check vertical 
        count = 0;
        for(int i=0; i<board[0].length; i++){
            for(int j=0; j<board.length; j++){
                if(board[j][i] == 'r'){
                    count = count + 1;
                    if(count >= 4){
                        hasWon = true;
                        System.out.println("You Have Won!!!");
                    }
                }
                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<board.length; i++){
                for(int j=0; j<board[i].length; j++){
                    if(board[i][j] == 'y'){
                        count = count + 1;
                        if(count >= 4){
                            hasWon = true;
                            System.out.println("You Have Won!!!");
                        }
                    }
                    else{
                        count = 0;
                    }
                }

            }

            // check vertical 
            count = 0;
            for(int i=0; i<board[0].length; i++){
                for(int j=0; j<board.length; j++){
                    if(board[j][i] == 'y'){
                        count = count + 1;
                        if(count >= 4){
                            hasWon = true;
                            System.out.println("You Have Won!!!");
                        }
                    }
                    else{
                        count = 0; 
                    }
                }

            }
            boardObj.printBoard();
            if(hasWon){
                win = true;
                System.out.println("You Have Won!!!");
            }
        }

    }

}



public String getUserInput(){
    String toReturn = null;
    try{            
        toReturn = input.readLine();
    }
    catch(Exception e){

    }
    return toReturn;
    }
}

board.java

public class board extends Connect4Game {

public void printBoard(){

    for(int i=0;i<board.length;i++){
        for(int j=0;j<board[0].length;j++){
            if(board[i][j] == 0)
                System.out.print(".  ");
            else
                System.out.print(board[i][j]+"  ");
        }
        System.out.println();
    }

    for(int i=0;i<boardWidth;i++)
        System.out.print("*  ");
    System.out.println();

    for(int i=0;i<boardWidth;i++)
        System.out.print(i+"  ");
    System.out.println();
    }

}

counter.java

public class counter extends Connect4Game {

public void placeCounter(char player, int position){
    boolean placed = false;


    if(player == 'r'){
        for( int i=board.length-1; i>=0; i--){
            if(!placed && board[i - 1][position] != 'r' && board[i - 1][position] != 'y') {
                if(board[i][position] == 'y'){
                    board[i-1][position] = 'r';
                    placed = true;
                }

                else if(board[i][position] != 'r'){
                    board[i][position] = 'r';
                    placed = true;
                }
            }
        }
    }

    else {
        for( int i=board.length-1; i>=0; i--){
            if (!placed && board[i - 1][position] != 'r' && board[i - 1][position] != 'y'){
                if(board[i][position] == 'r'){
                    board[i-1][position] = 'y';
                    placed = true;
                }

                else if(board[i][position] != 'y'){
                    board[i][position] = 'y';
                    placed = true;
                }
            }
        }
    }
}
}

2 个答案:

答案 0 :(得分:4)

Connect4Game的构造函数中,您正在调用子类play的构造函数,但是该子类没有自己的构造函数,因此实际上您在为Connect4Game再次调用相同的构造函数,然后调用自身,依此类推,直到出现堆栈溢出

public Connect4Game(){
  board = new char[6][7];
  input = new BufferedReader(new InputStreamReader(System.in));

  play PlayObj = new play();
  PlayObj.playGame();
}

您的main方法应直接创建一个play对象,然后调用playGame方法

public static void main(String[] args){
    play PlayObj = new play();
    PlayObj.playGame()
}

请遵循Java命名标准,并以大写字母开头您的分类

答案 1 :(得分:4)

play扩展了Connect4Game。 因此,当实例化一个新的游戏对象时,这也会调用Connect4Game的无参数构造函数。 此Connect4Game()构造函数实例化一个新的游戏对象,该对象又再次实例化一个新的Connect4Game。因此,您已经建立了一个递归构造循环。

我认为游戏不应从Connect4Game扩展。播放实例不是Connect4Game的特定类型,因此在此处无需扩展它。

事实上,我认为其他任何类都不应该从Connect4Game扩展。

如果希望其他类可以访问开发板和输入变量,则应将Connect4Game作为构造函数参数传递给这些实例:

public class play {
    private Connect4Game connect;
    public play(Connect4Game connect) {
        this.connect=connect;
    }
    ...
}

然后,您可以在代码中使用connect.board而不是单板。 您的主要代码将变为:

public static void main(String[] args){
    Connect4Game connect=new Connect4Game();
    play PlayObj = new play(connect);
    PlayObj.playGame();
}

public Connect4Game(){
    board = new char[6][7];
    input = new BufferedReader(new InputStreamReader(System.in));
}

您的董事会课程很难阅读。您的类名称应以大写字母开头,实例变量以小写字母开头。

对于您的董事会班,这可能变成:

public class Board {
    private Connect4Game connect;
    public Board(Connect4Game connect) {
        this.connect=connect;
    }
    // to refer to the board variable of Connect4Game:
    connect.board
}

现在您可以问自己是否使用了此类Class Board?