Witam, mam taką klasę z gry kółko i krzyżyk:
#pragma once
#include "Cell.h"
#include <ostream>
#include <array>
class GameBoard {
public:
Cell& operator[](std::size_t index) { return gameBoard[index]; }
const Cell& operator[](std::size_t index) const { return gameBoard[index]; }
std::size_t getRowCount() const { return rowCount; }
std::size_t getColumnCount() const { return columnCount; }
std::size_t getSize() const { return gameBoard.size(); }
friend std::ostream& operator<<(std::ostream& os, const GameBoard& gameBoard);
private:
static const std::size_t rowCount = 3, columnCount = 3;
std::array<Cell, rowCount * columnCount> gameBoard;
};
Brakuje jeszcze poniższych metod:
- isAnyWinner()
- isCircleWinner()
- isSharpWinner()
- isTie()
Teraz jest kilka możliwości:
Wersja 1: Umieścić powyższe metody w klasie GameBoard.
Wersja 2: Utworzyć osobną klasę np. GameBoardChecker.
Pytanie: Która z powyższych wersji będzie lepsza i dlaczego? Czy istnieje jakiś wzorzec projektowy wykorzystywany w takiej sytuacji?
Tutaj obie wersje w kodzie:
Wersja 1:
#pragma once
#include "Cell.h"
#include <ostream>
#include <array>
class GameBoard {
public:
Cell& operator[](std::size_t index) { return gameBoard[index]; }
const Cell& operator[](std::size_t index) const { return gameBoard[index]; }
std::size_t getRowCount() const { return rowCount; }
std::size_t getColumnCount() const { return columnCount; }
std::size_t getSize() const { return gameBoard.size(); }
bool isAnyWinner() const;
bool isCircleWinner() const;
bool isSharpWinner() const;
bool isTie() const;
friend std::ostream& operator<<(std::ostream& os, const GameBoard& gameBoard);
private:
static const std::size_t rowCount = 3, columnCount = 3;
std::array<Cell, rowCount * columnCount> gameBoard;
};
Wersja 2:
#pragma once
#include "GameBoard.h"
class GameBoardChecker {
public:
bool isAnyWinner(const GameBoard& gameBoard) const;
bool isCircleWinner(const GameBoard& gameBoard) const;
bool isSharpWinner(const GameBoard& gameBoard) const;
bool isTie(const GameBoard& gameBoard) const;
};