如何简化我的 Java 方法或将其更改为 DRY
How can I simplify my Java method or change it to be DRY
下面的代码按预期工作,但是我想简化该方法,因为它目前过于重复。我希望通过简化代码来开发一种增强 AI 的方法。我会让 AI 检查板上的模式并让它采取相应的行动。
public boolean checkWinner(){
//CHECK EVERY POSSIBLE WINNING OUTCOME and return true if you find one
//don't forget to check if the board is full (return true in that case)
if(gameboard[0] == gameboard[1] && gameboard[1] == gameboard[2] ||
gameboard[3] == gameboard[4] && gameboard[4] == gameboard[5] ||
gameboard[6] == gameboard[7] && gameboard[7] == gameboard[8] ||
gameboard[0] == gameboard[3] && gameboard[3] == gameboard[6] ||
gameboard[1] == gameboard[4] && gameboard[4] == gameboard[7] ||
gameboard[2] == gameboard[5] && gameboard[5] == gameboard[8] ||
gameboard[0] == gameboard[4] && gameboard[4] == gameboard[8] ||
gameboard[6] == gameboard[4] && gameboard[4] == gameboard[2] ){
bigWinner();
return true;
}
//loop through and look for tie
for(int x = 0; x< gameboard.length; x++){
if(gameboard[x] != 'O' && gameboard[x] != 'X'){
return false;
}
}
System.out.println("Tie Game.");
return true;
}
井字棋的完整代码class如下。游戏的 Main class 显示游戏菜单并创建新的 TicTacToe 游戏。
package pkg2baresb;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
/**
* This is the game logic for TicTacToe
* @author baresb
*/
public class TicTacToe {
//ENCAPUSLATED game variables. Super secret!
private char[] gameboard;
private boolean myTurn = true;
/**
* The TicTacToe's constructor
*/
public TicTacToe(){
//instantiate the previous declared value
gameboard = new char[9];
final int RADIX = 10;
//loop through game array and start each spot with a dash
for(int x = 0; x < gameboard.length; x++){
gameboard[x] = Character.forDigit(x, RADIX);
}
System.out.println("TICTACTOE ONLINE.");
//Loop until there's a winner
while(!checkWinner()){
printBoard();
yourTurn();
}
printBoard();
if(!checkWinner()) yourTurn();
else{
System.out.println("Game over.");
}
}
/**
*
* @return
*/
public boolean checkWinner(){
//CHECK EVERY POSSIBLE WINNING OUTCOME and return true if you find one
//don't forget to check if the board is full (return true in that case)
if(gameboard[0] == gameboard[1] && gameboard[1] == gameboard[2] ||
gameboard[3] == gameboard[4] && gameboard[4] == gameboard[5] ||
gameboard[6] == gameboard[7] && gameboard[7] == gameboard[8] ||
gameboard[0] == gameboard[3] && gameboard[3] == gameboard[6] ||
gameboard[1] == gameboard[4] && gameboard[4] == gameboard[7] ||
gameboard[2] == gameboard[5] && gameboard[5] == gameboard[8] ||
gameboard[0] == gameboard[4] && gameboard[4] == gameboard[8] ||
gameboard[6] == gameboard[4] && gameboard[4] == gameboard[2] ){
bigWinner();
return true;
}
//loop through and look for tie
for(int x = 0; x< gameboard.length; x++){
if(gameboard[x] != 'O' && gameboard[x] != 'X'){
return false;
}
}
System.out.println("Tie Game.");
return true;
}
/**
* Use a scanner and take an input from the user
*/
public void yourTurn(){
//instantiate a Scanner
Scanner s = new Scanner(System.in);
//take an input on the position the player would like
int selection;
while(true){
try{
System.out.print("What position would you like to play: ");
selection = s.nextInt();
if(gameboard[selection] != 'X' && gameboard[selection] != 'O'){
gameboard[selection] = 'X';
break;
}else{
System.out.println("That spot has already been taken");
}
}catch(Exception e){
System.out.println("Invalid selection. Please try again.");
}
}
if(!checkWinner()) {
this.myTurn = !myTurn;
//hands things over to the computer
computersTurn();
}
}
/**
* Announce who won using the myTurn boolean to remember whose turn it was
* last
*/
public void bigWinner(){
if(myTurn){
System.out.println("You won! Nice job!");
}else{
System.out.println("You have lost the game.");
}
}
/**
* Computer selects a random open slot and play its 'O'
*/
public void computersTurn(){
//OPTIONAL: MAKE THIS CODE SMARTER
System.out.println("Now it's the computer player's turn");
while(true){
//generate a random number between 0 - 8
int choice = ThreadLocalRandom.current().nextInt(0, 9);
//is the space free?
if(gameboard[choice] != 'X' && gameboard[choice] != 'O') {
//if so, set it equal to an 'O'
gameboard[choice] = 'O';
//bust out of this while loop
this.myTurn = !myTurn;
break;
}
} //closes while loop
} //closes computersTurn
public void printBoard(){
for(int x = 1; x <= gameboard.length; x++){
System.out.print(" | " + gameboard[x-1]);
if(x % 3 == 0) System.out.println(" |");
}
}
}
这对你来说可能还不够,但它总是一些东西,也许如果我以后有时间我会回来让它变得更好。这当然是 if's
你到达那里的一大块。
for(int i=0; i<=6; i=i+3){
if(gameboard[i]==gameboard[i+1] && gameboard[i+1]==gameboard[i+2])
return true;
}
for(int i=0; i<=2;i++){
if(gameboard[i]==gameboard[i+3] && gameboard[i+3] == gameboard[i+6])
return true;
}
if(gameboard[0] == gameboard[4] && gameboard[4] == gameboard[8] || gameboard[6] == gameboard[4] && gameboard[4] == gameboard[2] ){
return true;
}
减少代码重复。您可以创建一个将游戏板和矩阵作为参数的方法:
public boolean checkWin(int[] gameBoard, int[][] winPossibilities) {
}
winPossibilities
是您要检查的所有 rows/columns/diagonals。在你的情况下,它将是
final int[][] possibilities = {
{0, 1, 2},
{3, 4, 5},
{6, 7, 8},
{0, 3, 6},
{1, 4, 7},
{2, 5, 8},
{0, 4, 8},
{6, 4, 2},
};
在方法体中,你只需要一个像这样的简单算法:
for (int[] indices: winPossibilities) {
if (gameBoard[i[0]] == gameBoard[i[1]] && gameBoard[i[1]] == gameBoard[i[2]]) {
return true;
}
}
return false;
你可以这样调用这个方法:
if(checkWin(gameboard, possibilities)){
bigWinner();
return true;
}
//loop through and look for tie
for(int x = 0; x< gameboard.length; x++){
if(gameboard[x] != 'O' && gameboard[x] != 'X'){
return false;
}
}
System.out.println("Tie Game.");
return true;
这样做的好处之一是更加灵活。如果你想改变井字游戏的规则并决定你不能通过对角线获胜,只需删除 possibilities
矩阵的最后两项!
下面的代码按预期工作,但是我想简化该方法,因为它目前过于重复。我希望通过简化代码来开发一种增强 AI 的方法。我会让 AI 检查板上的模式并让它采取相应的行动。
public boolean checkWinner(){
//CHECK EVERY POSSIBLE WINNING OUTCOME and return true if you find one
//don't forget to check if the board is full (return true in that case)
if(gameboard[0] == gameboard[1] && gameboard[1] == gameboard[2] ||
gameboard[3] == gameboard[4] && gameboard[4] == gameboard[5] ||
gameboard[6] == gameboard[7] && gameboard[7] == gameboard[8] ||
gameboard[0] == gameboard[3] && gameboard[3] == gameboard[6] ||
gameboard[1] == gameboard[4] && gameboard[4] == gameboard[7] ||
gameboard[2] == gameboard[5] && gameboard[5] == gameboard[8] ||
gameboard[0] == gameboard[4] && gameboard[4] == gameboard[8] ||
gameboard[6] == gameboard[4] && gameboard[4] == gameboard[2] ){
bigWinner();
return true;
}
//loop through and look for tie
for(int x = 0; x< gameboard.length; x++){
if(gameboard[x] != 'O' && gameboard[x] != 'X'){
return false;
}
}
System.out.println("Tie Game.");
return true;
}
井字棋的完整代码class如下。游戏的 Main class 显示游戏菜单并创建新的 TicTacToe 游戏。
package pkg2baresb;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
/**
* This is the game logic for TicTacToe
* @author baresb
*/
public class TicTacToe {
//ENCAPUSLATED game variables. Super secret!
private char[] gameboard;
private boolean myTurn = true;
/**
* The TicTacToe's constructor
*/
public TicTacToe(){
//instantiate the previous declared value
gameboard = new char[9];
final int RADIX = 10;
//loop through game array and start each spot with a dash
for(int x = 0; x < gameboard.length; x++){
gameboard[x] = Character.forDigit(x, RADIX);
}
System.out.println("TICTACTOE ONLINE.");
//Loop until there's a winner
while(!checkWinner()){
printBoard();
yourTurn();
}
printBoard();
if(!checkWinner()) yourTurn();
else{
System.out.println("Game over.");
}
}
/**
*
* @return
*/
public boolean checkWinner(){
//CHECK EVERY POSSIBLE WINNING OUTCOME and return true if you find one
//don't forget to check if the board is full (return true in that case)
if(gameboard[0] == gameboard[1] && gameboard[1] == gameboard[2] ||
gameboard[3] == gameboard[4] && gameboard[4] == gameboard[5] ||
gameboard[6] == gameboard[7] && gameboard[7] == gameboard[8] ||
gameboard[0] == gameboard[3] && gameboard[3] == gameboard[6] ||
gameboard[1] == gameboard[4] && gameboard[4] == gameboard[7] ||
gameboard[2] == gameboard[5] && gameboard[5] == gameboard[8] ||
gameboard[0] == gameboard[4] && gameboard[4] == gameboard[8] ||
gameboard[6] == gameboard[4] && gameboard[4] == gameboard[2] ){
bigWinner();
return true;
}
//loop through and look for tie
for(int x = 0; x< gameboard.length; x++){
if(gameboard[x] != 'O' && gameboard[x] != 'X'){
return false;
}
}
System.out.println("Tie Game.");
return true;
}
/**
* Use a scanner and take an input from the user
*/
public void yourTurn(){
//instantiate a Scanner
Scanner s = new Scanner(System.in);
//take an input on the position the player would like
int selection;
while(true){
try{
System.out.print("What position would you like to play: ");
selection = s.nextInt();
if(gameboard[selection] != 'X' && gameboard[selection] != 'O'){
gameboard[selection] = 'X';
break;
}else{
System.out.println("That spot has already been taken");
}
}catch(Exception e){
System.out.println("Invalid selection. Please try again.");
}
}
if(!checkWinner()) {
this.myTurn = !myTurn;
//hands things over to the computer
computersTurn();
}
}
/**
* Announce who won using the myTurn boolean to remember whose turn it was
* last
*/
public void bigWinner(){
if(myTurn){
System.out.println("You won! Nice job!");
}else{
System.out.println("You have lost the game.");
}
}
/**
* Computer selects a random open slot and play its 'O'
*/
public void computersTurn(){
//OPTIONAL: MAKE THIS CODE SMARTER
System.out.println("Now it's the computer player's turn");
while(true){
//generate a random number between 0 - 8
int choice = ThreadLocalRandom.current().nextInt(0, 9);
//is the space free?
if(gameboard[choice] != 'X' && gameboard[choice] != 'O') {
//if so, set it equal to an 'O'
gameboard[choice] = 'O';
//bust out of this while loop
this.myTurn = !myTurn;
break;
}
} //closes while loop
} //closes computersTurn
public void printBoard(){
for(int x = 1; x <= gameboard.length; x++){
System.out.print(" | " + gameboard[x-1]);
if(x % 3 == 0) System.out.println(" |");
}
}
}
这对你来说可能还不够,但它总是一些东西,也许如果我以后有时间我会回来让它变得更好。这当然是 if's
你到达那里的一大块。
for(int i=0; i<=6; i=i+3){
if(gameboard[i]==gameboard[i+1] && gameboard[i+1]==gameboard[i+2])
return true;
}
for(int i=0; i<=2;i++){
if(gameboard[i]==gameboard[i+3] && gameboard[i+3] == gameboard[i+6])
return true;
}
if(gameboard[0] == gameboard[4] && gameboard[4] == gameboard[8] || gameboard[6] == gameboard[4] && gameboard[4] == gameboard[2] ){
return true;
}
减少代码重复。您可以创建一个将游戏板和矩阵作为参数的方法:
public boolean checkWin(int[] gameBoard, int[][] winPossibilities) {
}
winPossibilities
是您要检查的所有 rows/columns/diagonals。在你的情况下,它将是
final int[][] possibilities = {
{0, 1, 2},
{3, 4, 5},
{6, 7, 8},
{0, 3, 6},
{1, 4, 7},
{2, 5, 8},
{0, 4, 8},
{6, 4, 2},
};
在方法体中,你只需要一个像这样的简单算法:
for (int[] indices: winPossibilities) {
if (gameBoard[i[0]] == gameBoard[i[1]] && gameBoard[i[1]] == gameBoard[i[2]]) {
return true;
}
}
return false;
你可以这样调用这个方法:
if(checkWin(gameboard, possibilities)){
bigWinner();
return true;
}
//loop through and look for tie
for(int x = 0; x< gameboard.length; x++){
if(gameboard[x] != 'O' && gameboard[x] != 'X'){
return false;
}
}
System.out.println("Tie Game.");
return true;
这样做的好处之一是更加灵活。如果你想改变井字游戏的规则并决定你不能通过对角线获胜,只需删除 possibilities
矩阵的最后两项!