11.25

[实验任务一]:围棋
设计一个围棋软件,在系统中只存在一个白棋对象和一个黑棋对象,但是它们可以在棋盘的不同位置显示多次。
实验要求:

  1. 提交类图;

2.提交源代码;

package xiangyuan;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Hashtable;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static xiangyuan.ChessmanHelper.createDefaultPiece;

// 坐标类
class Coordinates {
    private int x;
    private int y;
    
    public Coordinates(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public int getX() { return x; }
    public void setX(int newX) { this.x = newX; }
    public int getY() { return y; }
    public void setY(int newY) { this.y = newY; }
}

// 抽象围棋棋子类
abstract class IgoChessman {
    protected BufferedImage image;
    
    public abstract String getColor();
    
    public void setImage(BufferedImage img) {
        this.image = img;
    }
    
    public BufferedImage getImage() {
        return this.image;
    }
}

// 白棋类
class WhiteIgoChessman extends IgoChessman {
    public WhiteIgoChessman() {
        try {
            this.image = ImageIO.read(new File("D:\\paradox\\jisuan\\src\\main\\resources\\baizi.png"));
        } catch (IOException e) {
            System.out.println("无法加载白子图片");
            // 创建一个默认的白色棋子图像
            this.image = createDefaultPiece(Color.WHITE);
        }
    }
    
    @Override
    public String getColor() {
        return "white";
    }
}

// 黑棋类
class BlackIgoChessman extends IgoChessman {
    public BlackIgoChessman() {
        try {
            this.image = ImageIO.read(new File("D:\\paradox\\jisuan\\src\\main\\resources\\heizi.png"));
        } catch (IOException e) {
            System.out.println("无法加载黑子图片");
            // 创建一个默认的黑色棋子图像
            this.image = createDefaultPiece(Color.BLACK);
        }
    }
    
    @Override
    public String getColor() {
        return "black";
    }
}

// 创建默认棋子图像的辅助方法(当无法加载图片时使用)
class ChessmanHelper {
    public static BufferedImage createDefaultPiece(Color color) {
        BufferedImage img = new BufferedImage(30, 30, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = img.createGraphics();
        g2d.setColor(color);
        g2d.fillOval(0, 0, 28, 28);
        g2d.setColor(color == Color.BLACK ? Color.WHITE : Color.BLACK);
        g2d.drawOval(0, 0, 28, 28);
        g2d.dispose();
        return img;
    }
}

// 享元工厂类(单例模式)
class IgoChessmanFactory {
    private static IgoChessmanFactory instance = new IgoChessmanFactory();
    private Hashtable<String, IgoChessman> ht;
    
    private IgoChessmanFactory() {
        ht = new Hashtable<String, IgoChessman>();
        IgoChessman black = new BlackIgoChessman();
        IgoChessman white = new WhiteIgoChessman();
        ht.put("black", black);
        ht.put("white", white);
    }
    
    public static IgoChessmanFactory getInstance() {
        return instance;
    }
    
    public IgoChessman getIgoChessman(String color) {
        return ht.get(color);
    }
}

// 棋盘面板类
class GoBoardPanel extends JPanel {
    private static final int BOARD_SIZE = 19;
    private static final int CELL_SIZE = 30;
    private static final int MARGIN = 20;
    private static final int PIECE_SIZE = 28;
    
    private List<PlacedPiece> pieces = new ArrayList<>();
    private boolean isBlackTurn = true;
    private IgoChessmanFactory factory = IgoChessmanFactory.getInstance();
    
    private class PlacedPiece {
        IgoChessman chessman;
        Point position;
        
        PlacedPiece(IgoChessman chessman, Point position) {
            this.chessman = chessman;
            this.position = position;
        }
    }
    
    public GoBoardPanel() {
        setBackground(new Color(0xcc5511));
        
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                handleMouseClick(e.getPoint());
            }
        });
    }
    
    private void handleMouseClick(Point clickPoint) {
        // 计算最近的交叉点
        int x = Math.round((float)(clickPoint.x - MARGIN) / CELL_SIZE);
        int y = Math.round((float)(clickPoint.y - MARGIN) / CELL_SIZE);
        
        // 检查是否在有效范围内
        if (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE) {
            // 检查该位置是否已经有棋子
            Point gridPoint = new Point(x, y);
            if (!isPositionOccupied(gridPoint)) {
                // 获取当前回合的棋子
                IgoChessman piece = factory.getIgoChessman(isBlackTurn ? "black" : "white");
                // 添加棋子到列表
                pieces.add(new PlacedPiece(piece, gridPoint));
                // 切换回合
                isBlackTurn = !isBlackTurn;
                // 重绘棋盘
                repaint();
            }
        }
    }
    
    private boolean isPositionOccupied(Point position) {
        for (PlacedPiece piece : pieces) {
            if (piece.position.equals(position)) {
                return true;
            }
        }
        return false;
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        
        // 启用抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        
        // 绘制棋盘线
        g2d.setColor(Color.BLACK);
        // 绘制垂直线
        for (int i = 0; i < BOARD_SIZE; i++) {
            g2d.drawLine(MARGIN + i * CELL_SIZE, MARGIN,
                        MARGIN + i * CELL_SIZE, MARGIN + (BOARD_SIZE - 1) * CELL_SIZE);
        }
        // 绘制水平线
        for (int i = 0; i < BOARD_SIZE; i++) {
            g2d.drawLine(MARGIN, MARGIN + i * CELL_SIZE,
                        MARGIN + (BOARD_SIZE - 1) * CELL_SIZE, MARGIN + i * CELL_SIZE);
        }
        
        // 绘制天元和星位
        drawStarPoints(g2d);
        
        // 绘制所有棋子
        for (PlacedPiece piece : pieces) {
            int screenX = MARGIN + piece.position.x * CELL_SIZE - PIECE_SIZE/2;
            int screenY = MARGIN + piece.position.y * CELL_SIZE - PIECE_SIZE/2;
            
            if (piece.chessman.getImage() != null) {
                g2d.drawImage(piece.chessman.getImage(), screenX, screenY, PIECE_SIZE, PIECE_SIZE, null);
            }
        }
    }
    
    private void drawStarPoints(Graphics2D g) {
        int[] starPoints = {3, 9, 15};  // 星位的坐标
        
        g.setColor(Color.BLACK);
        for (int x : starPoints) {
            for (int y : starPoints) {
                g.fillOval(MARGIN + x * CELL_SIZE - 3,
                          MARGIN + y * CELL_SIZE - 3,
                          6, 6);
            }
        }
    }
    
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(BOARD_SIZE * CELL_SIZE + 2 * MARGIN,
                           BOARD_SIZE * CELL_SIZE + 2 * MARGIN);
    }
}

// 主窗口类
class GoGame extends JFrame {
    public GoGame() {
        setTitle("围棋");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        GoBoardPanel boardPanel = new GoBoardPanel();
        add(boardPanel);
        
        pack();
        setLocationRelativeTo(null);  // 窗口居中
        setResizable(false);
    }
}

// 主类
public class Main {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            GoGame game = new GoGame();
            game.setVisible(true);
        });
    }
}

3.注意编程规范;
4.要求用简单工厂模式和单例模式实现享元工厂类的设计。

posted @   aallofitisst  阅读(6)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示