11.25
[实验任务一]:围棋
设计一个围棋软件,在系统中只存在一个白棋对象和一个黑棋对象,但是它们可以在棋盘的不同位置显示多次。
实验要求:
- 提交类图;
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.要求用简单工厂模式和单例模式实现享元工厂类的设计。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步