我们是由枫哥组建的IT技术团队,成立于2017年,致力于帮助IT从业者提供实力,成功入职理想企业,我们提供一对一学习辅导,由知名大厂导师指导,分享Java技术、参与项目实战等服务,并为学员定制职业规划,全面提升竞争力,过去8年,我们已成功帮助数千名求职者拿到满意的Offer:IT枫斗者、IT枫斗者-Java面试突击。
🔥 从零手写 Java 三子棋!数组 + 面向对象 + 人机对战,面试官看了都点头(附完整源码)
前言:为什么面试官爱问"三子棋"?
三子棋(Tic-Tac-Toe)是编程入门的经典项目,但用Java 面向对象的方式实现,能考察到:
- 二维数组操作 ✅
- 类与对象的设计 ✅
- 循环与分支逻辑 ✅
- 随机数生成 ✅
- 简单的 AI 算法 ✅
本文从 0 到 1,手把手教你用 Java 写出"工程级"三子棋,代码可直接运行,建议先收藏 ⭐。
一、项目结构(分模块设计)
tic-tac-toe/ ├── Game.java // 游戏核心逻辑类 ├── Player.java // 玩家/电脑抽象 ├── Board.java // 棋盘类 ├── GameStatus.java // 游戏状态枚举 └── Main.java // 入口主类💡设计思想:把"棋盘"、“玩家”、"游戏流程"拆成独立类,符合单一职责原则(SRP),这也是面试加分项。
二、完整源码(可直接复制运行)
1. GameStatus.java —— 游戏状态枚举
/** * 游戏状态枚举 */publicenumGameStatus{PLAYER_WIN,// 玩家赢COMPUTER_WIN,// 电脑赢DRAW,// 平局CONTINUE// 继续游戏}2. Board.java —— 棋盘类
/** * 棋盘类:负责棋盘初始化、打印、落子、胜负判断 */publicclassBoard{privatestaticfinalintSIZE=3;// 棋盘大小(3x3)privatestaticfinalcharEMPTY=' ';// 空位privatestaticfinalcharPLAYER='*';// 玩家棋子privatestaticfinalcharCOMPUTER='#';// 电脑棋子privatechar[][]board;// 二维数组存储棋盘publicBoard(){board=newchar[SIZE][SIZE];initBoard();}/** * 初始化棋盘:全部置为空格 */publicvoidinitBoard(){for(inti=0;i<SIZE;i++){for(intj=0;j<SIZE;j++){board[i][j]=EMPTY;}}}/** * 打印棋盘(带分隔线,美观版) */publicvoidprintBoard(){System.out.println();for(inti=0;i<SIZE;i++){// 打印棋子行for(intj=0;j<SIZE;j++){System.out.print(" "+board[i][j]+" ");if(j<SIZE-1){System.out.print("|");}}System.out.println();// 打印分隔线if(i<SIZE-1){for(intj=0;j<SIZE;j++){System.out.print("---");if(j<SIZE-1){System.out.print("|");}}System.out.println();}}System.out.println();}/** * 落子(玩家输入的是 1-based 坐标) * @param row 行(1-3) * @param col 列(1-3) * @param isPlayer true=玩家, false=电脑 * @return 是否落子成功 */publicbooleanplacePiece(introw,intcol,booleanisPlayer){// 转成 0-based 数组下标intr=row-1;intc=col-1;// 边界检查if(r<0||r>=SIZE||c<0||c>=SIZE){System.out.println("❌ 坐标超出边界,请重新输入(1-3)");returnfalse;}// 是否已被占用if(board[r][c]!=EMPTY){System.out.println("❌ 该位置已被占用,请重新选择");returnfalse;}board[r][c]=isPlayer?PLAYER:COMPUTER;returntrue;}/** * 电脑随机落子 */publicvoidcomputerMove(){java.util.Randomrandom=newjava.util.Random();while(true){intr=random.nextInt(SIZE);intc=random.nextInt(SIZE);if(board[r][c]==EMPTY){board[r][c]=COMPUTER;System.out.println("🤖 电脑下棋:("+(r+1)+", "+(c+1)+")");break;}}}/** * 判断游戏状态 */publicGameStatuscheckStatus(){// 检查行for(inti=0;i<SIZE;i++){if(board[i][0]!=EMPTY&&board[i][0]==board[i][1]&&board[i][1]==board[i][2]){returnboard[i][0]==PLAYER?GameStatus.PLAYER_WIN:GameStatus.COMPUTER_WIN;}}// 检查列for(inti=0;i<SIZE;i++){if(board[0][i]!=EMPTY&&board[0][i]==board[1][i]&&board[1][i]==board[2][i]){returnboard[0][i]==PLAYER?GameStatus.PLAYER_WIN:GameStatus.COMPUTER_WIN;}}// 检查主对角线if(board[0][0]!=EMPTY&&board[0][0]==board[1][1]&&board[1][1]==board[2][2]){returnboard[0][0]==PLAYER?GameStatus.PLAYER_WIN:GameStatus.COMPUTER_WIN;}// 检查副对角线if(board[0][2]!=EMPTY&&board[0][2]==board[1][1]&&board[1][1]==board[2][0]){returnboard[0][2]==PLAYER?GameStatus.PLAYER_WIN:GameStatus.COMPUTER_WIN;}// 检查是否平局(棋盘已满)if(isFull()){returnGameStatus.DRAW;}returnGameStatus.CONTINUE;}/** * 判断棋盘是否已满 */privatebooleanisFull(){for(inti=0;i<SIZE;i++){for(intj=0;j<SIZE;j++){if(board[i][j]==EMPTY){returnfalse;}}}returntrue;}// GetterpublicintgetSize(){returnSIZE;}}3. Game.java —— 游戏控制类
importjava.util.Scanner;/** * 游戏控制类:负责游戏流程、菜单、交互 */publicclassGame{privateBoardboard;privateScannerscanner;privatebooleanisRunning;publicGame(){board=newBoard();scanner=newScanner(System.in);isRunning=true;}/** * 显示菜单 */publicvoidshowMenu(){System.out.println("╔════════════════════════════════╗");System.out.println("║ 🎮 Java 三子棋大战 ║");System.out.println("╠════════════════════════════════╣");System.out.println("║ 1. 开始游戏 ║");System.out.println("║ 0. 退出游戏 ║");System.out.println("╚════════════════════════════════╝");System.out.print("请选择:");}/** * 游戏主循环 */publicvoidstart(){while(isRunning){showMenu();intchoice=scanner.nextInt();switch(choice){case1:System.out.println("\n🚀 三子棋,启动!");playGame();break;case0:System.out.println("\n👋 感谢游玩,再见!");isRunning=false;break;default:System.out.println("\n⚠️ 无效选项,请重新选择");}}}/** * 单局游戏流程 */privatevoidplayGame(){board.initBoard();// 重置棋盘while(true){// ========== 玩家回合 ==========board.printBoard();System.out.print("🧑 请输入下棋坐标(行 列,如:1 2):");introw=scanner.nextInt();intcol=scanner.nextInt();// 落子失败(越界/被占用)则重新输入while(!board.placePiece(row,col,true)){System.out.print("🧑 请重新输入坐标:");row=scanner.nextInt();col=scanner.nextInt();}// 检查状态GameStatusstatus=board.checkStatus();if(status!=GameStatus.CONTINUE){board.printBoard();printResult(status);break;}// ========== 电脑回合 ==========board.computerMove();status=board.checkStatus();if(status!=GameStatus.CONTINUE){board.printBoard();printResult(status);break;}}}/** * 打印游戏结果 */privatevoidprintResult(GameStatusstatus){switch(status){casePLAYER_WIN:System.out.println("🎉 恭喜!玩家获胜!");break;caseCOMPUTER_WIN:System.out.println("💻 电脑获胜!再接再厉!");break;caseDRAW:System.out.println("🤝 平局!棋逢对手!");break;default:break;}System.out.println();}}4. Main.java —— 程序入口
/** * 程序入口 */publicclassMain{publicstaticvoidmain(String[]args){Gamegame=newGame();game.start();}}三、运行效果演示
╔════════════════════════════════╗ ║ 🎮 Java 三子棋大战 ║ ╠════════════════════════════════╣ ║ 1. 开始游戏 ║ ║ 0. 退出游戏 ║ ╚════════════════════════════════╝ 请选择:1 🚀 三子棋,启动! | | ---+---+--- | | ---+---+--- | | 🧑 请输入下棋坐标(行 列,如:1 2):1 1 🤖 电脑下棋:(2, 3) * | | ---+---+--- | | # ---+---+--- | | 🧑 请输入下棋坐标(行 列,如:1 2):2 2 ...⭐️推荐:
- Offer训练营介绍
- Java 面试 & 后端通用面试八股文
- Java后端企业级实战面试
- Java后端校招算法学习