package game.game2048;
/**
* @BelongsProject: TimeGame
* @BelongsPackage: game
* @Author: 土里埋埋埋埋埋
* @CreateTime: 2025-07-31 11:04
* @Description: 数据库操作
* @Version: 1.0
*/
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class GameDAO {
private Connection connection;
// 登录数据库
public GameDAO() throws SQLException {
connection = DriverManager.getConnection(
"jdbc:mysql://117.72.189.79:3306/2048",
"root",
"Fbb608425@"
);
}
// 用户注册
public boolean registerUser(String username, String password) throws SQLException {
String sql = "INSERT INTO users (username, password) VALUES (?, ?)";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, username);
stmt.setString(2, password);
return stmt.executeUpdate() > 0;
}
}
// 用户登录
public int authenticateUser(String username, String password) throws SQLException {
String sql = "SELECT id FROM users WHERE username = ? AND password = ?";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, username);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
return rs.getInt("id");
}
}
return -1;
}
// 保存分数
public void saveScore(int userId, int score) throws SQLException {
String sql = "INSERT INTO scores (user_id, score, is_timed_mode) VALUES (?, ?, ?)";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setInt(1, userId);
stmt.setInt(2, score);
boolean isTimedMode = false;
stmt.setBoolean(3, isTimedMode);
stmt.executeUpdate();
}
}
// 个人最高分
public List<String> maxscore(int user_id) throws SQLException {
List<String> ranking = new ArrayList<>();
// 普通模式最高分
String normalSql = "SELECT MAX(score) AS max_normal_score " +
"FROM scores WHERE user_id = ? AND is_timed_mode = false";
try (PreparedStatement stmt = connection.prepareStatement(normalSql)) {
stmt.setInt(1, user_id);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
int maxScore = rs.getInt("max_normal_score");
ranking.add("最高分: " + maxScore);
}
}
// 限时模式最高分
String timedSql = "SELECT MAX(score) AS max_timed_score " +
"FROM scores WHERE user_id = ? AND is_timed_mode = true";
try (PreparedStatement stmt = connection.prepareStatement(timedSql)) {
stmt.setInt(1, user_id);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
int maxScore = rs.getInt("max_timed_score");
ranking.add("");
}
}
return ranking;
}
// 总排行榜
public List<String> getGlobalRanking(boolean b) throws SQLException {
List<String> ranking = new ArrayList<>();
boolean isTimedMode = false;
String modeName = isTimedMode ? "限时模式" : "普通模式";
String sql = "SELECT u.username, s.score " +
"FROM scores s " +
"JOIN users u ON s.user_id = u.id " +
"WHERE s.is_timed_mode = ? " +
"ORDER BY score DESC LIMIT 10";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setBoolean(1, isTimedMode);
ResultSet rs = stmt.executeQuery();
int rank = 1;
while (rs.next()) {
ranking.add(rank++ + ". " + rs.getString("username") +
" - " + rs.getInt("score") + "分");
}
}
return ranking;
}
public List<String> getAllRankings() throws SQLException {
List<String> allRankings = new ArrayList<>();
// 普通模式排行榜
allRankings.addAll(getGlobalRanking(false));
// 添加分隔线
allRankings.add("----------------------");
// 限时模式排行榜
allRankings.addAll(getGlobalRanking(true));
return allRankings;
}
// 个人历史记录
public List<String> getUserHistory(int userId) throws SQLException {
List<String> history = new ArrayList<>();
String sql = "SELECT score, game_time, is_timed_mode FROM scores " +
"WHERE user_id = ? ORDER BY game_time DESC LIMIT 10";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setInt(1, userId);
ResultSet rs = stmt.executeQuery();
int count = 1;
while (rs.next()) {
String mode = rs.getBoolean("is_timed_mode") ? "限时" : "普通";
history.add(count++ + ".得分:" +
rs.getInt("score") + " - " +
rs.getTimestamp("game_time"));
}
}
return history;
}
// 存档操作
public void saveGame(int userId, String saveName, String boardState, int score,
boolean isTimedMode, int timeLimit, int remainingTime) throws SQLException {
String sql = "INSERT INTO saves (user_id, save_name, board_state, score, " +
"is_timed_mode, time_limit, remaining_time) " +
"VALUES (?, ?, ?, ?, ?, ?, ?)";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setInt(1, userId);
stmt.setString(2, saveName);
stmt.setString(3, boardState);
stmt.setInt(4, score);
stmt.setBoolean(5, isTimedMode);
stmt.setInt(6, timeLimit);
stmt.setInt(7, remainingTime);
stmt.executeUpdate();
}
}
// 获取用户存档
public List<GameSave> getUserSaves(int userId) throws SQLException {
List<GameSave> saves = new ArrayList<>();
String sql = "SELECT id, save_name, score, save_time, " +
"is_timed_mode, time_limit, remaining_time " +
"FROM saves WHERE user_id = ? ORDER BY save_time DESC";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setInt(1, userId);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
saves.add(new GameSave(
rs.getInt("id"),
rs.getString("save_name"),
rs.getString("board_state"),
rs.getInt("score"),
rs.getBoolean("is_timed_mode"),
rs.getInt("time_limit"),
rs.getInt("remaining_time"),
rs.getTimestamp("save_time").toString()
));
}
}
return saves;
}
// 读档操作
public GameSave loadGame(int saveId) throws SQLException {
String sql = "SELECT board_state, score, is_timed_mode, " +
"time_limit, remaining_time " +
"FROM saves WHERE id = ?";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setInt(1, saveId);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
return new GameSave(
saveId,
"", // 存档名称不需要在加载时使用
rs.getString("board_state"),
rs.getInt("score"),
rs.getBoolean("is_timed_mode"),
rs.getInt("time_limit"),
rs.getInt("remaining_time"),
null // 时间戳不需要
);
}
}
return null;
}
public void saveGame(int currentUserId, String saveName, String boardState, int score) {
}
// 增强的存档类
public static class GameSave {
private int id;
private String saveName;
private String boardState;
private int score;
private boolean isTimedMode;
private int timeLimit;
private int remainingTime;
private String timestamp;
public GameSave(int id, String saveName, String boardState, int score,
boolean isTimedMode, int timeLimit, int remainingTime,
String timestamp) {
this.id = id;
this.saveName = saveName;
this.boardState = boardState;
this.score = score;
this.isTimedMode = isTimedMode;
this.timeLimit = timeLimit;
this.remainingTime = remainingTime;
this.timestamp = timestamp;
}
// Getter方法
public int getId() { return id; }
public String getSaveName() { return saveName; }
public String getBoardState() { return boardState; }
public int getScore() { return score; }
public boolean isTimedMode() { return isTimedMode; }
public int getTimeLimit() { return timeLimit; }
public int getRemainingTime() { return remainingTime; }
public String getTimestamp() { return timestamp; }
}
}
package game.game2048;
/**
* @BelongsProject: TimeGame
* @BelongsPackage: Demo.game
* @Author: 土里埋埋埋埋埋
* @CreateTime: 2025-07-31 11:51
* @Description: 游戏界面
* @Version: 1.0
*/
import game.game2048.game.Direction;
import game.game2048.game.Game;
import java.sql.SQLException;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
public class ConsoleUI {
private static final int FIXED_TIME_LIMIT = 60;
private Scanner scanner;
private GameDAO gameDAO;
private int currentUserId;
public ConsoleUI() throws SQLException {
scanner = new Scanner(System.in);
gameDAO = new GameDAO();
currentUserId = -1;
}
public void start() throws SQLException {
while (true) {
if (currentUserId == -1) {
showLoginMenu();
} else {
showMainMenu();
}
}
}
//获取登录菜单
private void showLoginMenu() {
System.out.println("=== 2048 游戏 ===");
System.out.println("1. 登录");
System.out.println("2. 注册");
System.out.println("3. 退出");
System.out.print("请选择: ");
int choice = scanner.nextInt();
scanner.nextLine();
try {
switch (choice) {
case 1:
login();
break;
case 2:
register();
break;
case 3:
System.exit(0);
default:
System.out.println("无效选择!");
}
} catch (SQLException e) {
System.out.println("数据库错误: " + e.getMessage());
}
}
//登录界面
private void login() throws SQLException {
System.out.print("用户名: ");
String username = scanner.nextLine();
System.out.print("密码: ");
String password = scanner.nextLine();
int userId = gameDAO.authenticateUser(username, password);
if (userId != -1) {
currentUserId = userId;
captcha();
System.out.println("登录成功!");
} else {
System.out.println("用户名或密码错误!");
}
}
//注册界面
private void register() throws SQLException {
System.out.print("用户名: ");
String username = scanner.nextLine();
System.out.print("密码: ");
String password = scanner.nextLine();
if (gameDAO.registerUser(username, password)) {
System.out.println("注册成功!");
} else {
System.out.println("注册失败,用户名可能已存在!");
}
}
//登录验证
public void captcha() {
while (true) {
Scanner sc = new Scanner(System.in);
String code = getCode();
System.out.println("验证码:" + code);
System.out.print("请输入验证码:");
String userInput = sc.next();
if (validateCaptcha(code, userInput)) {
System.out.println("验证码正确!");
break;
} else {
System.out.println("验证码错误!");
}
}
}
public static String getCode() {
String box = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuilder captcha = new StringBuilder();
String codeBox = "";
for (int i = 0; i < 4; i++) {
int index = random.nextInt(box.length());
char c = box.charAt(index);
codeBox += c;
}
return codeBox;
}
public static boolean validateCaptcha(String captcha, String userInput) {
return captcha.equalsIgnoreCase(userInput);
}
//游戏主菜单
private void showMainMenu() throws SQLException {
System.out.println("=== 主菜单 ===");
System.out.println("1. 开始新游戏");
System.out.println("2. 加载存档");
System.out.println("3. 查看排行榜");
System.out.println("4. 查看历史记录");
System.out.println("5. 退出登录");
System.out.println("6. 退出游戏");
System.out.print("请选择: ");
int choice = scanner.nextInt();
scanner.nextLine();
System.out.println();
switch (choice) {
case 1:
startGame();
break;
case 2:
loadGame();
break;
case 3:
showRankings();
break;
case 4:
showUserHistory();
break;
case 5:
currentUserId = -1;
System.out.println("已退出登录");
break;
case 6:
System.exit(0);
default:
System.out.println("无效选择!");
}
}
//重新开始游戏
private void startGame() throws SQLException {
System.out.println("=== 选择游戏模式 ===");
System.out.println("1. 普通模式");
System.out.println("2. 限时模式");
System.out.println("3. 返回主菜单");
System.out.print("请选择: ");
int modeChoice = scanner.nextInt();
scanner.nextLine();
if (modeChoice == 3) return; // 返回主菜单
boolean isTimedMode = (modeChoice == 2);
int timeLimit = isTimedMode ? FIXED_TIME_LIMIT : 0;
while (true) {
Game game = isTimedMode ?
new Game(true, timeLimit) : // 限时模式
new Game(); // 普通模式
playGame(game, isTimedMode);
System.out.println("请选择是否重新开始: 1 - 重新开始 2 - 返回菜单");
int res = scanner.nextInt();
scanner.nextLine();
if (res != 1) {
break;
}
}
}
//游戏存档
private void loadGame() throws SQLException {
List<GameDAO.GameSave> saves = gameDAO.getUserSaves(currentUserId);
if (saves.isEmpty()) {
System.out.println("没有找到存档!");
return;
}
System.out.println("=== 您的存档 ===");
System.out.printf("%-6s %-20s %-8s %-10s %-15s%n",
"ID", "存档名称", "分数", "模式", "创建时间");
for (GameDAO.GameSave save : saves) {
String modeInfo = save.isTimedMode() ? "限时模式" : "普通模式";
System.out.printf("%-6d %-20s %-8d %-10s %-15s%n",
save.getId(),
save.getSaveName(),
save.getScore(),
modeInfo,
save.getTimestamp());
}
System.out.print("输入存档ID: ");
int saveId = scanner.nextInt();
scanner.nextLine();
GameDAO.GameSave gameSave = gameDAO.loadGame(saveId);
if (gameSave != null) {
// 创建游戏实例时传递模式信息
Game game = new Game(gameSave.getBoardState(),
gameSave.getScore(),
gameSave.isTimedMode(),
gameSave.getTimeLimit(),
gameSave.getRemainingTime());
// 传递模式信息给游戏循环
playGame(game, gameSave.isTimedMode());
} else {
System.out.println("加载存档失败!");
}
}
//游戏规则
private void playGame(Game game, boolean isTimedMode) throws SQLException {
List<String> userMaxScore = gameDAO.maxscore(currentUserId);
while (!game.isGameOver()) {
// 显示分数和时间
System.out.print("当前分数: " + game.getScore());
System.out.print("\t");
for (String rank : userMaxScore) {
System.out.print(rank);
}
if (isTimedMode) {
System.out.print("\t剩余时间: " + game.getRemainingTime() + "秒");
}
System.out.println();
displayBoard(game.getBoard());
System.out.println("操作: w(上) s(下) a(左) d(右) q(退出) x(存档) z(撤回)");
System.out.print("输入操作: ");
String input = scanner.nextLine().toLowerCase();
if (input.equals("q")) {
return;
} else if (input.equals("x")) {
System.out.print("输入存档名称: ");
String saveName = scanner.nextLine();
gameDAO.saveGame(currentUserId, saveName, game.getBoardState(), game.getScore());
System.out.println("游戏已保存!");
return;
} else if (input.equals("z")) {
if (game.canUndo()) {
game.undo();
System.out.println("已撤回一步");
} else {
System.out.println("无法撤回,一次仅可撤回一步");
}
} else {
Direction direction = null;
switch (input) {
case "w":
direction = Direction.UP;
break;
case "s":
direction = Direction.DOWN;
break;
case "a":
direction = Direction.LEFT;
break;
case "d":
direction = Direction.RIGHT;
break;
default:
System.out.println("操作无效");
continue;
}
game.move(direction);
}
}
// 游戏结束处理
displayBoard(game.getBoard());
if (isTimedMode && game.getRemainingTime() <= 0) {
System.out.println("时间到! 最终分数: " + game.getScore());
} else {
System.out.println("游戏结束! 最终分数: " + game.getScore());
}
gameDAO.saveScore(currentUserId, game.getScore());
}
//打印地图
private void displayBoard(int[][] board) {
for (int i = 0; i < 4; i++) {
System.out.print("");
for (int j = 0; j < 4; j++) {
if (board[i][j] == 0) {
System.out.print("\t0");
} else {
System.out.print("\t");
System.out.print(board[i][j]);
}
}
System.out.println();
}
}
//排行榜
private void showRankings() throws SQLException {
System.out.println("=== 排行榜 ===");
List<String> globalRanking = gameDAO.getGlobalRanking(false);
for (String rank : globalRanking) {
System.out.println(rank);
}
}
//游戏历史
private void showUserHistory() throws SQLException {
System.out.println("=== 游戏历史 ===");
List<String> userHistory = gameDAO.getUserHistory(currentUserId);
if (userHistory.isEmpty()) {
System.out.println("暂无记录");
} else {
for (String history : userHistory) {
System.out.println(history);
}
}
}
}
package game.game2048.util;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/**
* @BelongsProject: Game2048
* @BelongsPackage: game.game2048.util
* @Author: 土里埋埋埋埋埋
* @CreateTime: 2025-08-07 16:21
* @Description: TODO
* @Version: 1.0
*/
public class DbProUtils {
//驱动
private static String driver;
//ID
private static String url;
//数据库用户名
private static String username;
//数据库密码
private static String password;
//静态代码块
static {
try {
Properties prop = new Properties();
prop.load(new FileInputStream("config/db.properties"));
driver = prop.getProperty("driver");
url = prop.getProperty("url");
username = prop.getProperty("username");
password = prop.getProperty("password");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Connection getConnection(){
Connection conn = null;
try {
DbProUtils DbPropUtils = null;
Class.forName(DbPropUtils.getDriver());
conn = DriverManager.getConnection(DbPropUtils.getUrl(),
DbPropUtils.getUsername(),
DbPropUtils.getPassword());
} catch (Exception e) {
throw new RuntimeException(e);
}
return conn;
}
public static void closeConnection(Connection connection){
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public static String getDriver() {
return driver;
}
public static String getUrl() {
return url;
}
public static String getUsername() {
return username;
}
public static String getPassword() {
return password;
}
}
package game.game2048.util;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/**
* @BelongsProject: Game2048
* @BelongsPackage: game.game2048.util
* @Author: 土里埋埋埋埋埋
* @CreateTime: 2025-08-07 16:21
* @Description: TODO
* @Version: 1.0
*/
public class DbProUtils {
//驱动
private static String driver;
//ID
private static String url;
//数据库用户名
private static String username;
//数据库密码
private static String password;
//静态代码块
static {
try {
Properties prop = new Properties();
prop.load(new FileInputStream("config/db.properties"));
driver = prop.getProperty("driver");
url = prop.getProperty("url");
username = prop.getProperty("username");
password = prop.getProperty("password");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Connection getConnection(){
Connection conn = null;
try {
DbProUtils DbPropUtils = null;
Class.forName(DbPropUtils.getDriver());
conn = DriverManager.getConnection(DbPropUtils.getUrl(),
DbPropUtils.getUsername(),
DbPropUtils.getPassword());
} catch (Exception e) {
throw new RuntimeException(e);
}
return conn;
}
public static void closeConnection(Connection connection){
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public static String getDriver() {
return driver;
}
public static String getUrl() {
return url;
}
public static String getUsername() {
return username;
}
public static String getPassword() {
return password;
}
}
package game.game2048.game;
/**
* @BelongsProject: TimeGame
* @BelongsPackage: Demo.game
* @Author: 土里埋埋埋埋埋
* @CreateTime: 2025-07-31 11:14
* @Description: 方向
*/
public enum Direction {
UP, DOWN, LEFT, RIGHT
}
package game.game2048.game;
/**
* @BelongsProject: TimeGame
* @BelongsPackage: Demo.game
* @Author: 土里埋埋埋埋埋
* @CreateTime: 2025-07-31 11:14
* @Description: 游戏主体
*/
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class Game {
private static final int SIZE = 4;
private static final double PROBABILITY_4 = 0.1;
private int[][] board; //游戏地图
private int score; //游戏分数
private boolean gameOver; //游戏结束
private boolean moved; //游戏移动
private int[][] previousBoard; //上一步地图
private int previousScore; //上一步分数
private boolean canUndo; //是否重新开始
private int timeLimit; // 时间限制(秒)
private int remainingTime; // 剩余时间(秒)
private Timer timer; // 计时器
private boolean isTimedMode; // 是否开启计时器
//普通模式
public Game() {
board = new int[SIZE][SIZE];
initializeBoard();
score = 0;
gameOver = false;
canUndo = false;
this.isTimedMode = false;
}
// 限时模式
public Game(boolean isTimedMode, int timeLimit) {
this();
this.isTimedMode = isTimedMode;
this.timeLimit = timeLimit;
this.remainingTime = timeLimit;
if (isTimedMode) {
startTimer();
}
}
public Game(String boardState, int score, boolean timedMode, int timeLimit, int remainingTime) {
}
// 启动计时器
private void startTimer() {
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
synchronized (Game.this) {
if (remainingTime > 0) {
remainingTime--;
} else {
// 时间到,游戏结束
gameOver = true;
timer.cancel();
}
}
}
}, 1000, 1000);
}
// 停止计时器
public void stopTimer() {
if (timer != null) {
timer.cancel();
}
}
// 重新开始游戏
public void resetGame() {
stopTimer();
score = 0;
gameOver = false;
canUndo = false;
board = new int[SIZE][SIZE];
initializeBoard();
// 限时模式处理
if (isTimedMode) {
remainingTime = timeLimit;
startTimer();
}
}
//地图初始化
private void initializeBoard() {
Random random = new Random();
// 四个角落的坐标
int[][] corners = {{0, 0}, {0, SIZE - 1}, {SIZE - 1, 0}, {SIZE - 1, SIZE - 1}};
// 随机选择一个角落放置第一个方格
int cornerIndex = random.nextInt(4);
int row1 = corners[cornerIndex][0];
int col1 = corners[cornerIndex][1];
board[row1][col1] = random.nextDouble() < PROBABILITY_4 ? 4 : 2;
// 找到所有非角落的空位
int[][] nonCornerPositions = new int[(SIZE * SIZE) - 4][2];
int index = 0;
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if ((i == 0 || i == SIZE - 1) && (j == 0 || j == SIZE - 1))
continue;
nonCornerPositions[index][0] = i;
nonCornerPositions[index][1] = j;
index++;
}
}
// 随机选择一个非角落的空位放置第二个方格
int nonCornerIndex = random.nextInt((SIZE * SIZE) - 4);
int row2 = nonCornerPositions[nonCornerIndex][0];
int col2 = nonCornerPositions[nonCornerIndex][1];
board[row2][col2] = random.nextDouble() < PROBABILITY_4 ? 4 : 2;
}
private int[] compress(int[] row) {
int[] newRow = new int[SIZE];
int index = 0;
for (int value : row) {
if (value != 0) {
newRow[index++] = value;
}
}
return newRow;
}
// 合并相邻相同的数字
private int[] merge(int[] row) {
for (int i = 0; i < SIZE - 1; i++) {
if (row[i] != 0 && row[i] == row[i + 1]) {
row[i] *= 2;
row[i + 1] = 0;
}
}
return row;
}
// 加载存档的构造函数
public Game(String boardState, int score) {
board = new int[4][4];
String[] values = boardState.split(",");
int index = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
board[i][j] = Integer.parseInt(values[index++]);
}
}
this.score = score;
gameOver = false;
}
//控制移动
public void move(Direction direction) {
if (gameOver || (isTimedMode && remainingTime <= 0)) {
return;
}
savePreviousState();
moved = false;
switch (direction) {
case UP:
moveUp();
break;
case DOWN:
moveDown();
break;
case LEFT:
moveLeft();
break;
case RIGHT:
moveRight();
break;
}
if (moved) {
addRandomPieces();
gameOver = checkGameOver();
canUndo = true;
} else {
gameOver = checkGameOver();
canUndo = false;
}
savePreviousState();
moved = false;
}
// 矩阵转置
private void transpose() {
for (int i = 0; i < 4; i++) {
for (int j = i + 1; j < 4; j++) {
int temp = board[i][j];
board[i][j] = board[j][i];
board[j][i] = temp;
}
}
}
// 上下翻转(行反转)
private void reverseRows() {
for (int j = 0; j < 4; j++) { // 对每一列
for (int i = 0; i < 2; i++) { // 只需要交换上半部分和下半部分
int temp = board[i][j];
board[i][j] = board[3 - i][j];
board[3 - i][j] = temp;
}
}
}
//上
private void moveUp() {
for (int col = 0; col < 4; col++) {
for (int row = 1; row < 4; row++) {
if (board[row][col] != 0) {
int currentRow = row;
while (currentRow > 0 && board[currentRow - 1][col] == 0) {
board[currentRow - 1][col] = board[currentRow][col];
board[currentRow][col] = 0;
currentRow--;
moved = true;
}
if (currentRow > 0 && board[currentRow - 1][col] == board[currentRow][col]) {
board[currentRow - 1][col] *= 2;
score += board[currentRow - 1][col];
board[currentRow][col] = 0;
moved = true;
}
}
}
}
}
//下
private void moveDown() {
reverseRows();
moveUp();
reverseRows();
}
//左
private void moveLeft() {
transpose();
moveUp();
transpose();
}
//右
private void moveRight() {
transpose();
reverseRows();
moveUp();
reverseRows();
transpose();
}
//添加随机棋子
private void addRandomPieces() {
int emptyCells = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (board[i][j] == 0) {
emptyCells++;
}
}
}
if (emptyCells == 0) return;
Random random = new Random();
int position = random.nextInt(emptyCells);
int value = random.nextDouble() < 0.9 ? 2 : 4;
int count = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (board[i][j] == 0) {
if (count == position) {
board[i][j] = value;
return;
}
count++;
}
}
}
}
//游戏结束条件
public boolean checkGameOver() {
// 限时模式优先判断
if (isTimedMode && remainingTime <= 0) {
return true;
}
// 常规棋盘判断
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (board[i][j] == 0) return false;
if (j < SIZE - 1 && board[i][j] == board[i][j + 1]) {
return false;
}
if (i < SIZE - 1 && board[i][j] == board[i + 1][j]) {
return false;
}
}
}
return true;
}
// 获取剩余时间
public int getRemainingTime() {
return remainingTime;
}
//获取棋盘
public String getBoardState() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
sb.append(board[i][j]);
if (i != 3 || j != 3) {
sb.append(",");
}
}
}
return sb.toString();
}
//保存上一步操作
private void savePreviousState() {
previousBoard = new int[SIZE][SIZE];
for (int i = 0; i < SIZE; i++) {
System.arraycopy(board[i], 0, previousBoard[i], 0, SIZE);
}
previousScore = score;
}
//撤回操作
public void undo() {
if (!canUndo) return;
for (int i = 0; i < SIZE; i++) {
System.arraycopy(previousBoard[i], 0, board[i], 0, SIZE);
}
score = previousScore;
gameOver = false;
canUndo = false;
}
//检查是否可以撤回
public boolean canUndo() {
return canUndo;
}
public int[][] getBoard() {
return board;
}
public int getScore() {
return score;
}
public boolean isGameOver() {
return gameOver;
}
}
将以上代码拆分为类
最新发布