用Java写一个多线程赛跑游戏
GameFrame
package demo;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class GameJframe extends JFrame {
// 声明背景图片
Image[] bg_img = new Image[3];
// 声明动画秒面板
GameJpanel gameJpanel = new GameJpanel();
// 声明按钮面板
JPanel jPanel = new JPanel();
// 声明按钮
JButton jb_start = new JButton("开始");
// 声明准备状态小人
Image[] ready_img = new Image[3];
// 声明跑步状态小人
Image[] run_img = new Image[3];
// 声明三个参赛小人
RunningMan[] mans = new RunningMan[3];
// 设置小人名字
String[] names = { "みつかたさら", "あまきこういち", "ながはなだいすけ" };
// 重新开始按钮
JButton jb_restart = new JButton("重新开始");
// 定义单选按钮
JRadioButton[] rbs = new JRadioButton[3];
ButtonGroup jbg = new ButtonGroup();
// 定义一个下注标签
JLabel jl_xzbq = new JLabel("请输入下注金额:");
// 定义一个下注金额输入框
JTextField jt_xzje = new JTextField(20);
// 定义一个本金标签
JLabel jl_bjbq = new JLabel("我的本金:");
// 定义一个金额标签
JLabel jl_jebq = new JLabel("100000");
// 定义一个选中的按钮
JRadioButton jbxz;
public GameJframe() {
for (int i = 0; i < bg_img.length; i++) {
// 引入背景图片
bg_img[i] = this.getToolkit().getImage("imgBack/" + (i + 1) + ".gif");
// 引入准备图片
ready_img[i] = this.getToolkit().getImage("imgReady/" + (i + 1) + "2.gif");
// 引入跑步图片
run_img[i] = this.getToolkit().getImage("imgRun/" + (i + 1) + "1.gif");
// 实例化单选按钮
rbs[i] = new JRadioButton(names[i]);
jbg.add(rbs[i]);
jPanel.add(rbs[i]);
}
jPanel.add(jl_xzbq);
jPanel.add(jt_xzje);
jPanel.add(jl_bjbq);
jPanel.add(jl_jebq);
jPanel.add(jb_start);
jPanel.add(jb_restart);
jb_restart.setEnabled(false);
// 添加动画面板到窗体
this.add(gameJpanel, BorderLayout.CENTER);
this.add(jPanel, BorderLayout.SOUTH);
this.setTitle("赛跑游戏!!");
this.setResizable(false);
this.setSize(1200, 600);
this.setLocation(50, 50);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
for (int i = 0; i < mans.length; i++) {
// 实例化三个小人
mans[i] = new RunningMan(names[i], 0, (gameJpanel.getHeight() * i) / 3 + 85, ready_img[i], this);
}
// 重新开始按钮的监听
jb_restart.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
// 点击重新开始按钮,开始按钮可用,重新开始按钮不可用
jb_start.setEnabled(true);
jb_restart.setEnabled(false);
// 重新设置NO1布尔值
RunningMan.hasNO1 = false;
// 设置停止线程的布尔值
RunningMan.canRun = false;
// 重新设置计数器num的数值
RunningMan.num = 0;
super.mouseClicked(e);
//
for (int i = 0; i < mans.length; i++) {
mans[i] = new RunningMan(names[i], 0, (gameJpanel.getHeight() * i) / 3 + 85, ready_img[i],
GameJframe.this);
}
}
});
// 开始按钮的监听
jb_start.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
// 如果没有选择选手下注,不允许开始
if (!(rbs[0].isSelected() || rbs[1].isSelected() || rbs[2].isSelected())) {
JOptionPane.showMessageDialog(GameJframe.this, "请选择选手,开始比赛", "没选手呢", JOptionPane.WARNING_MESSAGE);
return;
}
// 如果没有下注金额,不允许开始
if (jt_xzje.getText().trim().equals("")) {
JOptionPane.showMessageDialog(GameJframe.this, "请输入下注金额,开始比赛", "没下注呢", JOptionPane.WARNING_MESSAGE);
return;
}
// 判断下注金额是否大于本金
int xzbj = Integer.parseInt(jl_jebq.getText());
int xzje = Integer.parseInt(jt_xzje.getText());
if (xzbj < xzje) {
JOptionPane.showMessageDialog(GameJframe.this, "下注的金额不能超过本金", "看着点", JOptionPane.WARNING_MESSAGE);
return;
}
for (JRadioButton j : rbs) {
if (j.isSelected()) {
jbxz = j;
}
}
// 点击开始按钮,开始按钮不可点,重新开始按钮可以点击
jb_start.setEnabled(false);
jb_restart.setEnabled(true);
// 重置能不能跑
RunningMan.canRun = true;
super.mouseClicked(e);
for (int i = 0; i < mans.length; i++) {
// 小人换衣服到跑动状态
mans[i].img = run_img[i];
// 各自执行跑动方法
mans[i].start();
}
}
});
}
// 自定义游戏面板
class GameJpanel extends JPanel {
@Override
public void paint(Graphics g) {
super.paint(g);
for (int i = 0; i < bg_img.length; i++) {
// 画背景图片
g.drawImage(bg_img[i], 0, (getHeight() * i) / 3, getWidth(), getHeight() / 3, this);
// 自己画自己
mans[i].drawSelf(g, this);
}
// 画终点线
g.setColor(Color.RED);
g.fillRect(950, 0, 5, getHeight());
}
}
public static void main(String[] args) {
new GameJframe();
}
}
`@TOC
``
JavaConnectMysql
package demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JavaConnectMysql {
public static void saveRankResult(String playerRank) {
// 加载java连接mysql数据库的工具类
try {
Class.forName("com.mysql.jdbc.Driver");
// 大家需要把selton.cn 换成 localhost
// connection 就是我们java连接到数据库的一条管道
// 设置连接字符编码为utf-8 和数据库中的utf-8对应起来
Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/runman?useUnicode=true&characterEncoding=UTF-8", "root", "mysql");
// sql语句的执行者
Statement statement = connection.createStatement();
// 使用statement执行sql语句
String first = playerRank;
String insertSql = "insert into finalresult values (NULL, '" + first + "')";
System.out.println("我要执行的sql 是 -> " + insertSql);
statement.executeUpdate(insertSql);
System.out.println("执行成功");
// 先关闭statement
statement.close();
// 再关闭connection
connection.close();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
# 欢迎使用Markdown编辑器
你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
## 新的改变
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
1. **全新的界面设计** ,将会带来全新的写作体验;
2. 在创作中心设置你喜爱的代码高亮样式,Markdown **将代码片显示选择的高亮样式** 进行展示;
3. 增加了 **图片拖拽** 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
4. 全新的 **KaTeX数学公式** 语法;
5. 增加了支持**甘特图的mermaid语法[^1]** 功能;
6. 增加了 **多屏幕编辑** Markdown文章功能;
7. 增加了 **焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置** 等功能,功能按钮位于编辑区域与预览区域中间;
8. 增加了 **检查列表** 功能。
[^1]: [mermaid语法说明](https://mermaidjs.github.io/)
## 功能快捷键
撤销:<kbd>Ctrl/Command</kbd> + <kbd>Z</kbd>
重做:<kbd>Ctrl/Command</kbd> + <kbd>Y</kbd>
加粗:<kbd>Ctrl/Command</kbd> + <kbd>B</kbd>
斜体:<kbd>Ctrl/Command</kbd> + <kbd>I</kbd>
标题:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>H</kbd>
无序列表:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>U</kbd>
有序列表:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>O</kbd>
检查列表:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>C</kbd>
插入代码:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>K</kbd>
插入链接:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>L</kbd>
插入图片:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>G</kbd>
查找:<kbd>Ctrl/Command</kbd> + <kbd>F</kbd>
替换:<kbd>Ctrl/Command</kbd> + <kbd>G</kbd>
## 合理的创建标题,有助于目录的生成
直接输入1次<kbd>#</kbd>,并按下<kbd>space</kbd>后,将生成1级标题。
输入2次<kbd>#</kbd>,并按下<kbd>space</kbd>后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用`TOC`语法后生成一个完美的目录。
## 如何改变文本的样式
*强调文本* _强调文本_
**加粗文本** __加粗文本__
==标记文本==
~~删除文本~~
> 引用文本
H~2~O is是液体。
2^10^ 运算结果是 1024.
## 插入链接与图片
链接: [link](https://mp.csdn.net).
图片: ![Alt](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9hdmF0YXIuY3Nkbi5uZXQvNy83L0IvMV9yYWxmX2h4MTYzY29tLmpwZw)
带尺寸的图片: ![Alt](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9hdmF0YXIuY3Nkbi5uZXQvNy83L0IvMV9yYWxmX2h4MTYzY29tLmpwZw =30x30)
居中的图片: ![Alt](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9hdmF0YXIuY3Nkbi5uZXQvNy83L0IvMV9yYWxmX2h4MTYzY29tLmpwZw#pic_center)
居中并且带尺寸的图片: ![Alt](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9hdmF0YXIuY3Nkbi5uZXQvNy83L0IvMV9yYWxmX2h4MTYzY29tLmpwZw#pic_center =30x30)
当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。
## 如何插入一段漂亮的代码片
去[博客设置](https://mp.csdn.net/configure)页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 `代码片`.
```javascript
// An highlighted block
var foo = 'bar';
ResultMoney
package demo;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class ResultMoney {
// 定义单选按钮
JRadioButton[] rbs;
// 定义一个下注金额输入框
JTextField jt_xzje;
// 定义一个金额标签
JLabel jl_jebq;
// 定义一个选中的按钮
JRadioButton jbxz;
public ResultMoney(GameJframe gj) {
rbs = gj.rbs;
jt_xzje = gj.jt_xzje;
jl_jebq = gj.jl_jebq;
jbxz = gj.jbxz;
}
public int resultMoney() {
// 下注金额和本金的格式转换
int xzbj = Integer.parseInt(jl_jebq.getText());
int xzje = Integer.parseInt(jt_xzje.getText());
if (jbxz.getText().equals(RunningMan.NO1.name)) {
return xzbj + xzje;
}
return xzbj - xzje;
}
public void szMyMoney() {
jl_jebq.setText(resultMoney() + "");
jt_xzje.setText("");
}
}
RunningMan
package demo;
import java.awt.Graphics;
import java.awt.Image;
import java.util.Random;
import javax.swing.JPanel;
public class RunningMan extends Thread {
public String name;
public int x_point, y_point;
public Image img;
// 备份准备衣服的初始值
public Image ready_img;
// 声明每个小人X轴的随即对象
static Random random = new Random();
// 声明第一名变量
static RunningMan NO1;
// 管理第一名的布尔值
static boolean hasNO1 = false;
// 停止线程的布尔值
static boolean canRun = true;
// 声明小人跑完的数值变量
static int num = 0;
// 人物排序说明
// int index = 0;
// int[] playerRank = new int[0];
GameJframe gj;
public RunningMan(String name, int x_point, int y_point, Image img, GameJframe gj) {
this.name = name;
this.x_point = x_point;
this.y_point = y_point;
this.img = img;
this.ready_img = img;
this.gj = gj;
}
// 每个参赛小人画自己的方法
public void drawSelf(Graphics g, JPanel jPanel) {
g.drawImage(img, x_point, y_point, 120, 92, jPanel);
}
// 增加x轴坐标的方法
public void moveX() {
x_point += 10 + random.nextInt(30);
}
// 奔跑的方式,x的移动
@Override
public void run() {
while (x_point < 950 && canRun) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
moveX();
}
synchronized (random) {
if (canRun) {
num++;
}
if (!hasNO1 && canRun) {
// 产生第一名
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
NO1 = this;
hasNO1 = true;
}
if (num == 3) {
System.out.println(NO1.name);
// System.out。println(Arrays.toString(playerRank));
JavaConnectMysql.saveRankResult(NO1.name);
new ResultMoney(gj).szMyMoney();
}
}
// 设置小人停止的位置
x_point = 950;
// 结束后把跑动衣服换成准备衣服
img = ready_img;
}
}