You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

567 lines
16 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package game;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
public class SDgame extends JFrame implements ActionListener, KeyListener {
private static final long serialVersionUID = 1L;
Container con;//申明容器
JPanel control;//申明面板容器
Toolkit toolkit = this.getToolkit();//得到窗口工具条
JMenuItem newGame = new JMenuItem("新建游戏");//菜单项
JMenuItem saveGame = new JMenuItem("保存游戏");
JMenuItem exitGame = new JMenuItem("退出游戏");
JMenuItem showMusic = new JMenuItem("显示所有窗口");
JMenuItem showInformationOfAuthor = new JMenuItem("关于作者");
JMenuItem rule = new JMenuItem("游戏规则");
JMenuItem nextStep = new JMenuItem("前进一步");
JMenuItem lastStep = new JMenuItem("后退一步");
JMenuItem off = new JMenuItem("关闭音乐");
JMenu open = new JMenu("打开音乐");
JMenuItem Music0 = new JMenuItem("下雨天");
JMenuItem Music1 = new JMenuItem("卡农");
JMenuItem Music2 = new JMenuItem("Flower Dance");
JMenuItem Music3 = new JMenuItem("菊次郎的夏天");
JMenuItem red = new JMenuItem("红色");
JMenu menuColor = new JMenu("填入字体颜色");
JMenuItem orange = new JMenuItem("橙色");
JMenuItem blue = new JMenuItem("蓝色");
JMenuItem pink = new JMenuItem("粉色");
JMenuItem green = new JMenuItem("绿色");
JMenuItem yellow = new JMenuItem("黄色");
// /////////////////////////////////////////////////////////////////////////////////
ArrayList<Step> stepArray = new ArrayList<Step>();
int currentStep = stepArray.size() - 1;
BackgroundMusicPlayer music0 = new BackgroundMusicPlayer("锦鲤 - 下雨天Piano ver..wav");
BackgroundMusicPlayer music1 = new BackgroundMusicPlayer("jentlemo - 卡农(钢琴版)(1).wav");
BackgroundMusicPlayer music2 = new BackgroundMusicPlayer("PianoPanda - Flower Dance钢琴版I.wav");
BackgroundMusicPlayer music3 = new BackgroundMusicPlayer("爱于海 - 菊次郎的夏天 钢琴独奏(翻自 久石让).wav");
BackgroundMusicPlayer victoerymusic = new BackgroundMusicPlayer(" ");
int forcusX = 0, forcusY = 0;//焦点
int[][] itemTotal = new int[9][9];//数独数组
public boolean [][]itemtoal=new boolean[9][9]; //数独伴生数组,用于固定系统给出数子的标签
Color typecolor=Color.red;//用于修改字体颜色的对象
JButton[][] buttonNum = new JButton[9][9];//创建标签按钮
Font font = new Font("", Font.BOLD, 35);//标签按钮字体
Border Green = BorderFactory.createLineBorder(Color.white);//界面边框颜色
Border raisedBevel = BorderFactory.createRaisedBevelBorder();//创建凸出边框
Border border = BorderFactory.createCompoundBorder(raisedBevel, Green);//创建复合边框
long starttime = -1, overtime = -1; // 游戏开始和结束的时间
int easyLevel = 0; // 控制游戏的难易程度
// ///////////////////////////////////////////////////////////////////////////////键盘事件监听
public void keyPressed(KeyEvent e) {
if (starttime < 0) {// 游戏还未开始,返回
return;
}
int keycode = e.getKeyCode();
int num = -1;
switch (keycode) {
case KeyEvent.VK_DELETE:
num = 0;
break;
case KeyEvent.VK_1:
num = 1;
break;
case KeyEvent.VK_2:
num = 2;
break;
case KeyEvent.VK_3:
num = 3;
break;
case KeyEvent.VK_4:
num = 4;
break;
case KeyEvent.VK_5:
num = 5;
break;
case KeyEvent.VK_6:
num = 6;
break;
case KeyEvent.VK_7:
num = 7;
break;
case KeyEvent.VK_8:
num = 8;
break;
case KeyEvent.VK_9:
num = 9;
break;
case KeyEvent.VK_NUMPAD1:
num = 1;
break;
case KeyEvent.VK_NUMPAD2:
num = 2;
break;
case KeyEvent.VK_NUMPAD3:
num = 3;
break;
case KeyEvent.VK_NUMPAD4:
num = 4;
break;
case KeyEvent.VK_NUMPAD5:
num = 5;
break;
case KeyEvent.VK_NUMPAD6:
num = 6;
break;
case KeyEvent.VK_NUMPAD7:
num = 7;
break;
case KeyEvent.VK_NUMPAD8:
num = 8;
break;
case KeyEvent.VK_NUMPAD9:
num = 9;
break;
case KeyEvent.VK_UP:
forcusX--;
toolkit.beep();
break;
case KeyEvent.VK_DOWN:
forcusX++;
toolkit.beep();
break;
case KeyEvent.VK_LEFT:
forcusY--;
toolkit.beep();
break;
case KeyEvent.VK_RIGHT:
forcusY++;
toolkit.beep();
break;
}
if (num >= 0&&itemtoal[forcusX][forcusY]==true) {
stepArray.add(new Step(forcusX, forcusY, num,
itemTotal[forcusX][forcusY]));
itemTotal[forcusX][forcusY] = num;//将输入的数字填入标签按钮
currentStep++;
showNumOnButtons(itemTotal);
this.lastStep.setEnabled(true);
showColorOnButtons();
if (SDgame.judge(itemTotal))
showWinGame();
}else {
if (forcusX < 0)
forcusX = 0;
if (forcusX > 8)
forcusX = 8;
if (forcusY < 0)
forcusY = 0;
if (forcusY > 8)
forcusY = 8;
}
showColorOnButtons();
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
// ///////////////////////////////////////////////////////////////////////////////
public void excuteStep(Step step, boolean flag) {
if (flag) {
itemTotal[step.x][step.y] = step.newnum;
} else
itemTotal[step.x][step.y] = step.orinum;
this.showNumOnButtons(itemTotal);
}
public SDgame() {
music0.play();//播放默认背景音乐
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
buttonNum[i][j] = new JButton("");
buttonNum[i][j].setFont(font);
buttonNum[i][j].setBackground(Color.white); //将标签按钮颜色改为白色
buttonNum[i][j].addActionListener(this);
buttonNum[i][j].addKeyListener(this);
}
}
// ////////////////////////////////////////////
JMenu menuFile = new JMenu("游戏");
menuFile.add(newGame);
newGame.addActionListener(this);
menuFile.add(saveGame);
saveGame.addActionListener(this);
menuFile.add(exitGame);
exitGame.addActionListener(this);
JMenu menuEdit = new JMenu("编辑");
menuEdit.add(lastStep);
lastStep.addActionListener(this);
menuEdit.add(nextStep);
nextStep.addActionListener(this);
JMenu menuView = new JMenu("音乐");
menuView.add(off);
off.addActionListener(this);
open.add(Music0);
Music0.addActionListener(this);
menuView.add(open);
open.add(Music1);
Music1.addActionListener(this);
open.add(Music2);
Music2.addActionListener(this);
open.add(Music3);
Music3.addActionListener(this);
JMenu menuTool = new JMenu("设置");
menuTool.add(menuColor);
menuColor.add(red);
red.addActionListener(this);
menuColor.add(orange);
orange.addActionListener(this);
menuColor.add(blue);
blue.addActionListener(this);
menuColor.add(pink);
pink.addActionListener(this);
menuColor.add(green);
green.addActionListener(this);
menuColor.add(yellow);
JMenu menuHelp = new JMenu("帮助");
menuHelp.add(showInformationOfAuthor);
menuHelp.add(rule);
rule.addActionListener(this);
showInformationOfAuthor.addActionListener(this);
JMenuBar menuBar = new JMenuBar();
menuBar.add(menuFile);
menuBar.add(menuEdit);
menuBar.add(menuView);
menuBar.add(menuTool);
menuBar.add(menuHelp);
this.setJMenuBar(menuBar);
// ////////////////////////////////////////////
con = this.getContentPane();
control = new JPanel();
control.setLayout(new GridLayout(3,3));
JPanel[] panelNum = new JPanel[9];
for (int i = 0; i < 9; i++) {
panelNum[i] = new JPanel();
panelNum[i].setLayout(new GridLayout(3,3 ));
panelNum[i].add(buttonNum[(i / 3) * 3][(i % 3) * 3]);
panelNum[i].add(buttonNum[(i / 3) * 3][(i % 3) * 3 + 1]);
panelNum[i].add(buttonNum[(i / 3) * 3][(i % 3) * 3 + 2]);
panelNum[i].add(buttonNum[(i / 3) * 3 + 1][(i % 3) * 3]);
panelNum[i].add(buttonNum[(i / 3) * 3 + 1][(i % 3) * 3 + 1]);
panelNum[i].add(buttonNum[(i / 3) * 3 + 1][(i % 3) * 3 + 2]);
panelNum[i].add(buttonNum[(i / 3) * 3 + 2][(i % 3) * 3]);
panelNum[i].add(buttonNum[(i / 3) * 3 + 2][(i % 3) * 3 + 1]);
panelNum[i].add(buttonNum[(i / 3) * 3 + 2][(i % 3) * 3 + 2]);
panelNum[i].setBorder(border);
control.add(panelNum[i]);
}
this.saveGame.setEnabled(false);
this.lastStep.setEnabled(false);
this.nextStep.setEnabled(false);
con.add(new JScrollPane(control));
this.setTitle("数独小游戏");
this.setLocation(650, 250);
this.setSize(620, 620);
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == lastStep) {
if (currentStep >= 0)
this.excuteStep(stepArray.get(currentStep), false);
if (currentStep > 0) {
currentStep--;
this.nextStep.setEnabled(true);
} else
lastStep.setEnabled(false);
} else if (ae.getSource() == nextStep) {
if (currentStep < stepArray.size())
this.excuteStep(stepArray.get(currentStep), true);
if (currentStep < stepArray.size() - 1) {
currentStep++;
this.lastStep.setEnabled(true);
} else
nextStep.setEnabled(false);
} else if (ae.getSource() == newGame) {
try {
String s = JOptionPane.showInputDialog(this, "请输入难度系数(0-81):");
if (s == null)
return;
int snum = Integer.parseInt(s);
if (snum >= 0 && snum <= 81) {
JOptionPane.showMessageDialog(this, "加油哦,小调皮!");
easyLevel = snum;
} else {
JOptionPane.showMessageDialog(this, "难度系数范围不正确,请重新输入!");
return;
}
} catch (NumberFormatException nfe) {
JOptionPane.showMessageDialog(this, "输入格式不正确,请重新输入!");
return;
}
itemTotal = getNewItems();//得到数独
systemfontcolor();
fixation();
starttime = System.currentTimeMillis();
this.saveGame.setEnabled(true);
showNumOnButtons(itemTotal);
showColorOnButtons();
} else if (ae.getSource() == saveGame) {
} else if (ae.getSource() == exitGame) {
System.exit(0);
} else if (ae.getSource() == showInformationOfAuthor) {
String information = SDgame.getFileText("author.txt");
JOptionPane.showMessageDialog(this, information);
} else if (ae.getSource() == rule) {
String rule = SDgame.getFileText("rule.txt");
JOptionPane.showMessageDialog(this, rule);
} else if (ae.getSource() ==off ) {
music0.stop();
music1.stop();
music2.stop();
music3.stop();
}else if (ae.getSource() ==Music0 ) {
music1.stop();
music2.stop();
music3.stop();
music0.play();
} else if (ae.getSource() ==Music1 ) {
music0.stop();
music2.stop();
music3.stop();
music1.play();
} else if (ae.getSource() ==Music2 ) {
music0.stop();
music1.stop();
music3.stop();
music2.play();
}else if (ae.getSource() ==Music3 ) {
music0.stop();
music1.stop();
music2.stop();
music3.play();
}else if (ae.getSource() ==red ) {
typecolor=Color.red;
} else if (ae.getSource() ==orange ) {
typecolor=Color.orange;
} else if (ae.getSource() ==blue ) {
typecolor=Color.blue;
} else if (ae.getSource() ==pink ) {
typecolor=Color.pink;
} else if (ae.getSource() ==green ) {
typecolor=Color.green;
} else if (ae.getSource() ==yellow ) {
typecolor=Color.yellow;
}
else {
if (starttime < 0) {// 游戏还未开始,返回
return;
}
JButton button = (JButton) ae.getSource();
// button.requestFocus();//申请得到焦点
// button.geta.getActionForKeyStroke(KeyStroke.);
int I = 0, J = 0;
for (I = 0; I < 9; I++) {// 找到发生事件的按钮的坐标
boolean ifFind = false;
for (J = 0; J < 9; J++) {
if (button == buttonNum[I][J]) {
ifFind = true;
break;
}
}
if (ifFind) {
break;
}
}
forcusX = I;
forcusY = J;
showColorOnButtons();
}
}
public void systemfontcolor() {//设置系统标签按钮字体颜色;
for(int i=0;i<9;i++) {
for(int j=0;j<9;j++)
buttonNum[i][j].setForeground(Color.black);
}
}
public static boolean judge(int[][] item) {// 整体判断当前是否已经正确填满
for (int i = 0; i < 9; i++) {
if (!SDgame.judgeLine(item[i]))
return false;
}
for (int j = 0; j < 9; j++) {
int[] temp = new int[9];
for (int i = 0; i < 9; i++) {
temp[i] = item[i][j];
}
if (!SDgame.judgeLine(temp))
return false;
}
int[][] newitem = SDgame.transformOfItems(item);
for (int i = 0; i < 9; i++) {
if (!SDgame.judgeLine(newitem[i]))
return false;
}
return true;
}
public static boolean judgeLine(int[] item) {// 判断一行是否符合数独规则
int[] temp = new int[9];
for (int i = 0; i < 9; i++) {
temp[i] = item[i];
}
Arrays.sort(temp);// 从小到大排序
for (int i = 0; i < 9; i++) {
if (temp[i] != i + 1)
return false;
}
return true;
}
public static int[][] transformOfItems(int[][] oriItem) {// 转换矩阵形式
int[][] result = new int[9][9];
for (int i = 0; i < 9; i++) {
int index = 0;
int n = (i / 3) * 3, m = (i % 3) * 3;
for (int j = n; j < n + 3; j++) {
for (int k = m; k < m + 3; k++) {
result[j][k] = oriItem[i][index++];
}
}
}
return result;
}
public boolean[][] fixation(){//初始化伴生数组
for(int i=0;i<9;i++) {
for(int j=0;j<9;j++) {
itemtoal[i][j]=false;
}
}
return itemtoal;
}
public void showNumOnButtons(int[][] item) {// 把item里保存的值显示到按钮上
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (item[i][j] == 0) {
buttonNum[i][j].setText(" ");
itemtoal[i][j]=true;
}
else {
buttonNum[i][j].setText("" + item[i][j]);
}
}
}
}
public void showColorOnButtons() {//设置填入的数字
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (i == forcusX && j == forcusY&&itemTotal[i][j]==0)
buttonNum[i][j].setForeground(typecolor); //填入数字的颜色;
//else
//buttonNum[i][j].setForeground(Color.red);
//this.getFocusOwner().setBackground(Color.white);//填入数字的背景颜色;
}
}
}
public int[][] getNewItems() {// 得到经随机遮盖处理好的数独矩阵
int[][] result = SDgame.getCompleteItems();
for (int i = 0; i < easyLevel; i++) {
int r = (int) (Math.random() * 81);
if (r == 81)
r -= 1;
int indexi = r / 9;
int indexj = r % 9;
result[indexi][indexj] = 0;
}
return result;
}
public static int[][] getCompleteItems() {// 得到填好的数独矩阵
int[][] temp = { { 7, 1, 6, 3, 5, 8, 4, 2, 9 },
{ 8, 4, 9, 2, 6, 7, 3, 1, 5 }, { 3, 5, 2, 4, 1, 9, 6, 8, 7 },
{ 5, 6, 7, 9, 4, 1, 8, 3, 2 }, { 4, 8, 1, 5, 3, 2, 7, 9, 6 },
{ 9, 2, 3, 8, 7, 6, 5, 4, 1 }, { 2, 9, 4, 6, 8, 5, 1, 7, 3 },
{ 1, 3, 5, 7, 2, 4, 9, 6, 8 }, { 6, 7, 8, 1, 9, 3, 2, 5, 4 } };
int[][] result = new int[9][9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
result[i][j] = temp[i][j];
}
}
return result;
}
public void showWinGame( ) {// 游戏过关后的处理函数
if (starttime > 0) {
String message = new String("恭喜你,已过关!");
message += "\n本关难度系数";
Integer cureasyLevel = easyLevel;
message += cureasyLevel.toString();
message += "\n过关共用时间";
overtime = System.currentTimeMillis();
Integer usetime = (int) (overtime - starttime);
usetime /= 1000;
String time;
if (usetime <= 60) {
time = usetime.toString();
time += " 秒";
} else if (usetime <= 3600) {
Integer minute = usetime / 60;
Integer second = usetime % 60;
time = minute.toString() + " 分 " + second.toString() + " 秒";
} else {
Integer hour = usetime / 3600;
Integer minute = usetime / 60;
Integer second = usetime % 60;
time = hour.toString() + " 小时 " + minute.toString() + " 分 "
+ second.toString() + " 秒";
}
message += time;
new ImageApp(message);
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
itemTotal[i][j] = 0;
}
}
showNumOnButtons(itemTotal);
starttime = -1;
}
}
public static String getFileText(String filePath) {
File f = new File(filePath.trim());
if (!f.exists())
return null;
try {
int len = (int) f.length();
char[] acContent = new char[len];
FileReader fr = new FileReader(f);
int textLen = fr.read(acContent);
String strContent = String.valueOf(acContent, 0, textLen);
return strContent;
} catch (IOException ioe) {
return null;
}
}
}