Java实现简单井字棋(OX游戏)V2.0

Willow ·
更新时间:2024-11-01
· 961 次阅读

简介

作业描述
还是承接着上次的OX游戏,这次老师提的要求奇奇怪怪的,说实话真的挺费解的,但多读几遍以后要抓住几个关键点,“左上角”、“绘制”。看刚好学了paint嘛,所以,十有八九就是用paint()写啦。注意:paint()是自动执行的!!!也就是说你不用去调用它,它就会在你运行程序时自动在所在类的图层上画图!!

主要思路 将button放在每个方格左上角。取消原本的将九个button填充到了一个chessboard(JPanel),替代为将9个chesspanel(ChessPanel extends JPanel)按表格布局填充到chessboard中,再将原先的button分别填充入空布局(null)的chesspanel中(1.不是空布局的话不能设置button的大小,2.空布局默认将组件放在左上角)。设置chesspanel边界可见,体现出“小方格”。(主要修改在initChessboard()中) 响应事件并画图。首先我们要明确,我们的目标是在button被点击后才进行在chesspanel上画圈或叉的操作,但paint是自动执行的,我们没有办法直接控制,因此,我们只能通过设置其每个chesspanal里圈或叉的可见性,再通过事件响应(修改actionPerformed())进行重绘(加上repaint())以达到效果(详见paint())。怎么画图呢?题目要求画圈和叉,因此用drawLine()画两条竖线,用drawOval画圈就够了,如果想美观点的话,就先调整下画笔粗细颜色在画,也可以考虑直接放图片进去,这两种方法我的代码里都有体现。最后强调一点,坐标是相对坐标,也就是如果你的paint是再chesspanel[3]里的,那么当中的坐标是指所被绘制组件的左上角到chesspannel[3]左上角的相对位置。具体可以看看这篇博文,有图。 效果

在这里插入图片描述
PS:本来还想把按钮改成保持数字不变的,但改起来太麻烦了,就没搞了。

代码 import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class TestOXGame { public static void main(String[] args) { MyOXGame myoxgame=new MyOXGame(); } } class MyOXGame extends JFrame implements ActionListener { //主体部分,绘制GUI,编辑有关响应 JButton[] button;//对象数组,表示棋盘上的九个格子 ChessPanel[] chessPanel;//小方格,放棋子的panel JButton restart;//重置键 JLabel judgement;//裁判,用来显示游戏的结果 JPanel chessboard,basicPanel;//棋盘,棋盘下部区域 int player=0;//显示当前玩家编号 boolean gameOverFlag=false;//记录游戏是否结束,如果结束值为true,停止对事件的响应 MyOXGame(){//生成函数,生成游戏 setTitle("MY OXGAME"); setBounds(400,400,340,360);//窗体基本设置 button=new JButton[10]; chessPanel=new ChessPanel[10]; restart=new JButton("Restart"); chessboard=new JPanel(); basicPanel=new JPanel(); judgement=new JLabel(""); chessboard.setLayout(new GridLayout(3,3)); basicPanel.setLayout(new FlowLayout());//组件初始化设置 add(chessboard,BorderLayout.CENTER); add(basicPanel,BorderLayout.SOUTH); basicPanel.add(restart); basicPanel.add(judgement);//布局设置 initChessboard();//初始化棋盘,使九个按钮按顺序加上1-9的标签, addChessToChessboard(chessboard);//将九个按钮添加至chessboard restart.addActionListener(this);//添加监听器 buttonListener();//为按钮添加监听器 setVisible(true);//设置可视化 setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);//使关闭键有用 } private void addChessToChessboard(JPanel chessboard){ //添加按钮至小方格 for(int i=1;i<=9;i++) { chessboard.add(chessPanel[i]); } } private void initChessboard(){ //使棋子按钮初始化为1-9 for(int i=1;i<=9;i++){ button[i]=new JButton( ""+i); button[i].setSize(45,45); chessPanel[i]=new ChessPanel(); chessPanel[i].setLayout(null); chessPanel[i].setBorder(BorderFactory.createLineBorder(Color.black, 1)); chessPanel[i].add(button[i]); } } private void buttonListener(){ //为棋子按钮添加监听器 for(int i=1;i<=9;i++) { button[i].addActionListener(this); } } private void restartTheGame(){ //重置游戏 chessboard.removeAll();//必须于repaint和updateUI一起用不然要不啥都没有,要不没有改动 //必须注意removll会清空布局 chessboard.setLayout(new GridLayout(3,3)); initChessboard(); addChessToChessboard(chessboard); buttonListener(); chessboard.updateUI(); chessboard.repaint(); judgement.setText(""); gameOverFlag=false; } private boolean checkDogfall(char[] chess){ //检查是否被填满,填满即为平局 for(int i=1;i='1'&&chess[i]<='9') return false; } return true; } private int checkWinner(int playerNow) { //检查当前游戏状态,-2表示没有决出胜负,-1表示平局。0表示O玩家胜利,1表示X玩家胜利 char[] chess=new char[10]; for(int i=1;i<=9;i++){ chess[i]=button[i].getLabel().charAt(0); } if( (chess[1]==chess[2]&&chess[2]==chess[3])|| (chess[4]==chess[5]&&chess[5]==chess[6])|| (chess[7]==chess[8]&&chess[8]==chess[9])|| (chess[1]==chess[5]&&chess[5]==chess[9])|| (chess[7]==chess[5]&&chess[5]==chess[3])|| (chess[1]==chess[4]&&chess[4]==chess[7])|| (chess[2]==chess[5]&&chess[5]==chess[8])|| (chess[3]==chess[6]&&chess[6]==chess[9])){ //判断当前玩家是否为赢家 return playerNow; } else if(checkDogfall(chess)) return -1; return -2; } public class ChessPanel extends JPanel{ int paintCode=-1;//状态码,用来设置可见性及类型,-1表示不可见,0表示圈圈,1表示叉叉 public void paint(Graphics g) { super.paint(g); if(paintCode==0){ Graphics2D g_2D=(Graphics2D)g; g_2D.setStroke(new BasicStroke(6.0f)); g.drawOval(43,43,23,23);//用笔画 //Image oo = new ImageIcon("src/oo.png").getImage(); //g.drawImage(oo,40,40,40,40,this);//用图画 } else if(paintCode==1){ Image xx = new ImageIcon("src/xx.png").getImage(); g.drawImage(xx,43,43,25,25,this);//用图画 //g.drawLine(50,50,60,60); //g.drawLine(50,60,60,50);//用笔画 } } } @Override public void actionPerformed(ActionEvent actionEvent) { //对监听的事件进行响应 int statueCode; int id; JButton buttonSource=(JButton)actionEvent.getSource(); if(buttonSource==restart){ //判断是否使restart键,如果是,重置游戏 restartTheGame(); } if (gameOverFlag==true) return; String buttonMark=buttonSource.getLabel(); id=(int)(buttonMark.charAt(0)-'0'); if(buttonMark.matches("[0-9]")){ if(player==0){ //绘制o buttonSource.setLabel("O"); chessPanel[id].paintCode=0;//更改状态码 repaint();//使所有chessPanel重绘 } else{ //绘制x buttonSource.setLabel("X"); chessPanel[id].paintCode=1; repaint(); } statueCode=checkWinner(player); if(statueCode==0){ judgement.setText("Player O wins the game! "); gameOverFlag=true; } else if(statueCode==1){ judgement.setText("Player X wins the game!"); gameOverFlag=true; } else if(statueCode==-1){ judgement.setText("The game a draw!"); } player=(player+1)%2;//更换玩家 } } } 后记

本着互联网精神和大家交流一下经验啦,希望大家还是自己写一写,不要直接copy交作业影响我也影响你(你再怎么的把变量名改改嘛),这次的其他两个作业都挺好做的就不讲了!这道题废了不少时间,我查了好久才明白不能点一下直接画一个,找了半天绘制的坐标的原点是哪一个,走了不少绕路,相信大家看了我这篇博客可以省下不少时间吧。可以的话点个赞支持我一下?有问题可以评论哦~


作者:S.A.



井字棋 JAVA

需要 登录 后方可回复, 如果你还没有账号请 注册新账号