Java 第二周学习总结
一、数组
数组即一组用于存储相同数据类型的数据结构;数组是一种典型的线性结构(连续)。比如将一些商品数据呈现到页面中,此时可以将所有商品存储到数组中进行传递。数组是一种引用数据类型。数组中的每一个值都称之为元素
数组的声明和初始化
java中对输入的声明语法如下:
数据类型[] 数组名;
数据类型 数组名[];
//推荐
int[] i;
//不推荐
int j[];
double[] d;
boolean[] b;
char[] c;
String[] s;
数组初始化
动态初始化即,在声明数组时只指定数组的容量,不为数组中指定位置赋值
//声明一个长度(容量)为5的数组
int[] arr = new int[5];
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
arr[4] = 60;
System.out.println(arr[4]);
操作数组
组中每一个元素都有一个独一无二的索引(下标),通过语法数组名[索引]可以获取数组中指定位置的元素;数组的索引从0开始;比如一个数组中有10个元素则索引从0~9;任何一个数组都包含一个length属性用于获取数组中元素的个数;
int[] arr = {10,20,30,40};
//获取数组中第4个元素
int i = arr[3];
注意事项:
在对数组操作时如果下标(索引)使用不当 ,则会导致一个异常出现:
java.lang.ArrayIndexOutOfBoundsException
增强for循环-forEach
语法:
for(数据类型 变量名:数组名){
//循环体
}
以上循环中的数据类型表示的数组中每个元素对应的数据类型
int[] arr = {1,4,5,7,9,11,13,19};
//增强for循环(forEach:迭代器-Iterator)
for(int n:arr) {
System.out.println(n);
}
String[] names = {"德玛西亚","瑞兹","易大师","墨菲特"};
for(String name:names) {
System.out.println(name);
}
多维数组(二维数组)
**多维数组即数组中的数组。**在实际的应用中多维数组的使用也很常见(比如二维数组),电影院座位布局,教室座位布局,游戏开发中游戏元素的坐标。
声明语法
数据类型[][] 数组名
数据类型 数组名[][]
int[][] i;
//不推荐
int i[][];
二维数组即数组中的数组,一个数组中的每一个元素还是一个数组
int[][] i = {
{1,3,5},
{2,4,6},
{8,9}
};
// System.out.println(i[1][1]);
// System.out.println(i[2][1]);
//二维数组的遍历
//行
for(int m = 0; m < i.length;m++) {
//列
for(int n = 0;n < i[m].length; n++) {
int e = i[m][n];
System.out.print(e+" ");
}
System.out.println();
}
System.out.println("=================");
//1. 使用forEach对以上二维数组遍历
for(int[] m:i) {
for(int n:m) {
System.out.print(n+" ");
}
System.out.println();
}
数组复习
- 数组时一种只能够存储相同数据类型的数组结构
- 数组中每一个元素都有一个索引
- 数组中的索引从0开始
- 任何数组都存在length属性
- 数组的长度一旦定义则无法改变
- 数组动态初始化必须要指定长度(对于二维数必须要指定行数)
数组常见练习
去零问题
- 有一个数组{19,0,7,5,0,2,0,11,22,32,0},将数组中非0的数存储到一个新数组中
int[] i = {19,0,7,5,0,2,0,11,22,32,0};
//1.统计不为0的数总数
int count = 0;
for(int n:i) {
if(n != 0) {
count++;
}
}
//2.根据不为0的数个数创建对应容量的新数组
int[] j = new int[count];
//3.将原数组中不为0的数存储到新数组
for(int m = 0,n = 0;m < i.length; m++) {
if(i[m] != 0) {
j[n++] = i[m];
}
}
//输出新数组的元素
for(int n:j) {
System.out.println(n);
}
排序
冒泡排序
每两个相邻的数比较
/**
* 冒泡排序
* @author mrchai
*
*/
public class Exp02 {
public static void main(String[] args) {
int[] a = {9,5,4,8,7,6,3,18,2,1,11,12};
for(int i = 0;i < a.length;i++) {
//初始临时变量
int t = 0;
for(int j = 0;j < a.length - 1;j++) {
//判断左边的数是否大于右边的数
if(a[j] > a[j + 1]) {
t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
//输出第n趟排序
System.out.print("第"+(i+1)+"趟:");
for(int n:a) {
System.out.print(n+" ");
}
System.out.println();
}
}
}
选择排序
从第一个数开始依次跟之后的每一个数比较
public class Exp03 {
public static void main(String[] args) {
int[] a = {9,5,4,8,7,6,3,18,2,1,11,12};
for(int i = 0;i < a.length; i++) {
//声明临时变量
int t = 0;
for(int j = i + 1;j < a.length; j++) {
if(a[i] > a[j]) {
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
//输出第n趟排序
System.out.print("第"+(i+1)+"趟:");
for(int n:a) {
System.out.print(n+" ");
}
System.out.println();
}
}
}
折半查找(二分法)
折半查找也叫二分法,或者二分查找;从一组已经排好序的数组中搜索目标数的为止,思路:
- 先从数组中找到中间数
public class Exp05 {
public static void main(String[] args) {
//原数组
int[] a = {1,2,3,4,5,6,7,8,9,11,12,18,22,30,45};
//目标数
int target = 22;
//初始开始搜索位置
int start = 0;
//初始终止搜索位置
int end = a.length-1;
//初始目标数位置
int index = -1;
//统计搜索次数
int count = 0;
//当起始的搜索位置小于等于结束的搜索位置时执行比较
while(start <= end) {
//搜索次数递增
count++;
//获取中间数位置
int mid = (start + end) / 2;
//判断中间数和目标数的大小
if(target > a[mid]) {
//如果目标数大于了中间数,则搜索的起始位置设置到中间数位置+1
start = mid + 1;
}else if(target < a[mid]) {
//如果目标数小于中间数,则搜索的结束位置设置到中间数位置-1
end = mid - 1;
}else {
//找到目标数
index = mid;
break;
}
}
System.out.println("搜索次数"+count+"目标数位置:"+index);
}
}
约瑟夫环
/**
* 约瑟夫环
* 有500个人围城一个圈,依次报数,每数到3的倍数的人离开圈,数完一圈后继续从1开始数,
* 直到圈中剩下最后一个人,求剩下的人原来在圈中的位置(约瑟夫环问题)
* @author mrchai
*
*/
public class Exp07 {
public static void main(String[] args) {
//初始一个长度未500的布尔数组,表示所有人是否在圈中
boolean[] b = new boolean[500];
//初始所有人都在圈中
for(int i = 0;i < b.length;i++) {
b[i] = true;
}
//当前遍历到的索引
int index = 0;
//计数器(统计目前数到几)
int count = 0;
//初始总人数
int len = b.length;
//只要总人数超过1个就循环报数
while(len > 1) {
//判断当前报数的人是否在圈中
if(b[index]) {
//计数器递增
count++;
//判断是否到达3
if(count == 3) {
//如果到达3则当前位置的人从圈中离开
b[index] = false;
//人数减少一个
len--;
//计数器归零
count = 0;
}
}
index++;
//判断是否已经数完一圈
if(index == b.length) {
index = 0;
}
}
//对数组遍历
for(int i = 0;i<b.length;i++) {
//获取每一个位的结果
if(b[i]) {
//如果其中有一个元素为true,则表示剩下的最后一个人
System.out.println("最后剩下的人原来在圈中的位置:"+i);
break;
}
}
}
}
数组拷贝
System类中提供了arraycopy方法用于实现数组拷贝功能,该方法包含5个参数:
/*
* 参数1:需要被拷贝的原始数组
* 参数2:原数组的起始拷贝位置
* 参数3:目标数组
* 参数4:目标数组的存储起始位置
* 参数5:需要从参数1数组中拷贝元素个数
*/
int i = 100;
int[] a = {12,22,11,10,10};
int[] b = new int[a.length << 1];
//数组拷贝
/*
* 参数1:需要被拷贝的原始数组
* 参数2:原数组的起始拷贝位置
* 参数3:目标数组
* 参数4:目标数组的存储起始位置
* 参数5:需要从参数1数组中拷贝元素个数
*/
System.arraycopy(a, 0, b, 0, a.length);
b[a.length] = i;
for(int n:b) {
System.out.println(n);
}
动态数组
由于Java中的数组的长度一旦定义则无法改变,但是可以通过数组拷贝的方式实现数组容量扩充(创建新数组,将原来数组中的内容拷贝到新数组中);因此,Java中提供一个集合工具类:java.util.ArrayList可以用于存储任意类型的元素,并且,容量可以自动扩充;一旦ArrayList的容量超出,在下一次加入元素时会自动创建一个容量为原来数组1.5倍的新数组。
ArrayList基本使用:
public class ArrayListDemo {
public static void main(String[] args) {
//动态数组(长度可变(逻辑)的数组) 多态
//实现原理即:数组 + 数据拷贝
ArrayList list = new ArrayList(); //创建一个长度为0的空数组
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add(50);
list.add(60);
list.add(70);
list.add(80);
list.add(true);
list.add("hello");
list.add(3.14);
System.out.println(list);
System.out.println(list.size());
System.out.println(list.get(7));
//创建一个只能存放整数类型的动态数组
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(10);
list2.add(5);
}
}
二维数组
二位数组即数组中的数组,一个数组中的每一个元素还是一个数组
int[][] i = {
{1,3,5},
{2,4,6},
{8,9}
};
// System.out.println(i[1][1]);
// System.out.println(i[2][1]);
//二维数组的遍历
//行
for(int m = 0; m < i.length;m++) {
//列
for(int n = 0;n < i[m].length; n++) {
int e = i[m][n];
System.out.print(e+" ");
}
System.out.println();
}
System.out.println("=================");
//1. 使用forEach对以上二维数组遍历
for(int[] m:i) {
for(int n:m) {
System.out.print(n+" ");
}
System.out.println();
}
二、面向对象入门
面向对象程序设计概述
程序设计语言发展史
面向对象程序
Java中万事万物皆对象,面向对象编程即:将现实生活的事物以计算机的语言进行描述
类和对象
面向对象中的两个核心概念:
- 类:对一类具备相同特征(属性,行为)事物的抽象描述;例如:学生类
- 对象:类的一个实例;例如:学号时123的学生
类的成分
由于类中包含一类事物的属性和行为,因此类的成主要由属性和行为构成,对于以上两个特征Java中以如下的方式呈现:
属性---->变量
行为---->方法(函数)
类的声明语法:
[<修饰符>] class 类名称 {
//属性的定义
//行为的定义
}
例如:
public class Student {
//属性:成员变量、全局变量、实例(对象)变量
String sno;
String sname;
int age;
char sex;
/**学分*/
double score;
/**学校*/
String school = "**大学";
/**专业*/
String major;
//行为:方法(函数 function) f(x)
public void study() {
System.out.println("good good study,day day up!!!");
}
public void play() {
System.out.println("一起来玩有游戏吧!!");
}
}
属性
属性用于描述类的静态信息,表示类的数据;语法
[<修饰符>] 数据类型 变量名 = [<默认值>]
例如:
String sno;
String sname;
int age;
char sex;
/**学分*/
double score;
/**学校*/
String school = "**大学";
方法
类中另一个组成部分称之为行为,行为在java中的呈现方式以方法(函数)的形式存在,语法:
[<修饰符>] 返回值类型 方法名([<参数列表>]) {
//执行体
}
例如:
public void study(String kecheng,int hours) {
System.out.println("good good study,day day up!!!");
}
public void play() {
System.out.println("一起来玩有游戏吧!!");
}
对象创建与使用
对象即对类的具象化,即类的一个实例
构造器
方法详解
方法(Method)是由一些表达式组成的代码片段,通常用于完成某些特定的功能,实际开发中可以将一些反复需要使用到的代码编写到方法中,只需要对方法进行调用,即可执行这些代码片段,从而提高的代码的可复用性。
方法的分类
根据方法的声明语法:
[<修饰符>] 返回值类型 方法名([<参数列表>]) {
}
由于方法结构中包含返回值类型和参数成分,根据这两个成分的组合,方法可以分为4中类别:
- 无参数无返回值
- 无参数有返回值
- 有参数无返回值
- 有参数有返回值
public class Tools {
/**
* 有参有返回值
* @param a 数值1
* @param b 数值2
* @return 返回两个数值中较大的一个
*/
public int max(int a,int b) {
return a > b ? a : b;
}
/**
* 无参有返回值
* 返回字符串时间
* @return
*/
public String nowTime() {
return "2020年11月3日 10:46:22";
}
/**
* 有参无返回值
* 打印输出参数内容
* @param msg
*/
public void log(String msg) {
System.out.println(msg);
}
/**
* 无参无返回值
*/
public void tips() {
System.out.println("天气冷了,多穿衣服,多喝开水!");
}
public static voi d main(String[] args) {
Tools t = new Tools();
//调用包含返回值的方法,并且使用对应的数据类型变量接收返回值
int i = t.max(10, 15);
System.out.println(i);
String time = t.nowTime();
System.out.println(time);
t.log("helloworld,你好,世界");
t.tips();
// 创建一个方法,要求提供一个年份,返回该年份是否是闰年
}
}
参数(Parameter):在执行方法时需要传递到方法中使用的一些数据,参数的类型可以是任意的,数量可以是任意多个,参数顺序也可以任意的,在声明方法时定义的参数,称之形式参数(形参);在对象方法进行调用时传入的参数称之实际参数(实参)。
返回值(returns):在方法执行完毕之后,传递到方法之外的数据;返回值的类型可以是任意,返回的具体值(或者变量)必须要跟方法定义的返回类型匹配。
方法调用
java中方法的调用需要通过对象完成,语法如下:
引用对象.方法名(实参)
//对象创建(实例化对象)
Student stu = new Student();
//调用方法
stu.play();
值传递问题
基本类型传递问题
观察以下代码,给出程序运行结果:
public class Test {
public void change(int i) {
i = 10;
System.out.println("change--->" + i); // 10;
}
public static void main(String[] args) {
int a = 5;
System.out.println("change前:" + a); //5
Test t = new Test();
t.change(a);
System.out.println("change后:" + a); // ?
}
}
结果:
change前:5
change--->10
change后:5
分析以上程序,可以看出java中参数的传递为值传递,不存在引用传递的问题,change方法中改变的只是内部定义的局部变量i,不会影响main方法中的局部变量,内存模型如下:
注意事项:
java中局部变量的存储位置位于方法帧栈中,成员变量的存储位于堆内存中
引用类型参数传递问题
以上实例修改之后,观察执行结果
public class TestDog {
public void change(Dog d) {
System.out.println("change:"+d);
d.nickname = "旺财";
}
public static void main(String[] args) {
Dog d = new Dog();
System.out.println(d);
d.nickname = "来福";
System.out.println("change前:" + d.nickname);
TestDog td = new TestDog();
td.change(d);
System.out.println("change后:" + d.nickname);
}
}
class Dog{
String nickname;
}
以上程序执行的内存模型:
递归(Recursion)
递归即在一个方法内部对方法自身调用,递归可以以简单的代码解决复杂的算法问题,对文件夹的遍历,树形菜单遍历等等;递归操作不当将会导致栈溢出错误StackOverflowError
递归实例:
//5!
public int m(int n) {
if(n == 1) {
return 1;
}else {
return n * m(n - 1);
}
}
//1+2+...+100
public int add(int n) {
if(n == 1) {
return 1;
}else {
return n + add(n - 1);
}
}
//斐波拉契数列
public int fib(int n) {
if(n == 1 || n == 2) {
return 1;
}else {
return fib(n - 1) + fib(n - 2);
}
}
类的成分
一个类属性和行为构成:
属性:描述指定类型的数据(名词)
行为:描述指定类型的一种动作(动词)
属性详解(Field)
属性用于描述类的一些静态信息(数据),属性在代码中的呈现方式为变量,java中的变量根据出现的位置不同,又分为两种:
- 全局变量(global variable)
也称之成员变量,实践(对象)变量;直接在类结构中定义与方法同一级别,成员变量可以出现在类中的任意非静态方法中,成员变量在类加载时编译器会自动为期设置初始值(即便不手动赋值都存在默认值)
案例:
public class People {
// 成员变量
String name;
int age;
String sex;
double height;
}
各种类型成员变量的默认值
byte 0
short 0
int 0
long 0
float 0.0
double 0.0
char <空格>
boolean false
引用类型 null
- 局部变量(local variable)
也称之为临时变量;局部变量一般位于方法内部声明,方法的参数也是局部变量,局部变量的作用范围仅限于声明的区域;局部变量没有初始化前不能使用
案例:
public void speak(String s) {
int i = 10;
System.out.println(name + "说:" + s);
}
if(true){
int i = 10;
}
{
int i = 10;
}
static{
int i = 10;
}
构造器详解
构造器也称之为构造方法,构造函数,构建器;作用于对象创建时完成对于对象的相关属性初始化操作,减少方法对于参数依赖,可以直接在方法中使用由构造器赋值的成员变量;构造器是一种特殊的方法,语法规范:
[<修饰符>] 类名称([<参数列表>]){
//执行体
}
案例:
public Goods(){
}
public People(){
}
构造器的定义范围
- 构造器的名称必须跟类名称一致
- 构造器不能包含类型的返回值(包括void)
构造器注意事项
- 任何一个Java类存在一个默认的无参构造器(编译器自动添加)
- 如果一旦定义自定义的构造器,则默认无参构造器会被覆盖
- 一个类可以存在多个构造器,但是构造器中的参数个数,类型,顺序任意有一项不一致(方法的重载)
构造器使用
构造器的调用一般通过new关键字进行调用,一旦执行,就完成了对象的创建以及初始化。
new 构造器();
案例:
People p = new People();
Goods g = new Goods();
访问修饰符
Java中的访问修饰符分为4个
- defualt(空白)
不使用任何访问修饰符时,目标元素只能在同一个类或者同一个包的其他类被访问 - private
被private修饰的元素,只能够在当前类中被访问 - protected
被protected修饰的元素,只能在同一个包中,或者跨包的子类中被访问 - public
被public修饰的元素可以在同一个项目中的任意包被访问
各种访问修饰符的访问范围图
使用原则:
类一般使用public修饰(普通的类无法使用private和protected修饰)
属性一般使用private修饰
方法一般使用public
封装
面向对象语言包含三大核心特征:
- 封装
- 继承
- 多态
信息隐藏
信息隐藏是java中对类的一种保护机制,将一个类的具体实现细节隐藏起来,隐藏通常指的是使用private修饰符对属性或者方法修饰,使得外界无法随意访问该类中的成分。
对于一些属性来说,如果对外公开,则外界一旦获取到该类的实例(对象),即可对该公开的属性进行随意访问甚至修改,从而会造成一些不要的安全问题。
Setter & Getter方法
将类中的属性设置为private之后,外界无法访问,但是可以通过提供公开的方法对这些私有的属性进行访问。让外界访问方法的可控性要远远高于直接让外界访问属性;对于上述的操作,Java中提供了两种用于对属性操作的方法:
- setter
- getter
public class People {
private String idCard;
private String name;
private int age;
private String sex;
private boolean marry;
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
if(age > 18) {
age = 18;
}
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
/**
* boolean类型属性的get方法叫isXXX
* @return
*/
public boolean isMarry() {
return marry;
}
public void setMarry(boolean marry) {
this.marry = marry;
}
}
this关键字
this关键字在一个类中用于表示"当前对象”;this一般用于一个类的成员方法、构造器或者游离块中,作用于调用当前类的构造器,属性和其他方法
public class Dog {
private int id;
private String name;
public Dog() {
// 构造器中如果调用了其他构造器,则调用代码必须位于最前端
// System.out.println("---");
//调用包含String类型参数的构造器
this("来福");
}
public Dog(String name) {
System.out.println("执行带参数构造器。。。。");
this.name = name;
}
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 void eat() {
System.out.println(name+"吃肉肉");
}
public void drink() {
System.out.println(name+"和奶茶");
}
public void sleep() {
System.out.println(name+"碎觉觉");
}
public void oneDay() {
System.out.println(this);
this.eat();
this.drink();
this.sleep();
}
public static void main(String[] args) {
Dog d = new Dog();
System.out.println("$$$$"+d);
d.oneDay();
}
}
类之间关系(软件工厂与统一建模语言UML)
面向对象设计语言中,类和类之间是存在一定关系的,从关系角度考虑,分为两种:
- 横向关系(平级)
- 纵向关系(上下级)
横向关系
横向关系一般表示为多个类之间是同一级别,横向关系又分为以下几类
- 依赖关系
依赖关系表示为一个类的方法中需要另一个类型对象作为参数
public class Cat{
//依赖关系的代码表现方式
public boolean catchMouse(Mouse m) {
return false;
}
}
- 关联关系
- 聚合关系
- 组合关系
关联,聚合,组合三种关系在代码的表现形式上是相同,只是存在语义上的区别,主要区别为类和类之间的紧密程度;代码层面的表现方式是在一个类中将另一个类型对象作为属性定义。
public class Dept{
private int dno;
private String dname;
private String tel;
//setter/getter ...
}
public class Emp{
private int eno;
private String ename;
private double sal;
//员工关联部门
private Dept dept;
//setter/getter ...
}
典型的关联关系实例:
- 学生选课系统类设计
纵向关系
纵向关系是一种上下级的关系,表现方式在Java中通常以以下两种形式呈现:
- 继承(extends)
- 实现
继承(extends)
继承是面向对象程序设计中另一个重要的特征,继承即由一个类从另一个通过extends关键字继承,被继承的类称之为父类(也叫超类),继承的类称之为子类(扩展类);继承可以使得类的扩展性提高,减少重复代码的编写。
语法:
[<修饰符>] class 子类 extends 父类 {
}
实例:
父类Father:
public class Son extends Father{
//通过代码表现:动物 猫 老鼠之间的关系
public static void main(String[] args) {
Son s = new Son();
s.name = "张三";
s.coding();
s.love();
}
}
继承优点
- 子类可以直接通过对象调用父类中的非私有元素
- 子类还可以在父类的基础上扩展新的功能
继承注意事项
- 子类只能继承父类的属性和方法,不能继承构造器
- 子类对象构造之前会先执行父类的构造器(如果存在多重继承,则从最顶层父类构造器开始执行)
- 一个父类可以存在多个子类,但是一个子类只能存在一个父类
- Java不允许多继承,但是支持多重继承
- 被protected修饰的元素可以在子类中被访问(即便父类和子类不在同一个包)
super关键字
super关键字用于在子类中调用父类的元素:
- 构造器
- 属性
- 方法
使用案例:
public class Animal {
String name = "旺财";
double weight = 10 ;
public Animal(String name) {
// this.name = name;
}
public void eat() {
System.out.println("动物进食");
}
public void bark() {
System.out.println("咆哮");
}
}
public class Dog extends Animal{
public Dog(String name) {
//调用父类构造器
super(name);
}
public void play() {
//调用父类方法
super.eat();
super.bark();
//调用父类属性
System.out.println("我叫:" + super.name);
}
public static void main(String[] args) {
Dog d = new Dog("来福");
d.play();
}
}
练习
- 模拟地下城与勇士(DNF)的装备强化过程:
提示1:
- DNF装备强化在+1~+3 不会失败;
- +4~+7,失败后物品原有强化等级降低1级;
- +8~+10,失败后掉3级;
- 10上11或以上就爆了。
提示2:
- DNF装备强化1~3级,成功率100%
- DNF装备强化3~4级,成功率95%
- DNF装备强化4~5级,成功率90%
- DNF装备强化5~6级,成功率80%
- DNF装备强化6~7级,成功率75%
- DNF装备强化7~8级,成功率62.1%
- DNF装备强化8~9级,成功率53.7%
- DNF装备强化9~10级,成功率41.4%
- DNF装备强化10~11级,成功率33.9%
- DNF装备强化11~12级,成功率28%
- DNF装备强化12~13级,成功率20.7%
- DNF装备强化13~14级,成功率17.3%
- DNF装备强化14~15级,成功率13.6%
- DNF装备强化15~16级,成功率10.1%
实现流程:
要求输入装备的原始等级,输入1执行强化,根据原始等级以及强化的成功率,显示装备的强化结果
public void qianghua(int initLevel,int targetLevel) {
int count = 0;
do {
count++;
switch (initLevel) {
case 0:
case 1:
case 2:
//强化1-3级
initLevel = q1_3(initLevel);
break;
case 3:
case 4:
case 5:
case 6:
//强化4-7级
initLevel = q4_7(initLevel);
break;
case 7:
case 8:
case 9:
//强化8-10级
initLevel = q8_10(initLevel);
break;
default:
//强化10级以上
initLevel = q10(initLevel);
break;
}
} while (initLevel < targetLevel && initLevel != -1);
System.out.println("强化次数:"+count);
}
/**
* 强化1~3级
* @param level
* @return
*/
public int q1_3(int level) {
System.out.println("强化成功,当前等级为:" + level);
return ++level;
}
/**
* 随机一个浮点数表示成功率
* @return
*/
public double d() {
return Math.random();
}
/**
* 强化4~7级
* @param level
* @return
*/
public int q4_7(int level) {
int i = level;
switch (level) {
case 3:
i = d() < 0.95 ? level+1 : level-1;
break;
case 4:
i = d() < 0.9 ? level+1 : level-1;
break;
case 5:
i = d() < 0.8 ? level+1 : level-1;
break;
case 6:
i = d() < 0.75 ? level+1 : level-1;
break;
}
if (i > level) {
System.out.println("强化成功,当前等级为:" + i);
}else {
System.out.println("强化失败,当前等级为:" + i);
}
return i;
}
/**
* 强化8~10级
* @param level
* @return
*/
public int q8_10(int level) {
int i = level;
switch (level) {
case 7:
i = d() < 0.621 ? level+1 : level-3;
break;
case 8:
i = d() < 0.537 ? level+1 : level-3;
break;
case 9:
i = d() < 0.414 ? level+1 : level-3;
break;
}
if (i > level) {
System.out.println("强化成功,当前等级为:" + i);
}else {
System.out.println("强化失败,当前等级为:" + i);
}
return i;
}
/**
* 强化10级以上
* @param level
* @return
*/
public int q10(int level) {
int i = level;
switch (level) {
case 10:
i = d() < 0.339 ? level+1 : -1;
break;
case 11:
i = d() < 0.28 ? level+1 : -1;
break;
case 12:
i = d() < 0.207 ? level+1 : -1;
break;
case 13:
i = d() < 0.1731 ? level+1 : -1;
break;
case 14:
i = d() < 0.136 ? level+1 : -1;
break;
case 15:
i = d() < 0.101 ? level+1 : -1;
break;
}
if (i > level) {
System.out.println("强化成功,当前等级为:" + i);
}else {
System.out.println("强化失败,装备已损坏!");
}
return i;
}
public static void main(String[] args) {
DNF d = new DNF();
d.qianghua(0,15);
}
- 打印万年历
public class MyCalendar {
int year;
int month;
public MyCalendar(int _year,int _month) {
year = _year;
month = _month;
}
/**
* 判断指定的年份是否是闰年
*
* @param year
* @return
*/
public boolean isLeapYear(int year) {
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}
/**
* 根据提供的年份月份,返回当前月的总天数
*
* @param y
* @param m
* @return
*/
public int getDaysOfMonth(int y, int m) {
switch (m) {
case 4:
case 6:
case 9:
case 11:
return 30;
case 2:
return isLeapYear(y) ? 29 : 28;
default:
return 31;
}
}
/**
* 计算从1900年1月份到目标的年份月份上一个月的总天
*
* @param y
* @param m
* @return
*/
public int getTotalDaysFrom1900() {
// 局部变量使用前必须先初始化
int days = 0;
// 计算整年的总天数1900~(y-1)
for (int i = 1900; i < year; i++) {
days += isLeapYear(i) ? 366 : 365; // days = days + 366/365
}
// 计算从1-(m-1)月的总天数 1 2 3 4 5 .. 10
for (int i = 1; i < month; i++) {
days += getDaysOfMonth(year, i); // days = days + 28/29/30/31
}
return days;
}
/**
* 打印日历
*
* @param y
* @param m
*/
public void printCalendar() {
// 获取打印日历之前需要预留的空格数
int space = getTotalDaysFrom1900() % 7;
// 获取目标年份月份的总天数
int days = getDaysOfMonth(year, month);
System.out.println("============SOFTEEM万年历 【" + year + "】年【" + month + "】月=============");
System.out.println("一\t二\t三\t四\t五\t六\t日");
System.out.println("====================================================");
int count = 0;
//打印空格
for (int i = 0; i < space; i++) {
System.out.print("\t");
count++;
}
//打印日期
for (int i = 1; i <= days; i++) {
count++;
System.out.print(i + "\t");
//是否达到周天
if(count == 7) {
System.out.println();
//计数器归零
count = 0;
}
}
}
public static void main(String[] args) {
MyCalendar mc = new MyCalendar(2020,11);
mc.printCalendar();
}
}
- 基于面向对象实现:猫抓老鼠小游戏有一只猫和一只老鼠,当猫的体重是小老鼠体重的5倍时,猫可以抓到老鼠,猫每吃掉一只老鼠,体重增加老鼠的体重的0.5倍,但是当猫的体重超过了老鼠体重的5倍,猫无法抓到老鼠,老鼠逃脱并对猫发出嘲讽。
public class Cat {
private String name;
private double weight;
public Cat() {
}
public Cat(String name, double weight) {
this.name = name;
this.weight = weight;
}
/**猫抓老鼠*/
public boolean catchMouse(Mouse m) {
//判断猫的体重是否小于老鼠体重的5倍
if (this.weight < m.getWeight() * 5) {
//猫抓住老鼠,体重增加
this.weight += m.getWeight() / 2;
System.out.println(name+"抓住了"+m.getName()+",当前体重:"+this.weight);
return true;
}
m.runaway();
this.weight -= m.getWeight()/4;
System.out.println("老鼠"+m.getName()+",成功逃脱,"+this.name+"体重减少,当前体重:"+this.weight);
return false;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
}
public class Mouse {
private String name;
private double weight;
public Mouse() {
}
public Mouse(String name, double weight) {
this.name = name;
this.weight = weight;
}
public void runaway() {
System.out.println("大笨猫,来抓我呀....");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
}
public class TomAndJerry {
public static void main(String[] args) {
//初始化猫对象
Cat c = new Cat("Tom",3);
System.out.println("游戏开始....");
Scanner sc = new Scanner(System.in);
while (true) {
//接收输入:老鼠体重
System.out.println("请输入老鼠的体重:");
int w = sc.nextInt();
//创建老鼠对象
Mouse m = new Mouse("Jerry",w);
//判断是否抓住老鼠
// if (!c.catchMouse(m)) {
// //一旦老鼠逃脱则游戏结束
// System.out.println("游戏结束!");
// break;
// }
c.catchMouse(m);
}
}
}
-
根据LOL,创建一个英雄类(Hero),包含以下属性:
- 编号(int)
- 昵称(String)
- 名称(String)
- 类型(法师,射手,战士,坦克,辅助,打野)
- 攻击力(int)
- 防御力(int)
- 血量(int)
- 魔法值(int)
英雄包含两个构造方法
- 无参数
- 所有参数
英雄包含三个方法:
- 攻击attack(Hero h)
- 死亡
- 重生
- 移动
要求完成如下功能:
- 分别创建两个不同类型的英雄
- 实现攻击的功能(轮流攻击)
- 血量先归零的英雄死亡
public class Hero {
/**编号*/
private int number;
/**昵称*/
private String nickname;
/**真是名称*/
private String realname;
/**类型*/
private String type;
/**攻击力*/
private int atk;
/**防御力*/
private int defense;
/**血量*/
private int hp;
/**魔法值*/
private int mp;
public Hero() {
}
public Hero(int number, String nickname, String realname, String type, int atk, int defense, int hp, int mp) {
this.number = number;
this.nickname = nickname;
this.realname = realname;
this.type = type;
this.atk = atk;
this.defense = defense;
this.hp = hp;
this.mp = mp;
}
/**攻击*/
public void attack(Hero h) {
//减少被攻击的英雄血量
h.hp = (int) (h.hp-Math.random() * this.atk)+h.defense/10;
System.out.println(this.realname+"正在攻击"+h.realname+",血量剩余:"+h.hp);
System.out.println(h.realname+"英雄防御,血量减少:"+h.defense/10);
//判断英雄是否死亡
if (h.hp <= 0) {
h.die();
}else {
h.attack(this);
}
}
/**移动*/
public void move() {
System.out.println("前进10步");
}
/**复活*/
public void reLife() {
System.out.println("我胡汉三有回来了....");
}
/**死亡*/
public void die() {
System.out.println(nickname+"-"+realname+"死亡,10秒之后又是一条好汉!");
}
}
public class TestHero {
public static void main(String[] args) {
Hero h1 = new Hero(1,"德玛西亚","盖伦","战士",80,120,800,0);
Hero h2 = new Hero(2,"无极剑圣","易大师","刺客",120,90,600,0);
h1.attack(h2);
}
}
-
基于数组+面向对象完成一个学生信息管理系统,初始化一个长度为100的学生数组,学生信息包含如下:
- 学号(int)
- 姓名(String)
- 性别(String)
- 年龄(int)
- 专业(String)
- 学分(double)
要求实现以下功能
- 完成学生添加的功能呢
- 根据指定的学号,删除学生
- 根据学号,修改指定学生的学分
- 显示所有学生的信息
- 查询所有学分超过80的学生信息
创建两个类:
- 学生类(属性,setter/getter,构造器)
- 学生管理类(对学生操作的所有方法)
public class Student {
private int sno;
private String name;
private String sex;
private int age;
/**专业*/
private String major;
/**学分*/
private double score;
public Student() {
}
public Student(int sno, String name, String sex, int age, String major, double score) {
this.sno = sno;
this.name = name;
this.sex = sex;
this.age = age;
this.major = major;
this.score = score;
}
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
/**
* 显示当前所有学生的信息
*/
public void details() {
System.out.println(sno+"\t"+name+"\t"+sex+"\t"+age+"\t"+major+"\t"+score);
}
}
public class StudentManager {
/**声明一个学生数组,用于存储所有的学生对象*/
private Student[] list;
/**声明一个索引,用来表示目前数组中元素存储的位置*/
private int index;
/**对象构造时,初始数组的容量为100*/
public StudentManager() {
list = new Student[100];
}
/**
* 添加学生
* @param s 学生
*/
public void add(Student s) {
list[index++] = s;
}
/**
* 根据提供的学号删除学生
* @param sno
*/
public void del(int sno) {
//先循环遍历数组中的元素
int i = findBySno(sno);
//一旦返回索引为-1则说明指定学号的学生不存在
if (i==-1) {
System.out.println("未找到指定学号的学生!");
}else {
//逻辑删除
list[i] = null;
}
// for(int i=0;i<list.length;i++) {
// //获取遍历到的一个学生对象
// Student s = list[i];
// //判断当前遍历到的学生的学号是否等于需要删除的学生学号
// if (s.getSno() == sno) {
// //逻辑删除
// list[i] = null;
// System.out.println("删除成功!");
// return;
// }
// }
}
/**
* 根据提供的学号将学生的学分改成指定的学分
* @param sno
* @param score
*/
public void update(int sno,double score) {
int i = findBySno(sno);
if (i == -1) {
System.out.println("未找到指定学号的学生");
}else {
list[i].setScore(score);
System.out.println("修改成功!");
}
}
/**
* 根据提供的学号查询学生对象
* @param sno
* @return
*/
private int findBySno(int sno) {
for(int i=0;i<list.length;i++) {
Student s = list[i];
//判断目标位置的学生是否存在,以及学号是否与参数一致
if (s != null && s.getSno() == sno) {
//当遍历到的对象存在(即不为null) 且学号等于参数值时,返回学生所在的位置
return i;
}
}
return -1;
}
/**
* 显示所有的学生信息
*/
public void showAll() {
for(int i=0;i<list.length;i++) {
Student s = list[i];
if (s!=null) {
//显示学生详情
s.details();
}
}
}
/**
* 显示超过指定学分的学生
* @param score
*/
public void showHighScoreStus(double score) {
for(int i=0;i<list.length;i++) {
Student s = list[i];
if (s!=null && s.getScore() >= score) {
//显示学生详情
s.details();
}
}
}
}
public static void main(String[] args) {
StudentManager sm = new StudentManager();
//添加学生
sm.add(new Student(1001,"孙悟空","男",500,"散打",99));
sm.add(new Student(1002,"金角大王","男",499,"挨打",79));
sm.add(new Student(1003,"白骨精","女",1000,"挨打",69));
sm.add(new Student(1004,"牛魔王","男",800,"散打",89));
sm.add(new Student(1005,"白龙马","男",400,"运输",99));
sm.add(new Student(1006,"沙和尚","男",600,"烹饪",99));
sm.showAll();
System.out.println("================================");
sm.del(1004);
sm.update(1006, 50);
System.out.println("================================");
sm.showAll();
System.out.println("================================");
sm.showHighScoreStus(70);
}
}
- (1)创建一个叫做机动车的类:
属性:车牌号(String),车速(int),载重量(double)
功能:加速(车速自增)、减速(车速自减)、修改车牌号,查询车的载重量。
编写两个构造方法:一个没有形参,在方法中将车牌号设置“XX1234”,速
度设置为100,载重量设置为100;另一个能为对象的所有属性赋值;
(2)创建主类:
在主类中创建两个机动车对象。
创建第一个时调用无参数的构造方法,调用成员方法使其车牌为“辽A9752”,并让其加速。
创建第二个时调用有参数的构造方法,使其车牌为“辽B5086”,车速为150,
载重为200,并让其减速。
输出两辆车的所有信息
public class Car {
String card;
int speed;
double storage;
//构造器方法
public Car() {
card = "xx1234";
speed = 100;
storage = 100;
}
public Car(String $card,int $speed,double $storage) {
card = $card;
speed = $speed;
storage = $storage;
}
public void addSpeed() {
speed++;
}
public void minusSpeed() {
speed--;
}
public void modifyCard(String $card) {
card = $card;
}
public double getStorage() {
return storage;
}
/**
* 显示当前对象的详细信息
*/
public void showInfo() {
System.out.println("车牌:"+card+",车速:"+speed+",载重量:"+storage);
}
}
public class TestCar {
public static void main(String[] args) {
Car c = new Car();
c.modifyCard("鄂ACM124");
c.addSpeed();
c.showInfo();
Car c2 = new Car("琼BMM123",150,200);
c2.minusSpeed();
c2.showInfo();
}
}