Presentation of game states in Tic Tac Toe

The goal of the assignment I'm currently working on for my Data Structures class is to create a quantum Tic Tac Toe with AI that plays to win.

I'm currently having trouble finding the most efficient way to represent states.

Overview of the current structure:

Abstract game

  • Owned and managed by AbstractPlayers (game.nextPlayer () returns the next player by identifier int)
  • Has and enforces AbstractBoard at the start of the game.
  • Has a GameTree (completed if called in initialization, incomplete otherwise)

Abstractboard

  • Has a state, size and parental game.
  • Mediates between Player and State (Converts states from row sets to Point view
  • Is StateConsumer

AbstractPlayer

  • ConcreteEvaluationStrategy

StateTransveralPool

  • " ".
  • HashMap, Set nextStates "3-"

  • 3 - X-, O-
  • . Integer StateTransversalPool

SO, ​​ 000-111, 0 , 1 - .

, TTT:

From the Set<Integer> board perspective:
X_X  R1 might be: 101
OO_  R2 might be: 110
X_X  R3 might be: 101, where 1 is an open space, and 0 is a closed space

From the Set<Integer> xMoves perspective:
X_X  R1 might be: 101
OO_  R2 might be: 000
X_X  R3 might be: 101, where 1 is an X and 0 is not

From the Set<Integer> oMoves perspective:
X_X  R1 might be: 000
OO_  R2 might be: 110
X_X  R3 might be: 000, where 1 is an O and 0 is not

, x {R1, R2, R3} o {R1, R2, R3} = > {R1, R2, R3}

GameTree. Max (x) {R1, R2, R3}, R1, R2 R3 ..

Set<Integer> R1nextStates = StateTransversalPool.get(R1); 

, R1 R2.

, Set, ? ? , Point ↔ . , ?

!

ConcretePlayer. , , StateProducer (, , StateFactory StateBuilder).

public class ConcretePlayerGeneric extends AbstractPlayer {

 @Override
 public BinaryState makeMove() {
  // Given a move and the current state, produce a new state
  Point playerMove = super.strategy.evaluate(this);
  BinaryState currentState = super.getInGame().getBoard().getState();


  return StateProducer.getState(this, playerMove, currentState);
 }
}

EDIT: TTT Quantum TTT. , , Concrete .

+3
2

:

  • , , +1 == O, -1 == X 0 . , , , +3 -3.
  • -, "" 2D 3x3 , [0-2] , [3-5] , [6-8] .
  • , .

, " " , , . , . ...

$ java Board
Creating board:

---
---
---

Initialising board:

-OX
O--
XO-
Terminal state: false


Generating next move states:

XOX
O--
XO-

-OX
OX-
XO-

-OX
O-X
XO-

-OX
O--
XOX

import java.util.List;
import java.util.LinkedList;
import java.util.Random;

public class Board {
    private final int[] squares;

    public Board() {
    this.squares = new int[9];
    }

    protected Board(int[] squares) {
    this.squares = squares;
    }

    public void init() {
    Random rnd = new Random();
    int turn = 1; // 'O' always goes first.

        for (int i=0; i<squares.length; ++i) {
        double d = rnd.nextDouble();

        if (d < 0.75) {
        squares[i] = turn;
        turn = turn == 1 ? -1 : 1; // Flip to other player turn.
        } else {
        squares[i] = 0; // Empty square.
        }

        if (isTerminalState()) {
        break;
        }
    }
    }

    public boolean isTerminalState() {
    boolean ret = false;

    boolean foundEmpty = false;
    int hSum = 0;
    int[] vSum = new int[3];

    for (int i=0; i<squares.length; ++i) {
        hSum += squares[i];

        if (isWinningRow(hSum)) {
        ret = true;
        break;
        } else if (i == 2 || i == 5) {
        hSum = 0;
        }

        int col = i % 3;
        vSum[col] += squares[i];

        if (isWinningRow(vSum[col])) {
        ret = true;
        break;
        }

        if (squares[i] == 0) {
        foundEmpty = true;
        }
    }

    if (!ret) {
        if (!foundEmpty) {
        ret = true;
        } else {
        int diag1 = 0;
        int diag2 = 0;
        int rowSz = (int)Math.sqrt(squares.length);

        for (int i=0; i<squares.length; ++i) {
            if (i % (rowSz + 1) == 0) {
            diag1 += squares[i];

            if (isWinningRow(diag1)) {
                ret = true;
                break;
            }
            }

            if (i > 0 && i % (rowSz - 1) == 0) {
            diag2 += squares[i];

            if (isWinningRow(diag2)) {
                ret = true;
                break;
            }
            }
        }
        }
    }

    return ret;
    }

    private boolean isWinningRow(int rowSum) {
    return rowSum == 3 || rowSum == -3;
    }

    public List<Board> getNextStates() {
    List<Board> ret = new LinkedList<Board>();

    int tmp = 0;
    for (int i=0; i<squares.length; ++i) {
        tmp += squares[i];
    }

    // Next turn is 'O' (i.e. +1) if the board sums to 0.
    // Otherwise it 'X turn.
    int turn = tmp == 0 ? 1 : -1;

    if (!isTerminalState()) {
        for (int i=0; i<squares.length; ++i) {
        if (squares[i] == 0) { // Empty square          
            int[] squaresA = new int[squares.length];
            System.arraycopy(squares, 0, squaresA, 0, squares.length);
            squaresA[i] = turn;
            ret.add(new Board(squaresA));
        }
        }
    }

    return ret;
    }

    public String toString() {
    StringBuilder sb = new StringBuilder();

    for (int i=0; i<squares.length; ++i) {
        if (squares[i] == 1) {
        sb.append('O');
        } else if (squares[i] == -1) {
        sb.append('X');
        } else {
        assert squares[i] == 0;
        sb.append('-');
        }

        if (i == 2 || i == 5) {
        sb.append('\n');
        }
    }

    return sb.toString();
    }

    public static void main(String[] args) {
    System.err.println("Creating board:\n");
    Board bd = new Board();
    System.err.println(bd);

    System.err.println("\nInitialising board:\n");
    bd.init();
    System.err.println(bd);
    System.err.println("Terminal state: " + bd.isTerminalState() + '\n');

    System.err.println("\nGenerating next move states:\n");
    List<Board> nextStates = bd.getNextStates();

    for (Board bd1 : nextStates) {
        System.err.println(bd1.toString() + '\n');
    }
    }
}
+3

(, X, O)?

, 2 . , .

, :

GameTree

GameTree? " "?

0

Source: https://habr.com/ru/post/1723286/


All Articles