Skip to content

Commit f452a9e

Browse files
authored
Merge pull request #6 from VishalMCF/feature/tic-tac-toe
Feature/tic tac toe
2 parents d3b9016 + 72f6181 commit f452a9e

File tree

12 files changed

+431
-0
lines changed

12 files changed

+431
-0
lines changed

src/main/java/com/gatomalvado/Main.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.gatomalvado;
22

3+
import java.util.Stack;
4+
35
public class Main {
46

57
public static void main(String[] args) {
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.gatomalvado.tictactoe;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Scanner;
6+
import java.util.function.IntConsumer;
7+
import java.util.stream.IntStream;
8+
9+
import com.gatomalvado.tictactoe.model.Move;
10+
import com.gatomalvado.tictactoe.model.Symbol;
11+
import com.gatomalvado.tictactoe.model.User;
12+
import com.gatomalvado.tictactoe.orchestrator.TicTacToeGame;
13+
14+
public class Main {
15+
16+
public static void main(String[] args) {
17+
System.out.println("Hello Tic tac Toe");
18+
System.out.println("Enter number of users -> ");
19+
Scanner scanner = new Scanner(System.in);
20+
int numberOfUsers = scanner.nextInt();
21+
System.out.println("Total number of users -> "+numberOfUsers);
22+
if(numberOfUsers <= -1){
23+
System.out.println("Number of users cannot be less than 2");
24+
System.exit(0);
25+
}
26+
List<User> users = new ArrayList<>();
27+
List<Symbol> symbols = getSymbols(numberOfUsers);
28+
for(int i=1; i<=numberOfUsers; i++){
29+
System.out.println("Enter the name of user"+i+" -> ");
30+
String currName = scanner.next();
31+
scanner.nextLine();
32+
users.add(new User(currName, symbols.get(i-1)));
33+
}
34+
System.out.println("Following users will play the game -> ");
35+
for(int i=0; i<numberOfUsers; i++){
36+
System.out.println(users.get(i).getName()+" <-> "+users.get(i).getSymbol().getSign());
37+
}
38+
39+
// users and their symbols have been taken as input
40+
// declare the board
41+
TicTacToeGame game;
42+
try{
43+
game = new TicTacToeGame(symbols, users);
44+
game.printGameCurrentStatus();
45+
int totalMoves = game.getTotalMoves();
46+
for(int i=0; i<totalMoves; i++){
47+
String moveString = scanner.nextLine();
48+
String[] strings = moveString.split(" ");
49+
if(strings.length != 3){
50+
System.out.println("Invalid Move");
51+
i--;
52+
} else{
53+
User user = game.getUser(strings[0]);
54+
if(user == null){
55+
i--;
56+
continue;
57+
}
58+
try{
59+
Move move = new Move(Integer.parseInt(strings[1]), Integer.parseInt(strings[2]), user);
60+
if(!game.takeMove(move)){
61+
i--;
62+
} else if(game.checkAnyWinner()){
63+
System.out.println(game.getWinner().getName()+" won the game");
64+
break;
65+
}
66+
game.printGameCurrentStatus();
67+
}catch(Exception exc){
68+
exc.printStackTrace();
69+
System.out.println("Invalid Move");
70+
i--;
71+
}
72+
}
73+
}
74+
}catch(UnsupportedOperationException exc){
75+
exc.printStackTrace();
76+
System.out.println(exc.getMessage());
77+
System.exit(0);
78+
}
79+
}
80+
81+
private static List<Symbol> getSymbols(int noOfUsers){
82+
if(noOfUsers==2){
83+
return List.of(new Symbol("X"), new Symbol("O"));
84+
} else {
85+
List<Symbol> symbols = new ArrayList<>();
86+
for(int i=0; i<noOfUsers; i++){
87+
symbols.add(new Symbol("X"+(i+1)));
88+
}
89+
return symbols;
90+
}
91+
}
92+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
1. -> X 1 1
2+
O 2 1
3+
X 2 1
4+
X 1 3
5+
O 1 2
6+
X 2 2
7+
O 3 1
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.gatomalvado.tictactoe.model;
2+
public class Board {
3+
4+
private Symbol[][] cells;
5+
private int size;
6+
7+
public Board(int size) {
8+
this.size = size;
9+
this.cells = new Symbol[size][size];
10+
initBoard();
11+
}
12+
13+
private void initBoard() {
14+
for (int i = 0; i < size; i++) {
15+
for (int j = 0; j < size; j++) {
16+
cells[i][j] = new Symbol("_");
17+
}
18+
System.out.println();
19+
}
20+
}
21+
22+
public void printBoard() {
23+
for (int i = 0; i < size; i++) {
24+
for (int j = 0; j < size; j++) {
25+
if (cells[i][j] != null) {
26+
System.out.print(cells[i][j] + " ");
27+
} else {
28+
System.out.print("_" + " ");
29+
}
30+
}
31+
System.out.println();
32+
}
33+
}
34+
35+
public int getSize() {
36+
return size;
37+
}
38+
39+
public boolean isCellAlreadyOccupied(int x, int y) {
40+
return !cells[x][y].getSign().equals("_");
41+
}
42+
43+
public void updateCell(Move move){
44+
this.cells[move.getXPos()-1][move.getYPos()-1] = move.getUser().getSymbol();
45+
}
46+
47+
public Symbol getCell(int x, int y){
48+
return this.cells[x][y];
49+
}
50+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.gatomalvado.tictactoe.model;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
6+
@AllArgsConstructor
7+
@Getter
8+
public class Move {
9+
private int xPos;
10+
private int yPos;
11+
private User user;
12+
13+
@Override
14+
public String toString() {
15+
return user.getName()+" -> {"+xPos+", "+yPos+"}";
16+
}
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.gatomalvado.tictactoe.model;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
import lombok.NoArgsConstructor;
6+
7+
@Data
8+
@NoArgsConstructor
9+
@AllArgsConstructor
10+
public class Symbol {
11+
private String sign;
12+
13+
@Override
14+
public String toString() {
15+
return sign;
16+
}
17+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.gatomalvado.tictactoe.model;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
import lombok.NoArgsConstructor;
6+
7+
@Data
8+
@NoArgsConstructor
9+
@AllArgsConstructor
10+
public class User {
11+
private String name;
12+
private Symbol symbol;
13+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package com.gatomalvado.tictactoe.orchestrator;
2+
3+
import java.util.ArrayList;
4+
import java.util.HashMap;
5+
import java.util.LinkedList;
6+
import java.util.List;
7+
import java.util.Map;
8+
import java.util.Queue;
9+
10+
import com.gatomalvado.tictactoe.model.Board;
11+
import com.gatomalvado.tictactoe.model.Move;
12+
import com.gatomalvado.tictactoe.model.Symbol;
13+
import com.gatomalvado.tictactoe.model.User;
14+
import com.gatomalvado.tictactoe.service.BoardFactory;
15+
import com.gatomalvado.tictactoe.service.StrategyFactory;
16+
17+
18+
public class TicTacToeGame {
19+
20+
private List<Symbol> symbolList;
21+
private List<User> users;
22+
private Board board;
23+
private Map<String, User> symbolUserMap;
24+
private Queue<User> turnQueue;
25+
private List<Move> moves;
26+
private StrategyFactory strategyFactory;
27+
private BoardFactory boardFactory;
28+
private User winner;
29+
30+
public TicTacToeGame(List<Symbol> symbolList, List<User> users) {
31+
this.symbolList = symbolList;
32+
this.users = users;
33+
this.moves = new ArrayList<>();
34+
this.boardFactory = new BoardFactory();
35+
this.strategyFactory = new StrategyFactory();
36+
this.board = this.boardFactory.createBoard(users.size());
37+
generateSymbolUserMap();
38+
createTurns();
39+
}
40+
41+
public void printGameCurrentStatus() {
42+
board.printBoard();
43+
}
44+
45+
private void generateSymbolUserMap() {
46+
symbolUserMap = new HashMap<>();
47+
for (int i = 0; i < users.size(); i++) {
48+
symbolUserMap.put(symbolList.get(i).getSign(), users.get(i));
49+
}
50+
}
51+
52+
private void createTurns() {
53+
turnQueue = new LinkedList<>();
54+
turnQueue.addAll(users);
55+
}
56+
57+
public boolean takeMove(Move move) {
58+
if (!validateMove(move)) {
59+
return false;
60+
}
61+
this.moves.add(move);
62+
this.board.updateCell(move);
63+
User currUser = this.turnQueue.remove();
64+
this.turnQueue.add(currUser);
65+
return true;
66+
}
67+
68+
69+
public boolean checkAnyWinner() {
70+
boolean isThereAnyWinner = this.strategyFactory.getWinnerStrategy(this.board).isThereIsAnyWinner(board);
71+
if(isThereAnyWinner){
72+
this.winner = moves.getLast().getUser();
73+
return true;
74+
}
75+
return false;
76+
}
77+
78+
private boolean validateMove(Move move) {
79+
User user = turnQueue.peek();
80+
if (move.getUser() != user) {
81+
System.out.println("Invalid Move");
82+
return false;
83+
}
84+
if (move.getXPos() > board.getSize() || move.getYPos() > board.getSize() || move.getYPos() <= 0 || move.getXPos() <= 0) {
85+
System.out.println("Invalid Move");
86+
return false;
87+
}
88+
if (board.isCellAlreadyOccupied(move.getXPos()-1, move.getYPos()-1)) {
89+
System.out.println("Invalid Move");
90+
return false;
91+
}
92+
return true;
93+
}
94+
95+
public User getUser(String symbol) {
96+
if (symbolUserMap.containsKey(symbol)) {
97+
return symbolUserMap.get(symbol);
98+
}
99+
System.out.print("Invalid Move");
100+
return null;
101+
}
102+
103+
public User getWinner(){
104+
return this.winner;
105+
}
106+
107+
public int getTotalMoves(){
108+
return board.getSize()*board.getSize();
109+
}
110+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.gatomalvado.tictactoe.service;
2+
3+
import com.gatomalvado.tictactoe.model.Board;
4+
5+
public class BoardFactory {
6+
public Board createBoard(int noOfUsers){
7+
switch(noOfUsers){
8+
case 2:
9+
return new Board(3);
10+
default:
11+
throw new UnsupportedOperationException("This is not supported yet");
12+
}
13+
}
14+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.gatomalvado.tictactoe.service;
2+
3+
import com.gatomalvado.tictactoe.model.Board;
4+
5+
public interface IWinnerDeciderStrategy {
6+
7+
boolean isThereIsAnyWinner(Board board);
8+
}

0 commit comments

Comments
 (0)