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用最少代码实现五子棋-玩家对战模式-人机对战模式-电脑策略对战相关推荐
- 五子棋小游戏 java版(代码+详细注释)
游戏展示 这周闲来无事,再来写个五子棋小游戏.基本功能都实现了,包括人人对战.人机对战.界面布局和功能都写的还行,没做到很优秀,但也不算差.如有需要,做个java初学者的课程设计或者自 ...
- Java 设计模式 本文代码拉取链接 https://gitlab.com/zhangpengweiLJ/designpettern.git
目录 什么是设计模式? 设计模式目的 设计模式七大原则: 单一职责原则: 接口隔离原则 依赖倒转原则(Dependence Inversion Principle) 在这顺带说明聚合和组合的区别 里氏 ...
- java实现注册登录版五子棋对战平台(超详细注释,内含人机实现)
目录 前言 项目介绍 功能演示 登录 注册 选择对手 落子提示 局时步时 查看战绩 落子五连 悔棋 聊天 新局 棋谱 保存棋谱 打开棋谱 其它功能 刷新 上下页 认输 退出 轮播图片 背景音乐 求助小 ...
- JAVA课设单人版五子棋小游戏
内容介绍:该程序为Java课设的单人版五子棋小游戏,通过eclipse编辑,实现了动作事件的监听与处理,以及JavaSwing的界面编程. 编辑排行榜,包含局数,结果,步数,以及"关于我们 ...
- 控制台五子棋java源代码_两套 五子棋小游戏源码(控制台+JavaSWing)
[实例简介] [实例截图] [核心代码] 五子棋 ├── 图形 │ ├── java五子棋小程序.doc │ ├── 五子棋 │ │ ├── bin │ │ │ └── c ...
- Java设计模式的代码演示(结构型模式一)
目录 写在前面 一.适配器模式 1.1. 类适配器模式 1.2. 对象适配器模式 二.桥接模式 三.装饰器模式 写在前面 上一篇我们学习了创建型设计模式 本篇文章通过代码演示的形式,记录结构型设计模式 ...
- c# typescript_在任何IDE中从C#,Java或Python代码获取TypeScript接口的简单方法
c# typescript by Leonardo Carreiro 莱昂纳多·卡雷罗(Leonardo Carreiro) 在任何IDE中从C#,Java或Python代码获取TypeScript接 ...
- java培训教程分享:Java编写软件代码自动提示功能
本期的java培训教程分享主要是介绍的java编写软件代码的一个自动提示功能,很多零基础和初学java的同学们对这一块还不是很了解,Eclipse for android 实现代码自动提示智能提示功能 ...
- java 用程序代码解释继承_关于初级java程序员笔试题
关于初级java程序员笔试题 Sun 认证Java程序员考试内容涉及Java所有相关知识.编程概念及applet开发技巧.下面是小编整理的关于初级java程序员笔试题,欢迎大家参考! 第一题:判断题 ...
最新文章
- 基于SSVEP-EOG的混合BCI用于机械臂控制
- 授予数据库账号dba权限_从自建Oracle迁移至云原生数据仓库AnalyticDB PostgreSQL
- 【Linux】一步一步学Linux——usernetctl命令(175)
- 基于Delphi的接口编程入门
- java获取界面输入数字_通过JAVA设计 GUI 界面的计算器程序,用户可以通过鼠标依次输入参加计算的数值,进行加、减、乘、...
- Spark集群,多个版本Python/Python Package管理
- LeetCode 646. 最长数对链
- ggplot2 | ggplot2作图语法入门
- Smali动态调试方法
- BUAAOO——UNIT2 SUMMARY
- Atitit.基于dsl的methodinvoker
- @Value 注入 map、List,yaml 格式
- 用友U8 ERP系统材料出库单打印格式设置-表格格式调整
- 教育类产品 竞品分析
- 模糊综合评价模型 ——确定隶属度
- python3.6实现的A星算法
- 结构力学用计算机算的优势和不足,计算结构力学
- 电梯轿厢场景下的电动车数据集
- 计算机组装的配置清单,2018最新组装电脑高配置清单推荐
- 问题 A: 买牛奶 某同学负责给班里的同学买牛奶 ,每人两瓶。输入一个整数,表示班级人数。输出牛奶瓶数
热门文章
- hive创建hbase外部表
- 网站降权后应该如何去处理
- Warning: mysqli::mysqli(): (HY000/2002): No connection could be made because the target machine acti
- 在家也能健身(05):腹肌
- 云计算(Day 8)
- 【JAVA】解决mapper绑定异常:nested exception is org.apache.ibatis.binding.BindingException:
- 计算机毕业设计SSM鞍山丘比特房屋租赁管理系统【附源码数据库】
- 厉害了隔壁老王,带你入坑腾讯联机对战引擎!
- 通过注册表添加受信任站点
- 拍乐云创始人CEO赵加雨:深耕18载,打造全景式音视频服务