目录
前言
项目设计
工具类
功能操作类
主程序类
总结
前言
????????他来了他来了,他带着小游戏的源码向大家走来了...
????????本期主要介绍的是结合文件IO流编写的一款小游戏,将程序运行的执行效果与文件结合起来,实现动态永久存储信息的效果。本项目的代码内容完善,内部结构简单,主要是为了巩固新学的知识,以便能够达到熟练运用。
项目设计
工具类
概述:将不同的功能封装为方法,就是可以直接通过调用方法使用它的功能,而无需考虑具体的功能实现细节。
简单来说,工具类是内部封装方法的一种类,是为了供主程序调用而存在的,以此来提高主程序的健壮性。但其实也可以不使用工具类,工具类里面的方法完全也可以写在主程序类中,为了使主程序类中结构清晰、代码明了,还是不建议这么做,最好还是创建一个工具类。
public class TSUtility {
//静态私有(供本类静态方法使用)
private static Scanner scanner = new Scanner(System.in);
//判断用户输入是否合法
public static char readMenuSelectionPro() {
char c;
for (; ; ) {
String str = readKeyBoard(1, false);
c = str.charAt(0);
if (c != '1' && c != '2' &&
c != '3' && c != '4' && c != '5') {
System.out.print("选择错误,请重新输入:");
} else break;
}
return c;
}
//判断是否确认操作
public static char readConfirmSelection() {
char c;
for (; ; ) {
String str = readKeyBoard(1, false).toUpperCase();
c = str.charAt(0);
if (c == 'Y' || c == 'N') {
break;
} else {
System.out.print("选择错误,请重新输入:");
}
}
return c;
}
//判断输入长度是否合法,合法就返回此字符串
public static String readKeyBoard(int limit, boolean blankReturn) {
String line = "";
while (scanner.hasNextLine()) {
line = scanner.nextLine();
if (line.length() == 0) {
if (blankReturn) return line;
else continue;
}
if (line.length() < 1 || line.length() > limit) {
System.out.print("输入长度(不大于" + limit + ")错误,请重新输入:");
continue;
}
break;
}
return line;
}
//延时加载
public static void loadSpecialEffects() throws InterruptedException {
System.out.println("请稍等:");
for (int i1 = 1; i1 <= 100; i1++) {
System.out.print("加载中:" + i1 + "%");
Thread.sleep(new Random().nextInt(25) + 1);
if (i1 == 100) {
Thread.sleep(50);
}
System.out.print("\r");
}
}
//把全为数字的字符串转换为int类型,并返回其数值
public static int printInt(String x){
Scanner sc = new Scanner(System.in);
if(isNumberic(x)==true){
int y = Integer.parseInt(x);
return y;
}else{
while(true){
System.out.print("你输入的值无意义! 请你重新输入: ");
String num = sc.next();
if(isNumberic(num)==true){
int y1 = Integer.parseInt(num);
return y1;
}
}
}
}
//判断字符串是否全是数字,是返回true,否则返回false
public static boolean isNumberic(String str) {
//使用正则表达式进行判断是否全为数字
Pattern pattern = Pattern.compile("[0-9]*");
return pattern.matcher(str).matches();
}
}
功能操作类
概述:实现一个特定的功能,提供使用,和工具类相似。
本项目此次使用该类用于实现显示二维码图片,想要更改图片只需修改图片存放的路径,在主程序类中写new PayView();?就创建好了这个对象,即可展示二维码图片。
public class PayView extends JFrame {
MyPanel mp=null;
public PayView(){
mp=new MyPanel();
this.add(mp);
this.setSize(1273, 809);
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args){
new PayView();
}
}
class MyPanel extends JPanel{
Image image=null;
public void paint(Graphics g){
try {
image= ImageIO.read(new File("E:\\java\\idea_test_8\\src\\game\\1.jpg"));
g.drawImage(image, 0, 0, 1273, 809, null);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
主程序类
代码结构图:设计各个模块的方法供主方法调用,最终实现项目完整效果。(将余额和游戏次数定义为全局变量,为了避免数据意外重置)
main()方法:实现主界面的显示、用户的选择操作。
public static void main(String[] args) throws IOException, InterruptedException {
while (true) {
System.out.println("**************** TESTGAME ****************");
System.out.println("*** 1.登录账号 ———> 开始猜数游戏 ***");
System.out.println("*** 2.修改密码 ———> 修改后可保存 ***");
System.out.println("*** 3.猜拳游戏 ———> 真好玩到爆炸 ***");
System.out.println("*** 4.赞助作者 ———> 可微信支付宝 ***");
System.out.println("*** 5.退出游戏 ———> 欢迎下次光临 ***");
System.out.println("**********(内测小程序 功能未完善)**********");
System.out.print("请输入选择:");
//调用工具类中的判断输入方法
char c = TSUtility.readMenuSelectionPro();
switch (c) {
case '1':
loginView();
break;
case '2':
updatePw();
break;
case '3':
moraGame();
break;
case '4':
//创建操作类对象
new PayView();
System.out.println("显示完成!");
break;
case '5':
System.out.println("确认退出? y/n");
char c1 = TSUtility.readConfirmSelection();
if (c1 == 'Y') {
System.out.println("退出程序成功!");
System.exit(0); //结束程序,JVM退出
} else {
System.out.println("已取消退出!");
}
}
}
}
界面效果:
loginView()方法、guessNumber()方法:
1.用户登录,账户存在的话验证文件中的密码是否匹配,密码相同则登录成功进行猜数游戏;如没有账户则进行注册,用户名作为文件名,文件用于存储用户密码(Password)、用户余额(Money)、用户游戏次数(count)。
2.定义用户初始条件,新注册的用户有一次试玩的机会(count=1)余额为零(Money=0),消耗完次数之后必须进行充值才能继续玩游戏。充值后的规则是,优先消耗用户的游戏次数,当游戏次数为零时,则五十元余额视为一次游戏次数?(确认玩游戏后在余额充足的情况下自动扣费),当游戏次数为零且余额低于五十时需充值才能继续玩游戏。
public static void loginView() throws IOException, InterruptedException {
//控制循环
boolean b = true;
//创建集合
Properties popr = new Properties();
//定义文件
File file;
File file1;
while (b) {
System.out.println("请输入账号和密码");
System.out.print("账号:");
String userName = sc.next();
//文件路径初始化
file = new File("idea_test_8\\src\\game", userName);
//判断文件是否存在
if (!file.exists()) {
System.out.println("账户不存在是否注册账号y/n");
//使用工具类判断用户输入
char c = TSUtility.readConfirmSelection();
if (c == 'Y') {
System.out.print("账号为:");
String userName1 = sc.next();
//定义文件路径
file1 = new File("idea_test_8\\src\\game", userName1);
file1.createNewFile(); //创建文件
System.out.print("密码为:");
String pw = sc.next();
//密码存到集合、设置其他初始值
popr.setProperty("Password", pw);
popr.setProperty("Money", String.valueOf(money));
popr.setProperty("count", String.valueOf(count));
FileWriter fw = new FileWriter(file1);
//集合中的数据保存到文件
popr.store(fw, "------UserInfo------");
fw.close(); //释放资源
//使用工具类,调用延时方法
TSUtility.loadSpecialEffects();
System.out.println("注册成功!");
} else {
System.out.println("已取消注册账号!");
b = false; //结束循环
}
} else {
System.out.print("密码:");
String pw = sc.next();
//文件中的内容读取到集合
FileReader fr = new FileReader(file);
popr.load(fr);
fr.close();
//判断密码是否正确
if (popr.get("Password").equals(pw)) {
System.out.println(userName + "欢迎你! " + "您目前余额为:"
+ popr.get("Money") + "元,免费次数为:" + popr.get("count"));
b = false;
//猜数小游戏,开始玩游戏
guessNumber(popr,file);
} else {
System.out.println("密码错误!");
}
}
}
}
public static void guessNumber(Properties popr, File file) throws IOException {
System.out.println("宇宙至尊游戏:猜数字(0-100)");
System.out.println("开始!");
while (true) {
//获取count和Money并转为int类型
int count1 = Integer.parseInt(popr.getProperty("count"));
int money1 = Integer.parseInt(popr.getProperty("Money"));
//判断账户是否还有免费的次数玩游戏
if (count1 <= 0 && money1 < 50) {
System.out.println("余额不足,是否充值y/n");
char c1 = TSUtility.readConfirmSelection();
if (c1 == 'Y') {
//充值
addMoney(popr, file);
} else {
System.out.println("已退出充值!");
break;
}
} else {
Random r = new Random();
//生成随机数
int number = r.nextInt(101);
System.out.println("测试使用:" + number);
while (true) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要猜的数字:");
int guessnumber = sc.nextInt();
if (guessnumber > number) {
System.out.println("你猜的数字" + guessnumber + "大了");
} else if (guessnumber < number) {
System.out.println("你猜的数字" + guessnumber + "小了");
} else {
System.out.println("恭喜你猜中了");
break;
}
}
//判断是否还有游戏次数
if (count1 != 0) {
count1--; //次数减一
//改变集合中的count值
popr.setProperty("count", String.valueOf(count1));
} else {
//判断是否有余额
if (money1 != 0) {
//设置使用金额50元玩一次
money1 -= 50;
//改变集合中的Money值
popr.setProperty("Money", String.valueOf(money1));
}
}
//集合中的内容写入到文件
FileWriter fw = new FileWriter(file);
popr.store(fw, null);
fw.close();
}
System.out.println("继续玩? y/n");
char c = TSUtility.readConfirmSelection();
if (c == 'Y') {
//重新获取一次值,为了保证获取到的是充值后的数据
int count2 = Integer.parseInt(popr.getProperty("count"));
int money2 = Integer.parseInt(popr.getProperty("Money"));
//判断是否有玩的条件
if (count2 <= 0 && money2 < 50) {
System.out.println("余额不足,是否充值y/n");
char c1 = TSUtility.readConfirmSelection();
if (c1 == 'Y') {
//充值模块
addMoney(popr, file);
} else {
System.out.println("已退出充值!");
break;
}
}
} else {
System.out.println("已退出游戏!");
break;
}
}
}
界面效果:
????????看到这里相信大家都有些疲惫了,其实博主的个人观点是劳逸结合才会让学习的效率变得更高,所以接下来让大家放松一下,换换脑子,欣赏一段最近比较流行的舞蹈,Show Time ~
舞蹈也看了,脑袋也换了,希望各位小伙伴能够收收心,继续来看接下来几个部分的方法设计。
addMoney()方法:实现用户充值的基本功能,并且设置充值金额只能是100、200、300、500及以上,充值成功后用户的余额会增加并且赠送的游戏次数也会到账,也就是修改的内容会保存到用户信息文件中,下次玩游戏时再读取出来并判断用户是否有条件玩游戏。
public static void addMoney(Properties popr, File file) throws IOException {
//设置死循环
while (true) {
System.out.println("¥¥¥¥ 充值系统 ¥¥¥¥");
System.out.println("¥¥ 充一百送5次 ¥¥");
System.out.println("¥¥ 充两百送12次 ¥¥");
System.out.println("¥¥ 充三百送18次 ¥¥");
System.out.println("¥ 充五百及以上送31次! ¥");
System.out.println("¥¥¥¥ 充值系统 ¥¥¥¥");
System.out.println("请输入您的充值金额:");
//使用工具类,让用户输入的字符串必须是数字,并转为int类型
String s = sc.next();
int money = TSUtility.printInt(s);
while (true) {
if (money != 100 && money != 200 && money != 300 && money < 500) {
System.out.println("输入金额错误!请重新输入:");
String s1 = sc.next();
int money1 = TSUtility.printInt(s1);
money = money1;
} else {
//修改集合中的数据
popr.setProperty("Money", String.valueOf(money));
if (money == 100) {
popr.setProperty("count", String.valueOf(5));
} else if (money == 200) {
popr.setProperty("count", String.valueOf(12));
} else if (money == 300) {
popr.setProperty("count", String.valueOf(18));
} else {
popr.setProperty("count", String.valueOf(31));
}
//集合中的数据写到文件
FileWriter fw = new FileWriter(file);
popr.store(fw, null);
fw.close();
System.out.println("充值成功!");
break;
}
}
break;
}
}
界面效果:
?
updatePw()方法:实现用户修改密码的功能,首先用户输入用户名,判断用户名是否存在,不存在给出提示信息直接退出该功能;如果存在直接设置新密码,然后将新密码写到文件。
public static void updatePw() throws IOException {
//创建集合
Properties popr = new Properties();
System.out.println("请输入你想要修改密码的账户:");
String userName = sc.next();
File file = new File("idea_test_8\\src\\game", userName);
//判断账户文件是否存在
if (!file.exists()) {
System.out.println("你输入的账户不存在!");
} else {
//文件内容读到集合
FileReader fr = new FileReader(file);
popr.load(fr);
fr.close();
//修改密码
System.out.print("新密码(" + popr.getProperty("Password") + "):");
String pw = sc.next();
//修改集合中的数据
popr.setProperty("Password", pw);
//集合中的内容写到文件
FileWriter fw = new FileWriter(file);
popr.store(fw, null);
fw.close();
System.out.println("修改密码成功!");
System.out.println("当前账户:" + userName);
System.out.println("当前密码:" + pw);
}
}
界面展示:
?
moraGame()方法:实现用户猜拳与系统随机出拳比较,然后输出比较结果,此处用简单的判断语句实现。该部分与用户文件信息无关,无需进行登录,可持续玩耍。
public static void moraGame() {
System.out.println("规则如下:");
System.out.println("1代表剪刀、2代表石头、3代表布。剪刀<石头<布,石头<布<剪刀,布<剪刀<石头\n" +
"首先由用户输入一个数字代表给定的出拳,然后再由系统随机给定一个数字代表给定的" +
"\n出拳,最后判定结果输赢!");
while (true) {
int n = 0; //定义用户输入的拳数数字
while (true) {
System.out.println("请输入你的出拳数字:");
n = sc.nextInt();
if (n != 1 && n != 2 && n != 3) {
System.out.println("输入错误!");
} else break;
}
if (n == 1) {
System.out.println("你出的拳是:剪刀");
} else if (n == 2) {
System.out.println("你出的拳是:石头");
} else {
System.out.println("你出的拳是:布");
}
Random r = new Random();
int num = r.nextInt(3) + 1;
if (num == 1) {
System.out.println("系统出的拳是:剪刀");
} else if (num == 2) {
System.out.println("系统出的拳是:石头");
} else {
System.out.println("系统出的拳是:布");
}
if (n == num) {
System.out.println("出拳一样,平局!");
} else {
if (n == 1) {
if (num == 2) {
System.out.println("很遗憾,你输了!");
} else if (num == 3) {
System.out.println("恭喜你,你赢了!");
}
} else if (n == 2) {
if (num == 1) {
System.out.println("恭喜你,你赢了!");
} else if (num == 3) {
System.out.println("很遗憾,你输了!");
}
} else {
if (num == 1) {
System.out.println("很遗憾,你输了!");
} else if (num == 2) {
System.out.println("恭喜你,你赢了!");
}
}
}
System.out.println("继续玩? y/n");
char c = TSUtility.readConfirmSelection();
if (c != 'Y') {
System.out.println("已退出游戏!");
break;
}
}
}
界面效果:
赞助作者功能界面展示:跳出一个弹窗显示给定的二维码图片。
总结
????????本项目的设计可灵活多变,没有固定的设计要求,这也是为什么一开始没有介绍项目需求的原因,可以在博主书写的基础上自行设计其他功能,或者在某些方面做的更加完善一些。不知道大家有没有发现,博主是一个注重细节的人,仔细看过博主代码的小伙伴应该都会知道,博主的细节都藏在注释里,希望你们也能够注重细节,对于编写代码,在每一次运行时,都能够想起第一次运行显示出"HelloWorld"那样的喜悦。
????????本项目到此就已经介绍完毕了,是不是还是比较有趣呢,感兴趣的小伙伴可以写来玩一玩,该项目的代码量其实并不是很多,主要就是让我们能够熟练使用文件IO流中的各种方法,程序运行时达到动态永久存储信息的效果。
|