Java-数独游戏
引言
如何用Java语言开发出一个带有界面的数独游戏?
这篇文章将带你从零开始写出完整的游戏小项目。
游戏成品请进 源程序试玩
开始
首先看下运行界面图
src目录是我们存放代码的地方,那么我们在该目录下新建一个目录名叫com,然后在com目录下新建两个类,分别是
SudokuMaker.java
SodokuPlayer.java
没错,这个游戏只需要两个类即可。
然后分别确定好各类的职责,SudokuMaker类负责数独数据的生成以及数独面板,SudokuPlayer类负责主界面以及交互。
首先,包名引入应该都是这样:
package com.suduku;
首先我是用Swing插件生成的界面代码,代码有些繁琐,但是很省事,所以尽量还是手打吧。
随机数独生成流程:
1.生成9*9空白数独数组
2.随机往数独数组填数
3.DFS生成数独标准解(即数独数组81个格子都填满数字)
4.先挖n个空,对挖完空的数独进行求解(全部)
5.将所有解与标准解进行对比,将不一样的地方记录下。这些地方不允许被被挖空
代码
SudokuMaker.java
package com.suduku;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
/*生成随机数独
* 流程:
* 1.生成9*9空白数独数组
* 2.随机往数独数组填数
* 3.DFS生成数独标准解(即数独数组81个格子都填满数字)
* 4.先挖n个空,对挖完空的数独进行求解(全部)
* 5.将所有解与标准解进行对比,将不一样的地方记录下。这些地方不允许被被挖空
*/
public class SudokuMaker {
private int[][] Arr;//临时数组
private int [][]Sudoku;
private int [][]Answer;//答案
private int [][]Game;
public static void main(String arg[]){
new UI();
}
public SudokuMaker( int grade ){
this.Arr=new int[9][9];
this.Sudoku=new int[9][9];
this.Answer=new int[9][9];
rand();
DFS(Arr,0,false);
diger( grade );
// DevTools.showGame(Game);
// DevTools.showAnswer(Answer);
}
private void rand(){
int t=0;
int x,y,num;
//先往数组里面随机丢t个数
while(t<15){//t不宜多,否则运行起来耗费时间;t也不宜少,否则生成的游戏看起来一点也不随机
x=new Random().nextInt(9);
y=new Random().nextInt(9);
num=new Random().nextInt(9)+1;
if(Arr[y][x]==0){
if(isTrue(Arr,x,y,num)==true){
Arr[y][x]=num;++t;
}
}
}
}
//判断该数字填写的地方是否符合数独规则
public static boolean isTrue(int arr[][],int x,int y,int num){//数字横坐标;数字纵坐标;数字数值
//判断中单元格(3*3)
for(int i=(y/3)*3;i<(y/3+1)*3;++i){
for(int j=(x/3)*3;j<(x/3+1)*3;++j){
if(arr[i][j]==num ){return false;}
}
}
//判断横竖
for(int i=0;i<9;++i){
if((arr[i][x]==num || arr[y][i]==num)){return false;}
}
return true;
}
//深度优先搜索寻找
//绝对有很多种解法,但是我们只需要第一个解出来的
private boolean flag=false;//判断是否不再求解
int total=0;
private void DFS(int arr[][],int n,boolean all){//arr是数独数组,n是探索深度(一共81个格子,深度为81,n为0~80),是否要求全部解
//n/9为格子的纵坐标,n%9为格子的横坐标
if(n<81){
//如果已经求出了一种解,终止递归就行了,不用继续求下去了
if(flag==true && all==false){return;}
if(arr[n/9][n%9]==0){
for(int i=1;i<10;++i){
if(isTrue(arr,n%9,n/9,i)==true){
arr[n/9][n%9]=i;
DFS(arr,n+1,all);
arr[n/9][n%9]=0;
}
}
}else{
DFS(arr,n+1,all);
}
}else{
if(all==false){
flag=true;
for(int i=0;i<9;++i){
for(int j=0;j<9;++j){
Sudoku[i][j]=arr[i][j];
Answer[i][j]=arr[i][j];
}
}
}else{
for(int i=0;i<9;++i){
for(int j=0;j<9;++j){
if(arr[i][j]!=Answer[i][j]){
Game[i][j]=Answer[i][j];
i=10;j=10;
break;
}
}
}
}
}
}
/**
* 根据等级返回挖空数
* @param grade
* @return
*/
private int getDigNumber( int grade ){
int digNum = 20;
switch (grade) {
case 1:
digNum = 20;
break;
case 2:
digNum = 25;
break;
case 3:
digNum = 30;
break;
case 4:
digNum = 35;
break;
case 5:
digNum = 40;
break;
case 6:
digNum = 45;
break;
case 7:
digNum = 50;
break;
case 8:
digNum = 55;
break;
default: digNum = 20 ;
break;
}
return digNum;
}
//给数独挖空
//保证仅有一解
private void diger( int grade ){
int t=getDigNumber(grade);//55
Game=new int[9][9];
while(t>0){
int x=new Random().nextInt(9);
int y=new Random().nextInt(9);
if(Sudoku[y][x]!=0){
Sudoku[y][x]=0;--t;
}
}
for(int i=0;i<9;++i){
for(int j=0;j<9;++j){
Game[i][j]=Sudoku[i][j];
}
}
DFS(Sudoku,0,true);
}
//获取最终数独
public int[][] getArr(){
return this.Game;
}
//获取数独答案
public int[][] getAnswer(){
return this.Answer;
}
}
//游戏界面
class UI{
private JFrame gameUI;
private JLabel gameGrid;//数独81宫格
private SudokuMaker game;//数独
private JLabel[][] smallGrid;//数独小格子
private UserEvents [][] mouseListen;//监听器
public UI(){
gameUI=new JFrame();
gameUI.setVisible(true);
gameUI.setLayout(null);
gameUI.setSize(600,430);
gameUI.setResizable(false);//不允许窗口最大化
gameUI.setLocationRelativeTo(null);
JButton bt1=new JButton("生成新数独");
gameUI.add(bt1);
bt1.setBounds(400,10,100,20);
bt1.addActionListener(new OtherGameEvent());
JButton bt2=new JButton("显示答案");
gameUI.add(bt2);
bt2.setBounds(400,110,100,20);
bt2.addActionListener(new ShowAnswer());
gameGrid=new JLabel();
gameGrid.setBounds(10,10,365,365);
gameUI.add(gameGrid);
java.net.URL imgURL;
try {
imgURL = new URL("/image/grid.png");
gameGrid.setIcon(new ImageIcon(imgURL));
gameGrid.setOpaque(true);
} catch (MalformedURLException e) {
e.printStackTrace();
}
Font font=new Font("宋体",Font.BOLD,25);
smallGrid=new JLabel[9][9];
mouseListen=new UserEvents[9][9];
for(int i=0;i<9;++i){
for(int j=0;j<9;++j){
smallGrid[i][j]=new JLabel("",JLabel.CENTER);
gameGrid.add(smallGrid[i][j]);
mouseListen[i][j]=new UserEvents(smallGrid[i][j],i,j,false);
smallGrid[i][j].setFont(font);
smallGrid[i][j].setBounds(j*40+1,i*40+1,40,40);
smallGrid[i][j].addMouseListener(mouseListen[i][j]);
}
}
newGame();
}
//新游戏
private void newGame(){
game=new SudokuMaker( 1 );
int [][]gameArr=game.getArr();
for(int i=0;i<9;++i){
for(int j=0;j<9;++j){
if(gameArr[i][j]!=0){
smallGrid[i][j].setText(gameArr[i][j]+"");
mouseListen[i][j].setUse(false);
smallGrid[i][j].setForeground(Color.black);
}else{
smallGrid[i][j].setText(null);
mouseListen[i][j].setUse(true);
}
}
}
}
private class ShowAnswer implements ActionListener{
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
for(int i=0;i<9;++i){
for(int j=0;j<9;++j){
if(mouseListen[i][j].getUse()==true){
smallGrid[i][j].setText(game.getAnswer()[i][j]+"");
smallGrid[i][j].setForeground(Color.BLUE);
mouseListen[i][j].setUse(false);
}
}
}
}
}
private class OtherGameEvent implements ActionListener{
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
newGame();
}
}
private class UserEvents implements MouseListener{
private JTextArea jta;
private JLabel focus;//聚焦
private int gridX;
private int gridY;
private boolean isUse;//是否开启事件
public UserEvents(JLabel f,int y,int x,boolean u){
focus=f;
gridX=x;
gridY=y;
isUse=u;
jta=new JTextArea();
jta.setBounds(5,5,30,30);
jta.setVisible(false);
jta.setOpaque(false);
jta.setFont(new Font("宋体",Font.BOLD,25));
focus.add(jta);
}
@Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
if(isUse==true){
focus.setBorder(BorderFactory.createLineBorder(Color.red,5));
jta.setVisible(true);
focus.setText(null);
}
}
@Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
int X=arg0.getX(),Y=arg0.getY();
if(isUse==true){
if(X<=0 || X>=40 || Y<=0 || Y>=40){
focus.setBorder(BorderFactory.createLineBorder(Color.red,0));
try{
int t=new Integer(jta.getText());
if(t>0 && t<10){
game.getArr()[gridY][gridX]=0;
if(SudokuMaker.isTrue(game.getArr(), gridX, gridY, t)==true){
focus.setForeground(Color.green);
}else{
focus.setForeground(Color.red);
}
game.getArr()[gridY][gridX]=t;
}
focus.setText(jta.getText());
}catch(Exception e){
jta.setText(null);
}
jta.setVisible(false);
}
}
}
@Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
if(this.isUse==true){
focus.setBorder(BorderFactory.createLineBorder(Color.red,5));
}
}
@Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void setUse(boolean u){
this.isUse=u;
if(u==true){
jta.setText(null);
}else{
focus.setBorder(BorderFactory.createLineBorder(Color.red,0));
}
}
public boolean getUse(){
return isUse;
}
}
}
class Main {
//测试方法
public static void main(String arg[]){
new UI();
}
}
//开发工具包
class DevTools{
public static void showAnswer(int arr[][]){
System.out.println("\n答案:");
for(int i[]:arr){
for(int j:i){
System.out.print(j);
}
System.out.println();
}
System.out.println();
}
public static void showGame(int arr[][]){
System.out.println("\n题目:");
int total=0;
for(int i[]:arr){
for(int j:i){
System.out.print(j);
if(j==0){++total;}
}
System.out.println();
}
System.out.println("挖空数:"+total);
}
}
SodokuPlayer.java
package com.suduku;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.JTextArea;
public class SudokuPlayer extends JFrame {
/**
* 数独游戏
*/
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private JTextField textField;
JTextArea textArea; // 答对提示文本框
private JTextField[][] numberFields;
private JButton[] setNumButtons;
JButton lastButton; // 上一关
JButton nextButton; // 下一关
JButton changeButton; // 换一题
JButton answerButton; // 显示答案
JButton resetButton; // 重新开始
JLabel diffLabel; // 难度标签
JLabel timeLabel; // 时间标签
private SudokuMaker gameMaker;// 数独
Color green = new Color(93, 200, 138);
Color pink = new Color(255, 123, 168);
Color blue = new Color(102, 183, 255);
Color red = new Color(211, 48, 48);
Color lightGray = new Color(217, 217, 217);
int[][] sudokuArray;// 成型的数独数组
int selectX = 10; // 上锁
int selectY = 10;
int grade = 1;// 难度等级
Timer timer;
TimerTask task;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
// org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper.launchBeautyEyeLNF();
// UIManager.put("RootPane.setupButtonVisible", false);
SudokuPlayer frame = new SudokuPlayer();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public SudokuPlayer() {
setTitle("\u6570\u72EC\u6E38\u620F");
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(400, 0, 1100, 1000);
contentPane = new JPanel();
contentPane.setBackground(SystemColor.control);
contentPane.setBorder(null);
setContentPane(contentPane);
contentPane.setLayout(new BorderLayout(0, 0));
JPanel bodyPanel = new JPanel();
bodyPanel.setBackground(Color.WHITE);
contentPane.add(bodyPanel, BorderLayout.CENTER);
bodyPanel.setLayout(new GridLayout(9, 9, 0, 0));
JPanel bottomPanel = new JPanel();
bottomPanel.setBackground(green);
bottomPanel.setPreferredSize(new Dimension(1333, 100));
contentPane.add(bottomPanel, BorderLayout.SOUTH);
bottomPanel.setLayout(new GridLayout(0, 10, 0, 0));
JPanel rightPanel = new JPanel();
rightPanel.setBackground(new Color(230, 230, 230));
rightPanel.setPreferredSize(new Dimension(200, 789));
contentPane.add(rightPanel, BorderLayout.EAST);
rightPanel.setLayout(null);
timeLabel = new JLabel("00:00");
timeLabel.setFont(new Font("微软雅黑", Font.PLAIN, 30));
timeLabel.setBounds(60, 485, 90, 50);
rightPanel.add(timeLabel);
lastButton = new JButton("\u4E0A\u4E00\u5173");
lastButton.setEnabled(false);
lastButton.setFont(new Font("微软雅黑", Font.PLAIN, 25));
lastButton.setBackground(lightGray);
lastButton.setForeground(Color.BLACK);
lastButton.setFocusPainted(false);
lastButton.setBounds(47, 150, 112, 50);
lastButton.addActionListener(new FunctionActionListener());
rightPanel.add(lastButton);
answerButton = new JButton("\u7B54\u6848");
answerButton.setFont(new Font("微软雅黑", Font.PLAIN, 25));
answerButton.setBackground(lightGray);
answerButton.setForeground(Color.BLACK);
answerButton.setFocusPainted(false);
answerButton.setBounds(47, 420, 112, 50);
answerButton.addActionListener(new FunctionActionListener());
rightPanel.add(answerButton);
nextButton = new JButton("\u4E0B\u4E00\u5173");
nextButton.setFont(new Font("微软雅黑", Font.PLAIN, 25));
nextButton.setBackground(lightGray);
nextButton.setForeground(Color.BLACK);
nextButton.setFocusPainted(false);
nextButton.setBounds(47, 222, 112, 50);
nextButton.addActionListener(new FunctionActionListener());
rightPanel.add(nextButton);
changeButton = new JButton("\u6362\u4E00\u9898");
changeButton.setFont(new Font("微软雅黑", Font.PLAIN, 25));
changeButton.setBackground(lightGray);
changeButton.setForeground(Color.BLACK);
changeButton.setFocusPainted(false);
changeButton.setBounds(47, 287, 112, 50);
changeButton.addActionListener(new FunctionActionListener());
rightPanel.add(changeButton);
diffLabel = new JLabel("\u96BE\u5EA6:1");
diffLabel.setFont(new Font("微软雅黑", Font.PLAIN, 30));
diffLabel.setBounds(60, 64, 90, 50);
rightPanel.add(diffLabel);
resetButton = new JButton("\u91CD\u73A9");
resetButton.setForeground(Color.BLACK);
resetButton.setFont(new Font("微软雅黑", Font.PLAIN, 25));
resetButton.setFocusPainted(false);
resetButton.setBackground(new Color(217, 217, 217));
resetButton.setBounds(47, 355, 112, 50);
resetButton.addActionListener(new FunctionActionListener());
rightPanel.add(resetButton);
textArea = new JTextArea();
textArea.setOpaque(false);
textArea.setVisible(false);
textArea.setText("\u606D\u559C,\u5168\u90E8\u7B54\u5BF9!");
textArea.setFont(new Font("微软雅黑", Font.PLAIN, 25));
textArea.setBounds(15, 564, 170, 146);
rightPanel.add(textArea);
Border centernBorder = BorderFactory.createMatteBorder(1, 1, 1, 1, Color.GRAY);
Border rightAndBottomBorder = BorderFactory.createMatteBorder(1, 1, 4, 4, Color.GRAY);
Border bottomBorder = BorderFactory.createMatteBorder(1, 1, 4, 1, Color.GRAY);
Border rightBorder = BorderFactory.createMatteBorder(1, 1, 1, 4, Color.GRAY);
numberFields = new JTextField[9][9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
numberFields[i][j] = new JTextField(Integer.toString(i) + " " + Integer.toString(j));
numberFields[i][j].setEditable(false);
numberFields[i][j].setFont(new Font("微软雅黑", Font.BOLD, 35));
numberFields[i][j].setHorizontalAlignment(JTextField.CENTER);
numberFields[i][j].setBackground(Color.WHITE);
numberFields[i][j].setForeground(Color.BLACK);
if (i == 2 && j == 2 || i == 2 && j == 5 || i == 5 && j == 2 || i == 5 && j == 5) {
numberFields[i][j].setBorder(rightAndBottomBorder);
} else if (j == 2 || j == 5) {
numberFields[i][j].setBorder(rightBorder);
} else if (i == 2 || i == 5) {
numberFields[i][j].setBorder(bottomBorder);
} else {
numberFields[i][j].setBorder(centernBorder);
}
numberFields[i][j].addFocusListener(new TextFocusHandle());
numberFields[i][j].setName(Integer.toString(i) + Integer.toString(j));
bodyPanel.add(numberFields[i][j]);
}
}
newGame(grade);
setNumButtons = new JButton[10];
for (int i = 0; i < 10; i++) {
if (i == 9) {
setNumButtons[i] = new JButton("清除");
setNumButtons[i].addActionListener(new ClearNumberActionListener());
} else {
setNumButtons[i] = new JButton(Integer.toString(i + 1));
setNumButtons[i].addActionListener(new PutNumberActionListener());
}
setNumButtons[i].setFont(new Font("微软雅黑", Font.PLAIN, 35));
setNumButtons[i].setBackground(green);
setNumButtons[i].setForeground(Color.WHITE);
setNumButtons[i].setFocusPainted(false);
bottomPanel.add(setNumButtons[i]);
}
timer = new Timer();
task = new TimerTask() {
int count = 1;
@Override
public void run() {
timeLabel.setText(getFormattime(count));
count++;
}
};
timer.schedule(task, 1000L, 1000L); // 开始游戏时自动计时
}
/**
* 开始新游戏
*/
private void newGame(int grade) {
gameMaker = new SudokuMaker(grade);
sudokuArray = gameMaker.getArr();
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
numberFields[i][j].setBackground(Color.WHITE);
numberFields[i][j].setForeground(Color.BLACK);
if (sudokuArray[i][j] != 0) {
numberFields[i][j].setText(Integer.toString(sudokuArray[i][j]));
numberFields[i][j].setBackground(lightGray);
// mouseListen[i][j].setUse(false);
} else {
numberFields[i][j].setText(null);
numberFields[i][j].setBackground(Color.WHITE);
numberFields[i][j].setForeground(Color.BLUE);
// mouseListen[i][j].setUse(true);
}
}
}
}
/**
* 将时间格式化输出例如将120秒转换为02:00的字符串
*
* @param count
* @return
*/
public static String getFormattime(int count) {
String second = null;
String minute = null;
if (count / 60 < 10) {
minute = "0" + (count / 60);
} else {
minute = "" + (count / 60);
}
if (count % 60 < 10) {
second = ":0" + count % 60;
} else {
second = ":" + count % 60;
}
return minute + second;
}
/**
* 重新计时
*/
public void restartTimer() {
timer.cancel();
timeLabel.setText("00:00");
textArea.setVisible(false);
timer = new Timer();
task = new TimerTask() {
int count = 1;
@Override
public void run() {
timeLabel.setText(getFormattime(count));
count++;
}
};
timer.schedule(task, 1000L, 1000L);
}
/**
* 检测是否填对所有数字
*/
public boolean chickAllright() {
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
if (!numberFields[i][j].getText().equals(Integer.toString(gameMaker.getAnswer()[i][j]))) {
return false;
}
}
}
return true;
}
/**
* 检查填数是否符合正确格式
*/
public void wrrongNumber() {
for (int i = (selectX / 3) * 3; i < (selectX / 3 + 1) * 3; ++i) {
for (int j = (selectY / 3) * 3; j < (selectY / 3 + 1) * 3; ++j) {
if (numberFields[selectX][selectY].getText().equals(numberFields[i][j].getText()) && selectX != i
&& selectY != j) {
numberFields[selectX][selectY].setBackground(red);
numberFields[i][j].setBackground(red);
}
}
}
for (int i = 0; i < 9; ++i) {
if (numberFields[selectX][selectY].getText().equals(numberFields[selectX][i].getText()) && selectY != i) {
numberFields[selectX][selectY].setBackground(red);
numberFields[selectX][i].setBackground(red);
}
if (numberFields[selectX][selectY].getText().equals(numberFields[i][selectY].getText()) && selectX != i) {
numberFields[selectX][selectY].setBackground(red);
numberFields[i][selectY].setBackground(red);
}
}
}
/**
* 回复初始颜色
*/
public void reAllColor() {
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
if (sudokuArray[i][j] == 0) {
numberFields[i][j].setBackground(Color.WHITE);
} else {
numberFields[i][j].setBackground(lightGray);
}
}
}
}
/**
* 检查全部方格,有相同的就错误提示
*/
public void chickAllWrrongNumber() {
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
for (int row1 = (i / 3) * 3; row1 < (i / 3 + 1) * 3; ++row1) {
for (int colum1 = (j / 3) * 3; colum1 < (j / 3 + 1) * 3; ++colum1) {
if (numberFields[row1][colum1].getText().equals(numberFields[i][j].getText()) && row1 != i
&& colum1 != j && !numberFields[i][j].getText().equals("")) {
numberFields[row1][colum1].setBackground(red);
numberFields[i][j].setBackground(red);
}
}
}
for (int i1 = 0; i1 < 9; ++i1) {
if (numberFields[i][j].getText().equals(numberFields[i][i1].getText()) && j != i1
&& !numberFields[i][j].getText().equals("")) {
numberFields[i][j].setBackground(red);
numberFields[i][i1].setBackground(red);
}
if (numberFields[i][j].getText().equals(numberFields[i1][j].getText()) && i != i1
&& !numberFields[i][j].getText().equals("")) {
numberFields[i][j].setBackground(red);
numberFields[i1][j].setBackground(red);
}
}
}
}
}
/**
* 文本框焦点失去、获取事件
*
* @author Jack
*
*/
class TextFocusHandle implements FocusListener {
@Override
public void focusGained(FocusEvent e) {// 获得焦点
JTextField field = (JTextField) e.getSource();
sameNumber(field, numberFields);
}
@Override
public void focusLost(FocusEvent e) {// 失去焦点
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
numberFields[i][j].setForeground(Color.BLACK);
if (sudokuArray[i][j] != 0) {
numberFields[i][j].setBackground(lightGray);
} else {
numberFields[i][j].setBackground(Color.WHITE);
numberFields[i][j].setForeground(Color.BLUE);
}
for (int row = (i / 3) * 3; row < (i / 3 + 1) * 3; ++row) {
for (int colum = (j / 3) * 3; colum < (j / 3 + 1) * 3; ++colum) {
if (numberFields[row][colum].getText().equals(numberFields[i][j].getText()) && row != i
&& colum != j && !numberFields[i][j].getText().equals("")) {
numberFields[row][colum].setBackground(red);
numberFields[i][j].setBackground(red);
}
}
}
}
}
}
/**
* 对数据进行上锁解锁,并设置所选单元格所在的九宫格与行列颜色
*
* @param field
* @param fields
*/
public void sameNumber(JTextField field, JTextField[][] fields) {
String name = field.getName();
int row = Integer.parseInt(name.substring(0, 1));
int colum = Integer.parseInt(name.substring(1));
String number = field.getText();
if (sudokuArray[row][colum] != 0) {
selectX = 10; // 预置数上锁
selectY = 10;
} else {
selectX = row; // 挖空的方格可以解锁
selectY = colum;
}
if (!number.equals("")) { // 所选方格不为空
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
if (fields[i][j].getText().equals(number)) {
fields[i][j].setBackground(pink);
}
}
}
chickAllWrrongNumber();
} else {
for (int i = 0; i < 9; i++) {
numberFields[row][i].setBackground(blue);
numberFields[row][i].setForeground(Color.WHITE);
numberFields[i][colum].setBackground(blue);
numberFields[i][colum].setForeground(Color.WHITE);
}
for (int i = (row / 3) * 3; i < (row / 3 + 1) * 3; ++i) {
for (int j = (colum / 3) * 3; j < (colum / 3 + 1) * 3; ++j) {
numberFields[i][j].setBackground(blue);
numberFields[i][j].setForeground(Color.WHITE);
}
}
field.setBackground(green);
field.setForeground(Color.WHITE);
chickAllWrrongNumber();
}
}
}
/**
* 填数按钮事件监听器
*
* @author Jack
*
*/
class PutNumberActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JButton numButton = (JButton) e.getSource();
reAllColor();
if (selectX != 10 && selectY != 10) {
numberFields[selectX][selectY].setText(numButton.getText());
// wrrongNumber();
chickAllWrrongNumber();
if (chickAllright()) {// 如果全部填对
timer.cancel();
textArea.setVisible(true);
} else {
textArea.setVisible(false);
}
}
selectX = 10; // 预置数上锁
selectY = 10;
}
}
/**
* 清除填数按钮事件
*
* @author Jack
*
*/
class ClearNumberActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
reAllColor();
if (selectX != 10 && selectY != 10) {
numberFields[selectX][selectY].setText(null);
chickAllWrrongNumber();
}
selectX = 10; // 预置数上锁
selectY = 10;
}
}
/**
* 功能按钮事件监听器
*
* @author Jack
*
*/
class FunctionActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == changeButton) {
newGame(grade);
restartTimer();
}
if (e.getSource() == lastButton) {
if (grade >= 1) {
grade--;
newGame(grade);
diffLabel.setText("难度:" + grade);
nextButton.setEnabled(true);
if (grade == 1) {
lastButton.setEnabled(false);
}
restartTimer();
}
}
if (e.getSource() == nextButton) {
if (grade <= 8) {
grade++;
newGame(grade);
diffLabel.setText("难度:" + grade);
lastButton.setEnabled(true);
if (grade == 8) {
nextButton.setEnabled(false);
}
restartTimer();
}
}
if (e.getSource() == resetButton) {
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
numberFields[i][j].setBackground(Color.WHITE);
numberFields[i][j].setForeground(Color.BLACK);
if (sudokuArray[i][j] != 0) {
numberFields[i][j].setText(Integer.toString(sudokuArray[i][j]));
numberFields[i][j].setBackground(lightGray);
} else {
numberFields[i][j].setText(null);
numberFields[i][j].setBackground(Color.WHITE);
numberFields[i][j].setForeground(Color.BLUE);
}
}
}
restartTimer();
}
if (e.getSource() == answerButton) {
int[][] answer = gameMaker.getAnswer();
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
numberFields[i][j].setBackground(Color.WHITE);
numberFields[i][j].setForeground(Color.BLACK);
numberFields[i][j].setText(Integer.toString(answer[i][j]));
if (sudokuArray[i][j] != 0) {
numberFields[i][j].setBackground(lightGray);
} else {
numberFields[i][j].setBackground(Color.WHITE);
numberFields[i][j].setForeground(Color.BLUE);
}
}
}
timer.cancel();
}
}
}
}
好的,以上便是两个类的全部代码,如果有疑问欢迎交流,可以直接评论,我看到后会回复的