Commit 36b89b8c authored by 刘家荣's avatar 刘家荣 💬
Browse files

refactor(Front & Back, Singleton)

parent e55f7876
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
import view.ChessGameFrame;
import model.Chessboard;

import javax.swing.*;

public class Main {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            ChessGameFrame mainFrame = new ChessGameFrame(720, 720);
            ChessGameFrame mainFrame = new ChessGameFrame(1080, 720);
            mainFrame.setVisible(true);
        });
    }
+0 −111
Original line number Diff line number Diff line
package chessComponent;

import controller.CheckChessLogic;
import controller.ClickController;
import model.ChessColor;
import model.ChessType;
import model.ChessboardPoint;

import java.awt.*;

/**
 * 表示棋盘上非空棋子的格子,是所有非空棋子的父类
 */
public class ChessComponent extends SquareComponent {
    protected final ChessColor chessColor;

    protected final ChessType chessType;

    protected boolean alive;

    public ChessComponent(ChessboardPoint chessboardPoint, Point location,
                             ChessColor chessColor, ChessType chessType, ClickController clickController, int size) {
        super(chessboardPoint, location, clickController, size);
        this.chessColor = chessColor;
        this.chessType = chessType;
        this.alive = true;
    }

    public ChessColor getChessColor() {
        return chessColor;
    }

    public ChessType getChessType() {
        return chessType;
    }

    public boolean isAlive() {
        return alive;
    }

    public void kill(){
        this.alive = false;
    }

    public static String deduceChessName(ChessColor chessColor, ChessType chessType) {
        return switch (chessColor) {
            case RED -> switch (chessType) {
                case CANNON -> "炮";
                case GENERAL ->  "帅";
                case ADVISOR -> "仕";
                case MINISTER -> "相";
                case CHARIOT -> "俥";
                case HORSE -> "傌";
                case SOLDIER -> "兵";
            };
            case BLACK -> switch (chessType) {
                case CANNON ->  "砲";
                case GENERAL -> "将";
                case ADVISOR -> "士";
                case MINISTER -> "象";
                case CHARIOT -> "車";
                case HORSE -> "馬";
                case SOLDIER -> "卒";
            };
            case NONE -> null;
        };
    }
    // handleChess 当前选择的棋子
    public boolean canMoveTo(ChessComponent handleChess,SquareComponent[][] chessboard, ChessboardPoint destination) {
        SquareComponent destinationSquareChess = chessboard[destination.getX()][destination.getY()];
        // downcast
        ChessComponent destinationChess = (ChessComponent) destinationSquareChess;
        //此处判断 handleChess 是否翻转
        return handleChess.isReversal &&
                CheckChessLogic.checkPath(handleChess,chessboard,destinationSquareChess) &&
                CheckChessLogic.checkRank(handleChess,destinationChess) ;
//                (destinationSquareChess.isReversal|| destinationSquareChess instanceof EmptySlotComponent);
        //todo: complete this method
    }

    public String deduceChessName() {
        return deduceChessName(this.chessColor, this.chessType);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        //绘制棋子填充色
        g.setColor(Color.ORANGE);
        g.fillOval(spacingLength, spacingLength, this.getWidth() - 2 * spacingLength, this.getHeight() - 2 * spacingLength);
        //绘制棋子边框
        g.setColor(Color.DARK_GRAY);
        g.drawOval(spacingLength, spacingLength, getWidth() - 2 * spacingLength, getHeight() - 2 * spacingLength);

        if (isReversal) {
            //绘制棋子文字
            g.setColor(this.getChessColor().getColor());
            g.setFont(CHESS_FONT);
            g.drawString(this.deduceChessName(), this.getWidth() / 4, this.getHeight() * 2 / 3);

            //绘制棋子被选中时状态
            if (isSelected()) {
                g.setColor(Color.RED);
                Graphics2D g2 = (Graphics2D) g;
                g2.setStroke(new BasicStroke(4f));
                g2.drawOval(spacingLength, spacingLength, getWidth() - 2 * spacingLength, getHeight() - 2 * spacingLength);
            }
        }
    }

}
+0 −22
Original line number Diff line number Diff line
package chessComponent;

import controller.ClickController;
import model.ChessboardPoint;

import java.awt.*;

/**
 * 这个类表示棋盘上的空棋子的格子
 */
public class EmptySlotComponent extends SquareComponent {

    public EmptySlotComponent(ChessboardPoint chessboardPoint, Point location, ClickController clickController, int size) {
        super(chessboardPoint, location, clickController, size);
    }

    @Override
    public boolean canMoveTo(ChessComponent handleChess,SquareComponent[][] chessboard, ChessboardPoint destination) {
        return false;
    }

}
+0 −131
Original line number Diff line number Diff line
package chessComponent;

import controller.ClickController;
import model.ChessboardPoint;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;

/**
 * 这个类是一个抽象类,主要表示8*4棋盘上每个格子的棋子情况。
 * 有两个子类:
 * 1. EmptySlotComponent: 空棋子
 * 2. ChessComponent: 表示非空棋子
 */
public abstract class SquareComponent extends JComponent {

    private static final Color squareColor = new Color(250, 220, 190);
    protected static int spacingLength;
    protected static final Font CHESS_FONT = new Font("Rockwell", Font.BOLD, 36);

    /**
     * chessboardPoint: 表示8*4棋盘中,当前棋子在棋格对应的位置,如(0, 0), (1, 0)等等
     * chessColor: 表示这个棋子的颜色,有红色,黑色,无色三种
     * isReversal: 表示是否翻转
     * selected: 表示这个棋子是否被选中
     */
    private ChessboardPoint chessboardPoint;

    protected boolean isReversal;
    private boolean selected;

    /**
     * handle click event
     */
    private final ClickController clickController;

    protected SquareComponent(ChessboardPoint chessboardPoint, Point location, ClickController clickController, int size) {
        enableEvents(AWTEvent.MOUSE_EVENT_MASK);
        setLocation(location);
        setSize(size, size);
        this.chessboardPoint = chessboardPoint;
        this.selected = false;
        this.clickController = clickController;
        this.isReversal = false;
    }

    public boolean isReversal() {
        return isReversal;
    }

    public void setReversal(boolean reversal) {
        isReversal = reversal;
    }

    public static void setSpacingLength(int spacingLength) {
        SquareComponent.spacingLength = spacingLength;
    }

    public ChessboardPoint getChessboardPoint() {
        return chessboardPoint;
    }

    public void setChessboardPoint(ChessboardPoint chessboardPoint) {
        this.chessboardPoint = chessboardPoint;
    }

    public boolean isSelected() {
        return selected;
    }

    public void setSelected(boolean selected) {
        this.selected = selected;
    }

    /**
     * @param another 主要用于和另外一个棋子交换位置
     *                <br>
     *                调用时机是在移动棋子的时候,将操控的棋子和对应的空位置棋子(EmptySlotComponent)做交换
     */
    public void swapLocation(SquareComponent another) {
        ChessboardPoint chessboardPoint1 = getChessboardPoint(), chessboardPoint2 = another.getChessboardPoint();
        Point point1 = getLocation(), point2 = another.getLocation();
        setChessboardPoint(chessboardPoint2);
        setLocation(point2);
        another.setChessboardPoint(chessboardPoint1);
        another.setLocation(point1);
    }

    /**
     * @param e 响应鼠标监听事件
     *          <br>
     *          当接收到鼠标动作的时候,这个方法就会自动被调用,调用监听者的onClick方法,处理棋子的选中,移动等等行为。
     */
    @Override
    protected void processMouseEvent(MouseEvent e) {
        super.processMouseEvent(e);
        if (e.getID() == MouseEvent.MOUSE_PRESSED) {
            System.out.printf("Click [%d,%d]\n", chessboardPoint.getX(), chessboardPoint.getY());
            clickController.onClick(this);
        }
    }

    /**
     * @param chessboard  棋盘
     * @param destination 目标位置,如(0, 0), (0, 1)等等
     * @return this棋子对象的移动规则和当前位置(chessboardPoint)能否到达目标位置
     * <br>
     * 这个方法主要是检查移动的合法性,如果合法就返回true,反之是false。
     */
    //todo: Override this method for Cannon
    //todo: add color detect
    //todo: move it to ChessComponent
    public boolean canMoveTo(SquareComponent[][] chessboard, ChessboardPoint destination) {
        //                                                              目的地
        SquareComponent destinationChess = chessboard[destination.getX()][destination.getY()];
        return destinationChess.isReversal|| destinationChess instanceof EmptySlotComponent;
        //todo: complete this method
    }


    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponents(g);
        System.out.printf("repaint chess [%d,%d]\n", chessboardPoint.getX(), chessboardPoint.getY());
        g.setColor(squareColor);
        g.fillRect(1, 1, this.getWidth() - 2, this.getHeight() - 2);
    }

    public abstract boolean canMoveTo(ChessComponent handleChess, SquareComponent[][] chessboard, ChessboardPoint destination);
}
+8 −8
Original line number Diff line number Diff line
package controller;

import chessComponent.ChessComponent;
import chessComponent.EmptySlotComponent;
import chessComponent.SquareComponent;
import model.chess.Chess;
import model.chess.EmptySlot;
import model.chess.Square;
import model.ChessType;
import view.Chessboard;

public class CheckChessLogic  {

@@ -13,7 +12,7 @@ public class CheckChessLogic {

    // 对吃棋时的 path 判定
    // todo : optimize codes below
    public static boolean checkPath(ChessComponent handleChess, SquareComponent[][] chessboard, SquareComponent destination) {
    public static boolean checkPath(Chess handleChess, Square destination) {
        boolean check = false;
        if (handleChess.getChessType() != ChessType.CANNON) {
            check = ((Math.abs(handleChess.getX() - destination.getX()) == 1 && Math.abs(handleChess.getY() - destination.getY()) == 0) ||
@@ -22,7 +21,7 @@ public class CheckChessLogic {
            if (handleChess.getY() == destination.getY()) {
                int count = 0;
                for (int i = Math.min(handleChess.getX(), destination.getX()); i < Math.max(handleChess.getX(), destination.getX()); i++) {
                    if (!(chessboard[i][handleChess.getY()] instanceof EmptySlotComponent)) {
                    if (!(chessboard[i][handleChess.getY()] instanceof EmptySlot)) {
                        count++;
                    }
                }
@@ -30,7 +29,7 @@ public class CheckChessLogic {
            } else if (handleChess.getX() == destination.getX()) {
                int count = 0;
                for (int i = Math.min(handleChess.getY(), destination.getY()); i < Math.max(handleChess.getY(), destination.getY()); i++) {
                    if (!(chessboard[handleChess.getX()][i] instanceof EmptySlotComponent)) {
                    if (!(chessboard[handleChess.getX()][i] instanceof EmptySlot)) {
                        count++;
                    }
                }
@@ -38,12 +37,13 @@ public class CheckChessLogic {
            }
        }
        return check;
        return true;
    }

    /* handleChess 是所执棋子
     * destinationChess 是第二个选中棋子,即被吃的棋子
     * 此处利用 enum 索引,以 <= 判断吃棋是否合规 */
    public static boolean checkRank(ChessComponent handleChess, ChessComponent destinationChess) {
    public static boolean checkRank(Chess handleChess, Chess destinationChess) {
        boolean check = false;
        //已翻转的情况
        //todo: check and delete '!handleChess.isReversal()'
Loading