目录
一、团队成员及任务
队长:
管俊杰 计科(智能)22-1 202203200037
负责模块:界面设置中paint方法,功能中的双人对战功能和人机对战功能,以及判断游戏输赢的算法。
组员:
李启帆 计科(智能)22-1 202203200036
负责模块:登录注册的功能与界面设置,创建容器面板以及棋盘和棋子的绘制。
马林飞 计科(智能)22-1 202203200031
负责模块:界面设置中的创建提示区域、防止按钮和JLabel组件,以及实现基本功能中的悔棋、重开、结束游戏功能。
二、项目简介
本项目由我们三人合作完成,实现了登录注册功能,每次打开需要先进行注册,需要创建账号密码。注册完成后回到登录界面,输入注册的账号密码便可以进入游戏。进入游戏后可以选择双人对战以及人机对战功能,人机对战还可以选择棋子颜色。同时还有悔棋、重开功能,以及结束本次游戏的按键。棋子进行了消除锯齿的优化,使棋子看起来更加圆润。
三、功能设计图
四、运行结果截图
五.源代码
面向对象程序设计(Java)课程设计——五子棋小游戏_The_God_Tree的博客-CSDN博客
六.个人部分实现过程
1. User类创建
public class User {
String ID;
String password;
public User(String id, String password) {
this.ID=id;
this.password=password;
}
public void setID(String ID){
this.ID=ID;
}
public void setPassword(String password){
this.password=password;
}
public String getID(){
return ID;
}
public String getPassword(){
return password;
}
}
2.addUser方法的实现
private void addUser(ArrayList<User> list,String ID){
//安全校验 没有 => return -1,可以添加 ;有 => 新输入
String sid=ID;
//将sid设为全局变量
while(true){
int index= getIndex(list,sid);
if(index==-1){
break;
}else{
System.out.println("已存在相同账号");
flag=1;
break;
}
}
int index= getIndex(list,sid);
if(index==-1){
String Password=password;
//创建用户实体对象
User user = new User(ID,password);
//将用户对象放入集合统一管理
list.add(user);
System.out.println("添加用户成功");
flag=0;
}
}
该方法调用了后面的getIndex方法,可以先跳过看后面的内容。该部分利用了动态数组。其中的flag用于后面bt3的内容实现,如果已存在相同账号,则给flag赋值为1,如果不存在,则成功录入,给flag赋值为0。
3.getIndex以及getpasswordIndex方法实现过程
private int getIndex(ArrayList<User>list,String sid){
int index=-1;
for(int i=0;i<list.size();i++){
//得到集合中每一个用户对象
User user = list.get(i);
//拿到用户对象的id与sid比较
String id= user.getID();
if(sid.equals(id)){
index = i;
}
}
return index;
}
private int getpasswordIndex(ArrayList<User>list,String sid){
int index=-2;
for(int i=0;i<list.size();i++){
//得到集合中每一个用户对象
User user = list.get(i);
//拿到用户对象的id与sid比较
String password= user.getPassword();
if(sid.equals(password)){
index = i;
}
}
return index;
}
这两部分很相似,只是一个遍历的id的动态数组,返回下标,一个遍历password的动态数组,返回下标。返回的下标,用于了后面录入用户信息时是否已有相同账号和登录时账号和密码是否能够匹配。两个方法index初始值不一样目的是为了避免没有任何注册信息,直接登录时,不会遍历动态数组,返回的index值一样而导致登录成功。
4.bt1实现过程:
bt2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
f1.setVisible(false);
zhuce.setTitle("注册窗口");
zhuce.setLayout(null);
zhuce.setSize(500,350);
zhuce.setLocation(1000,500);//注册界面窗口设置
zhuce.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
zhuce.setVisible(true);
zhuce.add(text1);
zhuce.add(text2);
zhuce.add(text3);
zhuce.add(bt3);
zhuce.add(bt4);
zhuce.add(l2);
zhuce.add(l3);
zhuce.add(l4);
zhuce.add(l5);
}
});
登录页面确认按钮的实现。在鼠标点击该按钮后,会先获得用户输入到文本框中的账号和密码,将ID传入getindex方法中,获得返回值,然后再把password传入getpasswordindnex方法中,获得password的index值,然后将两个index进行比较,如果相等,则登录。其中getindex和getpasswordindex的初始赋值index不同,其目的是为了防止动态数组为空时,两个方法不会遍历数组,从而使两个返回值都为-1,进而使得登录成功。
5.bt2实现过程
bt2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
f1.setVisible(false);
zhuce.setTitle("注册窗口");
zhuce.setLayout(null);
zhuce.setSize(500,350);
zhuce.setLocation(1000,500);//注册界面窗口设置
zhuce.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
zhuce.setVisible(true);
zhuce.add(text1);
zhuce.add(text2);
zhuce.add(text3);
zhuce.add(bt3);
zhuce.add(bt4);
zhuce.add(l2);
zhuce.add(l3);
zhuce.add(l4);
zhuce.add(l5);
}
});
该部分内容为实现登录界面的注册按钮,在点击后会关闭登录界面并创建一个新的注册页面,该部分创建了一个新的JFrame窗口,并未之添加了一系列控件。
6.bt3实现过程
bt3.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
String text1a = text1.getText();
String text2a = text2.getText();
String text3a = text3.getText();
if(text1a.equals("")||text2a.equals("")){
System.out.println("账号或密码不能为空");
}else if(text2a.equals(text3a)){
ID=text1a;
password=text2a;
addUser(list,ID);
if(flag==0){
setSigninFrame();
zhuce.setVisible(false);
}
} else{
System.out.println("您两次输入的密码不同,请重新输入。");
}
}
});
本部分用于实现按钮bt3,既注册界面的确认按钮,通过文本框获得用户输入的信息。在本块实现过程中,遇到了许多的困难,例如不输入任何信息也可以完成注册,输入相同账号之后,无法完成注册,但是会直接返回登录界面,需要用户再次点击注册,在解决前面问题后,点击注册后必须完成注册才能返回登录界面。作为解决方案,我加入了一个flag,来传递判断是否存在账号后的结果,用于窗口的切换,然后添加一个新的按钮,来返回登录界面。然后再加入了一个安全检验,检验是文本框否为空,并作出相应的反馈。
7.bt4实现过程
bt4.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
zhuce.setVisible(false);
setSigninFrame();
}
});
注册界面的返回按钮实现。
更新日志2023/6/13
1.新添加方法
void tishi_dengluchuowu(){
JFrame t1=new JFrame();
t1.setTitle("提示弹窗");
t1.setSize(400,180);
t1.setLocation(1050,600);
t1.setResizable(false);
t1.setVisible(true);
t1.setLayout(null);
t1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel s=new JLabel("账号不存在或密码错误");
s.setBounds(120, 10, 200, 100);
JButton bt=new JButton("确认");
bt.setBounds(150,80,70,30);
t1.add(s);
t1.add(bt);
bt.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
t1.setVisible(false);
}
});
}
void tishi_zhucebutong(){
JFrame t2=new JFrame();
t2.setTitle("提示弹窗");
t2.setSize(400,200);
t2.setLocation(1050,600);
t2.setResizable(false);
t2.setVisible(true);
t2.setLayout(null);
t2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel s=new JLabel("您两次输入的密码不同,请重新输入。");
s.setBounds(100, 10, 220, 100);
JButton bt=new JButton("确认");
bt.setBounds(150,80,70,30);
t2.add(s);
t2.add(bt);
bt.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
t2.setVisible(false);
}
});
}
void tishi_zhucecunzai(){
JFrame t3=new JFrame();
t3.setTitle("提示弹窗");
t3.setSize(400,200);
t3.setLocation(1050,600);
t3.setResizable(false);
t3.setVisible(true);
t3.setLayout(null);
t3.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel s=new JLabel("已存在相同账号,请重新输入账号");
s.setBounds(100, 10, 220, 100);
JButton bt=new JButton("确认");
bt.setBounds(150,80,70,30);
t3.add(s);
t3.add(bt);
bt.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
t3.setVisible(false);
}
});
}
void tishi_zhucechenggong(){
JFrame t4=new JFrame();
t4.setTitle("提示弹窗");
t4.setSize(400,200);
t4.setLocation(1050,600);
t4.setResizable(false);
t4.setVisible(true);
t4.setLayout(null);
t4.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel s=new JLabel("注册成功");
s.setBounds(159, 10, 200, 100);
JButton bt=new JButton("确认");
bt.setBounds(150,80,70,30);
t4.add(s);
t4.add(bt);
bt.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
t4.setVisible(false);
}
});
}
void tishi_kong(){
JFrame t5=new JFrame();
t5.setTitle("提示弹窗");
t5.setSize(400,200);
t5.setLocation(1050,600);
t5.setResizable(false);
t5.setVisible(true);
t5.setLayout(null);
t5.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel s=new JLabel("账号或密码不能为空");
s.setBounds(125, 10, 200, 100);
JButton bt=new JButton("确认");
bt.setBounds(150,80,70,30);
t5.add(s);
t5.add(bt);
bt.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
t5.setVisible(false);
}
});
}
以上为在后期新增的五个方法,用于实现用户注册登录出现操作错误时,进行弹窗并给出提示。使得用户在使用该程序时更容易上手。这五个方法结构相同,下面是对这五个方法的解释:
第一块:
JFrame t1=new JFrame();
t1.setTitle("提示弹窗");
t1.setSize(400,180);
t1.setLocation(1050,600);
t1.setResizable(false);
t1.setVisible(true);
t1.setLayout(null);
t1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
初始化新窗口的属性
第二块:
JLabel s=new JLabel("账号不存在或密码错误");
s.setBounds(120, 10, 200, 100);
JButton bt=new JButton("确认");
bt.setBounds(150,80,70,30);
t1.add(s);
t1.add(bt);
添加新的标签,并设置其生成位置和标签大小。
添加新的按钮,并设置按钮名称,按钮位置以及大小
第三块:
bt.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
t1.setVisible(false);
}
});
为按钮添加事件监听器,并且完善按钮完成的内容。既关闭该弹窗。
2.源代码调用新方法的位置
private void addUser(ArrayList<User> list,String ID){
//安全校验 没有 => return -1,可以添加 ;有 => 新输入
String sid=ID;
//将sid设为全局变量
while(true){
int index= getIndex(list,sid);
if(index==-1){
break;
}else{
tishi_zhucecunzai();
flag=1;
break;
}
}
int index= getIndex(list,sid);
if(index==-1){
String Password=password;
//创建用户实体对象
User user = new User(ID,password);
//将用户对象放入集合统一管理
list.add(user);
flag=0;
}
}
bt1.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
String text4a = text4.getText();
String text5a = text5.getText();
ID=text4a;
password=text5a;
int index1=getIndex(list,ID);
int index2=getpasswordIndex(list,password);
if(text4a.equals("")||text5a.equals("")){
tishi_kong();
}else {
if(index2==index1){
JFrame jf = new JFrame("五子棋小游戏");
jf.add(new TablePanel());
jf.pack(); //自动适配大小
jf.setLocationRelativeTo(null); //居中
jf.setResizable(true); //可调整大小
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //按×关闭
jf.setVisible(true); //是否可见
f1.setVisible(false);
}else{
tishi_dengluchuowu();
}
}
}
});
bt2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
f1.setVisible(false);
zhuce.setTitle("注册窗口");
zhuce.setLayout(null);
zhuce.setSize(500,350);
zhuce.setLocation(1000,500);//注册界面窗口设置
zhuce.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
zhuce.setVisible(true);
zhuce.add(text1);
zhuce.add(text2);
zhuce.add(text3);
zhuce.add(bt3);
zhuce.add(bt4);
zhuce.add(l2);
zhuce.add(l3);
zhuce.add(l4);
zhuce.add(l5);
}
});
bt3.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
String text1a = text1.getText();
String text2a = text2.getText();
String text3a = text3.getText();
if(text1a.equals("")||text2a.equals("")){
tishi_kong();
}else if(text2a.equals(text3a)){
ID=text1a;
password=text2a;
addUser(list,ID);
if(flag==0){
setSigninFrame();
tishi_zhucechenggong();
zhuce.setVisible(false);
}
} else{
tishi_zhucebutong();
}
}
});