上次我们基本实现了五子棋游戏的功能,这次我们进行一些优化和添加一些便于用户使用的功能。

新增功能及优化

一、复盘功能

复盘功能就是指在下完一局棋后,我们可以通过复盘按钮使本局棋的所有棋子重头开始自动下一遍。分析得知,我们首先要保存以及下过的棋子数据,然后清空棋盘上的数据并刷新棋盘,然后利用保存的数据开始自动有间隔的绘制。

①保存数据

我们重绘所需要的数据都存在一个一维数组shapeArr中,我们需要取出并保存。

由于下一步需要清空这个数组的数据,我们需要定义一个新的数据依次保存shapeArr中的数据,我们命名为tempArr(临时数组)。需要注意的是,我们不能直接tempArr=shapeArr保存,否则这两个对象会公用同一个内存空间,到时候清空时两个会一起清空而无法保存数据。我们应该采用遍历的方法保存数组数据。最后,调用一下下棋面板的重绘方法刷新棋盘即可。⭐⭐⭐

//先保存所有下过的棋子数据for (int i = 0; i < shapeArr.length; i++) {tempArr[i] = shapeArr[i];}//再清除所有数据,刷新棋盘for (int i = 0; i < tempArr.length; i++) {shapeArr[i] = null;//tempArr数据还在!}
centerPanel.paint(g);

保存好数据之后,我们就可以利用保存的数据逐个绘制棋子。

②绘制棋子

我们希望的是点击复盘按钮后,先等待一会再开始下棋,并且下每颗棋子中间需要有间隔,所以需要使用到延时操作。代码为:

try {
Thread.sleep(延时时间,单位为毫秒);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}

然后我们遍历一下新定义的数组tempArr,取出数据调用定义的drawShape方法(绘制棋子)就可以重新绘制棋子,再加一个延时操作就可以实现复盘功能。

try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}//再遍历tempArr数组,重新绘制棋子for (int i = 0; i < tempArr.length; i++) {Shape s = tempArr[i];if (s == null) break;s.drawShape(g);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}

 

二、标注所下的最后一颗棋子

我们希望使用者能时刻知道所下最后一颗棋子的位置,所以我们可以添加在最后一颗棋子上绘制一个红点的功能。

分析可知道,我们可以在MPanel类里面书写,因为里面有paint方法,不用担心重绘的问题。我们可以单独书写一个方法point,用于书写绘制的代码,并在paint中调用。同时,我们需要随时更新chessX和chessY的数据以绘制在最后一颗棋子上,而所需的数据在drawListener里,所以在drawListener里调用centerPanel对象中的x,y,用本类中的chessX和chessY赋值即可。注意:要写在点击方法中,以实现每点击下一颗棋子就更新一次数据。

public void point(Graphics g){Graphics2D g1=(Graphics2D)g;((Graphics2D) g).setStroke(new BasicStroke(5));g.setColor(Color.RED);g.drawLine(x * SIZE + X0 , y * SIZE + Y0 , x * SIZE + X0, y * SIZE + Y0);}
//实时更新棋子的坐标情况(写在点击方法中)centerPanel.x = chessX;centerPanel.y = chessY;

完成上述步骤后,发现点击悔棋、复盘按钮时红色标注无法移动到上一颗棋子中,点击重新开始按钮时无法将红色标点去掉的问题,下面来逐个解决优化。

①悔棋移动

点击悔棋时,我们需要的效果是将红色标注移动到最近的上一颗棋子,其实就是我们需要的chessX和chessY发生了变化,而由于每步的点坐标数据都存储到一维数组shapeArr中,我们只需要定义一个同类对象保存数组下标为(index-1)对应的数据,并通过这个数据给MPanel里面的x,y重新赋值就可以了。

case "悔棋": {index--;
//保存上一颗最近棋子的数据Shape s1 = shapeArr[index - 1];centerPanel.x = s1.x;centerPanel.y = s1.y;
}

②重新开始、复盘时清空红色标注

点击重新开始和复盘时,我们需要棋盘上什么都没有,所以我们需要将传过去的chessX和chessY设置成不能用于绘制红色标点的数值,这样就不会残存红色标点了。

case "重新开始": {
//将最后一个红点去除掉centerPanel.x=-1;centerPanel.y=-1;
}
case "复盘": {//将最后一个红点去除掉centerPanel.x=-1;centerPanel.y=-1;
}

 

三、显示当前下棋方以及步数

我们希望在南边容器中显示当前下棋方以及步数,为了效果更好,建议使用JLabel标签组件,而不是绘制字符串的drawString。(注意:JLabel组件只能在GameUI(窗体)中创建并添加!)

添加好之后,我们需要用标记位flag来判断是哪方即将下棋,用index来显示当前的步数,而这些数据都在drawListener类中,但是千万注意:不能把数据传到GameUI中!因为这个类里面的init方法只能调用一次,即使传递数据也无法实现数据的更新,所以我们应该考虑将JLabel传递到drawLisener中去实现更改。由于在GameUI中已经创建过drawLisener对象,所以直接通过构造方法传递JLabel即可。

传递完毕之后,添加一个方法,按照下棋的情况用setText关键字输入对应的文字即可。设置字体:setFont;设置前颜色:setForeBackground

然后,在控制下棋的switch分支中调用UI方法。

JLabel jl=new JLabel("黑方执子:"+0);
jl.setFont(new Font("宋体",Font.BOLD,20));
//显示当前下棋方以及步数public void UI() {if (flag == 0) {jl.setFont(new Font("宋体", Font.BOLD, 20));jl.setText("黑方执子:" + (index + 1));} else if (flag == 1) {jl.setFont(new Font("宋体", Font.BOLD, 20));jl.setText("白方执子:" + (index + 1));}}

同时,我们可以优化显示胜利的标语,将其改成JLabel,并显示在北边的容器中。

 JLabel jl1=new JLabel("谁会获得最终胜利?敬请期待!");jl1.setForeground(Color.BLACK);
jl1.setFont(new Font("宋体",Font.BOLD,20));
northPanel.add(jl1);
//判断输赢if (isWin() >= 5 || isWin1() >= 5 || isWin2() >= 5 || isWin3() >= 5) {flag = 3;System.out.println("本局已结束,请点击重新开始按钮!");if (chess[chessY][chessX] == 1) {jl1.setForeground(Color.RED);jl1.setText("黑方获胜!");} else if (chess[chessY][chessX] == 2) {jl1.setForeground(Color.RED);jl1.setText("白方获胜!");}}}

经历以上的步骤,五子棋游戏的第一版本功能添加以及优化就基本完成了!

 

完整代码以及效果

完整代码

import javax.swing.*;
import java.awt.*;
public class GameUI implements Conbig {public void init() {JFrame jf = new JFrame();jf.setSize(700, 700);jf.setTitle("五子棋游戏1.0");jf.setLocationRelativeTo(null);jf.setDefaultCloseOperation(3);BorderLayout bl=new BorderLayout();jf.setLayout(bl);JPanel southPanel=new JPanel();JPanel northPanel=new JPanel();Dimension dm=new Dimension(0,35);southPanel.setBackground(Color.pink);southPanel.setPreferredSize(dm);northPanel.setPreferredSize(new Dimension(0,30));northPanel.setBackground(Color.lightGray);jf.add(southPanel,BorderLayout.SOUTH);jf.add(northPanel,BorderLayout.NORTH);JLabel jl=new JLabel("黑方执子:"+0);JLabel jl1=new JLabel("谁会获得最终胜利?敬请期待!");jl1.setForeground(Color.BLACK);jl.setFont(new Font("宋体",Font.BOLD,20));jl1.setFont(new Font("宋体",Font.BOLD,20));MPanel centerPanel=new MPanel();centerPanel.setBackground(Color.YELLOW);jf.add(centerPanel);drawListener listener = new drawListener(centerPanel,jl,jl1);//按钮添加JButton jb1=new JButton("开始");southPanel.add(jb1);JButton jb2=new JButton("悔棋");southPanel.add(jb2);JButton jb3=new JButton("重新开始");southPanel.add(jb3);JButton jb4=new JButton("复盘");southPanel.add(jb4);//添加显示组件southPanel.add(jl);northPanel.add(jl1);jf.setVisible(true);centerPanel.shapeArr=listener.shapeArr;centerPanel.addMouseListener(listener);jb1.addActionListener(listener);jb2.addActionListener(listener);jb3.addActionListener(listener);jb4.addActionListener(listener);Graphics g = centerPanel.getGraphics();listener.g = g;}public static void main(String[] args) {GameUI gu = new GameUI();gu.init();}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class drawListener implements MouseListener, ActionListener, Conbig {public Graphics g;public int x, y;public int chessX, chessY;public int flag;public String name = "null";public Color color;public static gl.game0820.Shape[] shapeArr = new gl.game0820.Shape[200];public int[][] chess = new int[LINE][LINE];public int index = 0;public boolean start = false;public MPanel centerPanel;public JLabel jl, jl1;//引用传递public drawListener(MPanel centerPanel, JLabel jl, JLabel jl1) {this.centerPanel = centerPanel;this.jl = jl;this.jl1 = jl1;}public void actionPerformed(ActionEvent e) {name = e.getActionCommand();switch (name) {case "开始": {start = true;break;}case "悔棋": {index--;jl1.setForeground(Color.BLACK);jl1.setText("谁会获得最终胜利?敬请期待!");gl.game0820.Shape s = shapeArr[index];//保存上一颗最近棋子的数据Shape s1 = shapeArr[index - 1];centerPanel.x = s1.x;centerPanel.y = s1.y;if (index > 0) {shapeArr[index] = null;} else {break;}//手动调用centerPanel里的paint方法,刷新棋盘centerPanel.repaint();if (flag == 0) {flag = 1;jl.setText("白方执子:" + (index));} else if (flag == 1) {flag = 0;jl.setText("黑方执子:" + (index));} else if (flag == 3 && chess[s.y][s.x] == 1) {flag = 0;} else if (flag == 3 && chess[s.y][s.x] == 2) {flag = 1;}if (s == null) break;chess[s.y][s.x] = 0;break;}case "重新开始": {//将最后一个红点去除掉centerPanel.x=-1;centerPanel.y=-1;//初始化标注jl.setText("黑方执子:" + 0);jl1.setForeground(Color.BLACK);jl1.setText("谁会获得最终胜利?敬请期待!");jl.setFont(new Font("宋体", Font.BOLD, 20));for (int i = 0; i < index; i++) {shapeArr[i] = null;}for (int i = 0; i < chess.length; i++) {  //行for (int j = 0; j < chess[0].length; j++) { //列chess[i][j] = 0;}}try {Thread.sleep(100);} catch (InterruptedException ex) {throw new RuntimeException(ex);}centerPanel.repaint();flag = 0;index = 0;
//                printArr();for (int i = index; i > 0; i--) {}break;}case "复盘": {//将最后一个红点去除掉centerPanel.x=-1;centerPanel.y=-1;drawAgain();break;}}}public void mouseClicked(MouseEvent e) {x = e.getX();y = e.getY();if ((x - X0) % SIZE > SIZE / 2 && (y - Y0) % SIZE < SIZE / 2) {//靠右,靠上chessX = (x - X0) / SIZE + 1;chessY = (y - Y0) / SIZE;} else if ((x - X0) % SIZE > SIZE / 2 && (y - Y0) % SIZE > SIZE / 2) {//靠右,靠下chessX = (x - X0) / SIZE + 1;chessY = (y - Y0) / SIZE + 1;} else if ((x - X0) % SIZE < SIZE / 2 && (y - Y0) % SIZE < SIZE / 2) {//靠左,靠上chessX = (x - X0) / SIZE;chessY = (y - Y0) / SIZE;} else if ((x - X0) % SIZE < SIZE / 2 && (y - Y0) % SIZE > SIZE / 2) {//靠左,靠下chessX = (x - X0) / SIZE;chessY = (y - Y0) / SIZE + 1;}if (!start) {System.out.println("请点击开始按钮!");return;}if (chess[chessY][chessX] != 0) {System.out.println("此处已有棋子,不可下棋!");return;}//实时更新棋子的坐标情况centerPanel.x = chessX;centerPanel.y = chessY;
//         printArr();switch (flag) {//标记位法case 0: {chess[chessY][chessX] = 1;//用1代表黑棋color = Color.BLACK;flag++;gl.game0820.Shape shape = new gl.game0820.Shape(chessX, chessY, SIZE, color);shape.drawShape(g);//刷新棋盘,清楚之前的红点标注centerPanel.repaint();UI();shapeArr[index] = shape;index++;break;}case 1: {chess[chessY][chessX] = 2;//用2代表白棋color = Color.WHITE;flag = 0;Shape shape = new Shape(chessX, chessY, SIZE, color);shape.drawShape(g);//刷新棋盘,清楚之前的红点标注centerPanel.repaint();UI();shapeArr[index] = shape;index++;break;}}//判断输赢if (isWin() >= 5 || isWin1() >= 5 || isWin2() >= 5 || isWin3() >= 5) {flag = 3;System.out.println("本局已结束,请点击重新开始按钮!");if (chess[chessY][chessX] == 1) {jl1.setForeground(Color.RED);jl1.setText("黑方获胜!");} else if (chess[chessY][chessX] == 2) {jl1.setForeground(Color.RED);jl1.setText("白方获胜!");}}}//复盘的功能方法public void drawAgain() {gl.game0820.Shape[] tempArr = new gl.game0820.Shape[200];//先保存所有下过的棋子数据for (int i = 0; i < shapeArr.length; i++) {tempArr[i] = shapeArr[i];}//再清除所有数据,刷新棋盘for (int i = 0; i < tempArr.length; i++) {shapeArr[i] = null;//tempArr数据还在!}centerPanel.paint(g);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}//再遍历tempArr数组,重新绘制棋子for (int i = 0; i < tempArr.length; i++) {Shape s = tempArr[i];if (s == null) break;s.drawShape(g);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}//显示当前下棋方以及步数public void UI() {if (flag == 0) {jl.setFont(new Font("宋体", Font.BOLD, 20));jl.setText("黑方执子:" + (index + 1));} else if (flag == 1) {jl.setFont(new Font("宋体", Font.BOLD, 20));jl.setText("白方执子:" + (index + 1));}}public void mousePressed(MouseEvent e) {}public void mouseReleased(MouseEvent e) {}public void mouseEntered(MouseEvent e) {}public void mouseExited(MouseEvent e) {}//统计棋子横向public int isWin() {int number = 0;//向左检查for (int i = chessX; i >= 0; i--) {if (chess[chessY][chessX] == chess[chessY][i]) {number++;} else {break;}}//向右检查for (int i = chessX + 1; i < chess.length; i++) {if (chess[chessY][chessX] == chess[chessY][i]) {number++;} else {break;}}return number;}//统计棋子纵向public int isWin1() {int number = 0;//向上检查for (int i = chessY; i >= 0; i--) {if (chess[chessY][chessX] == chess[i][chessX]) {number++;} else {break;}}//向下检查for (int i = chessY + 1; i < chess.length; i++) {if (chess[chessY][chessX] == chess[i][chessX]) {number++;} else {break;}}return number;}//统计棋子斜向(撇)public int isWin2() {int number = 0;//向右上方检查for (int i = chessY, j = chessX; i < chess.length && j > 0; i++, j--) {if (chess[chessY][chessX] == chess[i][j]) {number++;} else {break;}}//向左下方检查for (int i = chessY - 1, j = chessX + 1; i > 0 && j < chess.length; i--, j++) {if (chess[chessY][chessX] == chess[i][j]) {number++;} else {break;}}return number;}//统计棋子斜向(捺)public int isWin3() {int number = 0;//向右下方检查for (int i = chessY + 1, j = chessX + 1; i < chess.length && j < chess.length; i++, j++) {if (chess[chessY][chessX] == chess[i][j]) {number++;} else {break;}}//向左上方检查for (int i = chessY, j = chessX; i > 0 && j > 0; i--, j--) {if (chess[chessY][chessX] == chess[i][j]) {number++;} else {break;}}return number;}public void printArr() {for (int i = 0; i < chess.length; i++) {  //行for (int j = 0; j < chess[0].length; j++) { //列System.out.print(chess[i][j] + " ");}System.out.println();}}
}
import javax.swing.*;
import java.awt.*;
public class MPanel extends JPanel implements Conbig {public gl.game0820.Shape[] shapeArr;public int x=-1,y;public ImageIcon image=new ImageIcon("D:\\图片\\12.jpg");public void paint(Graphics g) {super.paint(g);g.drawImage(image.getImage(),0,0,900,900,null);//绘制棋盘for (int i = 0; i < LINE; i++) {g.drawLine(X0, Y0 + i * SIZE, (LINE - 1) * SIZE + X0, Y0 + i * SIZE);g.drawLine(X0 + i * SIZE, Y0, X0 + i * SIZE, (LINE - 1) * SIZE + Y0);}for (int i = 0; i < drawListener.shapeArr.length; i++) {Shape shape = drawListener.shapeArr[i];if (shape != null) {shape.drawShape(g);} else {break;}}if(x>=0){point(g);}}//标注最后一颗棋子的位子public void point(Graphics g){Graphics2D g1=(Graphics2D)g;((Graphics2D) g).setStroke(new BasicStroke(5));g.setColor(Color.RED);g.drawLine(x * SIZE + X0 , y * SIZE + Y0 , x * SIZE + X0, y * SIZE + Y0);}
}
import java.awt.*;public class Shape implements Conbig {public Color color;public int x, y, r;public MPanel centerPanel;public Shape(int x, int y, int r, Color color) {this.x = x;this.y = y;this.color = color;this.r = r;}//标注最后一颗棋子的位置public void drawShape(Graphics g) {if (color.equals(Color.BLACK)) {for (int i = 0; i < SIZE; i++) {g.setColor(new Color(i * 3, i * 3, i * 3));g.fillOval(x * SIZE + X0 - SIZE / 2 + i / 2, y * SIZE + Y0 - SIZE / 2 + i / 2, r - i, r - i);}} else if (color.equals(Color.WHITE)) {Graphics2D g3 = (Graphics2D) g;((Graphics2D) g).setStroke(new BasicStroke(1));for (int i = 0; i < SIZE; i++) {g.setColor(new Color(170 + i * 2, 170 + i * 2, 170 + i * 2));g.fillOval(x * SIZE + X0 - SIZE / 2 + i / 2, y * SIZE + Y0 - SIZE / 2 + i / 2, r - i, r - i);}}}
}
public interface Conbig {public int X0 = 50;public int Y0 = 36;public int LINE = 15;public int SIZE = 40;
}

 

效果

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/94509.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/94509.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/94509.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记录一次el-table+sortablejs的拖拽bug

bug回顾出现bug的情况时 当编辑表格过于紧凑的时候 有些非必要编辑或需要一眼看到的数据 移动到了el-table-column typeexpand时 同事&#xff1a;怎么拖拽功能用不了了 ok开始检查代码 当原来是个简单的编辑表格 不涉及展开和简单拖拽时 不会出现问题 解决了 出现了展开行以后…

利用go sort.Sort()排序自定义切片

1 sort.Sort()简介2 核心功能3 调用前提4 代码示例 1 sort.Sort()简介 Go语言中的sort.Sort函数是标准库提供的通用排序接口 2 核心功能 核心功能支持多种类型进行快速排序 基础类型支持‌&#xff1a;内置Ints、Float64s、Strings等函数直接排序常见切片 自定义排序‌&a…

Elasticsearch脑裂紧急处理与预防

在 Elasticsearch 中出现 网络分区&#xff08;Network Partition&#xff09; 或 脑裂&#xff08;Split-Brain&#xff09; 导致两个子集群各自选出 Master 的情况&#xff0c;是非常严重的问题。比如这个场景&#xff08;20个节点分裂成两个10节点的子集群&#xff0c;各自选…

华为网路设备学习-29(BGP协议 四)路由策略-实验

示例 延伸-具体实验1.代码部分&#xff1a;基础配置R1 [Huawei]int GigabitEthernet 0/0/0 [Huawei-GigabitEthernet0/0/0]ip address 10.1.13.1 24[Huawei]int LoopBack 1 [Huawei-LoopBack1]ip address 172.16.1.1 24 [Huawei-LoopBack1]q [Huawei]int LoopBack 2 [Huawei-Lo…

500系列状态码与可能的场景

501 Not Implemented&#xff08;未实现&#xff09;HTTP 方法不支持客户端发送了 PUT、DELETE、PATCH 请求但服务器只实现了 GET 和 POST协议功能不支持客户端使用了 HTTP/2 的某些高级特性服务器只支持 HTTP/1.1&#xff0c;无法处理&#xff0c;返回 501API 接口未完成开发中…

大数据、hadoop、爬虫、spark项目开发设计之基于数据挖掘的交通流量分析研究

大数据、hadoop、爬虫、spark项目开发设计之基于数据挖掘的交通流量分析研究

Pytest项目_day20(log日志)

Log日志优点&#xff1a;记录程序运行信息&#xff0c;方便定位问题python日志模块logging&#xff0c;日志等级如下&#xff1a; DEBUGINFO&#xff08;正常&#xff09;WARNINGERROR&#xff08;报错&#xff09;示例代码如下&#xff1a;import logging import os.path impo…

elasticsearch中的分词器配置及使用

一、什么是分词器&#xff1f; 在 Elasticsearch&#xff08;ES&#xff09;中&#xff0c;分词器&#xff08;Analyzer&#xff09; 是处理文本的核心组件&#xff0c;负责将原始文本转换为可搜索的索引词&#xff08;Term&#xff09;。它是文本分析过程的核心&#xff0c;直…

《Linux 网络编程二:UDP 与 TCP 的差异、应用及问题应对》

一、UDP 与 TCP 对比表对比项UDPTCP连接方式无需建立连接有连接&#xff08;三次握手建立&#xff0c;四次挥手断开&#xff09;传输可靠性尽最大努力交付&#xff0c;可能丢包安全可靠的数据传输机制面向对象面向数据包面向数据流传输模式一对一、一对多传输本质一对一&#x…

uniapp 页面跳转及字符串转义

1. uniapp 页面跳转及字符串转义 1.1. uniapp页面跳转方法 在uniapp中,页面跳转可以通过多种方式进行,包括但不限于路由跳转和页面间事件通信。   一. 路由跳转   在uniapp中,路由跳转是指通过改变页面url的方式来跳转到不同的页面。uni-app提供了一套路由跳转的API,包…

Vue中 this.$emit() 方法详解, 帮助子组件向父组件传递事件

this.$emit()是 Vue.js 中一个很有用的方法,可以帮助子组件向父组件传递事件1、原理说明&#xff1a;在Vue中&#xff0c;this.$emit()方法用于触发自定义事件。它是Vue实例的一个方法&#xff0c;可以在组件内部使用。使用 this.$emit() 方法&#xff0c;可以向父组件发送自定…

BUCK电路的环路补偿

芯片的COMP脚是用来设计环路补偿用的&#xff0c;它给芯片内部的误差放大器的输出和PWM控制器输入做补偿&#xff0c;如果环路补偿设计得不好&#xff0c;会更容易引起环路的不稳定或振荡&#xff0c;也可能导致输出电压异常。环路补偿涉及三个指标&#xff1a;剪切频率&#x…

Hyperledger Fabric官方中文教程-改进笔记(十六)-策略(policy)

本Fabric中文文档专栏的阅读前言&#xff1a;前言 文章目录什么是策略为什么需要策略策略如何实现访问控制列表 (ACLs)智能合约背书政策修改策略如何在 Fabric 中编写策略Signature policiesImplicitMeta policies例子: 通道配置策略Organizations 部分Application部分Fabric 链…

Flutter性能优化完全指南:构建流畅应用的实用策略

Flutter性能优化完全指南&#xff1a;构建流畅应用的实用策略 探索从UI构建到内存管理的全方位优化技巧&#xff0c;打造如丝般顺滑的Flutter体验 引言 在跨平台开发领域&#xff0c;Flutter以其出色的性能表现脱颖而出。然而&#xff0c;正如任何强大的框架一样&#xff0c;不…

jvm对象内存占用

欢迎访问我的主页: https://heeheeaii.github.io/ 在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;一个对象在内存中的存储布局可以分为三个部分&#xff1a;对象头&#xff08;Object Header&#xff09;、实例数据&#xff08;Instance Data&#xff09;和对齐填充…

嵌入式系统中mcu寄存器分类划分

目录一、 按行为特性分类二、 按功能角色分类&#xff08;更宏观的角度&#xff09;总结与注意事项在32位单片机&#xff08;尤其是基于ARM Cortex-M系列内核的&#xff09;中&#xff0c;寄存器的种类可以按照其“行为模式”和“功能”来进行分类。以下是32位单片机&#xff0…

Redis如何高效安全的遍历所有key?

大家好&#xff0c;我是锋哥。今天分享关于【Redis如何高效安全的遍历所有key?】面试题。希望对大家有帮助&#xff1b; Redis如何高效安全的遍历所有key? 超硬核AI学习资料&#xff0c;现在永久免费了&#xff01; 在 Redis 中&#xff0c;遍历所有的 key 是一个相对昂贵的…

网易云音乐歌曲导出缓存为原始音乐文件。低调,低调。。。

最近买了个榭兰图耳机头&#xff0c;拿到手第一件事当然是煲机了。弄个旧手机做24小时煲机但是不想再装多一个网易云音乐&#xff0c;省得一号多登录会问题。对于软工男最先想到的肯定是在本地直接播放音乐了&#xff0c;正好自己 有淘宝88VIP联合会员&#xff0c;于是琢磨着怎…

从Android到鸿蒙:一场本应无缝的转型-优雅草卓伊凡

从Android到鸿蒙&#xff1a;一场本应无缝的转型-优雅草卓伊凡看到Android开发者询问如何转向鸿蒙&#xff0c;卓伊凡不禁摇头&#xff1a;真正的Android工程师根本不需要“学习”鸿蒙&#xff0c;只需要简单查阅文档即可。近年来&#xff0c;随着鸿蒙系统的不断发展&#xff0…

HTML————更实用于后端宝宝们学习的前端

博主主攻后端&#xff0c;但是毕竟要做网站&#xff0c;我们来学习一点前端的知识&#xff0c;一共有三节&#xff0c;学完就能做一点小小的页面啦&#xff1b;1.1 HTML基础什么是HTML呢&#xff0c;他是超文本标记语言&#xff0c;还记得HTTP是啥不&#xff0c;HTTP是超文本传…