0
点赞
收藏
分享

微信扫一扫

自定义android音频焦点

何以至千里 03-24 21:01 阅读 2

文章目录

1. 每日一言

Every cloud has a silver lining.
天无绝人之路。


2. 游戏内容介绍

象棋是一种中国传统的棋类游戏,也是世界上最古老、最普及的棋类之一。象棋使用一个棋盘,上面有64个方格,棋盘被分成红棋和黑棋两方,每方有16个棋子。

棋子分别为:帅(将)、仕(士)、相(象)、马、车、炮和兵(卒)。每个棋子都有特定的移动方式和规则。帅/将是最重要的棋子,每方的目标就是要将对方的帅/将困住,使其无法移动。

象棋的游戏目标是要将对方的帅/将逼到无路可走的境地,即将军,并且无论如何对方都无法避免被将军,这就是将军、绝杀的最佳状态,获胜方即为胜利。

本游戏实现了"自弈"功能

游戏截图:
在这里插入图片描述

在这里插入图片描述

3. 代码介绍

该程序使用的GUI为 swing,听说已经过时了。他给我的感受就是,十分难用,而且还丑,也可能是因为我只了解一点点吧。

  1. MainFream 该类是用来管理游戏的总框架,也是程序的入口
  • 其中定义了一个简单的主界面窗口,包含了一个游戏面板和一些按钮,读者可以根据需要进行扩展和实现相应的功能。
  1. GamePanel 该类用来控制游戏面板
    • 主要功能包括:
      创建棋子并将棋子放到数组中
      通过点击事件,判断棋子的选择、移动和吃子操作
      绘制棋盘和棋子的图像
      其中的creatChesses()方法用于创建棋子并将棋子保存到数组中。每个棋子都有一个名称、阵营和网格坐标。棋子的名称、阵营和网格坐标通过数组和循环进行设置。
      MouseAdapter类用于处理鼠标点击事件。在点击事件中,通过获取鼠标点击的坐标,判断是否选中了棋子。根据不同的情况,进行重新选择、移动或吃子操作。在操作完成后,刷新棋盘。
      paint()方法用于绘制棋盘和棋子的图像。首先通过图片路径获取图片对象,然后使用drawImage()方法将图片绘制到面板上。最后调用drawChesses()方法画出棋子的图像。如果有棋子被选中,通过drawRect()方法在棋子周围画出一个矩形框。
  2. ChessFactory 顾名思义,该类用来快速生成棋子
    • 这段代码是一个棋子工厂类。它的作用是根据输入的棋子名称、玩家和位置信息来创建对应的棋子对象。棋子对象根据不同的名称会有不同的移动规则。如果输入的名称是"boss",则创建一个Boss棋子对象
  3. Bing 该类管理兵这个棋子
  4. Boss 该类管理将/帅这个棋子
  5. Che 该类管理车这个棋子
  6. Chess 该类为抽象类用来辅助生成棋子以及判断棋子的前进方式
  7. Ma 该类管理马这个棋子
  8. Pao 该类管理炮这个棋子
  9. Shi 该类管理士这个棋子
  10. Xiang 该类管理象这个棋子

具体可以看代码中的注释。

4. 全部代码

4.1 MainFream

package com.code.main;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

//主界面
public class MainFream extends JFrame implements ActionListener {
    public MainFream() {
        //设置窗口大小
        setSize(480,480);
//        setSize(580,500);
        //设置窗口居中
        setLocationRelativeTo(null);
        //设置点击关闭按钮同时结束虚拟机
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //设置布局管理员
        setLayout(new BorderLayout());
        //将游戏面板添加到窗口中
        GamePanel gp = new GamePanel();
        add(gp, BorderLayout.CENTER);
        //添加按钮面板
        JPanel btnPanel = new JPanel(new GridLayout(4,1));
        //add(btnPanel,BorderLayout.EAST);
        add(btnPanel,BorderLayout.EAST);
        JLabel hintLabel = new JLabel("红方走");
        btnPanel.add(hintLabel);
        gp.setHintLabel(hintLabel);
//        JButton btnHuiQi = new JButton("悔棋");
//        btnHuiQi.setActionCommand("huiqi");
//        btnHuiQi.addActionListener(this);
//        btnPanel.add(btnHuiQi);
//        JButton btnSave = new JButton("保存棋谱");
//        btnSave.setActionCommand("baocun");
//        btnSave.addActionListener(this);
//        btnPanel.add(btnSave);
//        JButton btnImport = new JButton("导入棋谱");
//        btnImport.setActionCommand("daoru");
//        btnImport.addActionListener(this);
//        btnPanel.add(btnImport);
//        JButton btnQiuHe = new JButton("求和");
//        btnQiuHe.setActionCommand("qiuhe");
//        btnQiuHe.addActionListener(this);
//        btnPanel.add(btnQiuHe);
//        JButton btnRenShu= new JButton("认输");
//        btnRenShu.setActionCommand("renshu");
//        btnRenShu.addActionListener(this);
//        btnPanel.add(btnRenShu);
        //设置窗口可见,建议放在后面
        setVisible(true);
    }
    public static void main(String[] args) {
        //JFrame frm = new JFrame();
        //JFrame默认是一个看不见的窗口

        new MainFream();//匿名对象
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("按钮被点击了");
        //获取按钮的ActionCommand
        String cmd = e.getActionCommand();
        switch (cmd) {
            case "huiqi":
                System.out.println("huiqi");
                break;
            case "baocun":
                System.out.println("baocun");
                break;
            case "daoru":
                System.out.println("daoru");

                break;
            case "qiuhe":
                System.out.println("qiuhe");

                break;
            case "renshu":
                System.out.println("renshu");

                break;
        }
    }
}

4.2 GamePanel

package com.code.main;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.Arrays;

//游戏面板
public class GamePanel extends JPanel {
    private Chess[] chesses = new Chess[32];//保存所有棋子

    private Chess selectedChess;//当前选中的棋子

    //记住当前阵营
    private int curPlayer = 0;//红方先手

    private JLabel hintLabel;

    public void setHintLabel(JLabel hintLabel) {
        this.hintLabel = hintLabel;
    }

    public GamePanel() {
        creatChesses();

        /*  如何操作棋子
                1 点击棋盘
                2 如何获取棋子对象(如何判断点击的地方是否有棋子)
                3 如何区分选择,重新选择,移动,吃子

            棋盘规则
                1 红方不能操作黑方的棋子
                2 一方走完,另一方才能走
         */

        //添加点击事件
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                //通过e可以获得鼠标点击的坐标
                Point p = Chess.getPointFromXY(e.getX(),e.getY());
                if(selectedChess == null) {
                    //没选过棋子
                    selectedChess = getChessByP(p);
                    if(selectedChess != null && selectedChess.getPlayer() != curPlayer) {
                        //选了对面的棋子
                        selectedChess = null;
                        hintLabel.setText("<html> 不能选择对方的棋子<br/> " + (curPlayer == 0 ? "红方走" : "黑方走") + "</html>");
                    }
                }else {
                    //重新选择,移动,吃子
                    Chess c = getChessByP(p);
                    if(c != null) {
                        //第n次点击的时候有棋子
                        //重新选择,吃子
                        if(c.getPlayer() == selectedChess.getPlayer()) {
                            //重新选择
                            System.out.println("重新选择");
                            selectedChess = c;
                        }else {
                            //吃子
                            System.out.println("吃子");
                            if(selectedChess.isAbleMove(p,GamePanel.this)) {
                                /*  从数组中删除被吃掉的棋子
                                    修改要移动的棋子
                                 */
                                chesses[c.getIndex()] = null;
                                if(c.getIndex() == 4) {
                                    hintLabel.setText("红方获胜");
//                                    while (true) {
//                                        try {
//                                            Thread.sleep(1000);
//                                        } catch (InterruptedException ex) {
//                                            throw new RuntimeException(ex);
//                                        }
//                                    }
                                } else if (c.getIndex() == 20) {
                                    hintLabel.setText("黑方获胜");
//                                    while (true) {
//                                        try {
//                                            Thread.sleep(1000);
//                                        } catch (InterruptedException ex) {
//                                            throw new RuntimeException(ex);
//                                        }
//                                    }
                                } else {
                                    selectedChess.setP(p);
                                    overMyTurn();
                                }

                            }
                        }
                    }else {
                        //第n次点击的时候没有棋子,点的是空地
                        //移动
                        System.out.println("移动");
                        if(selectedChess.isAbleMove(p,GamePanel.this)) {
                            selectedChess.setP(p);
                            overMyTurn();
                        }
                    }
                }
                //System.out.println("点击的棋子对象为:" + selectedChess);
                //刷新棋盘,即重新执行paint方法
                repaint();
            }
        });
    }

    //一方走完了,换成另一方走
    private void overMyTurn() {
        curPlayer = curPlayer == 0 ? 1 : 0;
        //将选择的棋子放下
        selectedChess = null;
        hintLabel.setText(curPlayer == 0 ? "红方走" : "黑方走");
    }

    //查找棋子对象
    public Chess getChessByP(Point p) {
        for (Chess item : chesses) {
            if(item != null && item.getP().equals(p)) {
                return item;
            }
        }
        return null;
    }

    //创建棋子并将棋子放到数组中
    private void creatChesses() {
        String[] names = {"che","ma","xiang","shi","boss","shi","xiang","ma","che","pao","pao","bing","bing","bing","bing","bing"};
        int[] xs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 2, 8, 1, 3, 5, 7, 9};
//        for (int i = 0; i < names.length; i++) {
            Chess c = new Chess(names[i],1,ps[i]);
            c.setName(names[i]);
            c.setP(ps[i]);//指定棋子的网格坐标
            c.setPlayer(1);//设置阵营
//            Chess c = ChessFactory.create(names[i],0,xs[i]);
//
//            c.reserve();
//            c.setIndex(i+16);
//            chesses[c.getIndex()] = c;
//        }
        for (int i = 0; i < names.length; i++) {
           Chess c = ChessFactory.create(names[i],1,xs[i]);
//            c.setName(names[i]);
//            c.setP(ps[i]);//指定棋子的网格坐标
//            c.setPlayer(0);//设置阵营
            c.setIndex(i);
            chesses[i] = c;//将棋子保存到数组中
            //System.out.println(c);
        }
        for (int i = 0; i < names.length; i++) {
//            Chess c = new Chess(names[i],1,ps[i]);
//            c.setName(names[i]);
//            c.setP(ps[i]);//指定棋子的网格坐标
//            c.setPlayer(1);//设置阵营
            Chess c = ChessFactory.create(names[i],0,xs[i]);

            c.reserve();
            c.setIndex(i+16);
            chesses[c.getIndex()] = c;
        }
    }


    //画棋子
    private void drawChesses(Graphics g) {
        for (Chess item:chesses) {
            if(item != null) {
                item.draw(g,this);
            }

        }
    }
    @Override
    public void paint(Graphics g) {
        //super.paint(g);//清除原来的痕迹

        /*  paint 方法是JPanel的绘制面板内容的方法
            Graphics:绘制类
                常用方法
                    g.drawImage:画图片
                    g.drawChars:画文字
                    g.drawLine:画直线
                    drawOval:画园或椭圆
            如何在Jpanel画一张图1
             1 准备图片路径
                File.separator:路径分隔符
             2 通过图片路径得到图片对象
             3 使用g.drawImage方法将图片绘制到面板上
         */
        //1.准备图片路径
        String bgPath = "pic" + File.separator +  "qipan.jpg";
        //2 通过图片路径得到图片对象
        /*  Toolkit.getDefaultToolkit():获取Toolkit的实例
            createImage():创建图片
            getImage():获取图片
         */
        Image bgImg = Toolkit.getDefaultToolkit().getImage(bgPath);
        //3 使用g.drawImage方法将图片绘制到面板上
        g.drawImage(bgImg,0,0,this);
        /*
            img:要汇总的图片对象
            x:坐标x,在编程中坐标都是从左上角开始,往右是正数
            y:坐标y,往下是正数
            observer:图片观察者,写JPanel对象即可
         */
        //如何画棋子
        /*String Path = "pic" + File.separator +  "che0.png";
        Image img = Toolkit.getDefaultToolkit().getImage(Path);
        //g.drawImage(che0Img,0,0,this);
        g.drawImage(img,5,5,30,30,this);
         */

        drawChesses(g);//画棋子

        if(selectedChess != null) {
            selectedChess.drawRect(g);
        }
    }


}

4.3 ChessFactory

package com.code.main;

//生成棋子
public class ChessFactory {
    private ChessFactory() {

    }

    public static Chess create(String name,int player,int px) {
        //定制棋子移动的规则
        if("boss".equals(name)) {
            return new Boss(player,px);
        }else if("shi".equals(name)){
            return new Shi(player,px);
        }else if("xiang".equals(name)){
            return new Xiang(player,px);
        }else if("ma".equals(name)){
            return new Ma(player,px);
        }else if("che".equals(name)){
            return new Che(player,px);
        }else if("pao".equals(name)){
            return new Pao(player,px);
        }else if("bing".equals(name)){
            return new Bing(player,px);
        }
        return null;
    }

}

4.4 Bing

package com.code.main;

import com.code.main.Chess;
import com.code.main.GamePanel;

import java.awt.*;

public class Bing extends Chess {
    public Bing(int player, Point p) {
        super("bing",player,p);
    }

    public Bing(int player, int px) {
        this(player, new Point(px,4));
    }

    @Override
    public boolean isAbleMove(Point tp, GamePanel gamePanel) {
        if(line(tp) < 2 || getStep(tp) > 1) {
                //不是走直线 || 走的步数大于一
                return false;
            }
            if(isOverRiver(p)) {
                //过河 ,不往前后
                return !isBack(tp);
            } else {
                //没过河,只能前进
                return isForward(tp);
            }
    }
}

4.5 Boss

package com.code.main;

import java.awt.*;

public class Boss extends Chess{
    public Boss(int player, Point p) {
        super("boss",player,p);
    }

    public Boss(int player, int px) {
        this(player, new Point(px,1));
    }

    @Override
    public boolean isAbleMove(Point tp, GamePanel gamePanel) {
        return line(tp) > 1 && isHome(tp) && getStep(tp) == 1;
    }
}

4.6 Che

package com.code.main;

import java.awt.*;

public class Che extends Chess{
    public Che(int player, Point p) {
        super("che", player, p);
    }

    public Che(int player, int px) {
        this(player, new Point(px,1));
    }

    @Override
    public boolean isAbleMove(Point tp, GamePanel gamePanel) {
    	//只能横竖走,并且与目的地之间没有棋子阻挡
        return line(tp) > 1 && getCount(tp,gamePanel) == 0;
    }
}

4.7 Chess

package com.code.main;

import javax.swing.*;
import java.awt.*;
import java.io.File;

public abstract class Chess {
    //棋子大小
    private static final int SIZE = 30;
    //棋盘外边距
    private static final int MARGIN = 20;
    //棋子间距
    private static final int SPACE = 40;
    //棋子名字
    private String name;
    //后缀
    private String suffix = ".png";
    //棋子阵营
    protected int player;

    //绘制时的坐标
    private int x,y;

    //棋子的网格坐标
    protected Point p;

    //棋子的网格坐标,初始位置,不可改变
    private Point initP;

    //保存每个棋子的索引位置
    private int index;
    public void setIndex(int index) {
        this.index = index;
    }

    public int getIndex() {
        return index;
    }

    public int isUpOrDown() {
        //上面和下面的棋子
        //1.上
        //2.下
        if(initP.y < 6 ) {
            //上面
            return 1;
        }else if(initP.y > 5) {
            //下面
            return 2;
        }else {
            return 0;
        }
    }

    //判断棋子是否在王宫范围内
    public boolean isHome(Point tp) {
        if(tp.x < 4 || tp.x > 6) {
            return false;
        }
        int upOrDown = isUpOrDown();
        if(upOrDown == 1) {
            //上
            if(tp.y > 3 || tp.y < 1) {
                return false;
            }
        } else if (upOrDown == 2) {
            //下
            if(tp.y > 10 || tp.y < 8) {
                return false;
            }
        }
        return true;
    }

    //判断棋子是否走直线
    //1.走斜线
    //2.y直线
    //3.x直线
    //0. x轴日字
    //-1 y轴日字
    //-2.都不是
    public int line(Point tp) {
        if(p.y == tp.y) {
            //X轴直线
            return 3;
        }else if(p.x == tp.x) {
            //Y轴直线
            return 2;
        }else  if(Math.abs(p.x - tp.x) == Math.abs(p.y - tp.y)) {
            //走斜线
            return 1;
        } else {
            //日字
            if(Math.abs(p.x - tp.x) == 2 && Math.abs(p.y - tp.y) == 1) {
                //x
                return 0;
            } else if (Math.abs(p.x - tp.x) == 1 && Math.abs(p.y - tp.y) == 2) {
                //y
                return -1;
            }
        }
        return -2;
    }

    //计算棋子走的步数,起点到终点的步数
    public int getStep(Point tp) {
        int line = line(tp);
        if(line == 3) {
            //x
            return Math.abs(p.x - tp.x);
        }else if(line == 2 || line == 1) {
            //y,正斜线
            return Math.abs(p.y - tp.y);
        }

        return 0;
    }

    //判断象或马是否蹩脚,原理是判断蹩脚点是否存在棋子
    public boolean isBieJiao(Point tp,GamePanel gamePanel) {
        Point center = new Point();//中心点
        if("xiang".equals(name)) {
            //象
            center.x = (p.x + tp.x) / 2;
            center.y = (p.y + tp.y) / 2;
            //System.out.println(gamePanel.getChessByP(center));
            return gamePanel.getChessByP(center) != null;
        }else if("ma".equals(name)) {
        	//马
            int line = line(tp);
            if(line == 0) {
                //x
                center.x = (p.x + tp.x) / 2;
                center.y = p.y;
                return gamePanel.getChessByP(center) != null;
            }else if(line == -1) {
                //y
                center.y = (p.y + tp.y) / 2;
                center.x = p.x;
                return gamePanel.getChessByP(center) != null;
            }
        }
        return true;
    }

    //判断目标点是否过河
    public boolean isOverRiver(Point tp) {
        int upOrDown = isUpOrDown();
        if(upOrDown == 1) {
            //上
            if(tp.y < 6) {
                return false;
            }
        } else if (upOrDown == 2) {
            //下
            if(tp.y > 5) {
                return false;
            }
        }

        return true;
    }

    //判断棋子是否能移动到指定的位置
    public abstract boolean isAbleMove(Point tp,GamePanel gamePanel);

    //计算起点到目标点之间的棋子数量,不计算起点的棋子
    public int getCount(Point tp,GamePanel gamePanel) {
        int start = 0;
        int end = 0;
        int count = 0;//统计棋子数量
        int line = line(tp);
        Point np = new Point();
        if(line == 2)  {
            //y
            np.x = tp.x;
            if(tp.y > p.y) {
                //从上往下
                start = p.y + 1;
                end = tp.y;
            } else {
                //从下往上
                start = tp.y + 1;
                end = p.y;
            }
            for(int i = start; i < end; i++) {
                np.y = i;
                if(gamePanel.getChessByP(np) != null) {
                    count++;
                }
            }
        } else if (line == 3) {
            //x
            np.y = tp.y;
            if(tp.x > p.x) {
                //从左往右
                start = p.x + 1;
                end = tp.x;
            } else {
                //从右往左
                start = tp.x + 1;
                end = p.x;
            }
            for(int i = start; i < end; i++) {
                np.x = i;
                if(gamePanel.getChessByP(np) != null) {
                    count++;
                }
            }
        }
        return count;
    }

    //是否前进
    public boolean isForward(Point tp) {
        int upOrDown = isUpOrDown();
        if(upOrDown == 1) {
            //上
            if(tp.y > p.y) {
                return true;
            }
        } else if (upOrDown == 2) {
            //下
            if(tp.y < p.y) {
                return true;
            }
        }
        return false;
    }

    //是否后退
    public boolean isBack(Point tp) {
        int upOrDown = isUpOrDown();
        if(upOrDown == 1) {
            //上
            if(tp.y < p.y) {
                return true;
            }
        } else if (upOrDown == 2) {
            //下
            if(tp.y > p.y) {
                return true;
            }
        }
        return false;
    }
    //棋子的绘制方法
    public void draw(Graphics g, JPanel panel) {
        String path = "pic" + File.separator + name + player +suffix;
        Image img = Toolkit.getDefaultToolkit().getImage(path);
        g.drawImage(img,x,y,SIZE,SIZE,panel);
    }

    //为选中的棋子画一个边框
    public void drawRect(Graphics g) {
        g.drawRect(x,y,SIZE,SIZE);
    }

        //计算xy的绘制坐标
    public void calXY() {
        this.x = MARGIN - SIZE / 2 + SPACE * (p.x - 1);
        this.y = MARGIN - SIZE / 2 + SPACE * (p.y - 1);
    }

    public void setP(Point p) {
        this.p = (Point) p.clone();
        if(initP == null) {
            initP = this.p;
        }
        calXY();
    }

    public int getPlayer() {
        return player;
    }

    public Point getP() {
        return p;
    }

    //根据xy坐标计算网格坐标对象
    public static Point getPointFromXY(int x,int y) {
        Point p = new Point();
        p.x = (x - MARGIN + SIZE / 2) / SPACE + 1;
        p.y = (y - MARGIN + SIZE / 2) / SPACE + 1;
        if (p.x < 1 || p.x > 9 || p.y < 1 || p.y > 10) {
            return null;
        }
        return p;
    }
    //反转网格坐标
    public void reserve() {
        p.x = 10 - p.x;
        p.y = 11 - p.y;
        initP = p;
        calXY();
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPlayer(int player) {
        this.player = player;
    }

    public void Point(int x,int y) {
        this.x = x;
        this.y = y;
    }

    public Chess(String name, int player, Point p) {
        this.name = name;
        this.player = player;
        setP(p);
    }

    public Chess() {

    }
}

4.8 Ma

package com.code.main;

import java.awt.*;

public class Ma extends Chess{
    public Ma(int player,Point p) {
        super("ma",player,p);
    }

    public Ma(int player, int px) {
        this(player, new Point(px,1));
    }

    @Override
    public boolean isAbleMove(Point tp, GamePanel gamePanel) {
            return (line(tp) == 0 || line(tp) == -1) && !isBieJiao(tp,gamePanel);
    }
}

4.9 Pao

package com.code.main;

import com.code.main.Chess;
import com.code.main.GamePanel;

import java.awt.*;

public class Pao extends Chess {
    public Pao(int player, Point p) {
        super("pao",player,p);
    }

    public Pao(int player, int px) {
        this(player, new Point(px,3));
    }
    @Override
    public boolean isAbleMove(Point tp, GamePanel gamePanel) {
        Chess c = gamePanel.getChessByP(tp);
            if(c != null) {
                //有棋子
                if(c.getPlayer() != this.player) {
                    //吃子
                    return line(tp) > 1 && getCount(tp, gamePanel) == 1;
                }
            } else {
                //移动
                return line(tp) > 1 && getCount(tp, gamePanel) == 0;
            }
            return false;
    }
}

4.10 Shi

package com.code.main;

import java.awt.*;

public class Shi extends Chess{
    public Shi(int player, Point p) {
        super("shi", player, p);
    }

    public Shi(int player, int px) {
        this(player, new Point(px,1));
    }

    @Override
    public boolean isAbleMove(Point tp, GamePanel gamePanel) {
        return line(tp) == 1 && isHome(tp) && getStep(tp) == 1;
    }
}

4.11 Xiang

package com.code.main;

import java.awt.*;

public class Xiang extends Chess{
    public Xiang(int player, Point p) {
        super("xiang",player,p);
    }

    public Xiang(int player, int px) {
        this(player, new Point(px,1));
    }

    @Override
    public boolean isAbleMove(Point tp, GamePanel gamePanel) {
        return  line(tp) == 1 && getStep(tp) == 2 && !isBieJiao(tp,gamePanel) && !isOverRiver(tp);
    }
}


结语

本人水平有限,如有bug还请见谅

请给自己些耐心,一口吃不成胖子。
山外青山楼外楼,莫把百尺当尽头。
保持空杯心态加油努力吧!


都看到这里啦!真棒(*^▽^*)

可以给作者一个免费的赞赞吗,这将会鼓励我继续创作,谢谢大家

编程小白写作,如有纰漏或错误,欢迎指正


举报

相关推荐

0 条评论