-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTicTacToeLLD.java
More file actions
272 lines (231 loc) · 8.84 KB
/
TicTacToeLLD.java
File metadata and controls
272 lines (231 loc) · 8.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
import java.util.*;
// --- ENUMS ---
enum PlayerType { HUMAN, BOT }
enum GameState { IN_PROGRESS, ENDED, DRAW }
enum BotDifficultyLevel { EASY, MEDIUM, HARD }
// --- MODELS ---
class PlayingPiece {
private char symbol;
public PlayingPiece(char symbol) { this.symbol = symbol; }
public char getSymbol() { return symbol; }
}
class Cell {
private int row, col;
private PlayingPiece piece;
public Cell(int row, int col) {
this.row = row;
this.col = col;
this.piece = null;
}
public boolean isEmpty() { return this.piece == null; }
public int getRow() { return row; }
public int getCol() { return col; }
public PlayingPiece getPiece() { return piece; }
public void setPiece(PlayingPiece piece) { this.piece = piece; }
}
class Board {
private int size;
private Cell[][] grid;
public Board(int size) {
this.size = size;
this.grid = new Cell[size][size];
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
grid[i][j] = new Cell(i, j);
}
}
}
public int getSize() { return size; }
public Cell getCell(int row, int col) { return grid[row][col]; }
public void printBoard() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (grid[i][j].isEmpty()) System.out.print(" - ");
else System.out.print(" " + grid[i][j].getPiece().getSymbol() + " ");
}
System.out.println();
}
System.out.println();
}
}
class Move {
private Cell cell;
private Player player;
public Move(Cell cell, Player player) {
this.cell = cell;
this.player = player;
}
public Cell getCell() { return cell; }
public Player getPlayer() { return player; }
}
// --- PLAYER HIERARCHY ---
abstract class Player {
private String name;
private PlayingPiece piece;
private PlayerType playerType;
public Player(String name, PlayingPiece piece, PlayerType playerType) {
this.name = name;
this.piece = piece;
this.playerType = playerType;
}
public PlayingPiece getPiece() { return piece; }
public String getName() { return name; }
public PlayerType getPlayerType() { return playerType; }
public abstract Move decideMove(Board board);
}
class HumanPlayer extends Player {
public HumanPlayer(String name, PlayingPiece piece) {
super(name, piece, PlayerType.HUMAN);
}
@Override
public Move decideMove(Board board) {
return null; // Handled externally by Game controller in this simulation
}
}
class BotPlayer extends Player {
private BotPlayingStrategy botPlayingStrategy;
public BotPlayer(String name, PlayingPiece piece, BotDifficultyLevel difficultyLevel, BotPlayingStrategy strategy) {
super(name, piece, PlayerType.BOT);
this.botPlayingStrategy = strategy;
}
@Override
public Move decideMove(Board board) {
return botPlayingStrategy.makeMove(board, this);
}
}
// --- STRATEGIES ---
interface BotPlayingStrategy { Move makeMove(Board board, Player bot); }
class RandomBotPlayingStrategy implements BotPlayingStrategy {
@Override
public Move makeMove(Board board, Player bot) {
for (int i = 0; i < board.getSize(); i++) {
for (int j = 0; j < board.getSize(); j++) {
Cell cell = board.getCell(i, j);
if (cell.isEmpty()) return new Move(cell, bot);
}
}
return null;
}
}
interface WinningStrategy { boolean checkWinner(Board board, Move lastMove); }
class OrderOneWinningStrategy implements WinningStrategy {
private int boardSize;
private List<Map<Character, Integer>> rowCounts;
private List<Map<Character, Integer>> colCounts;
private Map<Character, Integer> mainDiagCounts;
private Map<Character, Integer> antiDiagCounts;
public OrderOneWinningStrategy(int boardSize) {
this.boardSize = boardSize;
rowCounts = new ArrayList<>();
colCounts = new ArrayList<>();
for (int i = 0; i < boardSize; i++) {
rowCounts.add(new HashMap<>());
colCounts.add(new HashMap<>());
}
mainDiagCounts = new HashMap<>();
antiDiagCounts = new HashMap<>();
}
@Override
public boolean checkWinner(Board board, Move lastMove) {
int row = lastMove.getCell().getRow();
int col = lastMove.getCell().getCol();
char symbol = lastMove.getPlayer().getPiece().getSymbol();
rowCounts.get(row).put(symbol, rowCounts.get(row).getOrDefault(symbol, 0) + 1);
colCounts.get(col).put(symbol, colCounts.get(col).getOrDefault(symbol, 0) + 1);
if (row == col) mainDiagCounts.put(symbol, mainDiagCounts.getOrDefault(symbol, 0) + 1);
if (row + col == boardSize - 1) antiDiagCounts.put(symbol, antiDiagCounts.getOrDefault(symbol, 0) + 1);
return rowCounts.get(row).get(symbol) == boardSize ||
colCounts.get(col).get(symbol) == boardSize ||
(row == col && mainDiagCounts.get(symbol) == boardSize) ||
(row + col == boardSize - 1 && antiDiagCounts.get(symbol) == boardSize);
}
}
// --- GAME CONTROLLER ---
class Game {
private Board board;
private List<Player> players;
private List<Move> moves;
private int nextPlayerIndex;
private GameState gameState;
private Player winner;
private WinningStrategy winningStrategy;
public Game(int dimension, List<Player> players) {
this.board = new Board(dimension);
this.players = players;
this.moves = new ArrayList<>();
this.nextPlayerIndex = 0;
this.gameState = GameState.IN_PROGRESS;
this.winningStrategy = new OrderOneWinningStrategy(dimension);
}
public GameState getGameState() { return gameState; }
public Player getWinner() { return winner; }
public Board getBoard() { return board; }
public Player getCurrentPlayer() { return players.get(nextPlayerIndex); }
public void makeMove(int row, int col) {
if (gameState != GameState.IN_PROGRESS) return;
Player currentPlayer = players.get(nextPlayerIndex);
Move move;
if (currentPlayer.getPlayerType() == PlayerType.BOT) {
System.out.println("Bot " + currentPlayer.getName() + " is making a move...");
move = currentPlayer.decideMove(board);
} else {
Cell targetCell = board.getCell(row, col);
if (!targetCell.isEmpty()) {
System.out.println("Cell is already occupied! Try again.");
return; // Don't advance turn
}
move = new Move(targetCell, currentPlayer);
}
Cell cellToUpdate = move.getCell();
cellToUpdate.setPiece(currentPlayer.getPiece());
moves.add(move);
System.out.println(currentPlayer.getName() + " placed " +
currentPlayer.getPiece().getSymbol() + " at (" +
cellToUpdate.getRow() + ", " + cellToUpdate.getCol() + ")");
board.printBoard();
if (winningStrategy.checkWinner(board, move)) {
gameState = GameState.ENDED;
winner = currentPlayer;
return;
}
if (moves.size() == board.getSize() * board.getSize()) {
gameState = GameState.DRAW;
return;
}
nextPlayerIndex = (nextPlayerIndex + 1) % players.size();
}
}
// --- TicTacToeLLD EXECUTION CLASS ---
public class TicTacToeLLD {
public static void main(String[] args) {
System.out.println("Starting Tic-Tac-Toe Game...");
// Setup Players
Player p1 = new HumanPlayer("Alice", new PlayingPiece('X'));
Player p2 = new BotPlayer("RoboBob", new PlayingPiece('O'),
BotDifficultyLevel.EASY,
new RandomBotPlayingStrategy());
List<Player> players = new ArrayList<>();
players.add(p1);
players.add(p2);
// Start a 3x3 Game
Game game = new Game(3, players);
game.getBoard().printBoard();
// Simulating some moves
// Turn 1: Alice (Human) plays at 0, 0
game.makeMove(0, 0);
// Turn 2: RoboBob (Bot) plays (row, col ignored by bot logic)
game.makeMove(-1, -1);
// Turn 3: Alice plays at 1, 1
game.makeMove(1, 1);
// Turn 4: RoboBob plays
game.makeMove(-1, -1);
// Turn 5: Alice plays at 2, 2 (Should win diagonally)
game.makeMove(2, 2);
// Check Results
if (game.getGameState() == GameState.ENDED) {
System.out.println("Game Over! The winner is: " + game.getWinner().getName());
} else if (game.getGameState() == GameState.DRAW) {
System.out.println("Game Over! It's a draw.");
}
}
}