📄 hanoi.java
字号:
import java.awt.*;
import javax.swing.* ;
import java.awt.event.* ;
import javax.swing.border.*;
import javax.swing.event.*;
import java.lang.Thread ;
import javax.swing.plaf.basic.* ;
import java.io.*;
public class Hanoi extends JFrame implements ActionListener
{
//**********************定义成员变量******************
private int diskTotalNum ; //盘总数(3-10个) ,玩家可以自行选择盘个数
private int arrowHead ; //指向a,b,c三个柱子,指向的盘可以移动 , 0表示柱a 即最左边的柱
private int Pillar[][] = new int[3][]; //定义a,b,c三个柱子上是否有盘子,有哪些盘子,0表示无,1表示1号盘即最短的盘子
private int diskNum[] = new int[3]; //a,b,c三个柱子上盘总数,diskNum[0]表示a柱子
private ImageIcon diskIcon[] ; //存放盘图片
private ImageIcon diskSelIcon[] ;
private ImageIcon arrowIcon ;
private JLabel diskLabel[][] = new JLabel[3][11]; //显示盘图片,最多放10个
private JLabel arrowLabel[] = new JLabel[3] ;
private int diskMoveL , diskMoveR , arrowMoveL , arrowMoveR ; //控制移动键
private int totalSteps = 0; //记入盘移动的步骤总数
private String times = "0.0";
private long delay ; //单位毫秒
private Font defaultFont = new Font("宋体",Font.PLAIN,12);
private JRadioButtonMenuItem gradeItems[] ;
private ButtonGroup gradeGroup = new ButtonGroup();;
private JMenuItem menuG_newGame ;
private JMenuItem menuG_autoPlay ;
private JMenuItem menuG_Record ;
private JMenuItem menuG_Exit ;
private JMenuItem menuH_About ;
private JMenuItem menuH_Content ;
private JMenuItem menuS_Set ;
private JButton startButton ;
private JButton demoButton ;
private JLabel stepsLabel ;
private JLabel timeLabel ;
private JLabel startLabel ;
private boolean valid = false ;
private ThreadTime threadTime ;
private ThreadAutoPlay threadp ;
private JPanel centerPane ;
private File recordFile ;
private RecordWindow recordWindow ;
private String record ;
//******************************构造方法*************************
public Hanoi()
{
this.setTitle(" JAVA 汉诺塔");
this.setIconImage(new ImageIcon("images/hanoi.jpg").getImage()); //设置程序图标
MenuBar(); //构造菜单栏
ContentPane(); //构造界面
initRecordFile();
recordWindow = new RecordWindow(this);
addKeyListener(new KeyAdapter() { //键盘事件
public void keyPressed(KeyEvent e) {
if(valid == true) { //判断键盘事件是否有效,防止自动演示时触发。
int pressedKey = e.getKeyCode();
if(diskMoveL == pressedKey) { if(diskNum[arrowHead] != 0 ) moveDisk(-1); }
else if(diskMoveR == pressedKey) { if(diskNum[arrowHead] != 0 ) moveDisk(1); }
else if(arrowMoveL == pressedKey) { moveArrow(-1); }
else if(arrowMoveR == pressedKey) { moveArrow(1); }
else ;
if(diskNum[2] == diskTotalNum) { passGame(); }
}
}
});
this.pack(); //自动适应大小
this.setLocationRelativeTo(null); //居中
this.setResizable(false); //禁止改变大小
this.setDefaultCloseOperation(this.EXIT_ON_CLOSE); //关闭执行程序
JWindow start = new StartUp(this,"images/startup.jpg");
//this.show();
}
//*****************************主函数*****************************
public static void main(String args[])
{
JFrame.setDefaultLookAndFeelDecorated(true); //默认主题
JDialog.setDefaultLookAndFeelDecorated(true);
new Hanoi();
}
//*****************************菜单栏*****************************
public void MenuBar()
{
JMenuBar menuBar = new JMenuBar() ;
this.setJMenuBar(menuBar) ;
//---------------------游戏菜单---------------------
JMenu menuGame = new JMenu(" 游戏(G) ");
menuBar.add(menuGame);
menuGame.setMnemonic('G');
menuGame.setFont(defaultFont) ;
//游戏-子菜单
//新游戏
menuG_newGame = new JMenuItem(" 开始(N) ",'N');
menuGame.add(menuG_newGame );
menuG_newGame.setMnemonic('N');
menuG_newGame.setFont(defaultFont) ;
menuG_newGame.setIcon(new ImageIcon(getClass().getResource("images/start.jpg")));
menuG_newGame.addActionListener(this);
//
menuG_autoPlay = new JMenuItem(" 自动演示(P) ");
menuGame.add(menuG_autoPlay);
menuG_autoPlay.setMnemonic('P');
menuG_autoPlay.setFont(defaultFont) ;
menuG_autoPlay.setIcon(new ImageIcon(getClass().getResource("images/autoplay.jpg")));
menuG_autoPlay.addActionListener(this);
menuGame.addSeparator(); //分割线
menuG_Record = new JMenuItem(" 排行榜...(R) ");
menuGame.add(menuG_Record);
menuG_Record.setMnemonic('R');
menuG_Record.setFont(defaultFont) ;
menuG_Record.setIcon(new ImageIcon(getClass().getResource("images/record.jpg")));
menuG_Record.addActionListener(this);
menuGame.addSeparator();
menuG_Exit = new JMenuItem(" 退出(X) ");
menuGame.add(menuG_Exit);
menuG_Exit.setMnemonic('X');
menuG_Exit.setFont(defaultFont) ;
menuG_Exit.setIcon(new ImageIcon(getClass().getResource("images/exit.jpg")));
menuG_Exit.addActionListener(this) ;
//---------------------设置菜单---------------------
JMenu menuSet = new JMenu(" 设置(S) ");
menuBar.add(menuSet);
menuSet.setMnemonic('S');
menuSet.setFont(defaultFont) ;
//设置-首选项
menuS_Set = new JMenuItem(" 首选项(O) ");
menuSet.add(menuS_Set);
menuS_Set.setMnemonic('O');
menuS_Set.setFont(defaultFont) ;
menuS_Set.setIcon(new ImageIcon(getClass().getResource("images/option.jpg")));
menuS_Set.addActionListener(this);
//设置-子菜单
JMenu menuS_Grade = new JMenu(" 盘数(C) ");
menuSet.add(menuS_Grade);
menuS_Grade.setMnemonic('C');
menuS_Grade.setFont(defaultFont) ;
menuS_Grade.setIcon(new ImageIcon(getClass().getResource("images/disk.jpg")));
//设置-盘子个数-子菜单
String grades[] = {" 初级〔3〕"," 中级〔6〕"," 高级〔9〕"," 自定义(P)..."};
gradeItems = new JRadioButtonMenuItem[ grades.length ] ;
for(int i = 0 ; i < grades.length ; i ++)
{
gradeItems[i] = new JRadioButtonMenuItem(grades[i]);
menuS_Grade.add(gradeItems[i]);
gradeGroup.add(gradeItems[i]);
gradeItems[i].setFont(defaultFont) ;
gradeItems[i].addActionListener(this);
}
menuS_Grade.insertSeparator(3);
gradeItems[0].setSelected(true);
gradeItems[3].setMnemonic('P');
//--------------------帮助菜单---------------------
JMenu menuHelp = new JMenu(" 帮助(H) ");
menuBar.add(menuHelp);
menuHelp.setMnemonic('H');
menuHelp.setFont(defaultFont) ;
//帮助-帮助主题子菜单
menuH_Content = new JMenuItem(" 帮助主题(H)...");
menuHelp.add(menuH_Content);
menuH_Content.setMnemonic('H');
menuH_Content.setFont(defaultFont) ;
menuH_Content.setIcon(new ImageIcon(getClass().getResource("images/help.jpg")));
menuH_Content.addActionListener(this);
menuHelp.addSeparator();
//帮助-关于子菜单
menuH_About = new JMenuItem(" 关于(A)... ");
menuHelp.add(menuH_About);
menuH_About.setMnemonic('A');
menuH_About.setFont(defaultFont) ;
menuH_About.setIcon(new ImageIcon(getClass().getResource("images/about.jpg")));
menuH_About.addActionListener(this) ;
}
//****************************容器contentPane****************************
public void ContentPane()
{
Color DarkColor = new Color(55, 77, 118); //暗色
Color LightColor = new Color(111, 146, 212); //亮色
Border border = BorderFactory.createBevelBorder(BevelBorder.LOWERED,
new Color(45, 92, 162),
new Color(43, 66, 97),
new Color(45, 92, 162),
new Color(84, 123, 200));
Border border1 = BorderFactory.createBevelBorder(BevelBorder.RAISED,
new Color(45, 92, 162),
new Color(43, 66, 97),
new Color(45, 92, 162),
new Color(84, 123, 200));
Border border2 = BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.lightGray,1),BorderFactory.createEmptyBorder(2,10,2,10));
diskTotalNum = 3 ; //初始化一些成员变量
delay = 200 ; //单位毫秒
diskMoveL = KeyEvent.VK_F ; //初始化键值 即数字键 F
diskMoveR = KeyEvent.VK_J ; // J
arrowMoveL = KeyEvent.VK_D ; //D
arrowMoveR = KeyEvent.VK_K ; //K
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout()); //整体布局BorderLayout,分北和中
contentPane.setBorder(border); //设置边界
contentPane.setBackground(LightColor);
//-------------------northPane..------------------
JPanel northPane = new JPanel(new BorderLayout());
contentPane.add(northPane,BorderLayout.NORTH);
northPane.setPreferredSize(new Dimension(530,37));
northPane.setBackground(DarkColor);
northPane.setBorder(border);
//northPane.setOpaque(false);
startLabel = new LabelButton(this,"images/startbutton1.gif","images/startbutton2.gif","images/startbutton3.gif");
stepsLabel = new JLabel(" 步骤:"+totalSteps);
stepsLabel.setPreferredSize(new Dimension(140,35));
stepsLabel.setBorder(border1);
stepsLabel.setBackground(LightColor);
stepsLabel.setOpaque(true);
timeLabel = new JLabel("时间:"+times+" ",JLabel.RIGHT);
timeLabel.setPreferredSize(new Dimension(140,35));
timeLabel.setBorder(border1);
timeLabel.setBackground(LightColor);
timeLabel.setOpaque(true);
Font f2 = new Font("宋体",Font.BOLD,16);
stepsLabel.setFont(f2);
timeLabel.setFont(f2);
JPanel p = new JPanel(new FlowLayout(FlowLayout.CENTER,0,2));
p.add(startLabel);
p.setOpaque(false);
northPane.add(stepsLabel,BorderLayout.WEST);
northPane.add(p,BorderLayout.CENTER);
northPane.add(timeLabel,BorderLayout.EAST);
//------------------centerPane..------------------
centerPane = new ImageJPanel("images/backGround.jpg");
contentPane.add(centerPane,BorderLayout.CENTER); //centerPane布局BorderLayout,有北,东,西,中
centerPane.setPreferredSize(new Dimension(545,280));
centerPane.setBackground(DarkColor);
centerPane.setBorder(border);
//-----centerPane-north
JPanel centerPane_north = new JPanel();
centerPane.add(centerPane_north,BorderLayout.NORTH);
centerPane_north.setPreferredSize(new Dimension(536,30));
centerPane_north.setLayout(new GridLayout(1,3));
centerPane_north.setOpaque(false);
for(int i = 0 ; i < 3 ; i ++)
{
arrowLabel[i] = new JLabel() ;
arrowLabel[i].setOpaque(false) ;
centerPane_north.add(arrowLabel[i]) ;
}
//-----centerPane-west
JPanel centerPane_west = new ImageJPanel("images/pillar.gif");
centerPane.add(centerPane_west,BorderLayout.WEST);
centerPane_west.setPreferredSize(new Dimension(173,240));
centerPane_west.setLayout(new GridLayout(11,1));
centerPane_west.setOpaque(false);
//-----centerPane-center
JPanel centerPane_center = new ImageJPanel("images/pillar.gif");
centerPane.add(centerPane_center,BorderLayout.CENTER);
centerPane_center.setPreferredSize(new Dimension(173,240));
centerPane_center.setLayout(new GridLayout(11,1));
centerPane_center.setOpaque(false);
//----centerPane-east
JPanel centerPane_east = new ImageJPanel("images/pillar.gif");
centerPane.add(centerPane_east,BorderLayout.EAST);
centerPane_east.setPreferredSize(new Dimension(173,240));
centerPane_east.setLayout(new GridLayout(11,1));
centerPane_east.setOpaque(false);
for(int i = 10 ; i >= 0 ; i--)
{
diskLabel[0][i] = new JLabel(); //最底下的是diskLabel[0],
diskLabel[1][i] = new JLabel();
diskLabel[2][i] = new JLabel();
diskLabel[0][i].setOpaque(false);
diskLabel[1][i].setOpaque(false);
diskLabel[2][i].setOpaque(false);
centerPane_west.add(diskLabel[0][i]); //分别加到三个容器中
centerPane_center.add(diskLabel[1][i]);
centerPane_east.add(diskLabel[2][i]);
}
this.setContentPane(contentPane); //设置contentPane为顶层容器
}
//**************************初始化记录******************************
public void initRecordFile()
{
recordFile = new File(".\\record.txt");
if(!recordFile.exists())
{
try
{
recordFile.createNewFile();
}catch (IOException e) { }
}
}
//*******************************初始化游戏*******************************
public void initGame()
{
totalSteps = 0 ;
arrowHead = 0 ;
times = "0.0" ;
valid = false ;
diskNum[0] = diskTotalNum ;
diskNum[1] = 0 ;
diskNum[2] = 0 ;
Pillar = new int[3][diskTotalNum];
diskIcon = new ImageIcon[diskTotalNum];
diskSelIcon = new ImageIcon[diskTotalNum];
arrowIcon = new ImageIcon("images/arrow.gif");
for(int i = 0 ; i < 3 ; i ++) //初始化arrowLabel不可见
arrowLabel[i].setVisible(false) ;
arrowLabel[0].setIcon(arrowIcon); //设置箭头图片
arrowLabel[0].setHorizontalAlignment(JLabel.CENTER); //图片居中
arrowLabel[0].setVisible(true) ; //设为可见
for(int i = 0; i < diskTotalNum ; i ++) //循环设置abc柱子状态,并定义盘图
{
Pillar[0][i] = diskTotalNum - i ;
Pillar[1][i] = 0 ;
Pillar[2][i] = 0 ;
diskIcon[i] = new ImageIcon("images/disk"+(1+i)+".gif"); //diskIcon[0]放disk1.jpg ,
diskSelIcon[i] = new ImageIcon("images/disk"+(1+i)+"s.gif");
}
for(int i = 0 ; i < 11 ; i ++) //初始化所有JLabel不可见
{
diskLabel[0][i].setVisible(false);
diskLabel[1][i].setVisible(false);
diskLabel[2][i].setVisible(false);
}
for(int i = 0 ; i < diskTotalNum -1 ; i ++) //初始化柱a 显示diskTotalNum个盘子 ,柱b,c无盘;
{
diskLabel[0][i].setIcon(diskIcon[diskTotalNum-i-1]); //diskLabel[0][0]放disk3.gif
diskLabel[0][i].setHorizontalAlignment(JLabel.CENTER);
diskLabel[0][i].setVerticalAlignment(JLabel.CENTER);
diskLabel[0][i].setVisible(true);
}
diskLabel[0][diskTotalNum-1].setIcon(diskSelIcon[0]); //diskLabel[0][diskTotalNum-1]放disk1.gif
diskLabel[0][diskTotalNum-1].setHorizontalAlignment(JLabel.CENTER);
diskLabel[0][diskTotalNum-1].setVerticalAlignment(JLabel.CENTER);
diskLabel[0][diskTotalNum-1].setVisible(true);
stepsLabel.setText(" 步骤:"+totalSteps);
timeLabel.setText("时间:"+times+" ");
}
//*****************************新游戏**************************
public void newGame()
{
initGame(); //初始化游戏
valid = true ;
threadTime = new ThreadTime(this);
}
public void passGame()
{
timeStop();
this.valid = false ;
new DialogPassGame(this);
newGame();
}
//******************************移动操作******************************
//移动盘子
public void moveDisk(int LR) //LR=1或-2表示向右移动,LR=-1或2表示向左移动
{
if(threadTime!=null && !threadTime.isAlive())
threadTime.start();
int diskL = Pillar[arrowHead][diskNum[arrowHead]-1] ; // 箭头指向的竹子上最上面的盘子长度
int dPillar = (arrowHead+LR+3)%3 ; //目标柱子
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -