目录
一、团队成员及任务
队长:管俊杰 计科(智能)22-1 202203200037
负责模块:界面设置中paint方法,功能中的双人对战功能和人机对战功能,以及判断游戏输赢的算法。
Java课程设计——五子棋游戏(个人)_The_God_Tree的博客-CSDN博客
组员:
李启帆 计科(智能)22-1 202203200036
负责模块:登录注册的功能与界面设置,创建容器面板以及棋盘和棋子的绘制。
面向对象程序设计(Java)课程设计——五子棋小游戏 中注册登录模块的实现。_Solar_487的博客-CSDN博客
马林飞 计科(智能)22-1 202203200031
负责模块:界面设置中的创建提示区域、放置按钮和JLabel组件,以及实现基本功能中的悔棋、重开、结束游戏功能。
二、项目简介
本项目由我们三人合作完成,实现了登录注册功能,每次打开需要先进行注册,需要创建账号密码。注册完成后回到登录界面,输入注册的账号密码便可以进入游戏。进入游戏后可以选择双人对战以及人机对战功能,人机对战还可以选择棋子颜色。同时还有悔棋、重开功能,以及结束本次游戏的按键。棋子进行了消除锯齿的优化,使棋子看起来更加圆润。
三、功能设计图
四、运行结果截图
五、核心源码
Signin.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
public class Signin extends JFrame {
ArrayList<User>list = new ArrayList<User>();
private Button loginButton;
private Button signinButton;
String ID;
String password;
int flag=0;
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;
}
}
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;
}
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);
}
});
}
public void setSigninFrame(){
JFrame f1=new JFrame();
JFrame zhuce=new JFrame();
f1.setTitle("登录界面");
f1.setSize(500,400);
f1.setLocation(1000,500);
f1.setBackground(Color.white);
f1.setResizable(false);
f1.setVisible(true);
f1.setLayout(null);
f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//默认关闭操作//
JLabel l1=new JLabel("欢迎使用本程序");
l1.setBounds(200, 20, 100, 20); //这里表示对l1标签在窗口中的位置。
JLabel l2=new JLabel("注册页面");
l2.setBounds(200,20,500,50);
JLabel l3=new JLabel("请输入账号");
l3.setBounds(50,80,300,20);
JLabel l4=new JLabel("请输入密码");
l4.setBounds(50,120,300,20);
JLabel l5=new JLabel("请确认密码");
l5.setBounds(50,160,300,20);//注册界面文本显示
JLabel l6=new JLabel("账号");
l6.setBounds(50,80,300,20);
JLabel l7=new JLabel("密码");
l7.setBounds(50,120,300,20);
JLabel l8=new JLabel("账号不存在或密码错误");
l8.setBounds(50,200,300,20);
JLabel l9=new JLabel("您两次输入的密码不同,请重新输入。");
l9.setBounds(50,200,300,20);
JButton bt1 = new JButton("登录");
bt1.setBounds(70, 250, 120, 20);
JButton bt2 = new JButton("注册");
bt2.setBounds(290, 250, 120, 20);
JButton bt3=new JButton("确认");
bt3.setBounds(90, 250, 80, 20);
JButton bt4=new JButton("返回");
bt4.setBounds(310, 250, 80, 20);//注册界面按钮设置
JTextField text1 = new JTextField();
JTextField text2 = new JTextField();
JTextField text3 = new JTextField();
JTextField text4 = new JTextField();
JTextField text5 = new JTextField();
text1.setBounds(150, 80, 300, 20);
text2.setBounds(150, 120, 300, 20);
text3.setBounds(150, 160, 300, 20);//注册界面文本框设置
text4.setBounds(150, 80, 300, 20);
text5.setBounds(150, 120, 300, 20);//登录界面文本框设置
f1.add(l1);
f1.add(l6);
f1.add(l7);
f1.add(bt1);
f1.add(bt2);
f1.add(text4);
f1.add(text5);
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();
}
}
});
bt4.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
zhuce.setVisible(false);
setSigninFrame();
}
});
}
}
User.java
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;
}
}
Frame.java
public class Frame {
public static void main(String[] args) {
Signin a=new Signin();
a.setSigninFrame();
}
}
TablePanel.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import java.util.Vector;
public class TablePanel extends JPanel {
//设置Panel的大小
final int TABLE_WIDTH = 800;
final int TABLE_HEIGHT = 600;
final int NUM = 15;//棋盘线的条数,标准棋盘为15*15
final int OFFSET_X = 30; //棋盘左上角相对于panel左上角的偏移量(棋盘的起始位置)
final int OFFSET_Y = 80;
final int SP = 34; //棋盘每条线的间隔
final int RECT_SIZE = 6; //棋盘上五个提示点的位置
final int OVAL_SIZE = 32; //棋子的大小
int[][] table = new int[NUM][NUM]; //二维数字记录棋盘上每个位置上的棋子 (0无棋子 1白子 2黑子)
int step;
int oval_type = 2; //所要下的棋子的颜色 1白 2黑
int mouse_X;
int mouse_Y;
int select_X = -10;
int select_Y = -10;
//定义一个Vector,存储每次下的位置,来实现悔棋功能
Vector<Integer> last_xy = new Vector<>();
boolean isWin; //是否赢
int isStart; //是否开始游戏 0未开始 1 2 3
int robot_x;
int robot_y;
BasicStroke bs; //定义画笔宽度(因为不止一个方法用,就定义在外面)
SpringLayout springLayout = new SpringLayout(); //设置springLayout布局,方便按钮位置的部署
Dimension buttonSize = new Dimension(180, 35); //设置按钮大小
//设置字体的形状
Font font1 = new Font("楷体", Font.PLAIN, 30);
Font font2 = new Font("华文新魏", Font.PLAIN, 20);
Font font3 = new Font("华文琥珀", Font.PLAIN, 50);
Font font4 = new Font("微软雅黑", Font.PLAIN, 35);
//定义一系列button和label
JLabel titleLabel = new JLabel("五子棋");
JLabel selectLabel = new JLabel("游戏类型:");
JButton rrBtn = new JButton("双人对战");
JButton rjbBtn = new JButton("人机对战.持黑");
JButton rjwBtn = new JButton("人机对战.持白");
JLabel elseLabel = new JLabel("其他设置:");
JButton regretBtn = new JButton("悔棋");
JButton restartBtn = new JButton("重新开始");
JButton endBtn = new JButton("结束游戏");
public TablePanel() {
setLayout(springLayout); //设置弹性布局方式
setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HEIGHT)); //设置组件的首选大小
setBackground(Color.lightGray); //设置背景颜色亮灰色
initBtn(); //初始化按钮
init(); //初始化一些属性
isStart = 0;
addMouseListener(mouseAdapter); //添加鼠标监听
addMouseMotionListener(mouseAdapter);
}
//初始化一些属性
private void init() {
//初始化二维数组
for (int i = 0; i < NUM; i++) {
for (int j = 0; j < NUM; j++) {
table[i][j] = 0;
}
}
//初始化step
step = 0;
isWin = false;
oval_type = 2;
//初始化list
last_xy.clear();
}
@Override
public void paint(Graphics g) {
//定义一个Graphics2D消除棋子锯齿,使棋子更加圆润
Graphics2D gg = (Graphics2D) g;
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gg.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
//棋盘
initPaint(g, gg);
//棋子
ovalPaint(gg);
//提示框
sidePaint(gg);
}
private void ovalPaint(Graphics2D gg) {
//画棋子
//每次点击后,会刷新一下棋盘,根据table的值画黑或白字
//画实体棋子
for (int i = 0; i < NUM; i++) {
for (int j = 0; j < NUM; j++) {
int x = OFFSET_X + SP * i - OVAL_SIZE / 2;
int y = OFFSET_Y + SP * j - OVAL_SIZE / 2;
if (table[i][j] == 2) {
gg.setColor(Color.BLACK);
gg.fillOval(x, y, OVAL_SIZE, OVAL_SIZE);
} else if (table[i][j] == 1) {
gg.setColor(Color.WHITE);
gg.fillOval(x, y, OVAL_SIZE, OVAL_SIZE);
} else if (table[i][j] == 3) {
gg.setColor(Color.RED);
gg.drawOval(x, y, OVAL_SIZE, OVAL_SIZE);
}
}
}
if (isWin) {//赢了就把选择框隐藏起来
select_X = -10;
select_Y = -10;
} else {
bs = new BasicStroke(1); // 画笔宽度为1
gg.setStroke(bs);
//画选择框
gg.setColor(Color.RED);
gg.drawOval(OFFSET_X + SP * select_X - OVAL_SIZE / 2,
OFFSET_Y + SP * select_Y - OVAL_SIZE / 2,
OVAL_SIZE, OVAL_SIZE);
}
}
//画棋盘
private void initPaint(Graphics g, Graphics2D gg) {
super.paint(g);
//画棋盘的线
g.setColor(Color.BLACK);
for (int i = 0; i < NUM; i++) {
g.drawLine(OFFSET_X + SP * i, OFFSET_Y, OFFSET_X + SP * i, OFFSET_Y + SP * (NUM - 1));
}
for (int i = 0; i < NUM; i++) {
g.drawLine(OFFSET_X, OFFSET_Y + SP * i, OFFSET_X + SP * (NUM - 1), OFFSET_Y + SP * i);
}
//加点点缀
//五个定位的小方块
g.fillRect(OFFSET_X + SP * 3 - RECT_SIZE / 2, OFFSET_Y + SP * 3 - RECT_SIZE / 2, RECT_SIZE, RECT_SIZE);
g.fillRect(OFFSET_X + SP * 11 - RECT_SIZE / 2, OFFSET_Y + SP * 3 - RECT_SIZE / 2, RECT_SIZE, RECT_SIZE);
g.fillRect(OFFSET_X + SP * 3 - RECT_SIZE / 2, OFFSET_Y + SP * 11 - RECT_SIZE / 2, RECT_SIZE, RECT_SIZE);
g.fillRect(OFFSET_X + SP * 11 - RECT_SIZE / 2, OFFSET_Y + SP * 11 - RECT_SIZE / 2, RECT_SIZE, RECT_SIZE);
g.fillRect(OFFSET_X + SP * 7 - RECT_SIZE / 2, OFFSET_Y + SP * 7 - RECT_SIZE / 2, RECT_SIZE, RECT_SIZE);
//再加几条粗一点的线
bs = new BasicStroke(3); // 画笔宽度为5
gg.setStroke(bs);
gg.drawRect(OFFSET_X - 7, OFFSET_Y - 7, (NUM - 1) * SP + 14, (NUM - 1) * SP + 14);
bs = new BasicStroke(2);
gg.setStroke(bs);
for (int i = 1; i < NUM; i = i + 4) {
gg.drawLine(OFFSET_X + SP * i, OFFSET_Y, OFFSET_X + SP * i, OFFSET_Y + SP * (NUM - 1));
}
for (int i = 1; i < NUM; i = i + 4) {
gg.drawLine(OFFSET_X, OFFSET_Y + SP * i, OFFSET_X + SP * (NUM - 1), OFFSET_Y + SP * i);
}
}
//画侧面(右上角)的提示框
private void sidePaint(Graphics2D gg) {
if (isStart != 0) {
//开始游戏时
if (isWin) {
//赢了后
gg.setColor((oval_type == 1 ? Color.black : Color.white));
gg.setFont(font3);
gg.drawString((oval_type == 1 ? "黑方赢" : "白方赢"), 520, 170);
} else {
//没赢之前
gg.setColor(Color.red);
gg.setFont(font4);
gg.drawString("轮到:", 520, 105);
if (oval_type == 2) {
gg.setColor(Color.black);
} else if (oval_type == 1) {
gg.setColor(Color.white);
}
gg.drawString((oval_type == 2 ? "黑方" : "白方"), 530, 150);
gg.fillOval(610, 125, 40, 40);
gg.setColor(Color.red);
gg.drawString("步数:", 520, 200);
gg.setColor(Color.black);
gg.drawString(step + "", 620, 200);
}
} else {
gg.setColor(Color.RED);
gg.setFont(font4);
gg.drawString("请选择游戏类型", 525, 150);
}
}
private void initBtn() {
//将button和label设置各自的属性
selectLabel.setFont(font1);
rrBtn.setPreferredSize(buttonSize);
rrBtn.setFont(font2);
rjbBtn.setPreferredSize(buttonSize);
rjbBtn.setFont(font2);
rjwBtn.setPreferredSize(buttonSize);
rjwBtn.setFont(font2);
elseLabel.setFont(font1);
regretBtn.setPreferredSize(buttonSize);
regretBtn.setFont(font2);
restartBtn.setPreferredSize(buttonSize);
restartBtn.setFont(font2);
endBtn.setPreferredSize(buttonSize);
endBtn.setFont(font2);
titleLabel.setFont(font3); // 标题
//给按钮加上监听
rrBtn.addActionListener(actionListener);
rjbBtn.addActionListener(actionListener);
rjwBtn.addActionListener(actionListener);
regretBtn.addActionListener(actionListener);
restartBtn.addActionListener(actionListener);
endBtn.addActionListener(actionListener);
//将其放入
add(selectLabel);
add(rrBtn);
add(rjbBtn);
add(rjwBtn);
add(elseLabel);
add(regretBtn);
add(restartBtn);
add(endBtn);
add(titleLabel);
//设置各自的位置,使用弹性布局
//将标题放置到中位置
int offsetX = Spring.width(titleLabel).getValue() / 2;
springLayout.putConstraint(SpringLayout.WEST, titleLabel, -offsetX,
SpringLayout.HORIZONTAL_CENTER, this);
springLayout.putConstraint(SpringLayout.NORTH, titleLabel, 10, SpringLayout.NORTH, this);
springLayout.putConstraint(SpringLayout.WEST, selectLabel, 525,
SpringLayout.WEST, this);
springLayout.putConstraint(SpringLayout.NORTH, selectLabel, 260, SpringLayout.NORTH, this);
springLayout.putConstraint(SpringLayout.WEST, rrBtn, 5,
SpringLayout.WEST, selectLabel);
springLayout.putConstraint(SpringLayout.NORTH, rrBtn, 5, SpringLayout.SOUTH, selectLabel);
springLayout.putConstraint(SpringLayout.WEST, rjbBtn, 0,
SpringLayout.WEST, rrBtn);
springLayout.putConstraint(SpringLayout.NORTH, rjbBtn, 5, SpringLayout.SOUTH, rrBtn);
springLayout.putConstraint(SpringLayout.WEST, rjwBtn, 0,
SpringLayout.WEST, rjbBtn);
springLayout.putConstraint(SpringLayout.NORTH, rjwBtn, 5, SpringLayout.SOUTH, rjbBtn);
springLayout.putConstraint(SpringLayout.WEST, elseLabel, 0,
SpringLayout.WEST, selectLabel);
springLayout.putConstraint(SpringLayout.NORTH, elseLabel, 10, SpringLayout.SOUTH, rjwBtn);
springLayout.putConstraint(SpringLayout.WEST, regretBtn, 5,
SpringLayout.WEST, elseLabel);
springLayout.putConstraint(SpringLayout.NORTH, regretBtn, 5, SpringLayout.SOUTH, elseLabel);
springLayout.putConstraint(SpringLayout.WEST, restartBtn, 0,
SpringLayout.WEST, regretBtn);
springLayout.putConstraint(SpringLayout.NORTH, restartBtn, 5, SpringLayout.SOUTH, regretBtn);
springLayout.putConstraint(SpringLayout.WEST, endBtn, 0,
SpringLayout.WEST, restartBtn);
springLayout.putConstraint(SpringLayout.NORTH, endBtn, 5, SpringLayout.SOUTH, restartBtn);
regretBtn.setEnabled(false);
restartBtn.setEnabled(false);
endBtn.setEnabled(false);
}
ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JButton jButton = (JButton) e.getSource();
String text = jButton.getText();
if ("重新开始".equals(text)) {
init();
if(isStart==3){
machine();
step++;
table[robot_x][robot_y] = 2;
oval_type = 1;
}
regretBtn.setEnabled(false);
restartBtn.setEnabled(false);
} else if ("悔棋".equals(text)) {
int x = last_xy.get(last_xy.size() - 2);
int y = last_xy.get(last_xy.size() - 1);
table[x][y] = 0;
last_xy.remove(last_xy.size() - 2);
last_xy.remove(last_xy.size() - 1);
oval_type = oval_type % 2 + 1;
if (isStart == 2 || isStart == 3) {
x = last_xy.get(last_xy.size() - 2);
y = last_xy.get(last_xy.size() - 1);
table[x][y] = 0;
last_xy.remove(last_xy.size() - 2);
last_xy.remove(last_xy.size() - 1);
oval_type = oval_type % 2 + 1;
}
if (oval_type == 2||isStart==3) {
step--;
}
if (isWin) {
isWin = false;
}
if (last_xy.size() == 0) {
regretBtn.setEnabled(false);
restartBtn.setEnabled(false);
}
} else if ("结束游戏".equals(text)) {
isStart = 0;
init();
rrBtn.setEnabled(true);
rjbBtn.setEnabled(true);
rjwBtn.setEnabled(true);
regretBtn.setEnabled(false);
restartBtn.setEnabled(false);
endBtn.setEnabled(false);
} else {
//上面三个按钮
if ("双人对战".equals(text)) {
isStart = 1;
} else if ("人机对战.持黑".equals(text)) {
isStart = 2;
} else if ("人机对战.持白".equals(text)) {
isStart = 3;
machine();
step++;
table[robot_x][robot_y] = 2;
oval_type = 1;
}
rrBtn.setEnabled(false);
rjbBtn.setEnabled(false);
rjwBtn.setEnabled(false);
endBtn.setEnabled(true);
}
repaint();
}
};
MouseAdapter mouseAdapter = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
//赢的时候不能用
if (!isWin) {
if (isStart == 1) {
//来判断是否在棋盘内
if (e.getX() > OFFSET_X - OVAL_SIZE / 2 && e.getX() < OFFSET_X + (NUM - 1) * SP + OVAL_SIZE / 2
&& e.getY() > OFFSET_Y - OVAL_SIZE / 2 && e.getY() < OFFSET_Y + (NUM - 1) * SP + OVAL_SIZE / 2) {
//将坐标转换为二维数组的i和j
mouse_X = (e.getX() - OFFSET_X + OVAL_SIZE / 2) / SP;
mouse_Y = (e.getY() - OFFSET_Y + OVAL_SIZE / 2) / SP;
if (table[mouse_X][mouse_Y] == 0) {
table[mouse_X][mouse_Y] = oval_type;
if (oval_type == 2) {
oval_type = 1;
step++; //根据黑棋下的次数来增加总步数
} else if (oval_type == 1) {
oval_type = 2;
}
last_xy.add(mouse_X);
last_xy.add(mouse_Y);
//如果下了棋子,才能使用悔棋和重新游戏的按钮
restartBtn.setEnabled(true);
regretBtn.setEnabled(true);
judge(oval_type % 2 + 1, mouse_X, mouse_Y);
}
repaint();
}
} else if (isStart == 2) {
if (e.getX() > OFFSET_X - OVAL_SIZE / 2 && e.getX() < OFFSET_X + (NUM - 1) * SP + OVAL_SIZE / 2
&& e.getY() > OFFSET_Y - OVAL_SIZE / 2 && e.getY() < OFFSET_Y + (NUM - 1) * SP + OVAL_SIZE / 2) {
mouse_X = (e.getX() - OFFSET_X + OVAL_SIZE / 2) / SP;
mouse_Y = (e.getY() - OFFSET_Y + OVAL_SIZE / 2) / SP;
if (table[mouse_X][mouse_Y] == 0) {
table[mouse_X][mouse_Y] = 2;
oval_type = 1;
last_xy.add(mouse_X);
last_xy.add(mouse_Y);
repaint();
judge(2, mouse_X, mouse_Y);
if (!isWin) {
machine();
table[robot_x][robot_y] = 1;
oval_type = 2;
judge(1, robot_x, robot_y);
last_xy.add(robot_x);
last_xy.add(robot_y);
}
step++;
restartBtn.setEnabled(true);
regretBtn.setEnabled(true);
}
}
} else if (isStart == 3) {
if (e.getX() > OFFSET_X - OVAL_SIZE / 2 && e.getX() < OFFSET_X + (NUM - 1) * SP + OVAL_SIZE / 2
&& e.getY() > OFFSET_Y - OVAL_SIZE / 2 && e.getY() < OFFSET_Y + (NUM - 1) * SP + OVAL_SIZE / 2) {
mouse_X = (e.getX() - OFFSET_X + OVAL_SIZE / 2) / SP;
mouse_Y = (e.getY() - OFFSET_Y + OVAL_SIZE / 2) / SP;
if (table[mouse_X][mouse_Y] == 0) {
table[mouse_X][mouse_Y] = 1;
oval_type = 2;
last_xy.add(mouse_X);
last_xy.add(mouse_Y);
repaint();
judge(1, mouse_X, mouse_Y);
if (!isWin) {
machine();
table[robot_x][robot_y] = 2;
oval_type = 1;
judge(2, robot_x, robot_y);
last_xy.add(robot_x);
last_xy.add(robot_y);
}
step++;
restartBtn.setEnabled(true);
regretBtn.setEnabled(true);
}
}
}
}
}
@Override
public void mouseMoved(MouseEvent e) {
if (!isWin) {
if (isStart > 0) {
if (e.getX() > OFFSET_X - OVAL_SIZE / 2 && e.getX() < OFFSET_X + (NUM - 1) * SP + OVAL_SIZE / 2
&& e.getY() > OFFSET_Y - OVAL_SIZE / 2 && e.getY() < OFFSET_Y + (NUM - 1) * SP + OVAL_SIZE / 2) {
select_X = (e.getX() - OFFSET_X + OVAL_SIZE / 2) / SP;
select_Y = (e.getY() - OFFSET_Y + OVAL_SIZE / 2) / SP;
} else {
select_X = -10;
select_Y = -10;
}
}
}
repaint();
}
};
//判断谁赢,扫描整个棋盘,来判断是否连成五个
private void judge(int type, int x, int y) {
//传入参数,来判断是黑(2)或白(1)子
int sum=0;
//判断四个方向
//1.左 右
{
int k = x - 1;
while (k >= 0) {
if (table[k][y] == type) {
sum++;
} else {
break;
}
k--;
}
}
for (int k = x + 1; k < NUM; k++) {
if (table[k][y] == type) {
sum++;
} else {
break;
}
}
if (sum >= 4) {
isWin = true;
return;
}
//2.上 下
sum = 0;
for (int k = y - 1; k >= 0; k--) {
if (table[x][k] == type) {
sum++;
} else {
break;
}
}
for (int k = y + 1; k < NUM; k++) {
if (table[x][k] == type) {
sum++;
} else {
break;
}
}
if (sum >= 4) {
isWin = true;
return;
}
//3。左上 右下
sum = 0;
for (int i = x - 1, j = y - 1; i >= 0 && j >= 0; i--, j--) {
if (table[i][j] == type) {
sum++;
} else {
break;
}
}
for (int i = x + 1, j = y + 1; i < NUM && j < NUM; i++, j++) {
if (table[i][j] == type)
sum++;
else {
break;
}
}
if (sum >= 4) {
isWin = true;
return;
}
//3。右上 左下
sum = 0;
for (int i = x - 1, j = y + 1; i >= 0 && j < NUM; i--, j++) {
if (table[i][j] == type) {
sum++;
} else {
break;
}
}
for (int i = x + 1, j = y - 1; i < NUM && j >= 0; i++, j--) {
if (table[i][j] == type)
sum++;
else {
break;
}
}
if (sum >= 4) {
isWin = true;
//return;
}
}
//自动下棋的方法
private void machine() {
//传入棋子种类,判断颜色
int[][] ts = new int[NUM][NUM]; //来记录每个点上的得分
for (int i = 0; i < NUM; i++) {
for (int j = 0; j < NUM; j++) {
ts[i][j] = 0;
}
}
int wn; //白色个数
int bn; //黑色个数
//分4种情况
//横向
for (int i = 0; i < NUM; i++) {
for (int j = 0; j < NUM - 4; j++) {
wn = 0;
bn = 0;
//5个
for (int k = j; k < j + 5; k++) {
if (table[i][k] == 1) {
wn++;
} else if (table[i][k] == 2) {
bn++;
}
}
for (int k = j; k < j + 5; k++) {
if (table[i][k] == 0) {
ts[i][k] += score(wn, bn);
}
}
}
}
//纵向
for (int j = 0; j < NUM; j++) {
for (int i = 0; i < NUM - 4; i++) {
wn = 0;
bn = 0;
for (int k = i; k < i + 5; k++) {
if (table[k][j] == 1) {
wn++;
} else if (table[k][i] == 2) {
bn++;
}
}
for (int k = i; k < i + 5; k++) {
if (table[k][i] == 0) {
ts[k][i] += score(wn, bn);
}
}
}
}
//左上 右下
for (int i = 0; i < NUM - 4; i++) {
for (int j = 0; j < NUM - 4; j++) {
wn = 0;
bn = 0;
for (int ki = i, kj = j; ki < i + 5; ki++, kj++) {
if (table[ki][kj] == 1) {
wn++;
} else if (table[ki][kj] == 2) {
bn++;
}
}
for (int ki = i, kj = j; ki < i + 5; ki++, kj++) {
if (table[ki][kj] == 0) {
ts[ki][kj] += score(wn, bn);
}
}
}
}
//右上 左下
for (int i = 4; i < NUM; i++) {
for (int j = 0; j < NUM - 4; j++) {
wn = 0;
bn = 0;
for (int ki = i, kj = j; kj < j + 5; ki--, kj++) {
if (table[ki][kj] == 1) {
wn++;
} else if (table[ki][kj] == 2) {
bn++;
}
}
for (int ki = i, kj = j; kj < j + 5; ki--, kj++) {
if (table[ki][kj] == 0) {
ts[ki][kj] += score(wn, bn);
}
}
}
}
Vector<Integer> vv = new Vector<>();
int max = Integer.MIN_VALUE;
for (int i = 0; i < NUM; i++) {
for (int j = 0; j < NUM; j++) {
if (ts[i][j] > max) {
max = ts[i][j];
}
}
}
for (int i = 0; i < NUM; i++) {
for (int j = 0; j < NUM; j++) {
if (ts[i][j] == max) {
vv.add(i);
vv.add(j);
}
}
}
Random random = new Random();
int r = random.nextInt(vv.size() / 2);
robot_x = vv.get(r * 2);
robot_y = vv.get(r * 2 + 1);
vv.clear();
}
private int score(int wh, int bl) {
if (wh > 0 && bl > 0) {
return 0;
}
if (wh == 0 && bl == 0) {
return 7;
}
if (wh == 1) {
return 35;
}
if (wh == 2) {
return 800;
}
if (wh == 3) {
return 15000;
}
if (wh == 4) {
return 800000;
}
if (bl == 1) {
return 15;
}
if (bl == 2) {
return 400;
}
if (bl == 3) {
return 1800;
}
if (bl == 4) {
return 100000;
}
return -1;
}
}
六、课程设计感想与展望
通过团队十几天的努力,感觉收获颇丰,加强了对所学知识的巩固。不足之处是因能力有限,登陆注册没有使用数据库,所以每次打开都需要重新注册再登录。同时,界面设计有些简陋,只实现了这些基本功能。但通过参考和借鉴,实现了人机互动功能是团队的一大进步。