Vous êtes sur la page 1sur 12

Assignment No B-03

Aim
Implementation of MiniMax approach for TIC-TAC-TOE game.

Pre-requisite
1. Data Structure.
2. Game Theory.
3. MiniMax algorithm.
4. Programming language basics.

Objective
1. To understand idea of MiniMax Algorithm.
2. To implement TIC-TAC-TOE game using Minimax Algorithm.

Problem Statement
Implementation of MiniMax approach for TIC-TAC-TOE using Java/ Scala/ PythonEclipse. Use GUI. Player X and Player O are using their mobiles for the play. Refresh
the screen after the move for both the players.

Hardware / Software Used


1. Eclipse IDE.
2. log4j-1.2.17 Jar.

Mathematical Model
M = { s, e, X, Y, DD, NDD, fme , M emshared , success, f ailure, CP UCoreCount }

1. s: Start State - Initialize board.


2. e: End State - Player 1 or 2 won or lost.
3. X: Input - Moves given by player 1 or 2.
4. Y: Output - Player 1 or 2 won or lost.
5. DD: Deterministic Data - Board values and Players.
6. NDD: Non-Deterministic Data - If Player 1 a chance to miss a square and have player
2 X or O appear in a neighbouring square.
7. F me = HashMap() is used for mapping the Min-Max results with game.
8. Mem shared = No shared Memory is used.
9. Success: Any player won or lost.
10. Failure: Program interrupted or abnormal termination.
11. CPU CoreCount: 1.

Theory
Game Theory
The game theory is the study of decision making strategy. Game theory model are basically
understands the actions of the agents. The game playing is an application of heuristic search
of problem solving. The generator of game generates individual move in search space and these
are evaluated by tester. the most promising move is chosen.
Game tree is structure of evaluating all possible moves which allows transitions from one state
to another state in game. The computer easily decide the moves by traversing game tree. The
games are begins from Specified start state and ends in state which declared win or loss for one
or draw.
Game tree is a representation of all possible plays of the game. The root node is at start
state of game. Its next node is positioned to the first player which can reach in one move and
their successors are positioned to the second players replies. The leaf nodes of game tree are
represent Win, Loss and draw.The path from root node to leaf nodes represents the different
complete play of the game.

MinMax Algorithm
A MinMax is a recursive algorithm used for deciding next move in n-player game. The values
in algorithm are associated with the states of the game. These values are computed by position
evaluation function and indicates how good move it would be to reach goal state.The player then
makes the move that maximizes the minimum value of the state resulting from the opponents
possible following moves. The MinMax algorithm uses bottom up approach.
Two players - Max and Min. The algorithm steps are:
1. Create start node as a MAX node with current board configuration.
2. Expand nodes down to some depth of lookahead in the game.
3. Apply the evaluation function at each of the leaf nodes.
4. Back up values for each of the non-leaf nodes until a value is computed for the root node.
5. At MIN nodes, the backed-up value is the minimum of the values associated with its
children.
6. At MAX nodes, the backed up value is the maximum of the values associated with its
children.
7. Pick the operator associated with the child node whose backed-up value determined the
value at the root.

Procedure
Compiling Program: javac programname.java
Run The Program: java programname

Conclusion
Thus, we have studied and implemented TIC-TAC-TOE application using MinMax algorithm.
3

Program
=================================================
GROUP A
Assignment No : B3
Title : Implementation of MiniMax approach for TIC-TAC-TOE using Java/ Scala/
Python-Eclipse. Use GUI. Player X and Player O are using their mobiles for the play.
Refresh the screen after the move for both the players.
Roll No :
Batch : B
Class : BE( Computer )
=================================================

GameContrller.java
package com.kevinsmyth.tictactoe.controllers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import com.kevinsmyth.tictactoe.models.CellType;
import com.kevinsmyth.tictactoe.models.GameBoard;
import com.kevinsmyth.tictactoe.models.GameMode;
import com.kevinsmyth.tictactoe.models.MiniMaxResult;
import com.kevinsmyth.tictactoe.models.Player;
import com.kevinsmyth.tictactoe.models.PlayerPiece;
public class GameController {
private GameBoard _board;
private Player _player1; // X
private Player _player2; // O
private Player _currentPlayer;
public GameController(GameMode gameMode){
_board = new GameBoard();
_player1 = new Player(PlayerPiece.X, false);
_currentPlayer = _player1;
switch (gameMode){
case ONEPLAYER:
_player2 = new Player(PlayerPiece.O, true);
break;
case TWOPLAYER:
default:
_player2 = new Player(PlayerPiece.O, false);
break;
}
}
public GameBoard getBoard(){
4

return _board;
}
public Player getCurrentPlayer(){
return _currentPlayer;
}
public boolean isPlayer1Turn(){
return _currentPlayer == _player1;
}
public boolean isPlayer2Turn(){
return _currentPlayer == _player2;
}
public void placeMove(CellType cell){
// Place move for current player
_board.placeMove(cell, _currentPlayer)
if (!_board.isGameOver()){
// Make it the other players turn
_currentPlayer = getOpposingPlayer(_currentPlayer);
// If its now the AIs turn, place its optimal move
if (_currentPlayer.isAI()){
MiniMaxResult optimalMove = miniMax(_board, _currentPlayer);
_board.placeMove(optimalMove.getCell(), _currentPlayer);
if (!_board.isGameOver()){
_currentPlayer = getOpposingPlayer(_currentPlayer);
}
}
}
}
private Player getOpposingPlayer(Player player){
if (player == _player1) {
return _player2;
}
else {
return _player1;
}
}
private MiniMaxResult miniMax(GameBoard board, Player
currentPlayer){
if (board.isGameOver()){
int score = getBoardValue(board);
return new MiniMaxResult(score, CellType.NOCELL);
}
// If game is not over, determine the optimal move
return getOptimalMove(board, currentPlayer);
}
private MiniMaxResult getOptimalMove(GameBoard board,
Player currentPlayer){
HashMap<CellType, GameBoard> allPossibleMoves =
getAllPossibleMoves(board, currentPlayer);
HashMap<CellType, Integer> allPossibleMoveScores = new
HashMap<CellType, Integer>();
5

for (CellType move : allPossibleMoves.keySet()){


MiniMaxResult possibleMoveResult =
miniMax(allPossibleMoves.get(move),
getOpposingPlayer(currentPlayer));
allPossibleMoveScores.put(move,
possibleMoveResult.getScore());
}
// For the AI, we are trying to maximize our score
if (currentPlayer.isAI()){
int maxScore =
Collections.max(allPossibleMoveScores.values());
CellType optimalMove =
getAnyCellTypeWithScore(allPossibleMoveScores,
maxScore);
return new MiniMaxResult(maxScore, optimalMove);
}
// For the user, we are trying to minimize the score
else {
int minScore =
Collections.min(allPossibleMoveScores.values());
CellType optimalMove =
getAnyCellTypeWithScore(allPossibleMoveScores,
minScore);
return new MiniMaxResult(minScore, optimalMove);
}
}
private int getBoardValue(GameBoard board){
PlayerPiece aiPiece = getAIPiece();
if (board.isGameWon(aiPiece)){
return 1;
}
else if (board.isGameLost(aiPiece)){
return -1;
}
else {
return 0;
}
}
private PlayerPiece getAIPiece(){
if (_player1.isAI()){
return _player1.getPiece();
}
else if (_player2.isAI()){
return _player2.getPiece();
}
else {
return null;
}
}
private HashMap<CellType, GameBoard>
6

getAllPossibleMoves(GameBoard board, Player currentPlayer) {


HashMap<CellType, GameBoard> allPossibleMoves = new
HashMap<CellType, GameBoard>();
ArrayList<CellType> allEmptyCells =
board.getAllEmptyCells();
for (CellType cell : allEmptyCells){
GameBoard possibleMove = board.clone();
possibleMove.placeMove(cell, currentPlayer);
allPossibleMoves.put(cell, possibleMove);
}
return allPossibleMoves;
}
private CellType getAnyCellTypeWithScore(HashMap<CellType,
Integer> allPossibleMoveScores, int score){
ArrayList<CellType> optimalMoves = new
ArrayList<CellType>();
for (CellType cell : allPossibleMoveScores.keySet()){
if (allPossibleMoveScores.get(cell) == score){
optimalMoves.add(cell);
}
}
if (optimalMoves.size() > 0){
int randomIndex = (int) Math.random() *
optimalMoves.size();
return optimalMoves.get(randomIndex);
}
return null;
}
}

GameBoard.java
package com.kevinsmyth.tictactoe.models;
import java.util.ArrayList;
import java.util.HashMap;
public class GameBoard implements Cloneable {
// Global variable to store the actual board (a set of cells and piece types)
private HashMap<CellType, PlayerPiece> _board;
public GameBoard(){
_board = new HashMap<CellType, PlayerPiece>();
// Set all cells to empty
for (CellType cellType: CellType.values()){
if (cellType != CellType.NOCELL){
_board.put(cellType, PlayerPiece.EMPTY);
}
}
}
public GameBoard(HashMap<CellType, PlayerPiece> board){
7

_board = board;
}
public void placeMove(CellType cell, Player player){
_board.put(cell, player.getPiece());
}
public PlayerPiece getBoardPiece(CellType cell){
return _board.get(cell);
}
public boolean isBoardCellEmpty(CellType cell){
return getBoardPiece(cell) == PlayerPiece.EMPTY;
}
public boolean isGameOver(){
boolean _boardStateHasEmptySlots = false;
for (PlayerPiece piece : _board.values()){
if (piece == PlayerPiece.EMPTY){
_boardStateHasEmptySlots = true;
}
}
return !_boardStateHasEmptySlots ||
isGameWon(PlayerPiece.X) || isGameWon(PlayerPiece.O);
}
public boolean isGameLost(PlayerPiece piece){
switch (piece){
case X:
return isGameWon(PlayerPiece.O);
case O:
return isGameWon(PlayerPiece.X);
default:
return false;
}
}
public boolean isGameDraw(){
return isGameOver() && !isGameWon();
}
public boolean isGameWon(){
return isGameWon(PlayerPiece.X) ||
isGameWon(PlayerPiece.O);
}
public boolean isGameWon(PlayerPiece piece){
return isGameWonByHorizontal(piece) ||
isGameWonByVertical(piece) ||
isGameWonByDiagonal(piece);
}
private boolean isGameWonByHorizontal(PlayerPiece piece){
return isGameWonByTopHorizontal(piece) ||
isGameWonByMiddleHorizontal(piece) ||
isGameWonByBottomHorizontal(piece);
}
private boolean isGameWonByVertical(PlayerPiece piece){
8

return isGameWonByLeftVertical(piece) ||
isGameWonByMiddleVertical(piece) ||
isGameWonByRightVertical(piece);
}
private boolean isGameWonByDiagonal(PlayerPiece piece){
return isGameWonByTopLeftToBottomRightDiagonal(piece) ||
isGameWonByBottomLeftToTopRightDiagonal(piece);
}
private boolean isGameWonByTopHorizontal(PlayerPiece piece){
return _board.get(CellType.TOPLEFT) == piece &&
_board.get(CellType.TOPMIDDLE) == piece &&
_board.get(CellType.TOPRIGHT) == piece;
}
private boolean isGameWonByMiddleHorizontal(PlayerPiece piece)
{
return _board.get(CellType.MIDDLELEFT) == piece &&
_board.get(CellType.MIDDLE) == piece &&
_board.get(CellType.MIDDLERIGHT) == piece;
}
private boolean isGameWonByBottomHorizontal(PlayerPiece piece)
{
return _board.get(CellType.BOTTOMLEFT) == piece &&
_board.get(CellType.BOTTOMMIDDLE) == piece &&
_board.get(CellType.BOTTOMRIGHT) == piece;
}
private boolean isGameWonByLeftVertical(PlayerPiece piece){
return _board.get(CellType.TOPLEFT) == piece &&
_board.get(CellType.MIDDLELEFT) == piece &&
_board.get(CellType.BOTTOMLEFT) == piece;
}
private boolean isGameWonByMiddleVertical(PlayerPiece piece){
return _board.get(CellType.TOPMIDDLE) == piece &&
_board.get(CellType.MIDDLE) == piece &&
_board.get(CellType.BOTTOMMIDDLE) == piece;
}
private boolean isGameWonByRightVertical(PlayerPiece piece){
return _board.get(CellType.TOPRIGHT) == piece &&
_board.get(CellType.MIDDLERIGHT) == piece &&
_board.get(CellType.BOTTOMRIGHT) == piece;
}
private boolean
isGameWonByTopLeftToBottomRightDiagonal(PlayerPiece piece){
return _board.get(CellType.TOPLEFT) == piece &&
_board.get(CellType.MIDDLE) == piece &&
_board.get(CellType.BOTTOMRIGHT) == piece;
}
private boolean
isGameWonByBottomLeftToTopRightDiagonal(PlayerPiece piece){
return _board.get(CellType.TOPRIGHT) == piece &&
_board.get(CellType.MIDDLE) == piece &&
9

_board.get(CellType.BOTTOMLEFT) == piece;
}
public boolean isWinningCell(CellType cell){
for (PlayerPiece piece : PlayerPiece.values()) {
switch (cell){
case TOPLEFT:
if (isGameWonByTopHorizontal(piece) ||
isGameWonByLeftVertical(piece) ||\\
isGameWonByTopLeftToBottomRightDiagonal(piece)){
return true;
}
break;
case TOPMIDDLE:
if (isGameWonByTopHorizontal(piece) ||
isGameWonByMiddleVertical(piece)){
return true;
}
break;
case TOPRIGHT:
if (isGameWonByTopHorizontal(piece) ||
isGameWonByRightVertical(piece) ||
isGameWonByBottomLeftToTopRightDiagonal(piece)){
return true;
}
break;
case MIDDLELEFT:
if (isGameWonByMiddleHorizontal(piece) ||
isGameWonByLeftVertical(piece)){
return true;
}
break;
case MIDDLE:
if (isGameWonByMiddleHorizontal(piece) ||
isGameWonByMiddleVertical(piece) ||\\
isGameWonByTopLeftToBottomRightDiagonal(piece)||
isGameWonByBottomLeftToTopRightDiagonal(piece)){
return true;
}
break;
case MIDDLERIGHT:
if (isGameWonByMiddleHorizontal(piece) ||
isGameWonByRightVertical(piece)){
return true;
}
break;
case BOTTOMLEFT:
if (isGameWonByBottomHorizontal(piece)||
isGameWonByLeftVertical(piece) ||
isGameWonByBottomLeftToTopRightDiagonal(piece)){
return true;
10

}
break;
case BOTTOMMIDDLE:
if (isGameWonByBottomHorizontal(piece)||
isGameWonByMiddleVertical(piece)){
return true;
}
break;
case BOTTOMRIGHT:
if (isGameWonByBottomHorizontal(piece) ||
isGameWonByRightVertical(piece) ||
isGameWonByTopLeftToBottomRightDiagonal(piece)){
return true;
}
break;
}
}
return false;
}
public ArrayList<CellType> getAllEmptyCells(){
ArrayList<CellType> allEmptyCells = new
ArrayList<CellType>();
for (CellType cell : CellType.values()){
if (_board.get(cell) == PlayerPiece.EMPTY){
allEmptyCells.add(cell);
}
}
return allEmptyCells;
}
@SuppressWarnings("unchecked")
public GameBoard clone() {
return new GameBoard((HashMap<CellType,
PlayerPiece>)_board.clone());
}
}

Output

11

Plagiarism Score

12

Vous aimerez peut-être aussi