用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();
			}

		}

	}
}

好的,以上便是两个类的全部代码,如果有疑问欢迎交流,可以直接评论,我看到后会回复的

发布了12 篇原创文章 · 获赞 17 · 访问量 2903

猜你喜欢

转载自blog.csdn.net/weixin_44343074/article/details/105163679