gpt4 book ai didi

Java: Tic-Tac-Toe - 如何避免用户输入重复的单元格?

转载 作者:行者123 更新时间:2023-11-30 10:38:03 25 4
gpt4 key购买 nike

如何防止用户输入相同的井字坐标?

用户输入是在游戏类的主要方法中获取的。

[x, y] 坐标范围为 (0-2) 的井字游戏单元格可以是:

0(_)、1(X) 或 2(O)

具有 alpha beta 搜索树修剪算法的网格类

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;
}
}

具有 main 方法的游戏类 - 接受用户输入

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();
}
}
}

最佳答案

我的答案是在您的 Grid.java 类中添加一个 boolean 检查方法,然后在您的 main 方法中 - 在 placeAMove() 方法之前调用此 boolean 检查方法。

例如,在您的 Grid.java 类中,添加以下方法:

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

这样,使用您预先存在的 0/1/2 值来跟踪空/X/O 空间值,您可以检查空间值是否为零。

这是在您的主要方法中使用它的一种方式,可以回答您的问题“如何防止用户输入相同的井字坐标?”

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;

通过这种方式,我将跳过您的主方法循环中剩余的循环代码,直到有一个有效的开放空间。 (如果有,则程序应继续检查获胜值或是否继续播放)

希望这能回答您的问题! :)

干杯

关于Java: Tic-Tac-Toe - 如何避免用户输入重复的单元格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39884705/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com