失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Java用最少代码实现五子棋-玩家对战模式-人机对战模式-电脑策略对战

Java用最少代码实现五子棋-玩家对战模式-人机对战模式-电脑策略对战

时间:2019-11-26 17:10:53

相关推荐

Java用最少代码实现五子棋-玩家对战模式-人机对战模式-电脑策略对战

Java用最少代码实现五子棋-玩家对战模式-人机对战模式-电脑策略对战

玩家对战模式背景说明代码实现 人机对战模式背景说明完整代码实现 电脑根据优势分数对战背景说明完整代码实现 小结

玩家对战模式

背景说明

程序初始化一个15x15的棋盘,并允许两个玩家轮流在棋盘上放置棋子。第一个在横向纵向或对角线上连成五个子的玩家获胜。

代码实现

import java.util.Scanner;/*** @author bxa* 五子棋游戏V1*/public class FiveInARow1 {public static void main(String[] args) {FiveInARow game = new FiveInARow();game.start();}private static final int BOARD_SIZE = 15;private static final char EMPTY = ' ';private static final char BLACK = 'X';private static final char WHITE = 'O';private char[][] board = new char[BOARD_SIZE][BOARD_SIZE];private boolean blackTurn = true;public void start() {// 初始化棋盘for (int i = 0; i < BOARD_SIZE; i++) {for (int j = 0; j < BOARD_SIZE; j++) {board[i][j] = EMPTY;}}// 游戏循环while (true) {printBoard();if (checkWin()) {System.out.println(blackTurn ? "黑方胜利!" : "白方胜利!");break;}// 提示当前轮到哪个玩家System.out.println(blackTurn ? "黑方落子:" : "白方落子:");// 玩家输入落子位置Scanner scanner = new Scanner(System.in);int x = scanner.nextInt();int y = scanner.nextInt();// 判断落子是否合法if (!isValidMove(x, y)) {System.out.println("该位置已有落子,请重新选择!");continue;}// 在棋盘上落子board[x][y] = blackTurn ? BLACK : WHITE;// 切换玩家blackTurn = !blackTurn;}}/*** 打印当前棋盘状态*/private void printBoard() {System.out.print(" ");for (int i = 0; i < BOARD_SIZE; i++) {System.out.print(" " + i);}System.out.println();for (int i = 0; i < BOARD_SIZE; i++) {System.out.print(i + " ");for (int j = 0; j < BOARD_SIZE; j++) {System.out.print(board[i][j] + " ");}System.out.println();}}/*** 检查是否胜利* @return 是否胜利*/private boolean checkWin() {// 检查每一行for (int i = 0; i < BOARD_SIZE; i++) {int count = 0;for (int j = 0; j < BOARD_SIZE; j++) {count = board[i][j] == (blackTurn ? BLACK : WHITE) ? count + 1 : 0;if (count >= 5) {return true;}}}// 检查每一列for (int i = 0; i < BOARD_SIZE; i++) {int count = 0;for (int j = 0; j < BOARD_SIZE; j++) {count = board[j][i] == (blackTurn ? BLACK : WHITE) ? count + 1 : 0;if (count >= 5) {return true;}}}// 检查主对角线for (int i = 0; i <= BOARD_SIZE - 5; i++) {for (int j = 0; j <= BOARD_SIZE - 5; j++) {boolean win = true;for (int k = 0; k < 5; k++) {if (board[i + k][j + k] != (blackTurn ? BLACK : WHITE)) {win = false;break;}}if (win) {return true;}}}// 检查副对角线for (int i = 0; i <= BOARD_SIZE - 5; i++) {for (int j = BOARD_SIZE - 1; j >= 4; j--) {boolean win = true;for (int k = 0; k < 5; k++) {if (board[i + k][j - k] != (blackTurn ? BLACK : WHITE)) {win = false;break;}}if (win) {return true;}}}// 没有胜利状态return false;}/*** 判断落子是否合法* @param x 横坐标* @param y 纵坐标* @return 落子是否合法*/private boolean isValidMove(int x, int y) {if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE) {return false;}return board[x][y] == EMPTY;}}

人机对战模式

背景说明

程序初始化一个15x15的棋盘,第一个在横向纵向或对角线上连成五个子的玩家获胜。

在上一个基础上新增白棋随机落子支持一个玩家也能参与游戏的机会。

新增代码方法:

// 实现白棋随机落子Random random = new Random();int x = random.nextInt(BOARD_SIZE);int y = random.nextInt(BOARD_SIZE);if (!isValidMove(x, y)) {continue;}board[x][y] = WHITE;

完整代码实现

import java.util.Random;import java.util.Scanner;/*** @author bxa* 五子棋游戏V2*/public class FiveInARow2 {public static void main(String[] args) {FiveInARow2 game = new FiveInARow2();game.start();}private static final int BOARD_SIZE = 15;private static final char EMPTY = ' ';private static final char BLACK = 'X';private static final char WHITE = 'O';private char[][] board = new char[BOARD_SIZE][BOARD_SIZE];private boolean blackTurn = true;public void start() {// 初始化棋盘for (int i = 0; i < BOARD_SIZE; i++) {for (int j = 0; j < BOARD_SIZE; j++) {board[i][j] = EMPTY;}}// 游戏循环while (true) {printBoard();if (checkWin()) {System.out.println(blackTurn ? "黑方胜利!" : "白方胜利!");break;}// 提示当前轮到哪个玩家if (blackTurn) {System.out.println("黑方落子:");Scanner scanner = new Scanner(System.in);int x = scanner.nextInt();int y = scanner.nextInt();if (!isValidMove(x, y)) {System.out.println("该位置已有落子,请重新选择!");continue;}board[x][y] = BLACK;} else {System.out.println("白方落子:");Random random = new Random();int x = random.nextInt(BOARD_SIZE);int y = random.nextInt(BOARD_SIZE);if (!isValidMove(x, y)) {continue;}board[x][y] = WHITE;}// 切换玩家blackTurn = !blackTurn;}}/*** 打印当前棋盘状态*/private void printBoard() {System.out.print(" ");for (int i = 0; i < BOARD_SIZE; i++) {System.out.print(" " + i);}System.out.println();for (int i = 0; i < BOARD_SIZE; i++) {System.out.print(i + " ");for (int j = 0; j < BOARD_SIZE; j++) {System.out.print(board[i][j] + " ");}System.out.println();}}/*** 检查是否胜利** @return 是否胜利*/private boolean checkWin() {// 检查每一行for (int i = 0; i < BOARD_SIZE; i++) {int count = 0;for (int j = 0; j < BOARD_SIZE; j++) {count = board[i][j] == (blackTurn ? BLACK : WHITE) ? count + 1 : 0;if (count >= 5) {return true;}}}// 检查每一列for (int i = 0; i < BOARD_SIZE; i++) {int count = 0;for (int j = 0; j < BOARD_SIZE; j++) {count = board[j][i] == (blackTurn ? BLACK : WHITE) ? count + 1 : 0;if (count >= 5) {return true;}}}// 检查主对角线for (int i = 0; i <= BOARD_SIZE - 5; i++) {for (int j = 0; j <= BOARD_SIZE - 5; j++) {boolean win = true;for (int k = 0; k < 5; k++) {if (board[i + k][j + k] != (blackTurn ? BLACK : WHITE)) {win = false;break;}}if (win) {return true;}}}// 检查副对角线for (int i = 0; i <= BOARD_SIZE - 5; i++) {for (int j = BOARD_SIZE - 1; j >= 4; j--) {boolean win = true;for (int k = 0; k < 5; k++) {if (board[i + k][j - k] != (blackTurn ? BLACK : WHITE)) {win = false;break;}}if (win) {return true;}}}// 没有胜利状态return false;}/*** 判断落子是否合法** @param x 横坐标* @param y 纵坐标* @return 落子是否合法*/private boolean isValidMove(int x, int y) {if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE) {return false;}return board[x][y] == EMPTY;}}

电脑根据优势分数对战

背景说明

在原有程序落子的判断与胜利的判断基础上新增策略下棋的实现。下棋策略的实现是通过计算每个位置的分数,选择分数最高的位置进行落子。后期可以让策略在实现上进行优化,比如可以加入一些AI学习机制等。

关键实现代码:

// 根据策略下棋的方法实现/*** 根据分数落子* @param board 棋盘* @param player 玩家* @return 落子位置*/private int[] scoreStrategy(char[][] board, char player) {int[] move = new int[2];int maxScore = -1;for (int i = 0; i < BOARD_SIZE; i++) {for (int j = 0; j < BOARD_SIZE; j++) {if (board[i][j] == EMPTY) {int score = calculateScore(board, i, j, player);if (score > maxScore) {maxScore = score;move[0] = i;move[1] = j;}}}}return move;}/*** 计算落子位置的分数* @param board 棋盘* @param x 横坐标* @param y 纵坐标* @param player 玩家* @return 落子位置的分数*/private int calculateScore(char[][] board, int x, int y, char player) {int score = 0;// 计算横向分数for (int i = Math.max(0, x - 4); i <= Math.min(BOARD_SIZE - 1, x + 4); i++) {if (board[i][y] == player) {score++;}}// 计算纵向分数for (int i = Math.max(0, y - 4); i <= Math.min(BOARD_SIZE - 1, y + 4); i++) {if (board[x][i] == player) {score++;}}// 计算主对角线分数for (int i = Math.max(x - 4, 0), j = Math.max(y - 4, 0); i <= Math.min(x + 4, BOARD_SIZE - 1) && j <= Math.min(y + 4, BOARD_SIZE - 1); i++, j++) {if (board[i][j] == player) {score++;}}// 计算副对角线分数for (int i = Math.min(x + 4, BOARD_SIZE - 1), j = Math.max(y - 4, 0); i >= Math.max(x - 4, 0) && j <= Math.min(y + 4, BOARD_SIZE - 1); i--, j++) {if (board[i][j] == player) {score++;}}if (player == BLACK) {score += x * 0.1;} else {score += (BOARD_SIZE - x) * 0.1;}return score;}

完整代码实现

import java.util.Scanner;import java.util.Random;/*** @author bxa* 五子棋游戏V3*/public class FiveInARow3 {public static void main(String[] args) {FiveInARow3 game = new FiveInARow3();game.start();}private static final int BOARD_SIZE = 15;private static final char EMPTY = ' ';private static final char BLACK = 'X';private static final char WHITE = 'O';private char[][] board = new char[BOARD_SIZE][BOARD_SIZE];private boolean blackTurn = true;public void start() {// 初始化棋盘for (int i = 0; i < BOARD_SIZE; i++) {for (int j = 0; j < BOARD_SIZE; j++) {board[i][j] = EMPTY;}}// 游戏循环while (true) {printBoard();if (checkWin()) {System.out.println(blackTurn ? "黑方胜利!" : "白方胜利!");break;}// 提示当前轮到哪个玩家if (blackTurn) {// 根据分数落子int[] scoreMove = scoreStrategy(board, BLACK);int x = scoreMove[0];int y = scoreMove[1];if (!isValidMove(x, y)) {// 根据分数落子scoreMove = scoreStrategy(board, BLACK);x = scoreMove[0];y = scoreMove[1];}board[x][y] = BLACK;} else {System.out.println("白方落子:");Scanner scanner = new Scanner(System.in);int x = scanner.nextInt();int y = scanner.nextInt();if (!isValidMove(x, y)) {System.out.println("该位置已有落子,请重新选择!");continue;}board[x][y] = WHITE;}// 切换玩家blackTurn = !blackTurn;}}/*** 打印当前棋盘状态*/private void printBoard() {System.out.print(" ");for (int i = 0; i < BOARD_SIZE; i++) {System.out.print(" " + i);}System.out.println();for (int i = 0; i < BOARD_SIZE; i++) {System.out.print(i + " ");for (int j = 0; j < BOARD_SIZE; j++) {System.out.print(board[i][j] + " ");}System.out.println();}}/*** 检查是否胜利** @return 是否胜利*/private boolean checkWin() {// 检查每一行for (int i = 0; i < BOARD_SIZE; i++) {int count = 0;for (int j = 0; j < BOARD_SIZE; j++) {count = board[i][j] == (blackTurn ? BLACK : WHITE) ? count + 1 : 0;if (count >= 5) {return true;}}}// 检查每一列for (int i = 0; i < BOARD_SIZE; i++) {int count = 0;for (int j = 0; j < BOARD_SIZE; j++) {count = board[j][i] == (blackTurn ? BLACK : WHITE) ? count + 1 : 0;if (count >= 5) {return true;}}}// 检查主对角线for (int i = 0; i <= BOARD_SIZE - 5; i++) {for (int j = 0; j <= BOARD_SIZE - 5; j++) {boolean win = true;for (int k = 0; k < 5; k++) {if (board[i + k][j + k] != (blackTurn ? BLACK : WHITE)) {win = false;break;}}if (win) {return true;}}}// 检查副对角线for (int i = 0; i <= BOARD_SIZE - 5; i++) {for (int j = BOARD_SIZE - 1; j >= 4; j--) {boolean win = true;for (int k = 0; k < 5; k++) {if (board[i + k][j - k] != (blackTurn ? BLACK : WHITE)) {win = false;break;}}if (win) {return true;}}}// 没有胜利状态return false;}/*** 判断落子是否合法** @param x 横坐标* @param y 纵坐标* @return 落子是否合法*/private boolean isValidMove(int x, int y) {if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE) {return false;}return board[x][y] == EMPTY;}/*** 根据分数落子** @param board 棋盘* @param player 玩家* @return 落子位置*/private int[] scoreStrategy(char[][] board, char player) {int[] move = new int[2];int maxScore = -1;for (int i = 0; i < BOARD_SIZE; i++) {for (int j = 0; j < BOARD_SIZE; j++) {if (board[i][j] == EMPTY) {int score = calculateScore(board, i, j, player);if (score > maxScore) {maxScore = score;move[0] = i;move[1] = j;}}}}return move;}/*** 计算落子位置的分数** @param board 棋盘* @param x 横坐标* @param y 纵坐标* @param player 玩家* @return 落子位置的分数*/private int calculateScore(char[][] board, int x, int y, char player) {int score = 0;// 计算横向分数for (int i = Math.max(0, x - 4); i <= Math.min(BOARD_SIZE - 1, x + 4); i++) {if (board[i][y] == player) {score++;}}// 计算纵向分数for (int i = Math.max(0, y - 4); i <= Math.min(BOARD_SIZE - 1, y + 4); i++) {if (board[x][i] == player) {score++;}}// 计算主对角线分数for (int i = Math.max(x - 4, 0), j = Math.max(y - 4, 0); i <= Math.min(x + 4, BOARD_SIZE - 1) && j <= Math.min(y + 4, BOARD_SIZE - 1); i++, j++) {if (board[i][j] == player) {score++;}}// 计算副对角线分数for (int i = Math.min(x + 4, BOARD_SIZE - 1), j = Math.max(y - 4, 0); i >= Math.max(x - 4, 0) && j <= Math.min(y + 4, BOARD_SIZE - 1); i--, j++) {if (board[i][j] == player) {score++;}}if (player == BLACK) {score += x * 0.1;} else {score += (BOARD_SIZE - x) * 0.1;}return score;}}

小结

通过对五子棋程序的三次版本迭代思考对同类下棋游戏的思考,

从玩家对战模式判断规则到随机事件到策略事件的不断迭代升级,

之后的迭代方向通过策略方案计算出必胜树来指导玩家下棋的版本。

如果觉得《Java用最少代码实现五子棋-玩家对战模式-人机对战模式-电脑策略对战》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。