我们帮大家精选了相关的编程文章,网友寿宜年根据主题投稿了本篇教程内容,涉及到java、数独游戏、java版数独游戏界面实现相关内容,已被172网友关注,下面的电子资料对本篇知识点有更加详尽的解释。
java版数独游戏界面实现
之前学习javascript时用javascript写过一个数独游戏,最近看了一点java的内容,于是就心血来潮想搞一个java版的数独游戏。
现在将全部代码分享出来和大家学习交流,当然代码中有着各种各样的问题和不足之处,望各位朋友批评指点。
以下是生成数独地图的核心算法,算法不是很好,也是之前参考过网上的一些思想:
package hlc.shudu.src; /* * 数独的帮助类,里面提供数据所需的所有算法 */ public class ShuduHelper { //数独地图数组 private static int[][] maps = new int[9][9]; //每个小九宫格可放置位置的数 private static int[] canPutSum = new int[9]; //用来存储之前放置过的位置 static int[] used = new int[9]; //是否已经完成地图的生成 static boolean isOk = true; /* * 得到数独地图数组 */ public static int[][] getMap() { //判断是否已经完成地图的生成,要是没有完成就重新生成。 //从这里就可以看出算法还有待优化,如果回溯的好的话就一直可以通过回溯来重新生成,而这里是通过重新执行生成算法来重新生成。希望感兴趣的朋友可以去实现以下。 do{ isOk = true; initMaps(); }while(!isOk); return maps; } /* * 初始化maps */ private static void initMaps() { // 初始化地图数组中没有填入任何数字 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { maps[i][j] = -1; } } // 依次填入1~9 for (int num = 1; num <= 9; num++) { for (int i = 0; i < 9; i++) { used[i] = -1; canPutSum[i] = -1; } // 遍历大九宫格中的每个小九宫格 for (int i = 0; i < 9; i++) { if (canPutSum[i]==-1) { canPutSum[i] = getCanPutSum(i, num); } if (canPutSum[i]==1) { used[i] = -1; } if (canPutSum[i] == 0) { canPutSum[i] = -1; used[i] = -1; // 如果当前小九宫格中不能放入数字num,则回到前一个小九宫格 if (i > 0) { // 将前一个九宫格中放num的位置清空 if (used[i-1]!=-1) { //maps[(int) (Math.floor(used[i-1]/3)+Math.floor((i-1)/3)*3)][used[i-1]%3+((i-1)%3)*3]=-1; clearNum(i - 1, num); } // i回退一个,因为等会for循环灰给i加一,所以这里减2 i -= 2; continue; } else { isOk = false; return; } } else { // 将num放入当前小九宫格中 boolean flag = false; while (!flag) { int j = (int) (Math.random() * 9); // 当前小方格横坐标 int ii = (i / 3) * 3 + j / 3; // 当前小方格纵坐标 int jj = (i % 3) * 3 + j % 3; //System.out.println("num:"+num+"\tii:"+ii+"\tjj:"+jj); // 如果可以放置num则放置 if (maps[ii][jj] == -1 && j!=used[i] && isCanPut(ii, jj, num)) { maps[ii][jj] = num; used[i] = j; canPutSum[i] -= 1; flag = true; } } } } } } /* * 清空第i个小九宫格中的num */ private static void clearNum(int i, int num) { for (int j = 0; j < 9; j++) { // 当前小方格横坐标 int ii = (i / 3) * 3 + j / 3; // 当前小方格纵坐标 int jj = (i % 3) * 3 + j % 3; // 判断当前小方格是否可以放置 if (maps[ii][jj] == num) { maps[ii][jj] = -1; } } } /* * 得到当前小九宫格可以放入数字num的位置数目 */ private static int getCanPutSum(int i, int num) { int sum = 0; // 遍历小九宫格 for (int j = 0; j < 9; j++) { // 当前小方格横坐标 int ii = (i / 3) * 3 + j / 3; // 当前小方格纵坐标 int jj = i % 3 * 3 + j % 3; // 判断当前小方格是否可以放置 if (maps[ii][jj] == -1 && isCanPut(ii, jj, num)) { ++sum; } } return sum; } /* * 指定横纵坐标点是否可以放置num */ private static boolean isCanPut(int ii, int jj, int num) { // 判断指定坐标点的同行或同列是否有相同数字,要是有则为false for (int i = 0; i < 9; i++) { if (maps[ii][i] == num) { return false; } if (maps[i][jj] == num) { return false; } } return true; } }
本文实例为大家分享了java版数独游戏界面实现的具体代码,供大家参考,具体内容如下
实现效果图:
这里写图片描述
主函数用于启动程序:
package hlc.shudu.app; import hlc.shudu.src.ShuduHelper; import hlc.shudu.ui.ShuduMainFrame; public class AppStart { public static void main(String[] args) { ShuduMainFrame mainFrame = new ShuduMainFrame(); mainFrame.setVisible(true); } }
主窗体类(包含消息区,时间区,游戏区):
package hlc.shudu.ui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.sql.Time; import java.text.SimpleDateFormat; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.Timer; import javax.swing.border.TitledBorder; /* * 数独主窗体 */ public class ShuduMainFrame extends JFrame { public static int pass = 1; // 关卡 public static JLabel lbPass; // 显示关卡的lable public static long usedTime = 0; // 玩家用时 private ShuduCanvers panelCanvers; // 主游戏区 public static Timer userTimeAction; /* * 默认构造函数 */ public ShuduMainFrame() { // 初始化方法 init(); // 添加组件 addComponent(); // 添加主游戏区 addCanvers(); } /* * 添加主游戏区 */ private void addCanvers() { panelCanvers = new ShuduCanvers(); panelCanvers.setBorder(new TitledBorder("游戏区")); // 将主游戏区添加到窗体中 this.add(panelCanvers, BorderLayout.CENTER); } /* * 添加组件区 */ private void addComponent() { JPanel panelComponent = new JPanel(); // 添加消息区 addPanelMsg(panelComponent); // 添加时间区 addPanelTime(panelComponent); // 将组件添加到窗体顶部 this.add(panelComponent, BorderLayout.NORTH); } private void addPanelTime(JPanel panelComponent) { JPanel panelTime = new JPanel(); panelTime.setBorder(new TitledBorder("时间")); panelTime.setLayout(new GridLayout(2, 1)); final JLabel lbSysTime = new JLabel(); final JLabel lbUserTime = new JLabel(); panelTime.add(lbSysTime, BorderLayout.NORTH); panelTime.add(lbUserTime, BorderLayout.SOUTH); // 设置系统时间定时器 Timer sysTimeAction = new Timer(500, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { long timeMillis = System.currentTimeMillis(); SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); lbSysTime.setText(" 系统时间: " + df.format(timeMillis)); } }); sysTimeAction.start(); userTimeAction = new Timer(1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { lbUserTime.setText(" 您已用时: " + (++usedTime)+ " sec."); } }); userTimeAction.start(); panelComponent.add(panelTime, BorderLayout.EAST); } /* * 添加消息区 */ private void addPanelMsg(JPanel panelComponent) { // panelComponent.setBorder(new TitledBorder("消息区")); panelComponent.setLayout(new GridLayout(1, 3)); Font font14 = new Font("", 4, 14); Font font28 = new Font("", 2, 28); JPanel panelMsg = new JPanel(); panelMsg.setBorder(new TitledBorder("消息区")); JLabel lbPass1 = new JLabel("关卡:第"); lbPass1.setFont(font14); panelMsg.add(lbPass1); // 显示关卡数 lbPass = new JLabel("" + pass); lbPass.setForeground(Color.RED); lbPass.setFont(font28); panelMsg.add(lbPass); JLabel lbPass2 = new JLabel("关/总共10关"); lbPass2.setFont(font14); panelMsg.add(lbPass2); panelComponent.add(panelMsg, BorderLayout.CENTER); } /* * 界面初始化 */ private void init() { ImageIcon image = new ImageIcon("icon/icon.png"); this.setIconImage(image.getImage()); // 设置窗口初始大小 this.setSize(515, 600); // 设置窗口初始位置 this.setLocation(500, 50); // 设置窗口标题 this.setTitle("数独游戏(By:侯龙超)"); // 设置窗体不允许改变大小 this.setResizable(false); // 设置默认关闭操作 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }
游戏区画布:
package hlc.shudu.ui; import hlc.shudu.src.ShuduHelper; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dialog.ModalExclusionType; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.border.Border; import javax.swing.border.TitledBorder; public class ShuduCanvers extends JPanel implements MouseListener { ShuduCell[][] cells; // 得到数独数组 int[][] maps = new int[9][9]; private SelectNumFrame selectNum; /* * 默认构造函数 */ public ShuduCanvers() { ShuduMainFrame.usedTime = 0; maps = ShuduHelper.getMap(); // 加载数独区 this.setLayout(null); cells = new ShuduCell[9][9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { // this.remove(cells[i][j]); // 创建单元格 cells[i][j] = new ShuduCell(); // 设置位置 cells[i][j].setLocation(20 + i * 50 + (i / 3) * 5, 20 + j * 50 + (j / 3) * 5); if (passRole(ShuduMainFrame.pass)) { cells[i][j].setText("" + maps[i][j]); // 设置背景颜色 cells[i][j].setBackground(getColor(maps[i][j])); cells[i][j].setEnabled(false); cells[i][j].setForeground(Color.gray); } else { cells[i][j].addMouseListener(this); } this.add(cells[i][j]); } } checkFinish(); // reLoadCanvers(); } /* * 检查是否完成 */ private void checkFinish() { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (!check(i, j)) { return; } } } // 停止用户用时计时器 ShuduMainFrame.userTimeAction.stop(); // 清除所有cell监听 clearAllListener(); // 闯关数加一 ShuduMainFrame.pass += 1; if (ShuduMainFrame.pass > 10) { int o = JOptionPane .showConfirmDialog(this, "您已经通关了,是否重头开始?", "", 0); if (o == 1) { System.exit(0); } else { ShuduMainFrame.pass = 1; } } else { JOptionPane.showMessageDialog(this, "恭喜你通过本关!用时:" + ShuduMainFrame.usedTime + "秒\n即将进入下一关!"); } // 更新关卡提示 ShuduMainFrame.lbPass.setText("" + ShuduMainFrame.pass); // 开始新的关卡 reLoadCanvers(); // 打开用户用时计时器 ShuduMainFrame.userTimeAction.start(); } /* * 检查指定坐标处的单元格 */ private boolean check(int i, int j) { if (cells[i][j].getText().isEmpty()) { return false; } for (int k = 0; k < 9; k++) { if (cells[i][j].getText().trim().equals(cells[i][k].getText().trim()) && j!=k) { return false; } if (cells[i][j].getText().trim().equals(cells[k][j].getText().trim()) && i != k) { return false; } int ii = (i / 3) * 3 + k / 3; int jj = (j / 3) * 3 + k % 3; if (cells[i][j].getText().trim().equals(cells[ii][jj].getText().trim()) &&!(i == ii && j == jj)) { return false; } } return true; } /* * 重新加载数独区 */ public void reLoadCanvers() { ShuduMainFrame.usedTime = 0; maps = ShuduHelper.getMap(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { this.remove(cells[i][j]); // 创建单元格 cells[i][j] = new ShuduCell(); // 设置位置 cells[i][j].setLocation(20 + i * 50 + (i / 3) * 5, 20 + j * 50 + (j / 3) * 5); if (passRole(ShuduMainFrame.pass)) { cells[i][j].setText("" + maps[i][j]); // 设置背景颜色 cells[i][j].setBackground(getColor(maps[i][j])); cells[i][j].setEnabled(false); cells[i][j].setForeground(Color.gray); } else { cells[i][j].addMouseListener(this); } this.add(cells[i][j]); } } this.repaint(); checkFinish(); } /* * 根据关卡随机产生该位置是否显示数字 */ private boolean passRole(int pass) { // TODO Auto-generated method stub return Math.random() * 11 > pass; } /* * 根据数字获得颜色 */ private Color getColor(int i) { Color color = Color.pink; switch (i) { case 1: color = new Color(255, 255, 204); break; case 2: color = new Color(204, 255, 255); break; case 3: color = new Color(255, 204, 204); break; case 4: color = new Color(255, 204, 153); break; case 5: color = new Color(204, 255, 153); break; case 6: color = new Color(204, 204, 204); break; case 7: color = new Color(255, 204, 204); break; case 8: color = new Color(255, 255, 255); break; case 9: color = new Color(153, 255, 153); break; default: break; } return color; } @Override public void mouseClicked(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent e) { int modes = e.getModifiers(); if ((modes & InputEvent.BUTTON3_MASK) != 0) {// 点击鼠标右键 // 清空点击单元格上的内容 ((ShuduCell) e.getSource()).setText(""); } else if ((modes & InputEvent.BUTTON1_MASK) != 0) {// 点击鼠标左键 // 如果选择数字窗口存在则销毁 if (selectNum != null) { selectNum.dispose(); } // 新建一个选择窗口 selectNum = new SelectNumFrame(); // 设置成模态窗口 selectNum.setModal(true); // 设置选择窗口在显示器上的位置 selectNum.setLocation(e.getLocationOnScreen().x, e.getLocationOnScreen().y); // 将点击的单元格传递给数字选择窗口 selectNum.setCell((ShuduCell) e.getSource()); // 显示数字选择窗口 selectNum.setVisible(true); } checkFinish(); } /* * 清除所有cell的点击监听 */ private void clearAllListener() { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { cells[i][j].removeMouseListener(this); } } } @Override public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } }
数独单元格:
package hlc.shudu.ui; import java.awt.Color; import java.awt.Font; import javax.swing.JButton; public class ShuduCell extends JButton { public ShuduCell(){ this.setSize(50,50); Font font = new Font("",2,24); this.setFont(font); this.setBackground(new Color(255,153,102)); this.setForeground(Color.BLUE); } }
数字选择框:
package hlc.shudu.ui; import java.awt.Color; import java.awt.Window; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; public class SelectNumFrame extends JDialog implements MouseListener { private ShuduCell cell; public void setCell(ShuduCell cell) { this.cell = cell; } public SelectNumFrame(){ //隐藏界面上面的工具栏 this.setUndecorated(true); this.setSize(150, 150); this.setBackground(new Color(255,204,153, 123)); this.setLayout(null); addNum(); } //添加数字1~9 private void addNum() { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { JButton btn = new JButton(); btn.setSize(50, 50); btn.setLocation(i*50,j*50); btn.setText(""+(j*3+i+1)); btn.addMouseListener(this); this.add(btn); } } } @Override public void mouseClicked(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent e) { int modes = e.getModifiers(); if ((modes & InputEvent.BUTTON1_MASK) != 0) { JButton btn = (JButton) e.getSource(); cell.setText(btn.getText()); } this.dispose(); } @Override public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } }
完整程序包可在GitHub上下载:https://github.com/houlongchao/shudu.git
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持码农之家。