先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
正文
import javax.swing.JFrame;
import javax.swing.JPanel;
/*
- 画布类
*/
public class GamePanel extends JPanel {
private static final long serialVersionUID = 1L;
GamePanel gamePanel=this;
private JFrame mainFrame=null;
//构造里面初始化相关参数
public GamePanel(JFrame frame){
this.setLayout(null);
this.setOpaque(false);
mainFrame = frame;
mainFrame.requestFocus();
mainFrame.setVisible(true);
}
}
再创建一个Main类,来启动这个窗口。
public class Main {
//主类
public static void main(String[] args) {
GameFrame frame = new GameFrame();
GamePanel gamePanel = new GamePanel(frame);
frame.add(gamePanel);
frame.setVisible(true);//设定显示
}
}
右键执行这个Main类,窗口建出来了
创建菜单
private void initMenu(){
// 创建菜单及菜单选项
jmb = new JMenuBar();
JMenu jm1 = new JMenu(“游戏”);
jm1.setFont(new Font(“思源宋体”, Font.BOLD, 18));// 设置菜单显示的字体
JMenu jm2 = new JMenu(“帮助”);
jm2.setFont(new Font(“思源宋体”, Font.BOLD, 18));// 设置菜单显示的字体
JMenuItem jmi1 = new JMenuItem(“开始新游戏”);
JMenuItem jmi2 = new JMenuItem(“退出”);
jmi1.setFont(new Font(“思源宋体”, Font.BOLD, 18));
jmi2.setFont(new Font(“思源宋体”, Font.BOLD, 18));
JMenuItem jmi3 = new JMenuItem(“操作说明”);
jmi3.setFont(new Font(“思源宋体”, Font.BOLD, 18));
JMenuItem jmi4 = new JMenuItem(“成功/失败判定”);
jmi4.setFont(new Font(“思源宋体”, Font.BOLD, 18));
jm1.add(jmi1);
jm1.add(jmi2);
jm2.add(jmi3);
jm2.add(jmi4);
jmb.add(jm1);
jmb.add(jm2);
mainFrame.setJMenuBar(jmb);// 菜单Bar放到JFrame上
jmi1.addActionListener(this);
jmi1.setActionCommand(“Restart”);
jmi2.addActionListener(this);
jmi2.setActionCommand(“Exit”);
jmi3.addActionListener(this);
jmi3.setActionCommand(“help”);
jmi4.addActionListener(this);
jmi4.setActionCommand(“lost”);
}
实现ActionListener并重写方法actionPerformed
此时GamePanel是报错的,重写actionPerformed方法。
actionPerformed方法的实现
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
System.out.println(command);
UIManager.put(“OptionPane.buttonFont”, new FontUIResource(new Font(“思源宋体”, Font.ITALIC, 18)));
UIManager.put(“OptionPane.messageFont”, new FontUIResource(new Font(“思源宋体”, Font.ITALIC, 18)));
if (“Exit”.equals(command)) {
Object[] options = { “确定”, “取消” };
int response = JOptionPane.showOptionDialog(this, “您确认要退出吗”, “”,
JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null,
options, options[0]);
if (response == 0) {
System.exit(0);
}
}else if(“Restart”.equals(command)){
if(!“end”.equals(gamePanel.gameFlag)){
JOptionPane.showMessageDialog(null, “正在游戏中无法重新开始!”,
“提示!”, JOptionPane.INFORMATION_MESSAGE);
}else{
if(gamePanel!=null) {
gamePanel.restart();
}
}
}else if(“help”.equals(command)){
JOptionPane.showMessageDialog(null, “鼠标在指示器位置点下,则落子!”,
“提示!”, JOptionPane.INFORMATION_MESSAGE);
}else if(“lost”.equals(command)){
JOptionPane.showMessageDialog(null, “五子连珠方获得胜利!”,
“提示!”, JOptionPane.INFORMATION_MESSAGE);
}
}
此时的GamePanel代码如下:
package main;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;
/*
- 画布类
*/
public class GamePanel extends JPanel implements ActionListener{
private static final long serialVersionUID = 1L;
GamePanel gamePanel=this;
private JFrame mainFrame=null;
JMenuBar jmb=null;
public String gameFlag=“”;
//构造里面初始化相关参数
public GamePanel(JFrame frame){
this.setLayout(null);
this.setOpaque(false);
mainFrame = frame;
//创建按钮
initMenu();
mainFrame.requestFocus();
mainFrame.setVisible(true);
}
private void initMenu(){
// 创建菜单及菜单选项
jmb = new JMenuBar();
JMenu jm1 = new JMenu(“游戏”);
jm1.setFont(new Font(“思源宋体”, Font.BOLD, 18));// 设置菜单显示的字体
JMenu jm2 = new JMenu(“帮助”);
jm2.setFont(new Font(“思源宋体”, Font.BOLD, 18));// 设置菜单显示的字体
JMenuItem jmi1 = new JMenuItem(“开始新游戏”);
JMenuItem jmi2 = new JMenuItem(“退出”);
jmi1.setFont(new Font(“思源宋体”, Font.BOLD, 18));
jmi2.setFont(new Font(“思源宋体”, Font.BOLD, 18));
JMenuItem jmi3 = new JMenuItem(“操作说明”);
jmi3.setFont(new Font(“思源宋体”, Font.BOLD, 18));
JMenuItem jmi4 = new JMenuItem(“成功/失败判定”);
jmi4.setFont(new Font(“思源宋体”, Font.BOLD, 18));
jm1.add(jmi1);
jm1.add(jmi2);
jm2.add(jmi3);
jm2.add(jmi4);
jmb.add(jm1);
jmb.add(jm2);
mainFrame.setJMenuBar(jmb);// 菜单Bar放到JFrame上
jmi1.addActionListener(this);
jmi1.setActionCommand(“Restart”);
jmi2.addActionListener(this);
jmi2.setActionCommand(“Exit”);
jmi3.addActionListener(this);
jmi3.setActionCommand(“help”);
jmi4.addActionListener(this);
jmi4.setActionCommand(“lost”);
}
//重新开始
public void restart() {
//游戏开始标记
gameFlag=“start”;
}
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
System.out.println(command);
UIManager.put(“OptionPane.buttonFont”, new FontUIResource(new Font(“思源宋体”, Font.ITALIC, 18)));
UIManager.put(“OptionPane.messageFont”, new FontUIResource(new Font(“思源宋体”, Font.ITALIC, 18)));
if (“Exit”.equals(command)) {
Object[] options = { “确定”, “取消” };
int response = JOptionPane.showOptionDialog(this, “您确认要退出吗”, “”,
JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null,
options, options[0]);
if (response == 0) {
System.exit(0);
}
}else if(“Restart”.equals(command)){
if(!“end”.equals(gamePanel.gameFlag)){
JOptionPane.showMessageDialog(null, “正在游戏中无法重新开始!”,
“提示!”, JOptionPane.INFORMATION_MESSAGE);
}else{
if(gamePanel!=null) {
gamePanel.restart();
}
}
}else if(“help”.equals(command)){
JOptionPane.showMessageDialog(null, “鼠标在指示器位置点下,则落子!”,
“提示!”, JOptionPane.INFORMATION_MESSAGE);
}else if(“lost”.equals(command)){
JOptionPane.showMessageDialog(null, “五子连珠方获得胜利!”,
“提示!”, JOptionPane.INFORMATION_MESSAGE);
}
}
}
运行一下
重写paint方法
@Override
public void paint(java.awt.Graphics g) {
super.paint(g);
}
绘制横竖相交接的线
定义15行、15列
public static final int ROWS=15;
public static final int COLS=15;
绘制网格
//绘制网格
private void drawGrid(Graphics g) {
Graphics2D g_2d=(Graphics2D)g;
int start=26;
int x1=start;
int y1=20;
int x2=586;
int y2=20;
for (int i = 0; i < ROWS; i++) {
y1 = start + 40*i;
y2 = y1;
g_2d.drawLine(x1, y1, x2, y2);
}
y1=start;
y2=586;
for (int i = 0; i < COLS; i++) {
x1 = start + 40*i;
x2 = x1;
g_2d.drawLine(x1, y1, x2, y2);
}
}
绘制5个圆点
//绘制5个黑点
private void draw5Point(Graphics g) {
//第1个点
g.fillArc(142, 142, 8, 8, 0, 360);
//第2个点
g.fillArc(462, 142, 8, 8, 0, 360);
//第3个点
g.fillArc(142, 462, 8, 8, 0, 360);
//第4个点
g.fillArc(462, 462, 8, 8, 0, 360);
//中心点
g.fillArc(302, 302, 8, 8, 0, 360);
}
在paint方法里面调用以上2个方法
@Override
public void paint(java.awt.Graphics g) {
super.paint(g);
//绘制网格
drawGrid(g);
//绘制5个黑点
draw5Point(g);
}
棋盘已经绘制完成
- 创建指示器类
package main;
import java.awt.Color;
import java.awt.Graphics;
//指示器类
public class Pointer {
private int i=0;//二维下标i
private int j=0;//二维下标j
private int x=0;//坐标X
private int y=0;//坐标Y
private GamePanel panel=null;
private Color color=null;
private int h=40;//指示的大小
private boolean isShow=false;//是否展示
private int qizi = 0 ;//棋子类型 0:无 1:白棋 2:黑棋
public Pointer(int x,int y,int i,int j,Color color,GamePanel panel){
this.x=x;
this.y=y;
this.i=i;
this.j=j;
this.panel=panel;
this.color=color;
}
//绘制
void draw(Graphics g){
Color oColor = g.getColor();
if(color!=null){
g.setColor(color);
}
if(isShow){
//绘制指示器
g.drawRect(x-h/2, y-h/2, h, h);
}
if(color!=null){//用完设置回去颜色
g.setColor(oColor);
}
}
//判断鼠标是否在指针范围内
boolean isPoint(int x,int y){
//大于左上角,小于右下角的坐标则肯定在范围内
if(x>this.x-h/2 && y >this.y-h/2
&& x<this.x+h/2 && y <this.y+h/2){
return true;
}
return false;
}
public boolean isShow() {
return isShow;
}
public void setShow(boolean isShow) {
this.isShow = isShow;
}
public int getQizi() {
return qizi;
}
public void setQizi(int qizi) {
this.qizi = qizi;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public int getJ() {
return j;
}
public void setJ(int j) {
this.j = j;
}
}
- 初始化二维数组
public Pointer points[][] = new Pointer[ROWS][COLS];
- 创建指示器实例对象
//创建二维数组
private void createArr() {
int x=0,y=0;
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
y = 26 + 40*i;
x = 26 + 40*j;
Pointer pointer = new Pointer(x, y, i,j,new Color(255,0,0), this);
points[i][j] = pointer;
}
}
}
- 初始化调用
//初始化相关对象
private void init() {
createArr();
//游戏开始标记
gameFlag=“start”;
}
同时 init方法 在GamePanel 的构造方法调用。
- paint方法中遍历二维数组并且绘制。
@Override
public void paint(java.awt.Graphics g) {
super.paint(g);
//绘制网格
drawGrid(g);
//绘制5个黑点
draw5Point(g);
//绘制指示器
Pointer pointer = null;
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
pointer = points[i][j] ;
if(pointer!=null){
pointer.draw(g);
}
}
}
}
运行如下
但是这个指示器方块不是我们想要的,需要改一下
- 修改指示器类的绘图代码
在Pointer方法中新增方法,并在指示器绘制的时候调用此方法,而不是之前的drawRect。
private void drawPointer(Graphics g) {
Graphics2D g2 = (Graphics2D)g; //g是Graphics对象
g2.setStroke(new BasicStroke(2.0f));
/*
-
1.先计算4个顶点
-
2.依次从每个顶点绘制横竖两条线
*/
//左上角
int x1 = x-h/2;
int y1 = y-h/2;
//向右画线
int x2 = x1+1*h/4;
int y2 = y1;
g2.drawLine(x1, y1, x2, y2);
//向下画线
x2 = x1;
y2 = y1+1*h/4;
g2.drawLine(x1, y1, x2, y2);
//右上角
x1 = x+h/2;
y1 = y-h/2;
//向左画线
x2 = x1-1*h/4;
y2 = y1;
g2.drawLine(x1, y1, x2, y2);
//向下画线
x2 = x1;
y2 = y1+1*h/4;
g2.drawLine(x1, y1, x2, y2);
//右下角
x1 = x+h/2;
y1 = y+h/2;
//向左画线
x2 = x1-1*h/4;
y2 = y1;
g2.drawLine(x1, y1, x2, y2);
//向上画线
x2 = x1;
y2 = y1-1*h/4;
g2.drawLine(x1, y1, x2, y2);
//左下角
x1 = x-h/2;
y1 = y+h/2;
//向右画线
x2 = x1+1*h/4;
y2 = y1;
g2.drawLine(x1, y1, x2, y2);
//向上画线
x2 = x1;
y2 = y1-1*h/4;
g2.drawLine(x1, y1, x2, y2);
}
再运行
- 创建ImageValue加载类
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageValue {
public static BufferedImage whiteQiziImage ;
public static BufferedImage blackQiziImage ;
//路径
public static String ImagePath = “/images/”;
//将图片初始化
public static void init(){
String whitePath = ImagePath +“white.png”;
String blackPath = ImagePath +“black.png”;
try {
whiteQiziImage = ImageIO.read(ImageValue.class.getResource(whitePath));
blackQiziImage = ImageIO.read(ImageValue.class.getResource(blackPath));
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 创建落子类
import java.awt.Color;
import java.awt.Graphics;
import common.ImageValue;
public class Qizi {
private int x = 0;
private int y = 0;
private int r = 36;
private GamePanel panel = null;
private Color color = null;
private int type = 1;// 棋子类型 1:白棋 2:黑棋
public Qizi(int x, int y, int type, GamePanel panel) {
this.x = x;
this.y = y;
this.panel = panel;
this.type=type;
}
// 绘制
void draw(Graphics g) {
Color oColor = g.getColor();
if (type == 1) {// 白色
g.drawImage(ImageValue.whiteQiziImage, x - r / 2, y - r / 2,r,r, null);
} else {// 黑色
g.drawImage(ImageValue.blackQiziImage, x - r / 2, y - r / 2,r,r, null);
}
if (color != null) {// 用完设置回去颜色
g.setColor(oColor);
}
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
- 在createMouseListener方法中重写mouseClicked,创建棋子
@Override
public void mouseClicked(MouseEvent e) {
//在合适的位置点击则进行落子操作
if(!“start”.equals(gameFlag)) return ;
int x = e.getX();
int y = e.getY();
Pointer pointer;
for (int i = 0; i <ROWS; i++) {
for (int j = 0; j < COLS; j++) {
pointer = points[i][j];
if(pointer==null)continue;
//被点击,且没有棋子,则可以落子
if(pointer.isPoint(x, y) && pointer.getQizi()==0){
Qizi qizi = new Qizi(pointer.getX(), pointer.getY(), 2, gamePanel);
pointer.setQizi(2);
qizis.add(qizi);
//重绘画布
repaint();
return ;
}
}
}
}
- 在paint 方法中绘制棋子
@Override
public void paint(java.awt.Graphics g) {
super.paint(g);
//绘制网格
drawGrid(g);
//绘制5个黑点
draw5Point(g);
//绘制指示器
Pointer pointer = null;
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
pointer = points[i][j] ;
if(pointer!=null){
pointer.draw(g);
}
}
}
//绘制棋子
Qizi qizi=null;
for (int i = 0; i < qizis.size(); i++) {
qizi = (Qizi)qizis.get(i);
qizi.draw(g);
}
}
-
创建AI类
-
创建静态方法next(下一步)
-
创建静态方法has5(连成5子)
public class AI {
//AI进行下一步
static void next(GamePanel gamePanel){
}
//判断五子连珠
static boolean has5(Pointer pointer1,GamePanel gamePanel){
return false;
}
}
-
在你落子后,会先执行has5方法,根据返回来决定走向
-
has5返回true则表示你获得胜利,否则AI将会走一步棋
在刚才的mouseClicked修改代码
@Override
public void mouseClicked(MouseEvent e) {
//在合适的位置点击则进行落子操作
if(!“start”.equals(gameFlag)) return ;
int x = e.getX();
int y = e.getY();
Pointer pointer;
for (int i = 0; i <ROWS; i++) {
for (int j = 0; j < COLS; j++) {
pointer = points[i][j];
if(pointer==null)continue;
//被点击,且没有棋子,则可以落子
if(pointer.isPoint(x, y) && pointer.getQizi()==0){
Qizi qizi = new Qizi(pointer.getX(), pointer.getY(), 2, gamePanel);
pointer.setQizi(2);
qizis.add(qizi);
//重绘画布
repaint();
//判断有没有五子连珠的情况
if(AI.has5(pointer, gamePanel)){
gamePanel.gameWin();
}else{
AI.next(gamePanel);
}
return ;
}
}
}
}
- 在AI类中随机落子(创建方法)
- 随机获取下标 i 和 j。
- 通过下标从二维数组取到指示器对象。
- 如果此指示器被占用则再次随机(递归),直到正确获取到指示器对象。
- 在此指示器位置,创建棋子对象并更新指示器的棋子信息。
我的面试宝典:一线互联网大厂Java核心面试题库
以下是我个人的一些做法,希望可以给各位提供一些帮助:
整理了很长一段时间,拿来复习面试刷题非常合适,其中包括了Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等,且还会持续的更新…可star一下!
283页的Java进阶核心pdf文档
Java部分:Java基础,集合,并发,多线程,JVM,设计模式
数据结构算法:Java算法,数据结构
开源框架部分:Spring,MyBatis,MVC,netty,tomcat
分布式部分:架构设计,Redis缓存,Zookeeper,kafka,RabbitMQ,负载均衡等
微服务部分:SpringBoot,SpringCloud,Dubbo,Docker
还有源码相关的阅读学习
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
if(!“start”.equals(gameFlag)) return ;
int x = e.getX();
int y = e.getY();
Pointer pointer;
for (int i = 0; i <ROWS; i++) {
for (int j = 0; j < COLS; j++) {
pointer = points[i][j];
if(pointer==null)continue;
//被点击,且没有棋子,则可以落子
if(pointer.isPoint(x, y) && pointer.getQizi()==0){
Qizi qizi = new Qizi(pointer.getX(), pointer.getY(), 2, gamePanel);
pointer.setQizi(2);
qizis.add(qizi);
//重绘画布
repaint();
//判断有没有五子连珠的情况
if(AI.has5(pointer, gamePanel)){
gamePanel.gameWin();
}else{
AI.next(gamePanel);
}
return ;
}
}
}
}
- 在AI类中随机落子(创建方法)
- 随机获取下标 i 和 j。
- 通过下标从二维数组取到指示器对象。
- 如果此指示器被占用则再次随机(递归),直到正确获取到指示器对象。
- 在此指示器位置,创建棋子对象并更新指示器的棋子信息。
我的面试宝典:一线互联网大厂Java核心面试题库
以下是我个人的一些做法,希望可以给各位提供一些帮助:
整理了很长一段时间,拿来复习面试刷题非常合适,其中包括了Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等,且还会持续的更新…可star一下!
[外链图片转存中…(img-R4urCDHl-1713615151979)]
283页的Java进阶核心pdf文档
Java部分:Java基础,集合,并发,多线程,JVM,设计模式
数据结构算法:Java算法,数据结构
开源框架部分:Spring,MyBatis,MVC,netty,tomcat
分布式部分:架构设计,Redis缓存,Zookeeper,kafka,RabbitMQ,负载均衡等
微服务部分:SpringBoot,SpringCloud,Dubbo,Docker
[外链图片转存中…(img-A2XjZya1-1713615151979)]
还有源码相关的阅读学习
[外链图片转存中…(img-AycVn9nH-1713615151980)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-7QEetmPW-1713615151980)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!