2016-10-05 4 views
2

どのようにして、ユーザーが入力したのと同じチックタックトゥ座標を防ぐことができますか?Java:Tic-Tac-Toe - 反復されたセルをユーザーが入力するのを避けるには?

ユーザー入力は、ゲームクラスのメインメソッドで取得されます。

チックタックトー細胞[X、Y]の座標(0-2)の範囲のいずれかであり得る:

0(_)、1(X)または2(O)

グリッドアルファベータ探索木の枝刈りアルゴリズムmainメソッドを持つ

import java.util.ArrayList; 
import java.util.List; 
import java.util.Scanner; 

class Grid { 

    List<Cell> availableCells; 
    int[][] board = new int[3][3]; 
    Scanner scan = new Scanner(System.in); 
    // Set limit to search tree depth 
    int treeDepth = 9; 

    List<CellsAndScores> rootsChildrenScore = new ArrayList<>(); 

    public int score() { 
    int score = 0; 

    // Check all columns 
    for (int j = 0; j < 3; ++j) { 
     int X = 0; 
     int O = 0; 
     for (int i = 0; i < 3; ++i) { 
     if (board[i][j] == 0) { 
     } else if (board[i][j] == 1) { 
      X++; 
     } else { 
      O++; 
     } 
     } 
     score += changeInScore(X, O); 
    } 

    // Check all rows 
    for (int i = 0; i < 3; ++i) { 
     int X = 0; 
     int O = 0; 
     for (int j = 0; j < 3; ++j) { 
     if (board[i][j] == 0) { 
     } else if (board[i][j] == 1) { 
      X++; 
     } else { 
      O++; 
     } 
     } 
     score += changeInScore(X, O); 
    } 

    int X = 0; 
    int O = 0; 

    // Check diagonal (first) 
    for (int i = 0, j = 0; i < 3; ++i, ++j) { 
     if (board[i][j] == 1) { 
     X++; 
     } else if (board[i][j] == 2) { 
     O++; 
     } else { 
     } 
    } 

    score += changeInScore(X, O); 

    X = 0; 
    O = 0; 

    // Check Diagonal (Second) 
    for (int i = 2, j = 0; i > -1; --i, ++j) { 
     if (board[i][j] == 1) { 
     X++; 
     } else if (board[i][j] == 2) { 
     O++; 
     } else { 
     } 
    } 

    score += changeInScore(X, O); 

    return score; 
    } 

    private int changeInScore(int X, int O) { 
    int change; 
    if (X == 3) { 
     change = 100; 
    } else if (X == 2 && O == 0) { 
     change = 10; 
    } else if (X == 1 && O == 0) { 
     change = 1; 
    } else if (O == 3) { 
     change = -100; 
    } else if (O == 2 && X == 0) { 
     change = -10; 
    } else if (O == 1 && X == 0) { 
     change = -1; 
    } else { 
     change = 0; 
    } 
    return change; 
    } 

    public int alphaBetaMinimax(int alpha, int beta, int depth, int turn) { 

    if (beta <= alpha) { 
     System.out.println("Pruning at tree depth = " + depth + " alpha: " + alpha + " beta: " + beta); 
     if (turn == 1) 
     return Integer.MAX_VALUE; 
     else 
     return Integer.MIN_VALUE; 
    } 

    if (depth == treeDepth || gameOver()) { 
     return score(); 
    } 

    List<Cell> cellsAvailable = getAvailableStates(); 

    if (cellsAvailable.isEmpty()) { 
     return 0; 
    } 

    if (depth == 0) { 
     rootsChildrenScore.clear(); 
    } 

    int maxValue = Integer.MIN_VALUE, minValue = Integer.MAX_VALUE; 

    for (int i = 0; i < cellsAvailable.size(); ++i) { 
     Cell cell = cellsAvailable.get(i); 

     int currentScore = 0; 

     if (turn == 1) { 
     placeAMove(cell, 1); 
     currentScore = alphaBetaMinimax(alpha, beta, depth + 1, 2); 
     maxValue = Math.max(maxValue, currentScore); 

     // Set alpha 
     alpha = Math.max(currentScore, alpha); 

     if (depth == 0) { 
      rootsChildrenScore.add(new CellsAndScores(currentScore, cell)); 
     } 
     } else if (turn == 2) { 
     placeAMove(cell, 2); 
     currentScore = alphaBetaMinimax(alpha, beta, depth + 1, 1); 
     minValue = Math.min(minValue, currentScore); 

     // Set beta 
     beta = Math.min(currentScore, beta); 
     } 
     // reset board 
     board[cell.x][cell.y] = 0; 

     // Do not evaluate the rest of the branches after search tree is pruned 
     if (currentScore == Integer.MAX_VALUE || currentScore == Integer.MIN_VALUE) 
     break; 
    } 
    return turn == 1 ? maxValue : minValue; 
    } 

    public boolean gameOver() { 
    // Game is over is someone has won, or board is full (draw) 
    return (hasXWon() || hasOWon() || getAvailableStates().isEmpty()); 
    } 

    public boolean hasXWon() { 
    if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == 1) 
     || (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] == 1)) { 
     // System.out.println("X Diagonal Win"); 
     return true; 
    } 
    for (int i = 0; i < 3; ++i) { 
     if (((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 1) 
      || (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 1))) { 
     // System.out.println("X Row or Column win"); 
     return true; 
     } 
    } 
    return false; 
    } 

    public boolean hasOWon() { 
    if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == 2) 
     || (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] == 2)) { 
     // System.out.println("O Diagonal Win"); 
     return true; 
    } 
    for (int i = 0; i < 3; ++i) { 
     if ((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 2) 
      || (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 2)) { 
     // System.out.println("O Row or Column win"); 
     return true; 
     } 
    } 

    return false; 
    } 

    public List<Cell> getAvailableStates() { 
    availableCells = new ArrayList<>(); 
    for (int i = 0; i < 3; ++i) { 
     for (int j = 0; j < 3; ++j) { 
     if (board[i][j] == 0) { 
      availableCells.add(new Cell(i, j)); 
     } 
     } 
    } 
    return availableCells; 
    } 

    public void placeAMove(Cell Cell, int player) { 
    board[Cell.x][Cell.y] = player; // player = 1 for X, 2 for O 
    } 

    public Cell returnBestMove() { 
    int MAX = -100000; 
    int best = -1; 

    for (int i = 0; i < rootsChildrenScore.size(); ++i) { 
     if (MAX < rootsChildrenScore.get(i).score) { 
     MAX = rootsChildrenScore.get(i).score; 
     best = i; 
     } 
    } 

    return rootsChildrenScore.get(best).cell; 
    } 

    public void displayBoard() { 
    System.out.println(); 
    for (int i = 0; i < 3; ++i) { 
     for (int j = 0; j < 3; ++j) { 
     if (board[i][j] == 0) 
      System.out.print("_" + " "); 
     if (board[i][j] == 1) 
      System.out.print("X" + " "); 
     if (board[i][j] == 2) 
      System.out.print("O" + " "); 
     } 
     System.out.println(""); 
    } 
    System.out.println(); 
    } 

    public void resetGrid() { 
    for (int i = 0; i < 3; ++i) { 
     for (int j = 0; j < 3; ++j) { 
     board[i][j] = 0; 
     } 
    } 
    } 
} 

セルクラス

class Cell { 

    int x, y; 

    public Cell(int x, int y) { 
    this.x = x; 
    this.y = y; 
    } 

    public String toString() { 
    return "[" + x + ", " + y + "]"; 
    } 
} 

class CellsAndScores { 

    int score; 
    Cell cell; 

    CellsAndScores(int score, Cell cell) { 
    this.score = score; 
    this.cell = cell; 
    } 
} 

ゲームクラスを持つクラスは - 取りますユーザー入力

import java.util.Random; 

public class Game { 

    public static void main(String[] args) { 
    Grid grid = new Grid(); 
    Random random = new Random(); 

    grid.displayBoard(); 

    System.out.print("Who moves first? [1]Computer(X) [2]User(O): "); 
    int turn = grid.scan.nextInt(); 
    if (turn == 1) { 
     Cell p = new Cell(random.nextInt(3), random.nextInt(3)); 
     grid.placeAMove(p, 1); 
     grid.displayBoard(); 
    } 

    while (!grid.gameOver()) { 
     int x = 0, y = 0; 

     System.out.print("Please enter an x coordinate [0-2]: "); 
     x = grid.scan.nextInt(); 
     System.out.print("Please enter an y coordinate [0-2]: "); 
     y = grid.scan.nextInt(); 

     Cell userMove = new Cell(y, x); 

     grid.placeAMove(userMove, 2); // 2 for O and O is the user 
     grid.displayBoard(); 
     if (grid.gameOver()) 
     break; 

     grid.alphaBetaMinimax(Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 1); 
     for (CellsAndScores pas : grid.rootsChildrenScore) 
     System.out.println("Cell: " + pas.cell + " Score: " + pas.score); 

     grid.placeAMove(grid.returnBestMove(), 1); 
     grid.displayBoard(); 
    } 
    if (grid.hasXWon()) { 
     System.out.println("Unfortunately, you lost!"); 
     grid.resetGrid(); 
    } else if (grid.hasOWon()) { 
     System.out.println("You win!"); 
     grid.resetGrid(); 
    } else { 
     System.out.println("It's a draw!"); 
     grid.resetGrid(); 
    } 
    } 
} 
+0

あなたのボードは配列の 'int'配列です。プレイヤーが入力した値があるかどうかを確認してください。たとえば、スペースが開いているかどうかを知るために、空のスペースをすべて値に設定します。さらに、セルの値が「空の」値でないかどうかをチェックして、セルがすでに占有されているかどうかを判別できます。 – Charles

+0

また、あなたは、クラス 'Cell'を使って過度に複雑なことをしています。あなたは確かにそれなしで行うことができます。 – Charles

答えて

1

私の答えはあなたのGrid.javaクラスにブール値のチェック方法を追加し、あなたの主な方法にすることです - placeAMove()メソッドの前に、このブールチェックメソッドを呼び出します。空/ X/Oスペースを追跡するあなたの既存の0/1/2の値を使用して、

/* 
* Return true if space is ok to use. 
*/ 
public boolean isMoveOK(Cell cell) { 
    return board[cell.x][cell.y] == 0; 
} 

この方法:

はたとえば、あなたGrid.javaクラスで、次のメソッドを追加します値がゼロであるかどうかをチェックすることができます。

これは、メインの方法で使用する方法の1つで、「ユーザーが入力したのと同じチックタックの座標をどうして防止するのですか?

Cell userMove = new Cell(y, x); 

if (grid.isMoveOK(userMove)) { 
    grid.placeAMove(userMove, 2); // 2 for O and O is the user 
} else { 
    System.out.println("Please try a different space/cell"); 
    continue; 
} 

grid.displayBoard(); 
if (grid.gameOver()) 
    break; 

このように、有効な空きスペースがあるまで、メインループの残りのループコードをスキップしています。 (ある場合は、プログラムは勝ちの値を確認するか、再生を続けるかどうかを調べる必要があります)

これはあなたの質問にお答えします。 :)

乾杯

+0

ありがとうニック - それは動作します! :D – Tai

関連する問題