2016-10-05 11 views
2

사용자가 동일한 tic tac toe 좌표를 입력하지 못하게하려면 어떻게해야합니까?Java : Tic-Tac-Toe - 반복 된 셀을 사용자가 입력하지 못하도록하려면?

사용자 입력은 게임 클래스의 기본 메소드에서 가져옵니다. 함께

콩알 발가락 세포 [X, y]는 좌표 (0-2) 범위 일 수있다 :

0 (_), 1 (X) 2 (O)

그리드 알파 베타 탐색 트리 가지 치기 알고리즘의 주요 방법

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 클래스에서, 다음과 같은 방법을 추가 값이 0이면 공간 값이 0인지 아닌지 확인하기 위해 검사를 제공 할 수 있습니다.

이것은 '사용자가 입력 한 것과 같은 tic tac toe 좌표를 어떻게 방지합니까?'라는 질문에 대한 기본 방법으로 사용하는 한 가지 방법입니다.

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

감사합니다 닉 - 작동합니다! :디 – Tai