Advanced Programming Project – Poker

前言

这是进入 SDUT 以来的第一个 项目 作业,主要对过去一学期 Programming 课程中所学的知识进行了总结回顾,同时拓展了解了一些新知识。

项目要求

使用 Java 编写一个关于扑克游戏的程序。关于扑克游戏最基本的内容是:通过程序从剔除大小王的52张牌中随机抽取五张牌,然后对五张牌进行判断,根据不同的牌型,给予玩家不同的反馈,同时在必要的阶段需要给予玩家一定提示信息。

对于过程中的提示信息,包括但不限于以下几部分:

  1. 卡牌信息提示,包括五张牌的花色和点数以及构成的牌型
  2. 用户信息提示,包括玩家本轮游戏获得的奖励以及累计的金币
  3. 游戏结束提示,提示玩家是否重新进行游戏
  4. 用户退出提示,提示玩家是否退出游戏

在 项目 的基本要求上,可以进行美化创新。

对于牌型的判断规则,规定如下:

Rank Name Rule Example Worth
1 Royal Flush Five cards of the same suit in sequence and begin with the biggest card A A-K-Q-J-10 90
2 Straight Flush Five cards of the same suit in sequence 9-8-7-6-5 80
3 Four of a kind Four cards of the same rank accompanied by what is termed a kicker K-K-K-K-2 70
4 Full House Three cards of one rank accompanied by two of another Q-Q-Q-9-9 60
5 Flush Five cards of the same suit J-9-8-7-3 of spades 50
6 Straight Five cards in sequence , and Ace may play either high or low A-K-Q-J-10 or 5-4-3-2-A 40
7 Three of a kind Three cards of the same rank and two kickers of different ranks J-J-J-5-2 30
8 Two pair Two cards of one rank, two cards of another rank and one kicker of another rank J-J-4-4-2 20
9 One pair Two cards of one rank accompanied by three kickers of different ranks Q-Q-9-8-2 10

项目简介

围绕核心玩法,拓展出三种模式,“Simple” “Infinite” “Challenge”。

在进入游戏前,需要用户输入用户名, 在正确进入游戏之后可以选择不同的游戏模式或功能, 对于不同的游戏情况,程序会给出不同的反馈, 并根据用户名对三种模式的数据进行存储,存储格式为 txt.

除此之外,玩家还可以查看排行榜,排行榜显示三种模式的部分玩家数据,排名按照从高到低。

模式内容简介

  • Simple
    • 按照基本要求,实现随机抽牌、判断牌型、展示信息的功能。
  • Infinite
    • 在Simple的基础上,每次抽牌需要额外支付10元,直至破产。
  • Challenge
    • 在Infinite的基础上,程序随机生产两个牌组,玩家任意选择一个,然后与另一个比较牌组大小。
    • 牌组较小的一方需要向另一方支付对应的金额
    • 若两组牌大小相同,则没有人需要支付

txt 中的数据组织

对于 txt 中的数据,我们将 Key 值隐藏,形成一个 $ 3 \times 2$ 的表格,示例如下:

Coins Times
Simple 20 20
Infinite 100 0
Challenge 1000 0
txt

txt

功能模块的划分

在该 项目 中,共划分了五部分:

  1. GameInterface – 游戏界面
    • 程序的开始和结束页面,包含不同模式的选择等
  2. GameRunning – 游戏运行
    • 三种模式的具体实现
  3. RankList – 排行榜
    • 从文件中读取数据、排序、并显示
  4. GameDataProcess – 游戏数据处理
    • 游戏的核心,实现随机抽卡以及规则判断
  5. UserDataProcess – 用户数据处理
    • 对用户的数据进行临时存储、加载、保存

其中前三个部分是用户可以在程序运行中看到的,包含一定的图形界面和数据处理。

项目实现

GameInterface

本部分共包含两个类:

  • StartInterface
    • 游戏的开始界面,包含模式选择、排行榜、退出等。
  • EndInterface
    • 游戏的结束界面,包含信息的提示、用户操作的确认等。

Class StartInterface

功能描述

在该类中,程序会使用正则表达式判断用户名是否合法,如果不合法则提示用户并要求其重新输入。

当输入的用户名合法后会通过 Class UserFile 对数据进行读取,然后通过一个 JFrame 显示给用户。

关于 Class UserFile 将在后面 UserDataProcess 部分详述。

正则表达式匹配用户名

程序要求输入的用户名为”只包含数字和字母”,我们可以通过正则表达式 regex=”[^a-zA-Z0-9]” 匹配不合法的用户名,匹配成功即为不合法,则提示用户重新输入.

JFrame

JFrame 是 javax.swing 中的一个窗口组件,可以在 JFrame 中添加其他组件,如:JLabel 、 JButton 等。

JFrame 在使用时需要设置长宽并设置为可见后才可以为用户所见。

jframe.setSize(350,350);//设置窗口大小
jframe.setLocationRelativeTo(null);//设置窗口位置65t6
jframe.setVisible(true);//将窗口设置为可见

在 JFrame 中有三种布局:

  • 流布局(FlowLayout)
  • 边界布局(BorderLayout)
  • 网格布局(GridLayout)

JFrame中默认使用的是边界布局(BorderLayout)在本项目中使用到了后两种布局模式.

对于边界布局,在向JFrame中添加组件的时候在参数中传入相应的值即可达到布局效果.

jframe.add(jpanel,BorderLayout.NORTH);
//对于第二个参数可替换为 WEST CENTER 等

对于网格布局,需要首先创建 GriLayout 对象,创建时需要输入行和列,在调用 add 方法时将会按照从上到下 从左到右的顺序插入到创建的网格中.

jframe.setLayout(new GridLayout(3,1));
jframe.add(jpanel1);
jframe.add(jpanel2);
jframe.add(jpanel3);

Lambda 表达式

在 JButton 组件中通过事件监听,结合 Lambda 表达式实现了不同模式的选择。

//使用 Lambda 表达式及 try cathch
simpleMode.addActionListener(event ->{
    try{
        mainBox.setVisible(false);//设置开始窗口为不可见
        Simple simpleGame = new Simple();//创建 Simple 模式的对象
        user.saveData(user);//正式开始前保存数据
        simpleGame.startGame(user);//调用 Simple 模式的入口方法,开始游戏 
        mainBox.setVisible(true);//游戏结束,设置窗口为可见
    }catch(Exception error)
    {
      //如果运行中出现异常,提示错误信息并退出程序
        JOptionPane.showMessageDialog(null,"Program Error!");
        System.exit(0);
    }
});

Pseudo Code

while( username is right )
{
  do{
    Display the start interface.
    And choice :
      1. which mode you want to play
      2. display the rank list
      3. quit the game;
  }while(not chioce quit the game)
}

Class EndInterface

功能描述

通过用户数据处理部分获取到当前用户信息,然后将信息按照要求添加到 showConfirmDialog 中,在用户点击退出后弹出对话框, 并要求玩家再次确认是否退出.

showConfirmDialog

showConfirmDialog 同样属于 javax.swing , 使用方式类似 showMessageDialog.

该对象的最后一个参数用于控制按钮类型. 对于窗体的按钮, 按照从左到右从0递增的顺序具有唯一的索引, 当用户点击时会返回这个索引.

if(JOptionPane.showConfirmDialog(null,message,"Quit Game",2)==0) 
  return true;//索引为 0 , 用户选择了 yes
else return false;//索引不为 0 , 用户选择了其他按钮

Pseudo Code

Dispaly the massage.
if(user choice the "yes") exit the game
else return to start interface

RankList

本部分包含三个类

  • RankList
    • 排行榜的入口,读取、拼接数据,显示排行榜页面
  • RankListData
    • 排行榜中的基本数据单元,存储用户名以及要排序的数据
  • RankListContent
    • 作为排行榜中所用数据的集合,通过选择排序对其进行排序

Class RankList

功能描述

使用 File 对所有用户数据进行存储,将所有用户的数据进行读取,并将数据进行进行组合、拼接,通过 showMessageDialog 显示到屏幕上。

在输出时最多只会输出每种模式排名靠前的六位用户

File

在文件的输入输出中,File对象抽象的表示一个文件或者路径,通过构造方法可以传入一个文件路径。当需要调用输入输出时,将 File 对象作为参数传入,即可实现对文件的读写。

File file=new File("UserData.txt");//这里传入的是一个路径,使用的是相对路径(Relative Path)
Scanner in = new Scanner(file);//可以使用 in 对象读取文件中的内容
PrintWriter out=new PrintWriter(file,false);//可以使用out对文件进行写入,对于第二个参数,如果不写或false则为覆盖模式,true则为更新模式

在创建 File 对象后可以使用 listFiles() 方法获取当前路径下的所有文件(返回值是一个 File 数组), 作用类似控制台中的 dir 命令,可以同时读取当前目录下的文件夹和文件。

File file=new File("UserData");
File name[]=file.listFiles();

Class RankListContent

功能描述

在 RankList 中读取出的所有内容将会存储到该类的 ArrayList<RankListData> 对象中, 随后调用排序方法对 ArrayList 中的数据进行排序.

由于时间较紧, 这里没有使用复杂的数据结构和算法, 而是使用了选择排序.

存在问题

由于文件存储使用的是覆盖,对于第二种模式,当玩家破产之后会重新开始游戏,数据被重置为100,0,此时之前累积的次数将会清零. 再打开排行榜时显示的将是当前的游戏次数,而非最多的游戏次数.

对于这个问题, 需要对 txt 的数据组织进行修改, 将最大值加入数据列表, 同时在排序时以最大值为 Key即可解决这个问题.

GameDataProcess

  • Card
    • 牌组中最基本的元素,表示一张卡牌,包含点数和花色。
  • OOPoker
    • 表示抽到的五张卡牌,并执行抽取卡牌、判断组合的操作。

随机抽牌

功能描述

根据游戏规则,随机从52张牌中抽取五张牌作为手牌,要求手牌不能重复。

在本 项目 中,首先创建了一个完整的52张卡牌,并通过随机数函数 Random 生成一个 $[1,52]$ 的整数作为卡牌的 index ,然后判断这个卡牌是否被抽取过(通过一个标记数组),如果抽取过则重新生成一个整数,如果没有抽取过则添加到当前手牌中,直到手牌数为5.

生成52张牌

52张牌即去掉大小王,共有四种花色,每种花色共13个点数。
因为 index 是随机生成的,所以这里的牌序是没有要求的,可以通过一个二重循环以及一个映射关系生成52张牌。

在二重循环中第一重表示花色,第二重表示点数,使用表达式 $(i-1)*13+j$ 即可以遍历$[1,52]$.

另一种解决方案是通过“打表”的方式给 card 设置初始值,这样程序可以省去生成的时间。

Pseudo Code1

for(int i=1;i<=4;i++)
{
    for(int j=1;j<=13;j++)
    {
        make card[(i-1)*13+j].value=j;
        make card[(i-1)*13+j].suit=i;
    }
}

优化:不生成具体牌组

当我们有了映射关系 $index = (i-1)*13+j$ 后便可以通过index计算出$i$与$j$,即花色和点数。

  • $suit=(index/13)+1$
  • $value=(index \% 13)+1$

对于重复抽取的判断可以通过二进制状态压缩实现。

二进制状态压缩就是通过一个数的二进制形式存储一串布尔值

例如十进制的 6 转化为二进制为 110 ,我们再设置一个 f 数组:bool f[3]={1,1,0};. 此时我们可以观察到, 6 的二进制表示和 f 数组表示的状态是类似的.

在 Java 中 Boolean 类会被转化成 int 处理, 占用的空间为$1byte$, 在本项目中我们需要一个长度为 52 的 Boolean 数组,因此总共需要 $52byte$ 的空间进行存储。

而采用二进制状态压缩后,我们可以将原有的 52 个布尔值使用一个 $long$ 进行存储,只占用了 $8byte$.

Pseudo Code

long flag=0;
do{
  Get a random number, and named index.
  if(((flag>>index)&1)==1) continue;// 判断是否去取到过,等价于if(f[index])
  else flag+=(1<<index);// 标记当前卡牌已经取到了
  Then, add the card  to hand card;
}while(hand card are less than five);

规则判断

功能描述

判断规则,可以通过级联的 if else 等方法实现,但是大多数算法实现的长度较长,在本项目中使用了编码的方式进行判断。通过一定的预处理可以得出当前手中卡牌的编码,然后通过正则表达式匹配出对应的规则。

预处理使用桶排序对点数和花色进行维护,在于处理后通过相关方法取得:是否同花、最多几张连续、最多有几个对子、最多有几张相同的。通过这四个值组成一个编码,这里只需要对同花顺进行特判,看是否是通天顺即可。

在编码组合结束之后可以通过正则表达式对规则进行匹配。

编码表格

Rank Name Same Suit Num of Straight Num of Pair Num of max Same Regex p.s
1 Royal Flush 1 5 * * 15\d{2} The max is Ace.
2 Straight Flush 1 5 * * 15\d{2}
3 Four of a kind * * * 4 \d{3}4
4 Full House * * 2 3 \d{2}23
5 Flush 1 * * * 1 \d{3}
6 Straight * 5 * * \d5\d{2}
7 Three of a kind * * 1 3 \d{2}13
8 Two pair * * 2 * \d{2}2\d
9 One pair * * 1 * \d{2}1\d

获取编码

获取编码是在桶排序的基础之上进行的,根据桶排序后的性质进行判断:

  • countSuit
    • 判断是同花。遍历一遍 Suit 桶, 如果值为 5 则为同花
  • countStraight
    • 计算连续。若相邻的两个 Value 桶均不为空,则说明两张牌连续,以此类推记录一个最大值
  • countPair
    • 统计对子。如果 Value 桶的值大于等于2,则说明至少有一个对子,在这里,四张牌仅记作一个对子
  • countSame
    • 统计相同。遍历 Value 桶,取最大值

Pseudo Code

countSuit()
{
    for(int i=1;i<=4;i++)
        get the max of the bucket
    if(max is 5) return 1;
    else return 0;
}
countStraight()
{
    for(int i=1;i<14;i++)
    if(is i th ans i+1 th all were empty)
        get the max between num and count
        and let count is 1
    else
        count++
    return num
}
countPair()
{
    for(int i=1;i<14;i++)
    get the num of bucket which more than two.
    return the num.
}
countSame()
{
    for(int i=0;i<15;i++)
    get the max num of bucket.
    return max num.
}
getMax()
{
    return the max value of cards
}
ruleJudgement()
{
  through countSuit()+countStraight()+countPair()+countSame() 
  to get the code.
  for(int i=2;i<=9;i++)
    if(the regex matches)
      if(the index is 2, check the max whether the Ace) return 1
      else return index 
}

GameRunning

  • Simple
    • 简单模式,创建五张手牌,并显示相关信息。
  • Infinite
    • 在Simple的基础上,每次游戏-10元,并确认是否破产。
  • Challenge
    • 在Infinite的基础上创建两副手牌进行比较大小。

简单介绍

在该部分,类的主要功能是从游戏数据处理部分获取到当前的五张手牌以及手牌的牌型构成,然后将其转化为 String 并通过对话框显示给用户。

  • Infinite
    • 在保存游戏时,在Coins所对应的参数后添加$-10$即可
  • Challenge
    • 在游戏初始时生成两组手牌,由玩家选择第一组还是第二组,然后通过一个标记进行判断玩家选择的是哪一组牌

Infinite

这个模式最大的特点就是需要支付 10$. 10不仅仅是为了凑整,也蕴含着一个数学原理.

下面给出的是各种规则的概率以及按照奖励规则计算出的期望值:

期望

期望

根据表格可以看到,最终的期望约为$6.9$, 若用户每次支付的金额大于$6.9$且重复的次数足够多时,用户一定会破产,反之则一定会盈利.

在生活中大部分所谓的”运气”都是包含数学的背景的, 有可能一次就能赢得大奖,但更多的是投入越多、损失越多。

存在问题

Challenge 手牌生成重复

在正常的游戏中,两组手牌共十张应当从同一副卡牌(52张牌)中发出,这样就保证了十张卡牌的唯一性。但在该程序中,两组卡牌实际上是从两副卡牌中抽取的,也就是说有可能在两组牌中出现两张相同的牌,例如 First 和 Second 中都出现了方片4。

对于这个问题,最早尝试通过在 OOPoker 中创建另一个方法来实现第二组牌的发牌,这个方法需要接收第一组手牌(也就是第一个 OOPoker 对象),然后根据这个对象中的标记数组继续发牌,但是在调试过程中出现了一些小问题,于是在正式提交作业时删除了这个做法。

另一种解决方案是创建一个新类名为 PairOfPoker ,然后将全部的 52 张牌及标记数组放置到这个类中,每个 OOPoker 对象都需要从这个类中进行抽取。
同时在 OOPoker 中声明两个构造方法:

  1. 不带参数,在构造方法中创建一个新的 PairOfPoker 对象
  2. 带参数,参数为第一个 OOPoker 对象中的 PairOfPoker 对象,
    • 在构造方法中不需要重新创建,只需要将传入的 PairOfPoker 赋值给当前对象中的 PairOfPoker 即可.

Pseudo Code 1

New a array of object of OOPoker, named oopoker[];

Then, random to get the five cards of oopoker[0];

And let oopoker[1].flag = oopoker[0].flag;
Then, random to get the five cards of oopoker[1];

页面显示问题

最初的想法是默认窗口左面显示玩家手牌,右面显示另一组手牌,于是设计了一个标记变量 flag,对于这个标记变量的使用如下:

已知只有两组手牌,我们规定:

  • First 的 index 为 0
  • Seconde 的 index 为 1

如果用户选择了 First 则 flag=0 ,如果选择了 Second 则 flag=1。

同时使用一个 content 数组存储内容:

  • $content[0]$ 表示窗口左面的内容
  • $content[1]$ 表示窗口右面的内容

因为对提示信息的拼接是按照从上到下、从左到右的顺序进行的,所以如果要保持左面始终为用户选择的卡牌,则需要作出某种处理。

空间关系

空间关系

解决方案有很多,这里给出一种方式:异或运算

这样仅通过表达式 $ i\oplus flag $ 以及一个 for 循环即可实现用户选择的牌组内容填充在左面, 简化了代码.

i=0 i=1
flag=0 0 1
flag=1 1 0

Pseudo Code2

creat content[0] instead of left
creat content[1] instead of right

if (user choice the first) flag=0
else flag=1

for(int i=0;i<=1;i++)
{
  content[i]=oopoker[i^flag];
}

UserDataProcess

  • NowUser
    • 表示当前用户的所有数据,包括当前用户名、各项模式的金币和游戏次数等。是UserFile的子类。
  • UserFile
    • 处理用户数据的读写,包括加载数据和保存数据。是NowUser的父类。

加载数据

在用户输入正确的用户名后,程序首先会判断当前用户是否存在,如果不存在创建新用户并设置初始值,如果存在则直接读取。

关于文件读取在前面已经有所介绍,这里就不再详述了。

继承

在 项目 中 NowUser 对象是始终伴随着程序运行的,当一次游戏结束后需要进行游戏的保存,此时如果再实例化一个 UserFile 就会更加的臃肿复杂。

为了解决这个问题,同时从逻辑上也更加顺畅,在项目中使用了继承:public class NowUser extends UserFile,这样在保存数据时均可通过 NowUser 对象进行.

小问题: 在 项目 中仅在保存中使用了 NowUser, 如果要读取数据, 依旧是直接通过 UserFile 进行的, 更好的方式是将其重写为仅通过 NowUser 进行调用.

Pseudo Code

loadData(username)
{
    get the file name
    open the file reader
    if(File exists)
        read the file to NowUser of Object
    else
        create a new file and set the initial value
    close the file reader
}

saveData(NowUser)
{
    get the file name
    open the file writer
    for(int i = 0; i <3;i++)
        writh the data to file
    close the file writer
}

项目代码

GameInterface

StartInterface

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.regex.*;

/*
 * This is the start of the game.
 * Enter the username and choose gamemode.
 */

public class StartInterface {

    /*
     * The method will check the username whether legal or not.
     */
    public static Boolean checkUsername(String username) throws IOException
    {
        if(username==null) System.exit(0);
        if(username.equals("")) 
        {
            JOptionPane.showMessageDialog(null,"The username cannot be empty.");
            return false;
        }
        final String regex="[^a-zA-Z0-9]";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(username);

        if(matcher.find())
        {
            JOptionPane.showMessageDialog(null,"The username is illegal, please try again.");
            return false;
        } 
        else return true;
    }

    /* 
     * User the method to creat panel.
     * There use four methods.
     */
    private void creatNorthBox(JPanel northBox,NowUser user)
    {
        //Head of the windows.
        JLabel userNameData = new JLabel("Name: "+user.getUsername());
        northBox.add(userNameData,BorderLayout.WEST);
    }

    private void creatcenterBox(JPanel centerBox)
    {
        //Center of the windows
        JLabel gameTitle = new JLabel("POKER");
        ImageIcon pokerImage = new ImageIcon("img\\poker.png");
        gameTitle.setFont(new Font("Wide Latin", Font.PLAIN, 40)); 
        JLabel pokerImageLabel = new JLabel(pokerImage);
        gameTitle.setHorizontalAlignment(SwingConstants.CENTER);
        centerBox.setLayout(new GridLayout(2,1));
        centerBox.add(gameTitle);
        centerBox.add(pokerImageLabel);
    }

    private void creatSouthBox(JPanel southBox,JFrame mainBox,NowUser user)
    {
        //Bottom of the windows, and the button all in this.
        JPanel bottomUp = new JPanel();
        JPanel bottomDown = new JPanel();
        JButton simpleMode = new JButton("Simple");
        JButton infiniteMode = new JButton("Infinite");
        JButton challengeMode = new JButton("Challenge");
        bottomUp.add(simpleMode);
        bottomUp.add(infiniteMode);
        bottomUp.add(challengeMode);
        JButton rankList = new JButton("Rank List");
        JButton quitGame = new JButton("Quit");

        simpleMode.addActionListener(event ->{
            try{
                mainBox.setVisible(false);
                Simple simpleGame = new Simple();
                user.saveData(user);
                simpleGame.startGame(user);
                mainBox.setVisible(true);
            }catch(Exception error)
            {
                JOptionPane.showMessageDialog(null,"Program Error!");
                System.exit(0);
            }
        });
        infiniteMode.addActionListener(event ->{
            try{
                mainBox.setVisible(false);
                Infinite infiniteGame = new Infinite();
                user.saveData(user);
                infiniteGame.startGame(user);
                mainBox.setVisible(true);
            }catch(Exception error)
            {
                JOptionPane.showMessageDialog(null,"Program Error!");
                System.exit(0);
            }
        });
        challengeMode.addActionListener(event ->{
            try{
                mainBox.setVisible(false);
                Challenge challengeGame = new Challenge();
                challengeGame.startGame(user);
                user.saveData(user);
                mainBox.setVisible(true);
            }catch(Exception error)
            {
                JOptionPane.showMessageDialog(null,"Program Error!"+error);
                System.exit(0);
            }
        });
        rankList.addActionListener(event ->{
            try{
                mainBox.setVisible(false);
                RankList ranks = new RankList();
                ranks.getRankList();
                user.saveData(user);
                mainBox.setVisible(true);
            }catch(Exception error)
            {
                JOptionPane.showMessageDialog(null,"Program Error!");
                System.exit(0);
            }
        });
        quitGame.addActionListener(event -> {
            try{
                    EndInterface endGame=new EndInterface();
                    endGame.quitGame(user);
                    user.saveData(user);
                }catch(Exception error)
                {
                    JOptionPane.showMessageDialog(null,"Program Error!");
                    System.exit(0);
                }
        });

        bottomDown.add(rankList);
        bottomDown.add(quitGame);

        southBox.setLayout(new GridLayout(2,1));
        southBox.add(bottomUp);
        southBox.add(bottomDown);
    }
   
    public void creatPanel(JFrame mainBox,JPanel northBox,JPanel centerBox,JPanel southBox,NowUser user)
    {
        StartInterface start=new StartInterface();
        start.creatNorthBox(northBox, user);
        start.creatcenterBox(centerBox);
        start.creatSouthBox(southBox, mainBox, user);
    }
   
    /*
     * User will choice the gamemode, ranklist or quit the game.
     */
    public static void displayMainInterface(NowUser user)throws IOException
    {
        StartInterface start=new StartInterface();
        //Main windows
        JFrame mainBox = new JFrame("Poker");

        //The panel of the windows.
        JPanel northBox = new JPanel();
        JPanel centerBox = new JPanel();
        JPanel southBox = new JPanel();

        start.creatPanel(mainBox,northBox,centerBox,southBox,user);

        //Add the panel to the windows
        mainBox.add(northBox, BorderLayout.NORTH);
        mainBox.add(centerBox, BorderLayout.CENTER);
        mainBox.add(southBox, BorderLayout.SOUTH);

        //Set the windows attribute.
        mainBox.setSize(350,350);
        mainBox.setLocationRelativeTo(null);
        mainBox.setVisible(true);
        mainBox.setDefaultCloseOperation(2);

    }

    /*
     * The entrance of the game.
     */
    public static void main(String[] args)throws Exception
    {
        //Remand the user enter the username.
        String username="";
        final String hintMessage="Username only characters and numbers\nPlease enter usernamer:";
        do{
            //Check the username, untile it is legal.
            username=JOptionPane.showInputDialog(null, hintMessage);
        }while(!checkUsername(username));//check username

        //Read the user's gameData.
        UserFile userfile=new UserFile();
        NowUser userData=userfile.getData(username);
        
        //Enter the main interface
        displayMainInterface(userData);//choic which mode your want to play

        userData.saveData(userData);
    }
}

/*
 * ----------------In Jun.2022----------------
 * SDUT-Programming Final Project
 * By SDUT Bulbul.
 * Blog: https://bulbul559.cn
 * ----------------In Jun.2022----------------
 */

EndInterface

import java.io.*;
import javax.swing.*;

/*
 * When the game is over, the class will provide a interface.
 * User will confirm quit or return, and all the information will print to screen.
 */

public class EndInterface {
    
    /* This method will display the information and let user to choose */
    private Boolean dispalyGameData(NowUser user)
    {
        String topString="Hello "+user.getUsername()+":\n\n";
        String simpleData="Simple: Coins  "+user.getCoins(1)+"  Times  "+user.getTimes(1)+"\n";
        String infiniteData="Infinite: Coins  "+user.getCoins(2)+"  Times  "+user.getTimes(2)+"\n";
        String challengeData="Challenge: Coins  "+user.getCoins(3)+"   Times  "+user.getTimes(3)+"\n\n";
        String confirmMessage="Whether to quit the game?";

        int t=JOptionPane.showConfirmDialog(null,topString+simpleData+infiniteData+challengeData+confirmMessage,"Quit Game",2);
        
        if(t==0) return true;//check user choice yes/no
        return false;
    }

    public void quitGame(NowUser user)throws IOException
    {
        if(this.dispalyGameData(user))
        {
            //choice the yes then the program will quit.
            user.saveData(user);
            System.exit(0);
        }
        //else, program will return to the startInterface.
    }
}

/*
 * ----------------In Jun.2022----------------
 * SDUT-Programming Final Project
 * By SDUT Bulbul.
 * Blog: https://bulbul559.cn
 * ----------------In Jun.2022----------------
 */

RankList

RankList

import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;

/*
 * There is three Class about the RankList.
 *     1. RankList
 *     2. RankListContent
 *     3. RankListData
 * This is the entrance of RankList function. And it will display the RankList to the screen.
 * User can get three ranklist about different mode.
 */

public class RankList {

    private void creatNorthBox(JPanel northBox)
    {
        JLabel rankListTitle=new JLabel("RANK LIST");
        JLabel rules1=new JLabel("Simple is based on Coins");
        JLabel rules2=new JLabel("Infinite is based on Times");
        JLabel rules3=new JLabel("Challenge is based on Times");

        rankListTitle.setFont(new Font("Wide Latin", Font.BOLD, 30)); 
        rules1.setFont(new Font("Imprint MT Shadow", Font.PLAIN, 25)); 
        rules2.setFont(new Font("Imprint MT Shadow", Font.PLAIN, 25)); 
        rules3.setFont(new Font("Imprint MT Shadow", Font.PLAIN, 25)); 

        rankListTitle.setHorizontalAlignment(JLabel.CENTER);
        rules1.setHorizontalAlignment(JLabel.CENTER);
        rules2.setHorizontalAlignment(JLabel.CENTER);
        rules3.setHorizontalAlignment(JLabel.CENTER);

        northBox.setLayout(new GridLayout(4,1));
        northBox.add(rankListTitle);
        northBox.add(rules1);
        northBox.add(rules2);
        northBox.add(rules3);
    }
    private void creatCenterBox(JPanel centerBox,RankListContent []content)
    {
        centerBox.setLayout(new GridLayout(1,3));

        JPanel []rankContent=new JPanel[3];

        for(int i=0;i<3;i++)
        {
            rankContent[i]=new JPanel();
            rankContent[i].setLayout(new GridLayout(2,1));

            JLabel modeTitle=new JLabel(content[i].getGameModeName());
            JPanel mainContent = new JPanel();
            modeTitle.setHorizontalAlignment(JLabel.CENTER);
            modeTitle.setFont(new Font("MV Boli", Font.BOLD, 18));
            mainContent.setLayout(new GridLayout(1,2));

            JPanel rankName=new JPanel();
            JPanel rankData=new JPanel();
            int rankLen=6;
            if(rankLen>content[i].getUsernamList().size()) rankLen=content[i].getUsernamList().size();
            rankName.setLayout(new GridLayout(rankLen+1,1));
            rankData.setLayout(new GridLayout(rankLen+1,1));
            JLabel rankUsernameTitle=new JLabel(" Username ");
            rankUsernameTitle.setHorizontalAlignment(JLabel.CENTER);
            JLabel rankDataTitle=new JLabel();
            if(i==0) rankDataTitle.setText(" Coins ");
            else rankDataTitle.setText(" Times ");
            rankDataTitle.setHorizontalAlignment(JLabel.CENTER);
            rankName.add(rankUsernameTitle);
            rankData.add(rankDataTitle);

            for(int j=0;j<rankLen;j++)
            {
                JLabel _username= new JLabel(content[i].getUsernamList().get(j).getUsername());
                _username.setHorizontalAlignment(JLabel.CENTER);
                rankName.add(_username);
            }
            for(int j=0;j<rankLen;j++)
            {
                JLabel _userData= new JLabel(""+content[i].getUsernamList().get(j).getData());
                _userData.setHorizontalAlignment(JLabel.CENTER);
                rankData.add(_userData);
            }

            mainContent.add(rankName);
            mainContent.add(rankData);
            rankContent[i].add(modeTitle);
            rankContent[i].add(mainContent);
            centerBox.add(rankContent[i]);
        }
    }

    public void displayRankList(RankListContent []content)
    {
        JPanel northBox = new JPanel();
        JPanel centerBox = new JPanel();

        this.creatNorthBox(northBox);
        this.creatCenterBox(centerBox,content);

        JPanel rankMainPanel = new JPanel();
        rankMainPanel.setLayout(new GridLayout(2,1));
        rankMainPanel.add(northBox);
        rankMainPanel.add(centerBox);
        JOptionPane.showMessageDialog(null,rankMainPanel,"Rank List",-1);
    }

    private void getUseData(RankListContent []content)throws IOException
    {
        String []modeName={"Simple","Infinite","Challenge"};
        for(int i=0;i<3;i++)
        {
            content[i]=new RankListContent();
            content[i].setGameModeName(modeName[i]);
        }

        File file = new File("UserData");
        File []userList = file.listFiles();
        for(int i = 0; i < userList.length; i++)
        {
            //read the user data
            String tempString[]=userList[i].getName().split(".txt");
            String tempUsername = tempString[0];

            Scanner in = new Scanner(userList[i]);
            for(int j=0;j<3;j++)
            {
                if(!in.hasNextLine()) break;
                RankListData userData = new RankListData();
                userData.setUsername(tempUsername);
                tempString=in.nextLine().split(",");
                if(j==0){
                    userData.setData(Integer.parseInt(tempString[0]));
                }else{
                    userData.setData(Integer.parseInt(tempString[1]));
                }
                content[j].addData(userData);
            }
            in.close();
        }
        for(int i = 0; i < 3;i++) content[i].sortData();
    }

    public void getRankList()throws IOException
    {
        RankListContent []content=new RankListContent[3];
        RankList t= new RankList();
        t.getUseData(content);
        t.displayRankList(content);
    }
}

/*
 * ----------------In Jun.2022----------------
 * SDUT-Programming Final Project
 * By SDUT Bulbul.
 * Blog: https://bulbul559.cn
 * ----------------In Jun.2022----------------
 */

RankListContent

import java.util.*;

/*
 * There is three Class about the RankList.
 *     1. RankList
 *     2. RankListContent
 *     3. RankListData
 * This class is read the all user data and sort it.
 */

public class RankListContent {
    private String gameModeName;
    private ArrayList<RankListData> dataList=new ArrayList<RankListData>();

    public void sortData()
    {
        int length = this.dataList.size();
        for(int i=0; i<length-1; i++)
        {
            for(int j=i+1; j<length; j++)
            {
                if(this.dataList.get(i).getData()<this.dataList.get(j).getData())
                {
                    Collections.swap(this.dataList,i,j);
                }
            }
        }
    }

    public void setGameModeName(String gameModeName)
    {
        this.gameModeName = gameModeName;
    }
    public void addData(RankListData Data)
    {
        this.dataList.add(Data);
    }

    public String getGameModeName()
    {
        return this.gameModeName;
    }
    public ArrayList<RankListData>getUsernamList()
    {
        return this.dataList;
    }
}

/*
 * ----------------In Jun.2022----------------
 * SDUT-Programming Final Project
 * By SDUT Bulbul.
 * Blog: https://bulbul559.cn
 * ----------------In Jun.2022----------------
 */

RankListData

/*
 * There is three Class about the RankList.
 *     1. RankList
 *     2. RankListContent
 *     3. RankListData
 * This class is about the data which RankList needed.
 */

public class RankListData {
    /*
     * Packaging two variable.
     * All variables are private, you can only use set methods or get methods to set or get the value.
     */
    private String username;
    private int data;

    //The set methods of class.
    public void setUsername(String username) {
        this.username = username;
    }
    public void setData(int data) {
        this.data=data;
    }
    //The get methods of class.
    public String getUsername() {
        return this.username;    
    }
    public int getData() {
        return this.data;
    }
}

/*
 * ----------------In Jun.2022----------------
 * SDUT-Programming Final Project
 * By SDUT Bulbul.
 * Blog: https://bulbul559.cn
 * ----------------In Jun.2022----------------
 */

GameRunning

Simple

import javax.swing.*;
import java.io.*;

public class Simple {

    private String getGameResult(NowUser user)throws IOException
    {
        String []__value={"","Ace","One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"};
        String []__ruleName={"","Royal Flush","Straight Flush","Four of a kind","Full House","Flush","Straight","Three of a kind","Two pair","One pair"};
        int []__winningCoins={0,90,80,70,60,50,40,30,20,10};
        String handData = "";

        OOPoker handPoker = new OOPoker();

        //translate unmber to english
        Card []card=handPoker.getCard();
        for(int i=0;i<card.length;i++)
        {
            handData+=__value[card[i].getValue()]+" of "+card[i].getName()+"\n";
        }

        //connect the string
        int __result=handPoker.getResult();
        handData+="\n";
        if(__result==0) handData+="Not A Winning Hand.\n\n";
        else handData+="The Hand Is "+__ruleName[__result]+"\n\n";
        handData+="For this hand you win: "+__winningCoins[__result]+"$\n";

        //
        user.setSimple(user.getCoins(1)+__winningCoins[__result],user.getTimes(1)+1);
        user.saveData(user);
        

        handData+="Total winning to data are: "+user.getCoins(1)+"$\nAnd "+user.getTimes(1)+" times you play.";
        return handData;
    }

    public void startGame(NowUser user)throws IOException
    {
        int flag=1;
        do{
            String startMessage="Your hand of cards is :\n\n"+getGameResult(user);
            JOptionPane.showMessageDialog(null,startMessage,"Simple",JOptionPane.INFORMATION_MESSAGE);
            flag=JOptionPane.showConfirmDialog(null,"Do you want to play again?","Choise",2);
        }while(flag==0);
    }
}

/*
 * ----------------In Jun.2022----------------
 * SDUT-Programming Final Project
 * By SDUT Bulbul.
 * Blog: https://bulbul559.cn
 * ----------------In Jun.2022----------------
 */

Infinite

import javax.swing.*;
import java.io.*;

public class Infinite {
    private String getGameResult(NowUser user)throws IOException
    {
        String []__value={"","Ace","One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"};
        String []__ruleName={"","Royal Flush","Straight Flush","Four of a kind","Full House","Flush","Straight","Three of a kind","Two pair","One pair"};
        int []__winningCoins={0,90,80,70,60,50,40,30,20,10};
        String handData = "";
        OOPoker handPoker = new OOPoker();
        Card []card=handPoker.getCard();
        for(int i=0;i<card.length;i++)
        {
            handData+=__value[card[i].getValue()]+" of "+card[i].getName()+"\n";
        }
        int __result=handPoker.getResult();
        handData+="\n";
        if(__result==0) handData+="Not A Winning Hand.\n\n";
        else handData+="The Hand Is "+__ruleName[__result]+"\n\n";
        handData+="For this hand you win: "+__winningCoins[__result]+"$\n";

        user.setInfinite(user.getCoins(2)+__winningCoins[__result]-10,user.getTimes(2)+1);
        user.saveData(user);

        handData+="Total coins you have: "+user.getCoins(2)+"$\nAnd "+user.getTimes(2)+" times you play.";
        return handData;
    }

    public void startGame(NowUser user)throws IOException
    {
        int flag=1;
        do{
            flag=1;
            if(user.getCoins(2)<=0)
            {
                flag=JOptionPane.showConfirmDialog(null,"You were broke.\nDo you want to restart?\nAttention! Your data will be cover.","Restart?",2);
                if(flag==0)
                {
                    user.setInfinite(100,0);
                    continue;
                }
            }
            String startMessage="Your hand of cards is :\n\n"+getGameResult(user);
            JOptionPane.showMessageDialog(null,startMessage,"Infinite",JOptionPane.INFORMATION_MESSAGE);
            if(user.getCoins(2)>0) flag=JOptionPane.showConfirmDialog(null,"Do you want to play again?","Choise",2);
            else {
                flag=JOptionPane.showConfirmDialog(null,"You were broke.\nDo you want to restart?\nAttention! Your data will be cover.","Restart?",2);
                if(flag==0)
                {
                    user.setInfinite(100,0);
                }
            }
        }while(flag==0);
    }
}

/*
 * ----------------In Jun.2022----------------
 * SDUT-Programming Final Project
 * By SDUT Bulbul.
 * Blog: https://bulbul559.cn
 * ----------------In Jun.2022----------------
 */

Challenge

import javax.swing.*;
import java.awt.*;
import java.io.*;
/*
 * This is the Challenge mode of the game.
 */

public class Challenge {

    private int flag=1;

    private void getGameResult(NowUser user,JPanel mainBox)throws IOException
    {
         
        String []__value={"","Ace","One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"};
        String []__ruleName={"","Royal Flush","Straight Flush","Four of a kind","Full House","Flush","Straight","Three of a kind","Two pair","One pair"};
        int []__winningCoins={0,90,80,70,60,50,40,30,20,10};
        String []handData = new String[2];
        handData[0]="";
        handData[1]="";
        OOPoker []handPoker = new OOPoker[2];
        
        Card [][]card=new Card[2][];
        int []__result=new int[2];

        handPoker[0]=new OOPoker();
        handPoker[1]=new OOPoker();
       

        for(int i=0;i<2;i++)
        {
            card[i]=handPoker[i].getCard();
            __result[i]=handPoker[i].getResult();
        }

        //Let user to make a choice.
        Object[] __options ={ "First", "Second"}; 
        int userChoise=JOptionPane.showOptionDialog(null, "Which HandPoker you want?", "Choise HandPoker",JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, __options, __options[0]);  
        
        String __startMessage="Your HandPoker is <br>";
        if(userChoise==0) __startMessage+="&emsp;&emsp;&emsp;First<br>";
        else __startMessage+="&emsp;&emsp;&emsp;Second<br>";
        __startMessage+="&emsp;&emsp;Try your luck<br>";

        //fill the poker message
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<card[i].length;j++)
            {
                handData[i]+=__value[card[i][j].getValue()]+" of "+card[i][j].getName()+"<br>";
            }
        }
        
        for(int i=0;i<2;i++)
        {
            handData[i]+="<br>";
            if(__result[i]==0) handData[i]+="Not A Winning Hand.<br><br>";
            else handData[i]+="The Hand Is "+__ruleName[__result[i]]+"<br><br>";
        }

        int __coins=0;
        String __endMessage="";

        if(handPoker[userChoise].getResult()<handPoker[1-userChoise].getResult())
        {
            __endMessage="For this hand you will pay: "+__winningCoins[__result[1-userChoise]]+"$<br>";
            __coins=0-__winningCoins[__result[1-userChoise]];
        }else if(handPoker[userChoise].getResult()>handPoker[1-userChoise].getResult()){
            __endMessage="For this hand you win: "+__winningCoins[__result[userChoise]]+"$<br>";
            __coins=__winningCoins[__result[userChoise]];
        }else{
            __endMessage="For this hand you can not gat the Coins"+"$<br>";
            __coins=0;
        }
       
        user.setChallenge(user.getCoins(3)+__coins,user.getTimes(3)+1);
        user.saveData(user);

        __endMessage+="Total winning to data are: "+user.getCoins(3)+"$<br>And "+user.getTimes(3)+" times you play.";

        JPanel northPanel=new JPanel();
        JPanel centerPanel=new JPanel();
        JPanel southPanel=new JPanel();
        JPanel __empty=new JPanel();

        JLabel __statrLabel=new JLabel("<html><body>"+__startMessage+"<body></html>");
        __statrLabel.setFont(new Font("Calibri", Font.PLAIN, 20)); 
        __statrLabel.setHorizontalAlignment(SwingConstants.CENTER);

        northPanel.add(__statrLabel);

        centerPanel.setLayout(new GridLayout(1,3));
        centerPanel.add(new JLabel("<html><body>"+handData[0]+"<body></html>")); 
        centerPanel.add(__empty);
        centerPanel.add(new JLabel("<html><body>"+handData[1]+"<body></html>"));
       
        southPanel.add(new JLabel("<html><body>"+__endMessage+"<body></html>"));

        mainBox.setLayout(new GridLayout(3,1));
        mainBox.add(northPanel);
        mainBox.add(centerPanel);
        mainBox.add(southPanel);

        return ;
    }

    private int choiceAgain()
    {
        return JOptionPane.showConfirmDialog(null,"Do you want to play again?","Choise",2);
    }

    public void startGame(NowUser user)throws IOException
    {

        do{
            // String startMessage="Your hand of cards is :<br>\n"+getGameResult(user);
            flag=-1;
            JPanel mainBox = new JPanel();
            this.getGameResult(user,mainBox);

            JOptionPane.showMessageDialog(null,mainBox,"Challenge",-1);
            flag=choiceAgain();
            // flag=choiceAgain();
        }while(flag==0);
    }
}

/*
 * ----------------In Jun.2022----------------
 * SDUT-Programming Final Project
 * By SDUT Bulbul.
 * Blog: https://bulbul559.cn
 * ----------------In Jun.2022----------------
 */

GameDataProcess

Card

/*
 * One object of class represent one poker.
 */

public class Card
{
    /*
     * Packaging three variables.
     * All variables are private, you can only use set methods or get methods to set or get the value.
     */
    private int value;//value of the poker
    private int suit;//suit of the poker,use the number replace the string
    private String name;//name of the suit
    private String []suitNameList ={"","Spade","Heart","Club","Diamond"};

    /* This is a constructor of this methods, it will provide the inital value to the new object*/
    Card(){
        value = 0;
        suit = 0;
        name = "";
    }

    //The set methods of Class.
    public void setValue(int data)
    {
        this.value = data;
    }
    public void setSuit(int data)
    {
        this.suit = data;
        this.name = suitNameList[data];
    }
    public void setName(String data)
    {
        this.name = data;
    }
    //The get methods of Class.
    public int getValue()
    {
        return value;
    }
    public int getSuit()
    {
        return suit;
    }
    public String getName()
    {
        return name;
    }
}

/*
 * ----------------In Jun.2022----------------
 * SDUT-Programming Final Project
 * By SDUT Bulbul.
 * Blog: https://bulbul559.cn
 * ----------------In Jun.2022----------------
 */

OOPoker

import java.util.*;
import java.util.regex.*;

/*
 * This class is the core of the game.
 * It represent the hand poker of user.
 * You can throgh this to deal poker to player.
 * And this class can judge the poker whether following the rules or not.
 */

public class OOPoker{

    private Card []handPoker=new Card [5];
    private int []countValue=new int[15];
    private int []countSuit=new int[5];
    private Card []pariOfPoker = new Card[53];
    private int []choiceOrNot = new int[53];
    private String []rulePattern={"","15\\d{2}","15\\d{2}","\\d{3}4","\\d{2}23","1\\d{3}","\\d5\\d{2}","\\d{2}13","\\d{2}2\\d","\\d{2}1\\d"};
    
    OOPoker()
    {
        for(int i=0;i<5;i++)
        {
            handPoker[i]=new Card();
        }
        this.generateHandPoker();
    }

    /*
     * This part willdeal poker to player.
     */
    private void sortHandPoker()//Use the BucketSort to manage data.
    {
        for(int i=0;i<5;i++)
        {
            int __value=handPoker[i].getValue();
            int __suit=handPoker[i].getSuit();
            countValue[__value]++;
            if(__value==1) countValue[14]++;//if value is Ace, make a special judge.
            countSuit[__suit]++;
        }
    }

    private void generateHandPoker()
    {
        Random rand = new Random();
        /*
         * Set a pair of initial cards.
         */
        for(int i=1;i<=4;i++)
        {
            for(int j=1;j<=13;j++)
            {
                pariOfPoker[(i-1)*13+j]=new Card();
                pariOfPoker[(i-1)*13+j].setValue(j);
                pariOfPoker[(i-1)*13+j].setSuit(i);
            }
        }


        int __countSize=0;
        do{
            int __temp=rand.nextInt(52)+1;
            if(choiceOrNot[__temp]==0)
            {
                handPoker[__countSize]=new Card();
                choiceOrNot[__temp]=1;
                handPoker[__countSize]=pariOfPoker[__temp];
                __countSize++;
            }
        }while(__countSize<5);

        this.sortHandPoker();
    }

    /*
     * This part will judge the rules.
     */

    private int countSuit()
    {
        int __countSuit=0;
        for(int i=1;i<=4;i++)
        {
            if(this.countSuit[i]>__countSuit) __countSuit=countSuit[i];
        }
        if(__countSuit==5) return 1;
        else return 0;
    }
    private int countStraight()
    {
        int __countStraight=0;
        int temp=1;
        for(int i=1;i<14;i++)//Attention! Ace need calculate twice.
        {
            if(this.countValue[i]!=0&&this.countValue[i+1]!=0)
            {
                temp++;
            }else{
                if(temp>__countStraight) __countStraight=temp;
                temp=1;
            }
        }
        return __countStraight;
    }
    private int countPair()
    {
        int __countPair=0;
        for(int i=1;i<14;i++)//Attention! Ace only calculate once.
        {
            if(this.countValue[i]>=2) __countPair++;
        }
        return __countPair;
    }
    private int countSame()
    {
        int __countSame=0;
        for(int i=0;i<15;i++)
        {
            if(this.countValue[i]>__countSame) __countSame=this.countValue[i];
        }
        return __countSame;
    }
    private int getMax()
    {
        int __maxValue=0;
        for(int i=0;i<5;i++)
        {
            int temp=this.handPoker[i].getValue();
            if(temp==1)temp=14;
            if(temp>__maxValue) __maxValue=temp;
        }
        return __maxValue;
    }

    private int ruleJudgement()
    {
        String __result=""+countSuit()+countStraight()+countPair()+countSame();

        for(int i=2;i<=9;i++)
        {
            Pattern pattern=Pattern.compile(rulePattern[i]);
            Matcher matcher=pattern.matcher(__result);

            if(matcher.find())
            {
                if(i==2&&getMax()==14) return 1;
                else return i;
            }
        }
        return 0;
    }

    public int getResult()
    {
        return this.ruleJudgement();
    }

    public Card[] getCard()
    {
        return handPoker;
    }
}  

/*
 * ----------------In Jun.2022----------------
 * SDUT-Programming Final Project
 * By SDUT Bulbul.
 * Blog: https://bulbul559.cn
 * ----------------In Jun.2022----------------
 */

UserDataProcess

NowUser

/*
 * There is three Class about the UserData.
 *     1. UserFile
 *     2. NowUser
 * NowUser is extends from UserFile.
 * This class will store the data of the user who plays game now.
 */

public class NowUser extends UserFile {
/*
 * Packaging seven variables.
 * All variables are private, you can only use set methods or get methods to set or get the value.
 */
    private String username;
    private int SimpleCoins;
    private int SimpleGameTimes;
    private int InfiniteCoins;
    private int InfiniteGameTimes;
    private int ChallengeCoins;
    private int ChallengeGameTimes;

/* This is a constructor of this methods, it will provide the inital value to the new object*/
    NowUser(){
        SimpleCoins = 0;
        SimpleGameTimes = 0;
        InfiniteCoins = 100;
        InfiniteGameTimes = 0;
        ChallengeCoins = 1000;
        ChallengeGameTimes = 0;
    }
    //The set method of the class
    public void setUsername(String name) 
    {
        this.username=name;
    }
    public void setSimple(int coins,int times)
    {
        this.SimpleCoins = coins;
        this.SimpleGameTimes= times;
    }    
    public void setInfinite(int coins,int times)
    {
        this.InfiniteCoins = coins;
        this.InfiniteGameTimes = times;
    }
    public void setChallenge(int coins,int times)
    {
        this.ChallengeCoins = coins;
        this.ChallengeGameTimes = times;
    }
    public String getUsername()
    {
        return this.username;
    }
    // The get method of class.
    public int getCoins(int mode)
    {
        switch(mode)
        {
            case 1: return this.SimpleCoins;
            case 2: return this.InfiniteCoins;
            case 3: return this.ChallengeCoins;
        }
        return 0;
    }
    public int getTimes(int mode)
    {
        switch(mode)
        {
            case 1: return this.SimpleGameTimes;
            case 2: return this.InfiniteGameTimes;
            case 3: return this.ChallengeGameTimes;
        }
        return 0;
    }
}

/*
 * ----------------In Jun.2022----------------
 * SDUT-Programming Final Project
 * By SDUT Bulbul.
 * Blog: https://bulbul559.cn
 * ----------------In Jun.2022----------------
 */

UserFile

import java.util.*;
import java.io.*;

/*
 * There is three Class about the UserData.
 *     1. UserFile
 *     2. NowUser
 * Read and write the game-data.
 */

public class UserFile {

    /* 
     * This method will load the data from txt.
     * If username is not found, it will creat a new userfile.
     */
    private void loadData(String username,NowUser user) throws IOException
    {
        String fileName="UserData\\"+username+".txt";

        user.setUsername(username);// store the username to NowUser

        File file = new File(fileName);
        if(file.exists())
        {
            //if the username is found, program will read the data
            Scanner in = new Scanner(file); 
            String []tempData=new String[2];
            for(int i=1; i<=3;i++)
            {
                if(!in.hasNextLine()){
                    in.close();
                    return;
                }
                tempData=in.nextLine().split(",");
                int coins=Integer.parseInt(tempData[0]);
                int times=Integer.parseInt(tempData[1]);
                switch(i)
                {
                    case 1:user.setSimple(coins,times);break;
                    case 2:user.setInfinite(coins, times);break;
                    case 3:user.setChallenge(coins,times);break;
                }
            }
            in.close();
        }else{
            //else, not found the username, we will creat a new userfile
            file.createNewFile();
            user=new NowUser();
            user.setUsername(username);
        }
    }

    /* This method will save the data to the txt */
    public void saveData(NowUser toSave) throws IOException
    {
        String fileName="UserData\\"+toSave.getUsername()+".txt";
        File file=new File(fileName);
        
        PrintWriter out=new PrintWriter(file);
        String gameData="";
        for(int i=1;i<=3;i++)
        {
            gameData=toSave.getCoins(i)+","+toSave.getTimes(i);
            out.println(gameData);
        }
        out.close();
    }

    /* When user enter the useranme, this method is the entrance of the class*/
    public NowUser getData (String username) throws IOException
    {
        NowUser user=new NowUser();
        this.loadData(username,user);
        return user;
    }
}

/*
 * ----------------In Jun.2022----------------
 * SDUT-Programming Final Project
 * By SDUT Bulbul.
 * Blog: https://bulbul559.cn
 * ----------------In Jun.2022----------------
 */

运行截图

错误示例

错误示例

不合法提示

不合法提示

正确示例

正确示例

开始界面

开始界面

Simple模式

Simple模式

Infinite模式

Infinite模式

破产提示

破产提示

Challenge选择牌组

Challenge选择牌组

Challenge模式

Challenge模式

排行榜

排行榜

结束页面

结束页面

其他

在程序中使用了一张图片,需要将其放在与程序相同文件夹下的 img 文件夹,并命名为 poker.png, 相对路径为“img\poker.png”。

后记

本人水平有限,其中部分功能无法做到进一步优化、项目源代码中存在一些 bug 尚未修复、对于部分技术实现浅尝辄止没有做进一步学习研究,同时也存在与实际开发不符的一些编码习惯等。但总的来说还是收获良多,欢迎大家交流讨论。

 

面向对象课程导航

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇