Kołko i krzyzyk - OOP

0

Cześć,

Uczę się programowania w Java i dopiero wkraczam na OOP. Po napisaniu prostej konsolowej gry Kółko i krzyżyk pojawiło się troche pytań odnośnie OOP.

Na grę składa się klasa **Game **która odpowiada za logikę gry, klasa Board która przechowuje planszę gry, sprawdza wynik itp. oraz klasa Player po której dziedziczy klasa Human i Computer. Klasa enum **Sign **z symbolami X,O i E jako empty place.

Głównie mam pytanie o abstrakcyjną metodę move() w klasie Player. Metoda ta w klasie Human pyta gracza o podanie współrzednych gdzie ma być postawiony Krzyżyk lub kółko, następnie sprawdza metodą isAvailable czy to miejsce jest wolne, jeśli tak stawia Krzyżyk/kółko , jeśli nie, pyta gracza o podanie nowych współrzednych. Czy to co robi ta jest OK czy może lepiej gdyby to było zaimplementowane w klasie Game,
tj. klasa Game pyta Player o to gdzie postawić krzyzyk/kółko,
Player wybiera miejsce,
nastepnie klasa Game sprawdza czy miejsce jest wolne,
jeśli nie - pyta jeszcze raz Playera o miejsce
jesli tak - klasa Game umieszcza krzyzyk/kolko w to miejsce i pyta drugiego Playera.

  1. Chcialbym zrobic grę w ktorej gracze graja np. 10 rund po ktorych zakoneczeniu oglaszany jest wygrany. Za to odpowiadalaby klasa GameSession. Jak przeslac informacje odnosnie ile rund wygral Player 1? Czy w klasie Game umieszczenie pola które przechowywaloby ilosc rund wygranych przez Player1 ma sens? Czy moze metoda klasy Game, run() powinna zwracac informacje ktory player wygrał po każdej rundzie? Czy moze ta informacja powinna byc zawarta w klasie Player?

Kod poniżej.

package TicTacToe;

import java.util.Random;
import java.util.Scanner;

public class Game {
    Scanner scanner = new Scanner(System.in);
    Random rand = new Random();

    enum GameStatus {WON, DRAW,CONTINUE}

    Board board = new Board();
    Player player1 = new Human();
    Player player2;

    GameStatus status;
    Player currentPlayer;

    public void init(){
        System.out.println("TIC TAC TOE GAME");
        System.out.print("Choose 1 to play with computer. \nChoose 2 to play with another player.\n");
        int in = scanner.nextInt();

        if(in == 1)
            player2 = new Computer();
        else
            player2 = new Human();

        int whoFirst = 1+rand.nextInt(2);

        if(whoFirst == 1){
            currentPlayer = player1;
            player1.setSign(Sign.X);
            player2.setSign(Sign.O);
        } else{
            currentPlayer = player2;
            player1.setSign(Sign.O);
            player2.setSign(Sign.X);
        }
        status = GameStatus.CONTINUE;
    }

    void run(){
        board.displayBoard();

        while(status == GameStatus.CONTINUE){

            currentPlayer.move(board);

            if(board.checkForWin(currentPlayer.getSign())){
                status = GameStatus.WON;
                System.out.println(currentPlayer + " won!");
            } else if(board.isFull()){
                status = GameStatus.DRAW;
                System.out.println("Nobody win! Its draw.");
            }
            changePlayer();
            board.displayBoard();
        }

    }
    private void changePlayer(){
        if(currentPlayer == player1)
            currentPlayer = player2;
        else
            currentPlayer = player1;
    }

    public static void main(String[] args){
        Game g = new Game();
        g.init();
        g.run();
    }
public class Board {

    private Sign[][] board = new Sign[3][3];

    public Board(){
        clearBoard();
    }

    public void setPosition(int x, int y, Sign sign){
        board[x][y] = sign;
    }

    public Sign[][] getBoard(){
        return board;
    }

    public void displayBoard(){
        System.out.println();
        for(Sign[] mark: board){
            System.out.print("|");
            for(Sign m:mark){
                System.out.printf("%s|",m);
            }
            System.out.println();
        }
        System.out.println();

    }

    //check for draw
    public boolean isFull(){
        boolean result = true;
        for(Sign[] mark:board){
            for(Sign m:mark){
                if(m == Sign.E){
                    result = false;
                }
            }
        }
        return result;
    }

    public boolean checkForWin(Sign mark){
        if(checkColumn(mark) || checkDiagonal(mark) || checkRow(mark))
            return true;
        else
            return false;
    }

    private boolean checkRow(Sign mark){
        boolean result = false;
        for(int row = 0; row < board.length; row++){
            int count = 0;
            for(int col = 0; col <board[row].length; col++){
                if(board[row][col] == mark)
                    count++;
            }
            if(count == 3){
                result = true;
                break;
            }
        }
        return result;
    }

    private boolean checkColumn(Sign mark){
        boolean result = false;
        for(int col =0; col<board[0].length; col++){
            int count = 0;
            for(int row = 0; row <board.length;row++){
                if (board[row][col] == mark)
                    count++;
            }
            if (count == 3) {
                result = true;
                break;
            }
        }
        return result;
    }

    private boolean checkDiagonal(Sign mark){
        boolean result = false;
        if(board[0][0] == mark && board[1][1] == mark && board[2][2] == mark)
            result =  true;
        else if(board[0][2] == mark && board[1][1] == mark && board[2][0] == mark){
            result = true;
        }
        return result;
    }

    public void clearBoard(){
        for(int row = 0; row < board.length; row++){
            for(int col = 0; col < board[row].length; col++){
                board[row][col] = Sign.E;
            }
        }
    }

} 
public abstract class Player {

     private Sign sign;

     public void setSign(Sign sign){
          this.sign = sign;
     }

     public Sign getSign(){
          return sign;
     }

     abstract void move(Board board);

     protected boolean isAvailable(int x, int y, Board board){
          if(board.getBoard()[x][y] == Sign.E)
               return true;
          else
               return false;

     }
}
public class Human extends Player {
    Scanner scan = new Scanner(System.in);
    
    @Override
    public void move(Board board){
        int x ;
        int y;

        do{
            System.out.println("Player " + getSign() + "");
            x = scan.nextInt();
            y = scan.nextInt();
            if(!isAvailable(x,y,board))
                System.out.println("This spot is taken. Take another.");

        }while(!isAvailable(x,y,board));

        board.setPosition(x, y, getSign());
    }

    public String toString(){
        return "Player "+getSign();
    }


}
 */
public class Computer extends Player {
    Random rand = new Random();

    private int randNum(){
        return rand.nextInt(3);
    }

    @Override
    public String toString(){
        return "Computer "+getSign();
    }
    @Override
    public void move(Board board){
        int in ;
        int inn;

        do{
            in = randNum();
            inn = randNum();
        }while(!isAvailable(in,inn,board));

        System.out.print("Player "+getSign());
        board.setPosition(in, inn, getSign());

    }

}

Z gory dzieki za pomoc.

1

Najszybciej będzie u ciebie przechowywać te parametry w obiekcie gracza, który w sesji nie powinien się zmieniać/ tworzyć jego nowej instancji, gdybyś natomiast chciał przechowywać dodatkowe statystyki np. ilość ruchów do wygranej/przegranej, liczba przegranych to mógłbyś pomyśleć o innym obiekcie np. PlayerResult gdzie przechowywałbyś referencje do gracza i jego statystyki. Ale gra wygląda dobrze, brałbym się na twoim miejscu za coś większego:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1