手把手教你用Java做出一个五子棋小游戏(上)

举报
海拥 发表于 2021/12/11 15:56:51 2021/12/11
【摘要】 🌊 作者主页:海拥🌊 简介:🏆CSDN全栈领域优质创作者、🥇HDZ核心组成员、🥈蝉联C站周榜前十🌊 粉丝福利:粉丝群 每周送6~9本书,不定期送各种小礼品,往期获奖公布让我先来从注册到登陆再到玩一局演示一下(本来想录制个GIF,但是录制出来的动图太大了,有几百兆,想想还是录视频,但是掘金目前还没有开发出传视频的功能,我就传在哔哩哔哩了)代码可以通过文章末尾方式获取https://...

🌊 作者主页:海拥
🌊 简介:🏆CSDN全栈领域优质创作者、🥇HDZ核心组成员、🥈蝉联C站周榜前十
🌊 粉丝福利:粉丝群 每周送6~9本书,不定期送各种小礼品,往期获奖公布

让我先来从注册到登陆再到玩一局演示一下(本来想录制个GIF,但是录制出来的动图太大了,有几百兆,想想还是录视频,但是掘金目前还没有开发出传视频的功能,我就传在哔哩哔哩了)代码可以通过文章末尾方式获取

https://www.bilibili.com/video/BV1hU4y137es/

五子棋.gif这个也有点大,四十多兆,能不能加载出来随缘

🎯一、用户注册类

类名就叫做 Register.java

image.png

这里我们用到了JFrame,窗口。JFrame 是一个可以独立显示的组件,一个窗口通常包含有标题、图标、操作按钮(关闭、最小化、最大化),还可以为窗口添加菜单栏、工具栏等。一个进程中可以创建多个窗口,并可在适当时候进行显示、隐藏 或 销毁。

控制用户注册的类主要代码

这里只放主要代码,不然太长不利于阅读

public class Register extends JFrame{

/*
 * 用户注册
 */
final JLabel welcomeRegisterLabel = new JLabel("欢迎注册开心五子棋!");
final JLabel userLabel = new JLabel("用户名:");
final JTextField userjt = new JTextField(14);
final JLabel passwordLabel = new JLabel("密码:");
final JPasswordField passwordjp = new JPasswordField(14);
final JLabel confirmPasswordLabel = new JLabel("确认密码:");
final JPasswordField confirmPasswordjp = new JPasswordField(14);
final JLabel yanzhengmajl = new JLabel("验证码:");
final JTextField yanzhengmajt = new JTextField("请输入验证码", 7);
final JLabel yanzhengmaUpdate = new JLabel("看不清?换一张");
final JButton register = new JButton("               注  册               ");
final JLabel back = new JLabel("返回");
final JLabel tipUserAlreadyRegistered = new JLabel("该账号已经注册!");
final JLabel tipUserNameEmpty = new JLabel("用户名为空!");
final JLabel tipUserNameLessThan5Char = new JLabel("账号少于5个字符!");
final JLabel tipPasswordEmpty = new JLabel("密码不能为空!");
final JLabel tipPasswordLessThan6Char = new JLabel("密码少于6个字符!");
final JLabel tipPasswordInconfirmity = new JLabel("两次密码不一致!");
final JLabel tipConfirmPasswordqualified = new JLabel("重复密码正确!");
final JLabel tipyanzhengmaerror = new JLabel("验证码输入不正确!");
final DrawYZM drawyzm = new DrawYZM();
final Random r = new Random();
static String userName = new String();
static String password = new String();
final FileOperation read = new FileOperation();
String repeatPassword = new String();
String yanzhengma = new String();
String yzm = new String();
int flagUserName = 0;
int flagPassword = 0;
int flagConfirmedPassword = 0;
int flagyanzhengma = 0;
char[] YZM = new char[62];{
        for(int i = 0; i < 26; i++) {
                YZM[i] = (char) ('A' + i);
        }
        for(int i = 26; i< 52; i++) {
                YZM[i] = (char) ('a' + i - 26);
        }
        for(char i = 52; i < 62; i++) {
                YZM[i] = (char) (i - 4);
        }
}
SpringLayout springLayout = new SpringLayout();//使用弹簧布局管理器


}

注册时需要的验证码类

class DrawYZM extends JPanel{
        /*
         *验证码类
         */
        public void paint(Graphics g) {
                setBounds(269, 269, 100, 60);
                int R = r.nextInt(255);
                int G = r.nextInt(255);
                int B = r.nextInt(255);
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D)g;
            int n = 0;
            yzm = "";
                for(int i = 0; i < 4; i++) {
                        n = r.nextInt(62);
                        yzm += YZM[n];
                        int flag = r.nextInt(2);
                        Color color = new Color(r.nextInt(200) + 20, r.nextInt(200) + 20, r.nextInt(200) + 20);
                        g2.setColor(color);
                        Graphics2D g2d = (Graphics2D)g;
                        AffineTransform trans = new AffineTransform();//将文字旋转指定角度
                        if(flag == 0) {
                                trans.rotate(- r.nextInt(45) * 3.14 / 180, 275 + i * 25, 307);
                        }else {
                                trans.rotate(r.nextInt(45) * 3.14 / 180, 275 + i * 25, 307);
                        }
                        g2d.setTransform(trans);
                        g2.setFont(new Font("微软雅黑", 1, 24));
                        g2.drawString(YZM[n] + "", 277 + i * 22, 307);
                }

        }
}

🍺二、文件操作类

类名就叫做 FileOperation.java

首先我们需要创建excel文件

包括了编号,用户名,密码,分数,等级,胜利场数,总场数,是否记住密码,是否自动登录,以及注册时间

public void creatExcel(String path) {
        String data[] = { "Num","userName", "password", "points", "class", 
                        "winNum", "totalNum", "RememberPassword", "AutoLogin", "date"};
        try {  
    File file = new File(path);
    WritableWorkbook book = Workbook.createWorkbook(file); 
    WritableSheet sheet = book.createSheet("用户信息", 0); 
    for(int i = 0; i < data.length; i++) {//将信息写入xls文件中
        Label label = new Label(i, 0, data[i]);
        sheet.addCell(label);
    }
    book.write();  
    book.close();  

} catch (Exception e) {  
    System.out.println(e);  
}  
} 

下面的方法用于判断账号是否存在

public boolean readData(String path, String userName) {
        File file = new File(path);
        if(!file.exists()) {//如果文件不存在
                creatExcel("user.xls");//创建文件
        }
        Workbook workbook = null;
        Sheet sheet = null;
        Cell cell = null;
        boolean flag = false;
        try {
                workbook = Workbook.getWorkbook(file);
                sheet = workbook.getSheet(0);
                for(int i = 0; i < sheet.getRows(); i ++) {
                        cell = sheet.getCell(1, i);
                        String content = cell.getContents();//获取内容
                        if(content.equals(userName)) {
                                flag = true;
                                break;
                        }
                }
                workbook.close();
        }catch(Exception e) {
                e.printStackTrace();
        }
        return flag;
}

将用户将信息写入文件中

public void writeData(String path, String userName, String keyword, String data) {
		File file = new File(path);//创建文件对象
		if(!file.exists()) {//如果文件不存在
			creatExcel("user.xls");//创建文件
		}
	    Workbook workbook = null;  
        WritableWorkbook wtbook = null;  
        WritableSheet wtsheet = null;  
        WritableCell wtcell = null; 
        int flagx = 0; 
        int flagy = 0;
        try {
            workbook = Workbook.getWorkbook(file);  
            wtbook = Workbook.createWorkbook(file, workbook);  
            wtsheet = wtbook.getSheet(0);//获取第一张表格  
            for(int i = 0; i < wtsheet.getColumns(); i++) {//查找列
            	wtcell = wtsheet.getWritableCell(i, 0);
            	if(wtcell.getType() == CellType.LABEL) {
            		String cell = ((Label)wtcell).getContents();
		            if(cell.equals(keyword)) {//定位到关键词的那一行
		            	flagx = i;
		            	break;
		            }
            	}     
            }
            if(keyword.equals("userName")) {//如果写入用户名
            	flagy = wtsheet.getRows();
            }else {//写入其他
            	for(int i = 0; i < wtsheet.getRows(); i++) {//查找行
            		wtcell = wtsheet.getWritableCell(1, i);
	        		String cell = ((Label)wtcell).getContents();
	        		if(cell.equals(userName)) {
	        			flagy = i;
	        			break;
	        		}
	            }
            }
	        Label label = new Label(flagx, flagy, data);
	        wtsheet.addCell(label);
	        wtsheet.addCell(new Label(0, flagy, String.valueOf((wtsheet.getRows() - 1))));
	        
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                wtbook.write();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            try {  
                wtbook.close();  
            } catch (WriteException | IOException e) {  
                e.printStackTrace();  
            }  
            workbook.close();  
        }  
}

返回对应用户的对应信息

public String backData(String path, String userName, String keyword) {
        File file = new File(path);
        if(!file.exists()) {//如果文件不存在
                creatExcel("user.xls");//创建文件
        }
        Workbook workbook = null;
        Sheet sheet = null;
        Cell cell = null;
        int flagx = 0; 
        int flagy = 0;
        try {
                workbook = Workbook.getWorkbook(file);
                sheet = workbook.getSheet(0);
                for(int i = 0; i < sheet.getColumns(); i++) {//找到用户名所在行
                        cell = sheet.getCell(i, 0);
                        String s = cell.getContents();

                        if(s.equals(keyword)) {
                                flagx = i;
                                break;
                        }
                }
                for(int i = 0; i < sheet.getRows(); i++) {
                        cell = sheet.getCell(1, i);
                        String s = cell.getContents();
                        if(s.equals(userName)) {
                                flagy = i;
                                break;
                        }
                }
                workbook.close();
        }catch(Exception e) {
                e.printStackTrace();
        }
        try {
                cell = Workbook.getWorkbook(file).getSheet(0).getCell(flagx, flagy);
        }catch(Exception e) {
                e.printStackTrace();
        }
        String s = cell.getContents();
        return s;
}

✨三、棋盘页面类

棋盘页面类名 Chessboard.java

为棋色选择添加事件监听器

whiteChessLabel.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent e) {
                if(chessboardEmpty == 0) {//只有棋盘为空的时候才能选择棋子颜色
                    whiteChessjr.setSelected(true);
                }
        }
});
blackChessLabel.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent e) {
                if(chessboardEmpty == 0) {//只有棋盘为空的时候才能选择棋子颜色
                    blackChessjr.setSelected(true);
                }
        }
});

为新局按钮添加事件监听器

newRound.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
                for(int i = 0; i < map.length; i++) {//将map数组置0
                        for(int j = 0; j < map[i].length; j++) {
                                map[i][j] = 0;
                                mapflag[i][j] = 0;
                        }
                }
                for(int j = 0; j < 225; j++) {//将悔棋标记数组置为0
                        imapflag[j] = 0;
                        jmapflag[j] = 0;
                }
                flag = 0;//行列标记数组下表置0
                winFLAG = 0;//输赢标记置0
                playerColor = -1;//玩家棋色标记置-1
                computerColor = -1;//电脑棋色标记为-1
                chessboardEmpty = 0;//棋盘标记为空
                player = 1;//玩家先下棋
                computer = 0;//电脑后下
                newchessX = 0;//新棋子标记置0
                newchessY = 0;
                depth = 0;
                repaint();
        }
});

为悔棋添加事件监听器

back.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {

                if(flag - 1 >= 0) {//棋盘上面有棋子的时候, 点击一次棋盘上面少两颗棋子,一颗是自己的,另一颗是电脑的
                        for(int i = flag - 1; i > flag - 3; i--) {
                                map[imapflag[i]][jmapflag[i]] = 0;
                                mapflag[imapflag[i]][jmapflag[i]] = 0;
                                imapflag[i] = 0;//将坐标存放在悔棋标记数组中
                                jmapflag[i] = 0;
                        }
                        flag = flag - 2;//表示每次悔棋棋盘上双方均少一颗子
                        winFLAG = 0;
                        if(flag - 1 >= 0) {
                                newchessX = imapflag[flag - 1];
                                newchessY = jmapflag[flag - 1];
                        }
                        if(flag == 0) {//表示棋盘为空
                                chessboardEmpty = 0;//棋盘为空
                                playerColor = -1;//玩家和电脑棋子颜色置0
                                computerColor = -1;
                                depth = 0;
                        }
                        repaint();
                }else {
                        ;
                }

        }
});

返回按钮添加事件监听器

returnback.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
                dispose();
                new Main();
        }
});

退出按钮事件监听器

exit.addActionListener(new ActionListener() {//点击退出按钮退出程序
        public void actionPerformed(ActionEvent e) {
                System.exit(0);
        }
});

鼠标进入棋盘区域内,用于显示提示方框,表示点击之后可以在哪个区域内下棋

addMouseMotionListener(new MouseMotionListener() {
        public void mouseMoved(MouseEvent e) {
                // TODO 自动生成的方法存根
                x = e.getX();
                y = e.getY();
                if(x >= 247 && x <= 951 && y >=77 && y <= 781) {//如果鼠标点击的点在棋盘内或者边上一点
                        double m = (x - 270.0)/47.0;//判断点击位置最靠近的哪个交叉点
                        double n = (y - 100.0)/47.0;
                        int p = (x - 270)/47;
                        int q = (y - 100)/47;
                        int i, j;
                        if(m - p >= 0.5 || m - p <= -0.5) {
                                i = p + 1;
                        }else {
                                i = p;
                        }
                        if(n - q >= 0.5 || n - q <= -0.5) {
                                j = q + 1;
                        }else {
                                j = q;
                        }
                        if(i >=0 && i <= 15 && j >= 0 && j <= 15) {//识别到的区域为棋盘之内
                                if(mapflag[i][j] == 0 && winFLAG == 0 && player == 1) {//表示这个地方没有棋子,并且还没有赢
                                        promptBoxFlag[i][j] = 1;
                                        repaint();
                                }
                        }
                }		
        }
        public void mouseDragged(MouseEvent e) {}
});

电脑下棋函数

	private void tuntoComputer() {//电脑下棋
		// TODO 自动生成的方法存根
		if(depth >= 7) {
			depth = 6;
		}
		position = Algorithm.evalute(map, depth, computerColor);//调用估值函数
		map[position[0]][position[1]] = computerColor;
		imapflag[flag] = position[0];//将坐标存放在悔棋标记数组中
		jmapflag[flag] = position[1];
		newchessX = position[0];//新棋子标记记录坐标
		newchessY = position[1];
		int a = Math.max(Math.abs(position[0] - 7), Math.abs(position[1] - 7));//计算该点到中心的最大的距离
		depth = Math.max(depth, a);//不断更新depth的值
		flag ++;
		chessboardEmpty = 1;//棋盘标记为有棋子
		player = 1;//玩家下棋标志置0
		computer = 0;//电脑下棋标志为1
		judgeFlag = 1;
		repaint();
	}

绘制棋盘

    for(int i = 0; i < 15; i++) {//横线
            g2.drawLine(261, i * 47 + 63, 919, i * 47 + 63);
    }
    for(int j = 0; j < 15; j++) {//竖线
            g2.drawLine(j * 47 + 261, 64, j * 47 + 261, 721);
    }

绘制棋子

for(int i = 0; i < map.length; i++) {
        for(int j = 0; j < map[i].length; j++) {
                //白棋
                if(map[i][j] == 1) {
                        g2.drawImage(white, i * 47 + 241, j * 47 + 43, 40, 40, this);
                        mapflag[i][j] = 1;//标记位置表示这个地方已经有棋子
                }
                //黑棋
                if(map[i][j] == 2) {
                        g2.drawImage(black, i * 47 + 241, j * 47 + 43, 40, 40, this);
                        mapflag[i][j] = 1;
                }	
        }
}

判断棋子是否连成五个

if(judgeFlag == 1) {
        judge();
        judgeFlag = 0;
}

绘制新棋子红点标记

if(chessboardEmpty != 0) {
        g2.setColor(Color.red);
    g2.fillOval(newchessX * 47 + 254, newchessY * 47 + 55, 15, 15);
}

绘制鼠标移动方框

for(int i = 0; i < 15; i++) {
        for(int j = 0; j < 15; j++) {
                if(promptBoxFlag[i][j] == 1) {
                        g2.setColor(Color.RED);
                        g2.setStroke(new BasicStroke(2.5f));//设置线条大小
                        g2.drawLine(238 + i * 47, 40 + j * 47, 248 + i * 47, 40 + j * 47);//上左横线
                        g2.drawLine(275 + i * 47, 40 + j * 47, 285 + i * 47, 40 + j * 47);//上右横线
                        g2.drawLine(238 + i * 47, 40 + j * 47, 238 + i * 47, 50 + j * 47);//左上竖线
                        g2.drawLine(285 + i * 47, 40 + j * 47, 285 + i * 47, 50 + j * 47);//右上竖线
                        g2.drawLine(238 + i * 47, 77 + j * 47, 238 + i * 47, 87 + j * 47);//左下竖线
                        g2.drawLine(285 + i * 47, 77 + j * 47, 285 + i * 47, 87 + j * 47);//右下竖线
                        g2.drawLine(238 + i * 47, 87 + j * 47, 248 + i * 47, 87 + j * 47);//下左横线
                        g2.drawLine(275 + i * 47, 87 + j * 47, 285 + i * 47, 87 + j * 47);//下右横线
                        promptBoxFlag[i][j] = 0;
                }
        }
}
for(int i = 0; i < 5; i++) {//右上角星星
        g2.drawImage(happy, 711 + i * 47, 20, 40, 40, null);
}

代码下载:

关注作者同名公众号【海拥】回复【java五子棋小游戏】

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。