杂项
快捷键 I
while + iterator的快捷键itit,ctrl + j调出快捷键列表 ,遍历完一次后想重置iterator iterator = 名字.iterator
JAVA概述
JAVA API 在线文档 www.matools.com
JAVA发展历史
1990 sun公司启动绿色计划,1992年创建java语言,1994gosling参加硅谷大会演示java功能震惊世界,1995年sun公司发布java第一个版本,2009年甲骨文公司宣布收购sun公司。2014发布java8,广泛应用的版本。
JAVA技术平台
JAVA SE:JAVA标准版,支持面向桌面级应用的平台,提供了完整的JAVA核心API,此版本之前称为J2SE
JAVA EE:JAVA企业版,为开发企业环境下的应用程序提供一套解决方案。主要针对Web应用程序开发,此版本之前称为J2EE
JAVA ME:JAVA小型版,支持java程序运行在移动终端上的平台,对java api有所精简,加入了针对移动终端的支持,此版本之前称为J2ME
JAVA重要特点
- Java语言是面向对象的(oop)
- Java语言是健壮的。Java的强类型机制、异常处理、垃圾的自动收集等是Java程序健壮
性的重要保证 - Java语言是跨平台性的。[即:一个编译好的.class文件可以在多个系统下运行,这种特性称为跨平台]
- Java语言是解释型的
解释性语言:javascript,PHP., java 编译性语言:c/ c++
区别是:解释性语言,编译后的代码,不能直接被机器执行,需要解释器来执行,编译性语言,编译后的代码,可以直接被机器执行
JAVA运行机制
跨平台的核心:JVM(JAVA虚拟机)
JDK与JRE,JVM
关于环境变量的配置
JAVA开发注意事项
JAVA转义字符
这里需要注意的是换行和回车的区别,换行是将光标移动到下一行,而回车是将光标移动到当前行的开始第一个字符
JAVA易犯错误(新手时期)
JAVA注释类型
单行注释://
多行注释:/*
…
*/
多行注释内部不允许嵌套多行注释
文档注释:注释内容可以被JDK提供的工具javadoc解析,生成一套以网页文件形式体现的该程序的说明文档,一般写在类
基本格式:/**
*
*
*/
如何生成对应的文档注释:javadoc -d 文件夹 -xx -yy 需要生成的java文件名字
其中xx和yy是javadoc标签
JAVA代码规范
常用DOS命令
JAVA基本程序设计结构
数据类型
基本数据类型
整数
浮点数
字符类型
布尔类型
与C或C++不同,不可以用0或非0的数代替false或者true;
引用数据类型
数组
数组拷贝
- 浅拷贝
-
深拷贝
二维数组
数组的每个元素是一个数组
动态初始化,列数不确定,每个一维数组的长度不一样
数组练习
数据类型转换
自动转换
强制转换
基本数据类型与string类型的转换
运算符与标识符
算术运算符
关于%取模运算符,它的运算公式为 a % b = a − ( i n t ) a / b ∗ b a \%b = a - (int)a / b * b a%b=a−(int)a/b∗b,经过证明,取模的结果的符号与 a a a的符号相同。
++的魔鬼细节
“+” 的使用(连接符)
关系运算符
逻辑运算符
对于短路与 & & \&\& &&而言,如果第一个为假,后面的条件不会执行也不会判断,逻辑与 & \& &则都要判断执行;
同样的对于短路或 ∣ ∣ || ∣∣,如果第一个为真,后面的条件不会执行和判断,逻辑 ∣ | ∣则都要判断执行;
赋值运算符
三元运算符
位运算符
运算符优先级
标识符
控制结构
顺序控制
分支结构
switch细节
循环结构
for
while
do while
多重循环
跳转控制
break
continue
return
排序
查找
对象与类
对象与类介绍
类的内存分配
成员方法
对象克隆
递归
经典问题掌握猴子吃桃,斐波那契数列,汉诺塔问题,八皇后问题,走迷宫问题。
重载
可变参数的形参访问与数组类似,通过形参名[下标]访问.
作用域
构造方法/构造器
this
会发现打印的name和age仍然是默认值
哪个对象调用,this就指向哪个对象
访问修饰符
封装
继承
继承的本质
super
方法重写/覆盖
多态
Object类详解
类变量(静态变量)
会被该类的所有实例对象所共享
类方法
代码块
当涉及到继承的时候
final
抽象类
接口
可以对代码进行规范的管理调用
一方面相对于C++的多继承机制,或许JAVA中的接口实现是对单继承的补充
内部类
局部内部类
匿名内部类
成员内部类
静态内部类
枚举类
自定义枚举类型
enum关键字实现枚举
注解Annotation
Override
Override作语法校验
Deprecated
SuppressWarnings
元注解
Retention
Target
Documented
Inherited
异常
概念
体系图 (很重要)
常见运行时异常
常见编译异常
异常处理
try-catch-finally
throws处理机制
自定义异常
常用类
包装类
String
StringBuffer
StringBuilder
Math
Arrays
System
BigInteger和BigDecimal
Date,Calendar,第三代日期类
集合
单列集合,存放单值
双列集合,存放键值对
Collection
List
ArrayList
无参构造的源码
有参构造的源码
Vector
LinkedList
自己dubug下CRUD的源码
Set
HashSet
hashset加入节点时,只要增加一个元素不管是在数组上还是挂载在链表上,size都要自增
LinkedHashSet
Map
Hashtable
扩容机制是乘以2倍再加1
Propertise
# 工具类
Collections
泛型
JAVA绘图
多线程
interru一般用于中断线程休眠
IO流
mkdirs创建多级目录
InputStream
OutputStream
FileReader && FileWriter
包装流、处理流
网络编程
发送方通常要设置一个结束标记,socket.shutdownOutput().
netstat -anb 可以查看端口被哪个程序占用,cmd需要管理员权限
反射
int.class和Integer.TYPE是同一个对象
IDEA开发
常用快捷键
- 删除当前行 CTRL + D;
- 复制当前行 ctrl + alt +向下箭头
- 补全代码 alt + /
- 取消注释和添加注释 ctrl + /
- 自动导包 alt + enter
- 格式化代码 ctrl + alt + L
- 生成构造器 alt + insert
- 查看类的层级关系 ctrl + h
- 方法定位 ctrl + b
- 自动分配变量名,在后面加.var
- ctrl+alt+t 好东西
包
将set方法写入构造器可以控制外部通过构造器对属性的修改。
断点调试
数据库与MySql
Sqlyog注释的快捷键,shift + ctrl +c,取消为 shift + ctrl + r
单表查询
多表查询
自连接
把一个查询结果当做另一个查询的条件
把子查询当做临时表解决查询问题
多列子查询
自我复制
如何对一张表去重
查询合并
外连接
MySql约束
DESC 表名 查看表的结构
索引
事务
查看隔离级别 select @@tx_isolation
设置隔离级别 set session transaction isolation level 后跟隔离级别
存储引擎
视图
视图可以在创建视图
用户管理
JDBC和数据库连接池
用反射机制时,底层有个静态代码块完成了对驱动的注册,这是用的比较多的
将url,user ,password等写入配置文件,让连接更灵活
resultSet结果集,返回类似一张表的查询记录,是一个对象
引出数据库的实体类
参数列表中的1是赋值给sql中的?,是个可变参数,可以多个赋值
正则表达式
当.?*等出现在中括号中时,不用转义
matches方法用于整体匹配是否成功不保存匹配结果,只返回匹配成功与否,且不需要限定符。
项目
模拟微信零钱通
面向过程版本简单模拟微信零钱通功能
SmallChangeSystem.java
package smallchange;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
/**
* ClassName: SmallChangeSystem <br/>
* Description: <br/>
* date: 2023/3/30 14:11 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
@SuppressWarnings({"all"})
public class SmallChangeSystem {
//先显示菜单
public static void main(String[] args) {
//控制变量
boolean loop = true;
//接受输入
Scanner scanner = new Scanner(System.in);
String choice = "";
//用字符串存零钱通明细
String details = "---------------零钱通明细---------------" +
"\n操作\t\t金额\t\t时间\t\t\t\t\t\t余额";
//余额
double balance = 0;
//消费金额
double money = 0;
//时间
Date date = null;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm::ss");
//保存消费操作
String operation = "";
do {
System.out.println("\n===============零钱通菜单===============");
System.out.println("\t\t\t1 零钱通明细");
System.out.println("\t\t\t2 收益入账");
System.out.println("\t\t\t3 消\t费");
System.out.println("\t\t\t4 退\t出");
System.out.println("请选择(1-4):");
choice = scanner.next();
switch (choice) {
case "1":
System.out.println(details);
break;
case "2":
System.out.println("收入金额:");
money = scanner.nextDouble();
if (money > 0) {
balance += money;
date = new Date();
details += "\n收益入账\t+" + money + "\t" + simpleDateFormat.format(date) + "\t" + balance;
} else {
System.out.println("收入金额不能小于等于零,请重新输入");
}
break;
case "3":
System.out.println("输入消费金额:");
money = scanner.nextDouble();
System.out.println("消费说明:");
operation = scanner.next();
if (money > 0 && money <= balance) {
balance -= money;
date = new Date();
if (operation.length() <= 2)
details += "\n" + operation + "\t\t-" + money + "\t" + simpleDateFormat.format(date) + "\t" + balance;
else
details += "\n" + operation + "\t-" + money + "\t" + simpleDateFormat.format(date) + "\t" + balance;
}else {
System.out.println("消费金额应该在0-"+balance);
}
break;
case "4":
//定义退出标志
String exit = "";
while (true) {
System.out.println("是否确认退出系统(y/n):");
exit = scanner.next();
if ("y".equalsIgnoreCase(exit) || "n".equalsIgnoreCase(exit))
break;
}
if ("y".equalsIgnoreCase(exit))
loop = false;
break;
default:
System.out.println("输入有误,请重新选择");
}
} while (loop);
System.out.println("零钱通项目退出");
}
}
进行封装后的面对对象版本
SmallChangeSystemOOP.java
package smallchange;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
/**
* ClassName: SmallChangeSystemOOP <br/>
* Description: <br/>
* date: 2023/3/30 15:11 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
@SuppressWarnings({"all"})
public class SmallChangeSystemOOP {
//控制变量
boolean loop = true;
//接受输入
Scanner scanner = new Scanner(System.in);
String choice = "";
//用字符串存零钱通明细
String details = "---------------零钱通明细---------------" +
"\n操作\t\t金额\t\t时间\t\t\t\t\t\t余额";
//余额
double balance = 0;
//消费金额
double money = 0;
//时间
Date date = null;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm::ss");
//保存消费操作
String operation = "";
public void MainMenu(){
do {
System.out.println("\n===============零钱通菜单===============");
System.out.println("\t\t\t1 零钱通明细");
System.out.println("\t\t\t2 收益入账");
System.out.println("\t\t\t3 消\t费");
System.out.println("\t\t\t4 退\t出");
System.out.println("请选择(1-4):");
choice = scanner.next();
switch (choice) {
case "1":
this.detail();
break;
case "2":
this.income();
break;
case "3":
this.pay();
break;
case "4":
this.exit();
break;
default:
System.out.println("输入有误,请重新选择");
}
} while (loop);
}
public void detail(){
System.out.println(details);
}
public void income(){
System.out.println("收入金额:");
money = scanner.nextDouble();
if (money > 0) {
balance += money;
date = new Date();
details += "\n收益入账\t+" + money + "\t" + simpleDateFormat.format(date) + "\t" + balance;
} else {
System.out.println("收入金额不能小于等于零,请重新输入");
}
}
public void pay(){
System.out.println("输入消费金额:");
money = scanner.nextDouble();
System.out.println("消费说明:");
operation = scanner.next();
if (money > 0 && money <= balance) {
balance -= money;
date = new Date();
if (operation.length() <= 2)
details += "\n" + operation + "\t\t-" + money + "\t" + simpleDateFormat.format(date) + "\t" + balance;
else
details += "\n" + operation + "\t-" + money + "\t" + simpleDateFormat.format(date) + "\t" + balance;
}else {
System.out.println("消费金额应该在0-"+balance);
}
}
public void exit(){
//定义退出标志
String exit = "";
while (true) {
System.out.println("是否确认退出系统(y/n):");
exit = scanner.next();
if ("y".equalsIgnoreCase(exit) || "n".equalsIgnoreCase(exit))
break;
}
if ("y".equalsIgnoreCase(exit))
this.loop = false;
}
}
SmallChangeSystemApp.java进行调用
package smallchange;
/**
* ClassName: SmallChangeSystemApp <br/>
* Description: <br/>
* date: 2023/3/30 15:11 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
public class SmallChangeSystemApp {
public static void main(String[] args) {
SmallChangeSystemOOP smallChangeSystemOOP = new SmallChangeSystemOOP();
smallChangeSystemOOP.MainMenu();
}
}
房屋出租系统
HouseRentApp.java
package houserent;
import houserent.view.HouseView;
/**
* ClassName: HouseRentApp <br/>
* Description: <br/>
* date: 2023/3/30 17:58 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
public class HouseRentApp {
public static void main(String[] args) {
//程序的入口
HouseView houseView = new HouseView();
houseView.mainMenu();
System.out.println("退出了房屋出租系统");
}
}
House.java
package houserent.domain;
/**
* ClassName: House <br/>
* Description: House的一个对象表示一个房屋信息
* date: 2023/3/30 18:04 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
public class House {
private int id;
private String name;
private String phone;
private String address;
private int rent;
private String state;
public House(int id, String name, String phone, String address, int rent, String state) {
this.id = id;
this.name = name;
this.phone = phone;
this.address = address;
this.rent = rent;
this.state = state;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getRent() {
return rent;
}
public void setRent(int rent) {
this.rent = rent;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
@Override
public String toString() {
return id +
"\t\t" + name +
"\t" + phone +
"\t\t" + address +
"\t" + rent +
"\t" + state ;
}
}
HouseView.java
package houserent.view;
import houserent.domain.House;
import houserent.service.HouseService;
import houserent.utils.Utility;
import java.util.Scanner;
/**
* ClassName: HouseView <br/>
* Description: 1. 显示界面
* 2.接收用户输入
* 3.调用HouseService完成对房屋信息的操作
* date: 2023/3/30 18:10 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
@SuppressWarnings({"all"})
public class HouseView {
//菜单显示控制变量
private boolean loop = true;
//用户输入
private char key = ' ';
//初始的House数组大小
private HouseService houseService = new HouseService(2);
public void mainMenu() {
do {
System.out.println("===============房屋出租系统菜单===============");
System.out.println("\t\t\t1 新 增 房 源");
System.out.println("\t\t\t2 查 找 房 屋");
System.out.println("\t\t\t3 删 除 房 屋 信 息");
System.out.println("\t\t\t4 修 改 房 屋 信 息");
System.out.println("\t\t\t5 房 屋 列 表");
System.out.println("\t\t\t6 退 出");
System.out.println("请输入你的选择:");
key = Utility.readChar();
switch (key) {
case '1':
addHouse();
break;
case '2':
findHouse();
break;
case '3':
deleteHouse();
break;
case '4':
updateHouse();
break;
case '5':
listHouses();
break;
case '6':
exit();
break;
}
} while (loop);
}
//显示房屋列表
public void listHouses() {
System.out.println("===============房屋列表===============");
System.out.println("编号\t\t房主\t\t电话\t\t地址\t\t月租\t\t状态(未出租/已出租)");
House[] list = houseService.list();
for (House house : list) {
if (house != null)
System.out.println(house);
}
System.out.println("=============房屋列表显示完毕=============");
}
public void addHouse() {
System.out.println("===============添加房屋===============");
System.out.println("姓名:");
String name = Utility.readString(8);
System.out.println("电话:");
String phone = Utility.readString(12);
System.out.println("地址:");
String address = Utility.readString(16);
System.out.println("月租:");
int rent = Utility.readInt();
System.out.println("状态:");
String state = Utility.readString(3);
//创建一个house对象,id自增长
House house = new House(0, name, phone, address, rent, state);
if (houseService.add(house))
System.out.println("===============添加房屋成功===============");
else
System.out.println("===============添加房屋失败===============");
}
public void deleteHouse() {
System.out.println("===============删除房屋信息===============");
System.out.println("请输入待删除房屋的编号(-1退出):");
int deleteId = Utility.readInt();
if (deleteId == -1) {
System.out.println("放弃删除房屋信息");
return;
}
char choice = Utility.readConfirmSelection();
if (choice == 'Y') {
if (houseService.delete(deleteId)) {
System.out.println("===============删除房屋成功===============");
} else {
System.out.println("===============删除房屋失败,编号不存在===============");
}
} else {
System.out.println("===============放弃删除房屋===============");
}
}
public void exit() {
char c = Utility.readConfirmSelection();
if (c == 'Y') loop = false;
}
public void findHouse() {
System.out.println("请输入你要查找的房屋ID:");
int findId = Utility.readInt();
House house = houseService.findById(findId);
if (house != null) {
System.out.println(house);
} else {
System.out.println("===============查找的房屋ID不存在===============");
}
}
public void updateHouse() {
System.out.println("请输入你要修改的房屋ID(-1退出):");
int updId = Utility.readInt();
if (updId == -1) {
System.out.println("===============放弃修改房屋信息===============");
return;
}
House house = houseService.findById(updId);
if (house == null) {
System.out.println("===============修改房屋ID不存在===============");
return;
}
System.out.println("姓名(" + house.getName() + "):");
String name = Utility.readString(8, "");
if (!name.equals("")) {
house.setName(name);
}
System.out.println("电话(" + house.getPhone() + "):");
String phone = Utility.readString(12, "");
if (!phone.equals("")) {
house.setPhone(phone);
}
System.out.println("地址(" + house.getAddress() + "):");
String address = Utility.readString(16, "");
if (!address.equals("")) {
house.setAddress(address);
}
System.out.println("租金(" + house.getRent() + "):");
int rent = Utility.readInt(-1);
if (rent != -1) {
house.setRent(rent);
}
System.out.println("状态("+house.getState()+"):");
String state = Utility.readString(3, "");
if(!state.equals("")){
house.setState(state);
}
System.out.println("===============修改房屋信息成功===============");
}
}
HouseService.java
package houserent.service;
import houserent.domain.House;
/**
* ClassName: HouseService <br/>
* Description: 响应HouseView的调用
* 完成对房屋信息的crud
* date: 2023/3/30 18:35 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
@SuppressWarnings({"all"})
public class HouseService {
private House[] houses;
private int housenum = 1; //记录有多少房屋
private int idcounter = 1;//记录id增长
//通过size指定生成的House[]数组大小
public HouseService(int size) {
houses = new House[size];
houses[0] = new House(1, "jack", "154611", "徐州", 1500, "未出租");
}
public House[] list() {
return houses;
}
//房屋信息添加
public boolean add(House house) {
if (housenum == houses.length) {
int newSize = (int) (housenum * 1.5);
House[] temp = new House[newSize];
for (int i = 0; i < housenum; i++) {
temp[i] = houses[i];
}
houses = temp;
System.out.println("已经扩容");
}
houses[housenum++] = house;//加house数组
//同时更新刚加入的房屋id
house.setId(++idcounter);
return true;
}
//房屋信息删除
public boolean delete(int delId) {
int index = -1;//记录delId对应的下标
for (int i = 0; i < housenum; i++){
if(houses[i].getId() == delId){
index = i;
}
}
if(index == -1)
return false;
for(int i =index;i<housenum-1;i++){
houses[i]=houses[i+1];
}
houses[--housenum] = null;//当前有存在的房屋信息最后一个置为null
return true;
}
public House findById(int findId){
for(int i=0;i<housenum;i++){
if(findId == houses[i].getId())
return houses[i];
}
return null;
}
}
Utility.java
package houserent.utils;
/**
工具类的作用:
处理各种情况的用户输入,并且能够按照程序员的需求,得到用户的控制台输入。
*/
import java.util.*;
/**
*/
public class Utility {
//静态属性。。。
private static Scanner scanner = new Scanner(System.in);
/**
* 功能:读取键盘输入的一个菜单选项,值:1——5的范围
* @return 1——5
*/
public static char readMenuSelection() {
char c;
for (; ; ) {
String str = readKeyBoard(1, false);//包含一个字符的字符串
c = str.charAt(0);//将字符串转换成字符char类型
if (c != '1' && c != '2' &&
c != '3' && c != '4' && c != '5') {
System.out.print("选择错误,请重新输入:");
} else break;
}
return c;
}
/**
* 功能:读取键盘输入的一个字符
* @return 一个字符
*/
public static char readChar() {
String str = readKeyBoard(1, false);//就是一个字符
return str.charAt(0);
}
/**
* 功能:读取键盘输入的一个字符,如果直接按回车,则返回指定的默认值;否则返回输入的那个字符
* @param defaultValue 指定的默认值
* @return 默认值或输入的字符
*/
public static char readChar(char defaultValue) {
String str = readKeyBoard(1, true);//要么是空字符串,要么是一个字符
return (str.length() == 0) ? defaultValue : str.charAt(0);
}
/**
* 功能:读取键盘输入的整型,长度小于2位
* @return 整数
*/
public static int readInt() {
int n;
for (; ; ) {
String str = readKeyBoard(10, false);//一个整数,长度<=2位
try {
n = Integer.parseInt(str);//将字符串转换成整数
break;
} catch (NumberFormatException e) {
System.out.print("数字输入错误,请重新输入:");
}
}
return n;
}
/**
* 功能:读取键盘输入的 整数或默认值,如果直接回车,则返回默认值,否则返回输入的整数
* @param defaultValue 指定的默认值
* @return 整数或默认值
*/
public static int readInt(int defaultValue) {
int n;
for (; ; ) {
String str = readKeyBoard(10, true);
if (str.equals("")) {
return defaultValue;
}
//异常处理...
try {
n = Integer.parseInt(str);
break;
} catch (NumberFormatException e) {
System.out.print("数字输入错误,请重新输入:");
}
}
return n;
}
/**
* 功能:读取键盘输入的指定长度的字符串
* @param limit 限制的长度
* @return 指定长度的字符串
*/
public static String readString(int limit) {
return readKeyBoard(limit, false);
}
/**
* 功能:读取键盘输入的指定长度的字符串或默认值,如果直接回车,返回默认值,否则返回字符串
* @param limit 限制的长度
* @param defaultValue 指定的默认值
* @return 指定长度的字符串
*/
public static String readString(int limit, String defaultValue) {
String str = readKeyBoard(limit, true);
return str.equals("")? defaultValue : str;
}
/**
* 功能:读取键盘输入的确认选项,Y或N
* 将小的功能,封装到一个方法中.
* @return Y或N
*/
public static char readConfirmSelection() {
System.out.println("请输入你的选择(Y/N)");
char c;
for (; ; ) {//无限循环
//在这里,将接受到字符,转成了大写字母
//y => Y n=>N
String str = readKeyBoard(1, false).toUpperCase();
c = str.charAt(0);
if (c == 'Y' || c == 'N') {
break;
} else {
System.out.print("选择错误,请重新输入:");
}
}
return c;
}
/**
* 功能: 读取一个字符串
* @param limit 读取的长度
* @param blankReturn 如果为true ,表示 可以读空字符串。
* 如果为false表示 不能读空字符串。
*
* 如果输入为空,或者输入大于limit的长度,就会提示重新输入。
* @return
*/
private static String readKeyBoard(int limit, boolean blankReturn) {
//定义了字符串
String line = "";
//scanner.hasNextLine() 判断有没有下一行
while (scanner.hasNextLine()) {
line = scanner.nextLine();//读取这一行
//如果line.length=0, 即用户没有输入任何内容,直接回车
if (line.length() == 0) {
if (blankReturn) return line;//如果blankReturn=true,可以返回空串
else continue; //如果blankReturn=false,不接受空串,必须输入内容
}
//如果用户输入的内容大于了 limit,就提示重写输入
//如果用户如的内容 >0 <= limit ,我就接受
if (line.length() < 1 || line.length() > limit) {
System.out.print("输入长度(不能大于" + limit + ")错误,请重新输入:");
continue;
}
break;
}
return line;
}
}
坦克大战
其中涉及到爆炸的三张图片,以及音效文件,网上素材应该很多,有需要的私信我或下方评论我给你发。
MyTankGame.java 启动游戏
package tankgame;
import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Scanner;
/**
* ClassName: MyTankGame <br/>
* Description: <br/>
* date: 2023/4/2 5:54 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
@SuppressWarnings({"all"})
public class MyTankGame extends JFrame {
MyPanel myPanel = null;
Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
MyTankGame myTankGame = new MyTankGame();
}
public MyTankGame(){
System.out.println("请输入你的选择1:新游戏 2:继续上局游戏");
String key = scanner.next();
myPanel = new MyPanel(key);
new Thread(myPanel).start();
this.add(myPanel);//把面板放入
this.setSize(1300,950);
this.addKeyListener(myPanel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
//增加相应关闭窗口的监听器
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Recorder.keepRecord();
System.exit(0);
}
});
}
}
Tank.java 坦克父类
package tankgame;
/**
* ClassName: Tank <br/>
* Description: tank父类
* date: 2023/4/2 5:49 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
@SuppressWarnings({"all"})
public class Tank {
private int x;//坦克横坐标
private int y;//坦克纵坐标
private int direct;//坦克方向
private int speed;//坦克速度
private boolean isLive = true;//坦克存活
public boolean isLive() {
return isLive;
}
public void setLive(boolean live) {
isLive = live;
}
public void moveUp() {
y -= speed;
}
public void moveRight() {
x += speed;
}
public void moveDown() {
y += speed;
}
public void moveLeft() {
x -= speed;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
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 Tank(int x, int y) {
this.x = x;
this.y = y;
}
}
MyTank.java 玩家操控的tank对象
package tankgame;
import java.util.Vector;
/**
* ClassName: MyTank <br/>
* Description: <br/>
* date: 2023/4/2 5:50 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
@SuppressWarnings({"all"})
public class MyTank extends Tank{
//定义一个shot对象,对应射击行为
Shot shot = null;
//发射多颗子弹,用Vector存储
Vector<Shot> shots = new Vector<>();
public MyTank(int x, int y) {
super(x, y);
}
public void shotEnemy(){
if(shots.size() == 10){
return;
}
//子弹方向要和当前MyTank对象一致
switch (getDirect()){
case 0:
shot = new Shot(getX()+20,getY(),0);
break;
case 1:
shot = new Shot(getX()+60,getY()+20,1);
break;
case 2:
shot = new Shot(getX()+20,getY()+60,2);
break;
case 3:
shot = new Shot(getX(),getY()+20,3);
break;
}
shots.add(shot);
new Thread(shot).start();
}
}
EnemyTank.java 敌人tank
package tankgame;
import java.util.Vector;
/**
* ClassName: EnemyTank <br/>
* Description: 敌人的坦克
* date: 2023/4/3 11:55 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
@SuppressWarnings({"all"})
public class EnemyTank extends Tank implements Runnable {
//敌人坦克的子弹集合
Vector<Shot> shots = new Vector<>();
//存储所有敌方坦克的Vector
Vector<EnemyTank> enemyTanks = new Vector<>();
public EnemyTank(int x, int y) {
super(x, y);
}
public void setEnemyTanks(Vector<EnemyTank> enemyTanks) {
this.enemyTanks = enemyTanks;
}
//判断当前的敌人坦克是否和其他敌人坦克碰撞
public boolean isTouchEnemyTank() {
//判断当前敌人坦克方向
switch (getDirect()) {
case 0:
for (int i = 0; i < enemyTanks.size(); i++) {
EnemyTank enemyTank = enemyTanks.get(i);
if (this != enemyTank) {
//如果敌人是上下方向
//1.敌人坦克范围x[enemyTank.getX(),enemyTank.getX()+40]
//2.敌人坦克范围y[enemyTank.getY(),enemyTank.getY()+60]
//当前坦克坐标左上角[this.getX(),this.getY()]
//当前坦克坐标右上角[this.getX()+40,this.getY()]
if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
if (this.getX() >= enemyTank.getX()
&& this.getX() <= enemyTank.getX() + 40
&& this.getY() >= enemyTank.getY()
&& this.getY() <= enemyTank.getY() + 60) {
return true;
}
if (this.getX() + 40 >= enemyTank.getX()
&& this.getX() + 40 <= enemyTank.getX() + 40
&& this.getY() >= enemyTank.getY()
&& this.getY() <= enemyTank.getY() + 60) {
return true;
}
}
//如果敌人是左右方向
//1.敌人坦克范围x[enemyTank.getX(),enemyTank.getX()+60]
//2.敌人坦克范围y[enemyTank.getY(),enemyTank.getY()+40]
if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
if (this.getX() >= enemyTank.getX()
&& this.getX() <= enemyTank.getX() + 60
&& this.getY() >= enemyTank.getY()
&& this.getY() <= enemyTank.getY() + 40) {
return true;
}
if (this.getX() + 40 >= enemyTank.getX()
&& this.getX() + 40 <= enemyTank.getX() + 60
&& this.getY() >= enemyTank.getY()
&& this.getY() <= enemyTank.getY() + 40) {
return true;
}
}
}
}
break;
case 1:
for (int i = 0; i < enemyTanks.size(); i++) {
EnemyTank enemyTank = enemyTanks.get(i);
if (this != enemyTank) {
//如果敌人是上下方向
//1.敌人坦克范围x[enemyTank.getX(),enemyTank.getX()+40]
//2.敌人坦克范围y[enemyTank.getY(),enemyTank.getY()+60]
//当前坦克坐标右上角[this.getX()+60,this.getY()]
//当前坦克坐标右下角[this.getX()+60,this.getY()+40]
if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
if (this.getX() + 60 >= enemyTank.getX()
&& this.getX() + 60 <= enemyTank.getX() + 40
&& this.getY() >= enemyTank.getY()
&& this.getY() <= enemyTank.getY() + 60) {
return true;
}
if (this.getX() + 60 >= enemyTank.getX()
&& this.getX() + 60 <= enemyTank.getX() + 40
&& this.getY() + 40 >= enemyTank.getY()
&& this.getY() + 40 <= enemyTank.getY() + 60) {
return true;
}
}
//如果敌人是左右方向
//1.敌人坦克范围x[enemyTank.getX(),enemyTank.getX()+60]
//2.敌人坦克范围y[enemyTank.getY(),enemyTank.getY()+40]
if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
if (this.getX() + 60 >= enemyTank.getX()
&& this.getX() + 60 <= enemyTank.getX() + 60
&& this.getY() >= enemyTank.getY()
&& this.getY() <= enemyTank.getY() + 40) {
return true;
}
if (this.getX() + 60 >= enemyTank.getX()
&& this.getX() + 60 <= enemyTank.getX() + 60
&& this.getY() + 40 >= enemyTank.getY()
&& this.getY() + 40 <= enemyTank.getY() + 40) {
return true;
}
}
}
}
break;
case 2:
for (int i = 0; i < enemyTanks.size(); i++) {
EnemyTank enemyTank = enemyTanks.get(i);
if (this != enemyTank) {
//如果敌人是上下方向
//1.敌人坦克范围x[enemyTank.getX(),enemyTank.getX()+40]
//2.敌人坦克范围y[enemyTank.getY(),enemyTank.getY()+60]
//当前坦克坐标左下角[this.getX(),this.getY()+60]
//当前坦克坐标右下角[this.getX()+40,this.getY()+60]
if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
if (this.getX() >= enemyTank.getX()
&& this.getX() <= enemyTank.getX() + 40
&& this.getY() + 60 >= enemyTank.getY()
&& this.getY() + 60 <= enemyTank.getY() + 60) {
return true;
}
if (this.getX() + 40 >= enemyTank.getX()
&& this.getX() + 40 <= enemyTank.getX() + 40
&& this.getY() + 60 >= enemyTank.getY()
&& this.getY() + 60 <= enemyTank.getY() + 60) {
return true;
}
}
//如果敌人是左右方向
//1.敌人坦克范围x[enemyTank.getX(),enemyTank.getX()+60]
//2.敌人坦克范围y[enemyTank.getY(),enemyTank.getY()+40]
if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
if (this.getX() >= enemyTank.getX()
&& this.getX() <= enemyTank.getX() + 60
&& this.getY() + 60 >= enemyTank.getY()
&& this.getY() + 60 <= enemyTank.getY() + 40) {
return true;
}
if (this.getX() + 40 >= enemyTank.getX()
&& this.getX() + 40 <= enemyTank.getX() + 60
&& this.getY() + 60 >= enemyTank.getY()
&& this.getY() + 60 <= enemyTank.getY() + 40) {
return true;
}
}
}
}
break;
case 3:
for (int i = 0; i < enemyTanks.size(); i++) {
EnemyTank enemyTank = enemyTanks.get(i);
if (this != enemyTank) {
//如果敌人是上下方向
//1.敌人坦克范围x[enemyTank.getX(),enemyTank.getX()+40]
//2.敌人坦克范围y[enemyTank.getY(),enemyTank.getY()+60]
//当前坦克坐标左上角[this.getX(),this.getY()]
//当前坦克坐标左下角[this.getX(),this.getY()+40]
if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
if (this.getX() >= enemyTank.getX()
&& this.getX() <= enemyTank.getX() + 40
&& this.getY() >= enemyTank.getY()
&& this.getY() <= enemyTank.getY() + 60) {
return true;
}
if (this.getX() >= enemyTank.getX()
&& this.getX() <= enemyTank.getX() + 40
&& this.getY() + 40 >= enemyTank.getY()
&& this.getY() + 40 <= enemyTank.getY() + 60) {
return true;
}
}
//如果敌人是左右方向
//1.敌人坦克范围x[enemyTank.getX(),enemyTank.getX()+60]
//2.敌人坦克范围y[enemyTank.getY(),enemyTank.getY()+40]
if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
if (this.getX() >= enemyTank.getX()
&& this.getX() <= enemyTank.getX() + 60
&& this.getY() >= enemyTank.getY()
&& this.getY() <= enemyTank.getY() + 40) {
return true;
}
if (this.getX() >= enemyTank.getX()
&& this.getX() <= enemyTank.getX() + 60
&& this.getY() + 40 >= enemyTank.getY()
&& this.getY() + 40 <= enemyTank.getY() + 40) {
return true;
}
}
}
}
break;
}
return false;
}
@Override
public void run() {
while (true) {
//发射多颗子弹
if (shots.size() <= 5 && isLive()) {
//子弹方向要和当前MyTank对象一致
Shot shot = null;
switch (getDirect()) {
case 0:
shot = new Shot(getX() + 20, getY(), 0);
break;
case 1:
shot = new Shot(getX() + 60, getY() + 20, 1);
break;
case 2:
shot = new Shot(getX() + 20, getY() + 60, 2);
break;
case 3:
shot = new Shot(getX(), getY() + 20, 3);
break;
}
shots.add(shot);
new Thread(shot).start();
}
//进行随机移动且避免碰撞
switch (getDirect()) {
case 0:
for (int i = 0; i < 20; i++) {
if (getY() > 0 && !isTouchEnemyTank()) {
moveUp();
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 1:
for (int i = 0; i < 20; i++) {
if (getX() + 60 < 1000 && !isTouchEnemyTank()) {
moveRight();
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 2:
for (int i = 0; i < 20; i++) {
if (getY() + 60 < 750 && !isTouchEnemyTank()) {
moveDown();
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 3:
for (int i = 0; i < 20; i++) {
if (getX() > 0 && !isTouchEnemyTank()) {
moveLeft();
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
}
setDirect((int) (Math.random() * 4));
if (!isLive()) {
break;
}
}
}
}
Shot.java 描述子弹的类
package tankgame;
/**
* ClassName: Shot <br/>
* Description: 子弹类
* date: 2023/4/3 13:58 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
@SuppressWarnings({"all"})
public class Shot implements Runnable{
private int x;
private int y;
private int direct;
private int speed = 2;
private boolean isLive = true;
public Shot(int x, int y, int direct) {
this.x = x;
this.y = y;
this.direct = direct;
}
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 getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public boolean isLive() {
return isLive;
}
public void setLive(boolean live) {
isLive = live;
}
@Override
public void run() {
while (true){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
switch (direct){
case 0:
y-=speed;
break;
case 1:
x+=speed;
break;
case 2:
y+=speed;
break;
case 3:
x-=speed;
break;
}
if(!(x >= 0 && x<= 1000 && y>=0 && y<=750 && isLive)){
isLive = false;
break;
}
}
}
}
MyPanel.java 主要界面
package tankgame;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.util.Vector;
/**
* ClassName: MyPanel <br/>
* Description: 主要界面
* date: 2023/4/2 5:51 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
@SuppressWarnings({"all"})
public class MyPanel extends JPanel implements KeyListener, Runnable {
//定义我的坦克
MyTank myTank = null;
Vector<EnemyTank> enemyTanks = new Vector<>();
Vector<Node> nodes = new Vector<>();
int enemyTankSize = 5;
Vector<Bomb> bombs = new Vector<>();
Image image1 = null;
Image image2 = null;
Image image3 = null;
public MyPanel(String key) {
File file = new File(Recorder.getRecordFile());
if(file.exists()) {
nodes = Recorder.getNodesAndEnemyTankRecord();
}else{
System.out.println("上局游戏不存在,开始新游戏");
key = "1";
}
Recorder.setEnemyTanks(enemyTanks);
myTank = new MyTank(400, 300);//初始化位置
myTank.setSpeed(10);
switch (key){
case "1":
for (int i = 0; i < enemyTankSize; i++) {
EnemyTank enemyTank = new EnemyTank(100 * (i + 1), 0);
enemyTank.setDirect(2);
enemyTank.setSpeed(3);
enemyTank.setEnemyTanks(enemyTanks);
enemyTanks.add(enemyTank);
new Thread(enemyTank).start();
Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());
enemyTank.shots.add(shot);
new Thread(shot).start();
}
break;
case "2":
for (int i = 0; i < nodes.size(); i++) {
Node node = nodes.get(i);
EnemyTank enemyTank = new EnemyTank(node.getX(), node.getY());
enemyTank.setDirect(node.getDirect());
enemyTank.setSpeed(3);
enemyTank.setEnemyTanks(enemyTanks);
enemyTanks.add(enemyTank);
new Thread(enemyTank).start();
Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());
enemyTank.shots.add(shot);
new Thread(shot).start();
}
}
for (int i = 0; i < enemyTankSize; i++) {
EnemyTank enemyTank = new EnemyTank(100 * (i + 1), 0);
enemyTank.setDirect(2);
enemyTank.setSpeed(3);
enemyTank.setEnemyTanks(enemyTanks);
enemyTanks.add(enemyTank);
new Thread(enemyTank).start();
Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());
enemyTank.shots.add(shot);
new Thread(shot).start();
}
image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));
image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));
image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif"));
new AePlayWave("src\\111.wav").start();
}
//编写方法,提示击毁坦克的信息
public void showInfo(Graphics g){
g.setColor(Color.BLACK);
Font font = new Font("宋体", Font.BOLD, 25);
g.setFont(font);
g.drawString("您累积击毁敌方坦克",1020,30);
drawTank(1020,60,g,0,1);
g.setColor(Color.BLACK);
g.drawString(Recorder.getAllEnemyTankNum()+"",1080,100);
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.fillRect(0, 0, 1000, 750);//填充矩形
showInfo(g);
if(myTank.isLive() && myTank !=null) {
drawTank(myTank.getX(), myTank.getY(), g, myTank.getDirect(), 0);
}
for (int i = 0; i < myTank.shots.size(); i++) {
Shot shot = myTank.shots.get(i);
if (shot != null && shot.isLive()) {
g.draw3DRect(shot.getX(), shot.getY(), 1, 1, false);
} else {
myTank.shots.remove(shot);
}
}
for (int i = 0; i < enemyTanks.size(); i++) {
EnemyTank enemyTank = enemyTanks.get(i);
if (enemyTank.isLive() && enemyTank != null) {
drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);
for (int j = 0; j < enemyTank.shots.size(); j++) {
Shot shot = enemyTank.shots.get(j);
if (shot.isLive() && shot != null) {
g.draw3DRect(shot.getX(), shot.getY(), 1, 1, false);
} else {
enemyTank.shots.remove(shot);
}
}
} else {
enemyTanks.remove(enemyTank);
}
}
for (int i = 0; i < bombs.size(); i++) {
Bomb bomb = bombs.get(i);
if (bomb.getLife() > 6) {
g.drawImage(image1, bomb.getX(), bomb.getY(), 60, 60, this);
} else if (bomb.getLife() > 3) {
g.drawImage(image2, bomb.getX(), bomb.getY(), 60, 60, this);
} else {
g.drawImage(image3, bomb.getX(), bomb.getY(), 60, 60, this);
}
bomb.lifeDown();
if (bomb.getLife() == 0) {
bombs.remove(bomb);
}
}
}
//编写方法,画出坦克
/**
* @param x 坦克左上角的x坐标
* @param y 坦克左上角的y坐标
* @param g 画笔
* @param direct 坦克朝向
* @param type 坦克类型
*/
public void drawTank(int x, int y, Graphics g, int direct, int type) {
switch (type) {
case 0://自己的坦克
g.setColor(Color.cyan);
break;
case 1://敌人的坦克
g.setColor(Color.yellow);
break;
}
//根据方向来绘制坦克
switch (direct) {
case 0://上
g.fill3DRect(x, y, 10, 60, false);//坦克左边的轮子
g.fill3DRect(x + 30, y, 10, 60, false);//坦克右边的轮子
g.fill3DRect(x + 10, y + 10, 20, 40, false);//坦克中间的矩形
g.fillOval(x + 10, y + 20, 20, 20);//坦克的盖子
g.drawLine(x + 20, y + 30, x + 20, y);//坦克的炮筒
break;
case 1://右
g.fill3DRect(x, y, 60, 10, false);//坦克上边的轮子
g.fill3DRect(x, y + 30, 60, 10, false);//坦克下边的轮子
g.fill3DRect(x + 10, y + 10, 40, 20, false);//坦克中间的矩形
g.fillOval(x + 20, y + 10, 20, 20);//坦克的盖子
g.drawLine(x + 30, y + 20, x + 60, y + 20);//坦克的炮筒、
break;
case 2://下
g.fill3DRect(x, y, 10, 60, false);//坦克左边的轮子
g.fill3DRect(x + 30, y, 10, 60, false);//坦克右边的轮子
g.fill3DRect(x + 10, y + 10, 20, 40, false);//坦克中间的矩形
g.fillOval(x + 10, y + 20, 20, 20);//坦克的盖子
g.drawLine(x + 20, y + 30, x + 20, y + 60);//坦克的炮筒
break;
case 3://左
g.fill3DRect(x, y, 60, 10, false);//坦克上边的轮子
g.fill3DRect(x, y + 30, 60, 10, false);//坦克下边的轮子
g.fill3DRect(x + 10, y + 10, 40, 20, false);//坦克中间的矩形
g.fillOval(x + 20, y + 10, 20, 20);//坦克的盖子
g.drawLine(x + 30, y + 20, x, y + 20);//坦克的炮筒
break;
}
}
public void hitTank(Shot shot, Tank tank) {
switch (tank.getDirect()) {
case 0:
case 2:
if (shot.getX() >= tank.getX() && shot.getX() <=
tank.getX() + 40 && shot.getY() >= tank.getY()
&& shot.getY() <= tank.getY() + 60) {
shot.setLive(false);
tank.setLive(false);
Bomb bomb = new Bomb(tank.getX(), tank.getY());
bombs.add(bomb);
if(tank instanceof EnemyTank){
enemyTanks.remove(tank);
Recorder.addAllEnemyTankNum();
}
}
break;
case 1:
case 3:
if (shot.getX() >= tank.getX() && shot.getX() <=
tank.getX() + 60 && shot.getY() >= tank.getY()
&& shot.getY() <= tank.getY() + 40) {
shot.setLive(false);
tank.setLive(false);
Bomb bomb = new Bomb(tank.getX(), tank.getY());
bombs.add(bomb);
if(tank instanceof EnemyTank){
enemyTanks.remove(tank);
Recorder.addAllEnemyTankNum();;
}
}
break;
}
}
public void hitEnemyTank(){
for (int i = 0; i < myTank.shots.size(); i++) {
Shot shot = myTank.shots.get(i);
if (shot != null && shot.isLive()) {
for (int j = 0;j<enemyTanks.size();j++) {
EnemyTank enemyTank = enemyTanks.get(j);
hitTank(shot, enemyTank);
}
}
}
}
public void hitMyTank(){
for (int i = 0; i < enemyTanks.size(); i++) {
EnemyTank enemyTank = enemyTanks.get(i);
for (int j = 0; j < enemyTank.shots.size(); j++) {
Shot shot = enemyTank.shots.get(j);
if (shot.isLive() && myTank.isLive()){
hitTank(shot,myTank);
}
}
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W) {//按下W键
System.out.println((char) e.getKeyCode());
myTank.setDirect(0);
if (myTank.getY() > 0) {
myTank.moveUp();
}
} else if (e.getKeyCode() == KeyEvent.VK_D) {
System.out.println((char) e.getKeyCode());
myTank.setDirect(1);
if (myTank.getX() + 60 < 1000) {
myTank.moveRight();
}
} else if (e.getKeyCode() == KeyEvent.VK_S) {
System.out.println((char) e.getKeyCode());
myTank.setDirect(2);
if (myTank.getY() + 60 < 750) {
myTank.moveDown();
}
} else if (e.getKeyCode() == KeyEvent.VK_A) {
System.out.println((char) e.getKeyCode());
myTank.setDirect(3);
if (myTank.getX() > 0) {
myTank.moveLeft();
}
}
if (e.getKeyCode() == KeyEvent.VK_J) {
/**发射一颗子弹的情况
* if(myTank.shot == null || !myTank.shot.isLive()) {
* myTank.shotEnemy();
* }
*/
myTank.shotEnemy();
}
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
hitMyTank();
hitEnemyTank();
this.repaint();
}
}
}
Node.java 存储敌人位置方向,用于恢复实现继续上局游戏
package tankgame;
/**
* ClassName: Node <br/>
* Description: 一个node对象表示一个敌人坦克的信息
* date: 2023/4/6 0:10 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
public class Node {
private int x;
private int y;
private int direct;
public Node(int x, int y, int direct) {
this.x = x;
this.y = y;
this.direct = direct;
}
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 getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
}
Recorder.java 与文件进行交互,记录相关信息
package tankgame;
import java.io.*;
import java.util.Vector;
/**
* ClassName: Recoder <br/>
* Description: 该类用于记录相关信息和文件进行交互
* date: 2023/4/5 18:26 <br/>
*
* @author Mr.Shen <b/r>
* @since JDK 8
*/
@SuppressWarnings({"all"})
public class Recorder {
private static int allEnemyTankNum = 0;
private static BufferedReader bufferedReader = null;
private static BufferedWriter bufferedWriter = null;
private static String recordFile = "src\\myRecord.txt";
private static Vector<EnemyTank> enemyTanks = null;
private static Vector<Node> nodes = new Vector<>();
public static void setEnemyTanks(Vector<EnemyTank> enemyTanks) {
Recorder.enemyTanks = enemyTanks;
}
public static int getAllEnemyTankNum() {
return allEnemyTankNum;
}
public static void setAllEnemyTankNum(int allEnemyTankNum) {
Recorder.allEnemyTankNum = allEnemyTankNum;
}
public static void addAllEnemyTankNum() {
Recorder.allEnemyTankNum++;
}
public static String getRecordFile() {
return recordFile;
}
public static void keepRecord() {
try {
bufferedWriter = new BufferedWriter(new FileWriter(recordFile));
bufferedWriter.write(Recorder.getAllEnemyTankNum() + "\r\n");
for (int i = 0; i < enemyTanks.size(); i++) {
EnemyTank enemyTank = enemyTanks.get(i);
if (enemyTank.isLive()) {
String record = enemyTank.getX() + " " + enemyTank.getY() + " " + enemyTank.getDirect();
bufferedWriter.write(record + "\r\n");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedWriter != null) {
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//增加一个信息用于读取recordFile,恢复相关信息
public static Vector<Node> getNodesAndEnemyTankRecord(){
try {
bufferedReader = new BufferedReader(new FileReader(recordFile));
allEnemyTankNum = Integer.parseInt(bufferedReader.readLine());
String line = "";
while ((line = bufferedReader.readLine()) != null){
String[] s = line.split(" ");
Node node = new Node(Integer.parseInt(s[0]),
Integer.parseInt(s[1]),
Integer.parseInt(s[2]));
nodes.add(node);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(bufferedReader != null){
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return nodes;
}
}
韩老师的音屏处理类
package tankgame;
import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
/**
* @author 韩顺平
* @version 1.0
*/
public class AePlayWave extends Thread {
private String filename;
public AePlayWave(String wavfile) {
filename = wavfile;
}
public void run() {
File soundFile = new File(filename);
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
} catch (Exception e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat();
SourceDataLine auline = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (Exception e) {
e.printStackTrace();
return;
}
auline.start();
int nBytesRead = 0;
//这是缓冲
byte[] abData = new byte[512];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
auline.close();
}
}
}
设计模式
单例设计模式
懒汉式
模板模式
将重复代码提取到共同的父类,并声明为抽象类,子类继承并实现不同的方法