Java控制台实现3x3数字拼图游戏

Ryan
Ryan
发布时间:2026-10-16| 5人浏览过
原创

本文详解如何利用Java控制台开发3x3数字拼图游戏。通过二维数组管理棋盘,结合随机数打乱初始状态,并设计核心逻辑处理用户输入、合法性校验及邻接移动判断,最终实现通关检测。

项目目标

构建一个基于控制台的数字拼图程序,模拟经典滑块谜题的核心玩法。程序需在终端显示3x3的网格(其中一个位置为空),接受用户指令将相邻方块移入空位,并在所有方块归位时自动判定胜利。

核心数据结构与准备

整个游戏的状态由一个二维整型数组表示,其中1-8代表方块数字,9代表空白区域。为了实现交互,需要准备以下基础组件:

  • Scanner:用于读取控制台输入的指令。
  • Random:用于在游戏开始前对棋盘进行合法打乱。
  • int[][] grid:保存当前棋盘状态的矩阵变量。

关键功能模块设计

第1步:初始化与打乱局面

直接生成随机数字可能导致无法还原的局面,因此最佳实践是通过多次有效的“空白格交换”来模拟打乱过程,保证局面的可解性。

  • 逻辑:记录空白格当前位置(h, l)。
  • 操作:重复100次操作,随机选择一个与空白格相邻的有效坐标(x, y)并执行交换。
  • 目的:确保最终生成的局面必定可以通过逆向步骤回到有序状态。

第2步:游戏主循环与画面渲染

游戏运行时应持续绘制界面并等待指令。打印函数需遍历数组,若检测到值9则输出空格以体现“缺失”效果,否则输出对应数字。

  • 入口:主线程开始处调用playGrame方法。
  • 动作:在while(true)死循环中先刷新屏幕,再获取用户输入,最后根据结果尝试更新棋盘。
  • 状态:直到返回胜利标志时跳出循环。

第3步:输入校验与坐标定位

为保证用户体验,必须对用户的非法字符或越界操作进行拦截,并将抽象的“点击哪个数字”转化为具体的数组索引。

  • 验证:检查输入是否为单个字符且范围在'1'-'8'之间,递归提示错误信息。
  • 映射:扫描整个棋盘寻找该数字所在的(row, col)坐标,将其赋值给全局坐标变量供后续逻辑使用。

第4步:合法性校验与位置交换

这是游戏逻辑的核心。只有当目标数字与空白格存在邻接关系时,才允许发生位移。

  • 距离判断:计算两坐标点的曼哈顿距离,若行差与列差的绝对值之和为1,即视为相邻。
  • 数据交换:将空白格中的值暂存,将目标值赋给空白格,再将原空白格值回填到目标位置。
  • 更新标记:将全局空白格坐标(h, l)同步至新位置。

第5步:胜利判定

每次交换后,系统需即时检查是否达成目标。通常采用顺序比对法:

  • 从左上角开始,逐行逐列扫描数组元素。
  • 按1至8的顺序核对,一旦发现不匹配立即终止并返回失败;若全部匹配且未提前结束,则标记胜利。

完整代码示例

import java.util.Random;
import java.util.Scanner;

public class PingTuGame {

 private static Scanner scanner = new Scanner(System.in);
 private static Random random = new Random();
 
 // 记录空白格的行列坐标
 private static int h = 0; 
 private static int l = 0;
 private static int x = 0;
 private static int y = 0;

 public static void main(String[] args) {
    int[][] gameGrid = { 
        { 1, 2, 3 }, 
        { 4, 5, 6 }, 
        { 7, 8, 0 } 
    };
    initGrid(gameGrid);
    System.out.println("游戏开始!请输入要移动的数字(1-8):\n");
    playGame(gameGrid);
 }

 /**
  * 游戏主循环
  */
 public static void playGame(int[][] a) {
  while (true) {
   printfResult(a);
   int inputVal = getUserInput();
   locateCoord(inputVal, a);
   if (isValidMove()) {
    swapBlock(a);
    if (checkVictory(a)) {
     printfResult(a);
     System.out.println("恭喜,游戏完成!");
     break;
    }
   } else {
    System.out.println("\n无法移动,请重新输入有效方向。\n");
   }
  }
 }

 /**
  * 格式化打印当前棋盘
  */
 public static void printfResult(int[][] a) {
  for (int[] row : a) {
   for (int val : row) {
    System.out.print(val == 0 ? "[ ]" : String.format("[%d]", val));
   }
   System.out.println();
  }
  System.out.println();
 }

 /**
  * 随机化初始局面(保证可解)
  */
 public static void initGrid(int[][] a) {
  // 初始默认右下角是0
  h = 2; l = 2;
  for (int i = 0; i < 100; i++) {
   // 随机选取上下左右方向之一
   int dir = random.nextInt(4); 
   int nx = h + getDirOffset(dir, true);
   int ny = l + getDirOffset(dir, false);
   if (isInBound(nx, ny)) {
    swapOnce(nx, ny, a);
    h = nx; l = ny;
   }
  }
 }

 private static int getDirOffset(int d, boolean isRow) {
   switch(d) {
     case 0: return isRow ? -1 : 0;
     case 1: return isRow ? 1 : 0;
     case 2: return 0; case 3: return isRow ? 0 : -1;
     default: return 0;
   }
 }

 private static boolean isInBound(int x, int y) {
   return x >= 0 && x < 3 && y >= 0 && y < 3;
 }

 private static void swapOnce(int nx, int ny, int[][] a) {
   int temp = a[h][l];
   a[h][l] = a[nx][ny];
   a[nx][ny] = temp;
 }

 /**
  * 获取用户合法输入
  */
 public static int getUserInput() {
  System.out.print("输入目标数字: ");
  String str = scanner.nextLine().trim();
  try {
    int num = Integer.parseInt(str);
    if (num >= 1 && num <= 8) return num;
  } catch (Exception e) {}
  System.out.println("无效输入!\n");
  return getUserInput();
 }

 /**
  * 查找数字坐标存入全局x,y
  */
 public static void locateCoord(int target, int[][] a) {
   for (int i=0; i<a.length; i++) {
    for (int j=0; j<a[i].length; j++) {
      if (a[i][j] == target) { x=i; y=j; return; }
    }
   }
 }

 /**
  * 判断是否符合移动规则
  */
 public static boolean isValidMove() {
   // 检查是否与空白格相邻
   if ((Math.abs(h-x) == 1 && l == y) || 
       (Math.abs(l-y) == 1 && h == x)) {
     return true;
   }
   return false;
 }

 /**
  * 执行实际交换并更新全局空白位置
  */
 public static void swapBlock(int[][] a) {
   int t = a[h][l];
   a[h][l] = a[x][y];
   a[x][y] = t;
   h = x; l = y;
 }

 /**
  * 检查是否达到目标排序
  */
 public static boolean checkVictory(int[][] a) {
   int c = 1;
   for (int i=0; i<3; i++) {
     for (int j=0; j<3; j++) {
       if (i == 2 && j == 2) continue; // 跳过最后的0位
       if (a[i][j] != c++) return false;
     }
   }
   return true;
 }
}

简要总结

本例通过二维数组与循环逻辑展示了Java控制台编程的基础形态。在实际生产环境中,通常会引入更复杂的类封装与事件驱动机制,但对于入门掌握数组寻址、对象状态流转和算法边界测试而言,该实现具有极高的参考价值。以上就是Java控制台实现3x3数字拼图游戏的详细内容,更多关于Java图形界面的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。