具体如下:
连连看的小源码
package Lianliankan;。
import javax.swing.*;。
import java.awt.*;。
import java.awt.event.*;。
public class lianliankan implements ActionListener。
JFrame mainFrame; //主面板。
Container thisContainer;。
JPanel centerPanel,southPanel,northPanel; //子面板。
JButton diamondsButton[][] = new JButton[6][5];//游戏按钮数组。
JButton exitButton,resetButton,newlyButton; //退出,重列,重新开始按钮。
JLabel fractionLable=new JLabel("0"); //分数标签。
JButton firstButton,secondButton; //。
分别记录两次62616964757a686964616fe59b9ee7ad9431333335326239被选中的按钮。
int grid[][] = new int[8][7];//储存游戏按钮位置。
static boolean pressInformation=false; //判断是否有按钮被选中。
int x0=0,y0=0,x=0,y=0,fristMsg=0,secondMsg=0,validateLV; //游戏按钮的位置坐标。
int i,j,k,n;//消除方法控制。
代码(code)是程序员用开发工具所支持的语言写出来的源文件,是一组由字符、符号或信号码元以离散形式表示信息的明确的规则体系。
对于字符和Unicode数据的位模式的定义,此模式代表特定字母、数字或符号(例如 0x20 代表一个空格,而 0x74 代表字符“t”)。一些数据类型每个字符使用一个字节;每个字节可以具有 256 个不同的位模式中的一个模式。
在计算机中,字符由不同的位模式(ON 或 OFF)表示。每个字节有 8 位,这 8 位可以有 256 种不同的 ON 和 OFF 组合模式。对于使用 1 个字节存储每个字符的程序,通过给每个位模式指派字符可表示最多 256 个不同的字符。2 个字节有 16 位,这 16 位可以有 65,536 种唯一的 ON 和 OFF 组合模式。使用 2 个字节表示每个字符的程序可表示最多 65,536 个字符。
单字节代码页是字符定义,这些字符映射到每个字节可能有的 256 种位模式中的每一种。代码页定义大小写字符、数字、符号以及 !、@、#、% 等特殊字符的位模式。每种欧洲语言(如德语和西班牙语)都有各自的单字节代码页。
虽然用于表示 A 到 Z 拉丁字母表字符的位模式在所有的代码页中都相同,但用于表示重音字符(如"é"和"á")的位模式在不同的代码页中却不同。如果在运行不同代码页的计算机间交换数据,必须将所有字符数据由发送计算机的代码页转换为接收计算机的代码页。如果源数据中的扩展字符在接收计算机的代码页中未定义,那么数据将丢失。
如果某个数据库为来自许多不同国家的客户端提供服务,则很难为该数据库选择这样一种代码页,使其包括所有客户端计算机所需的全部扩展字符。而且,在代码页间不停地转换需要花费大量的处理时间。
import java.applet.Applet;。
import java.applet.AudioClip;。
import java.awt.Dimension;。
import java.awt.Font;。
import java.awt.Toolkit;。
import javax.sound.sampled.AudioFileFormat;。
import javax.sound.sampled.AudioSystem;。
import javax.swing.JFrame;。
import javax.swing.JPanel;。
import java.awt.Rectangle;。
import javax.swing.BorderFactory;。
import javax.swing.JButton;。
import javax.swing.JOptionPane;。
import javax.swing.JSlider;。
import javax.swing.JLabel;。
import javax.swing.SwingUtilities;。
import javax.swing.UIManager;。
import javax.swing.event.ChangeEvent;。
import javax.swing.event.ChangeListener;。
import java.awt.event.ActionEvent;。
import java.awt.event.ActionListener;。
import java.awt.event.KeyAdapter;。
import java.awt.event.KeyEvent;。
import java.io.File;。
import java.util.Vector;。
public class Frame extends JFrame implements Runnable {。
JPanel contentPane;。
JPanel jPanel1 = new JPanel();。
JButton jButton1 = new JButton();。
JSlider jSlider1 = new JSlider();。
JLabel jLabel1 = new JLabel();。
JButton jButton2 = new JButton();。
JLabel jLabel2 = new JLabel();。
int count = 1, rapidity = 80; // count 当前进行的个数, rapidity 游标的位置。
int zhengque = 0, cuowu = 0;。
int rush[] = { 10 ,20 ,30 }; //游戏每关的个数 可以自由添加.列 { 10 ,20 ,30 ,40,50}。
int rush_count = 0; //记录关数。
char list[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',。
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',。
'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; //随机出现的数字 可以自由添加。
Vector number = new Vector();。
String paiduan = "true";。
AudioClip Musci_anjian, Music_shibai, Music_chenggong;。
public Frame() {。
try {
setDefaultCloseOperation(EXIT_ON_CLOSE);。
//-----------------声音文件---------------------。
Musci_anjian = Applet.newAudioClip(new File("sounds//anjian.wav")。
.toURL());。
Music_shibai = Applet.newAudioClip(new File("sounds//shibai.wav")。
.toURL());。
Music_chenggong = Applet.newAudioClip(new File(。
"sounds//chenggong.wav").toURL());。
//---------------------------------------。
jbInit();
} catch (Exception exception) {。
exception.printStackTrace();。
}
/**
* Component initialization.。
*
* @throws java.lang.Exception。
*/
private void jbInit() throws Exception {。
contentPane = (JPanel) getContentPane();。
contentPane.setLayout(null);。
setSize(new Dimension(588, 530));。
setTitle("Frame Title");。
jPanel1.setBorder(BorderFactory.createEtchedBorder());。
jPanel1.setBounds(new Rectangle(4, 4, 573, 419));。
jPanel1.setLayout(null);。
jButton1.setBounds(new Rectangle(277, 442, 89, 31));。
jButton1.setText("开始");。
jButton1.addActionListener(new Frame1_jButton1_actionAdapter(this));。
jSlider1.setBounds(new Rectangle(83, 448, 164, 21));。
jSlider1.setMaximum(100);。
jSlider1.setMinimum(1);。
jSlider1.setValue(50);。
jLabel1.setText("速度");。
jLabel1.setBounds(new Rectangle(35, 451, 39, 18));。
jButton2.setBounds(new Rectangle(408, 442, 89, 31));。
jButton2.setText("结束");。
jButton2.addActionListener(new Frame1_jButton2_actionAdapter(this));。
jLabel2.setText("第一关:100个");。
jLabel2.setBounds(new Rectangle(414, 473, 171, 21));。
contentPane.add(jPanel1);。
contentPane.add(jButton2);。
contentPane.add(jButton1);。
contentPane.add(jSlider1);。
contentPane.add(jLabel1);。
contentPane.add(jLabel2);。
this.addKeyListener(new MyListener());。
jButton1.addKeyListener(new MyListener());。
jSlider1.addKeyListener(new MyListener());。
jSlider1.addChangeListener(new ChangeListener() {。
public void stateChanged(ChangeEvent e) {。
rapidity = jSlider1.getValue();。
}
});
public void run() {。
number.clear();。
zhengque = 0;。
cuowu = 0;
paiduan = "true";。
while (count <= rush[rush_count]) { 。
try {
Thread t = new Thread(new Tthread());。
t.start();。
count += 1;。
Thread.sleep(1000 + (int) (Math.random() * 2000)); // 生产下组停顿时间。
// 最快1快.最慢2秒。
} catch (InterruptedException e) {。
e.printStackTrace();。
}
}
while (true) { // 等待最后一个字符消失。
if (number.size() == 0) {。
break;
}
}
if (zhengque == 0) { // 为了以后相除..如果全部正确或者错误就会出现错误. 所以..。
zhengque = 1;。
}
if (cuowu == 0) {。
cuowu = 1;
}
if (paiduan.equals("true")) { // 判断是否是自然结束。
if (zhengque / cuowu >= 2) {。
JOptionPane.showMessageDialog(null, "恭喜你过关了");。
rush_count += 1; // 自动加1关。
if (rush_count < rush.length) {。
if (rapidity > 10) { // 当速度大于10的时候在-5提加速度.怕速度太快。
rapidity -= 5; // 速度自动减10毫秒。
jSlider1.setValue(rapidity); // 选择位置。
}
Thread t = new Thread(this);。
t.start();。
} else {
JOptionPane.showMessageDialog(null, "牛B...你通关了..");。
rush_count = 0;。
count = 0;。
}
} else {
JOptionPane.showMessageDialog(null, "请再接再励");。
rush_count = 0;。
count = 0;。
}
} else {
rush_count = 0;。
count = 0;
}
public void jButton1_actionPerformed(ActionEvent e) {。
Thread t = new Thread(this);。
t.start();
public void jButton2_actionPerformed(ActionEvent e) {。
count = rush[rush_count] + 1;。
paiduan = "flase";。
class Tthread implements Runnable {。
public void run() {。
boolean fo = true;。
int Y = 0, X = 0;。
JLabel show = new JLabel();。
show.setFont(new java.awt.Font("宋体", Font.PLAIN, 33));。
jPanel1.add(show);。
X = 10 + (int) (Math.random() * 400);。
String parameter = list[(int) (Math.random() * list.length)] + "";。
Bean bean = new Bean();。
bean.setParameter(parameter);。
bean.setShow(show);。
number.add(bean);。
show.setText(parameter);。
while (fo) {。
// ---------------------数字下移--------------------。
show.setBounds(new Rectangle(X, Y += 2, 33, 33));。
try {
Thread.sleep(rapidity);。
} catch (InterruptedException e) {。
e.printStackTrace();。
}
if (Y >= 419) {。
fo = false;。
for (int i = number.size() - 1; i >= 0; i--) {。
Bean bn = ((Bean) number.get(i));。
if (parameter.equalsIgnoreCase(bn.getParameter())) {。
cuowu += 1;。
jLabel2.setText("正确:" + zhengque + "个,错误:" + cuowu。
+ "个");。
number.removeElementAt(i);。
Music_shibai.play();。
break;
}
}
}
}
}
class MyListener extends KeyAdapter {。
public void keyPressed(KeyEvent e) {。
String uu = e.getKeyChar() + "";。
for (int i = 0; i < number.size(); i++) {。
Bean bean = ((Bean) number.get(i));。
if (uu.equalsIgnoreCase(bean.getParameter())) {。
zhengque += 1;。
number.removeElementAt(i);。
bean.getShow().setVisible(false);。
jLabel2.setText("正确:" + zhengque + "个,错误:" + cuowu + "个");。
Music_chenggong.play();。
break;
}
}
Musci_anjian.play();。
}
public static void main(String[] args) {。
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());。
} catch (Exception exception) {。
exception.printStackTrace();。
}
Frame frame = new Frame();。
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();。
Dimension frameSize = frame.getSize();。
if (frameSize.height > screenSize.height) {。
frameSize.height = screenSize.height;。
}
if (frameSize.width > screenSize.width) {。
frameSize.width = screenSize.width;。
}
frame.setLocation((screenSize.width - frameSize.width) / 2,。
(screenSize.height - frameSize.height) / 2);。
frame.setVisible(true);。
class Frame1_jButton2_actionAdapter implements ActionListener {。
private Frame adaptee;。
Frame1_jButton2_actionAdapter(Frame adaptee) {。
this.adaptee = adaptee;。
public void actionPerformed(ActionEvent e) {。
adaptee.jButton2_actionPerformed(e);。
class Frame1_jButton1_actionAdapter implements ActionListener {。
private Frame adaptee;。
Frame1_jButton1_actionAdapter(Frame adaptee) {。
this.adaptee = adaptee;。
public void actionPerformed(ActionEvent e) {。
adaptee.jButton1_actionPerformed(e);。
class Bean {
String parameter = null;。
JLabel show = null;。
public JLabel getShow() {。
return show;。
public void setShow(JLabel show) {。
this.show = show;。
public String getParameter() {。
return parameter;。
public void setParameter(String parameter) {。
this.parameter = parameter;。
这个是比较有名的那个烟花,不知道你有没有用:
建个工程,以Fireworks为类即可。
import java.awt.*;。
import java.applet.*;。
import java.awt.event.*;。
import javax.swing.*;。
public class Fireworks extends Applet implements MouseListener,Runnable。
int x,y;
int top,point;。
/**
*对小程序进行变量和颜色的初始化。
*/
public void init() 。
{
x = 0;
y = 0;
//设置背景色为黑色
setBackground(Color.black);。
addMouseListener(this);。
}
public void paint(Graphics g) 。
{
}
/**
*使该程序可以作为应用程序运行。
*/
public static void main(String args[]) {。
Fireworks applet = new Fireworks();。
JFrame frame = new JFrame("TextAreaNew");。
frame.addWindowListener(new WindowAdapter() {。
public void windowClosing(WindowEvent e){。
System.exit(0);。
}
});
frame.getContentPane().add(。
applet, BorderLayout.CENTER);。
frame.setSize(800,400);。
applet.init();。
applet.start();。
frame.setVisible(true);。
}
/**
*程序主线程,对一个烟花进行绘制。
*/
public void run()。
{
//变量初始化
Graphics g1;
g1 = getGraphics();。
int y_move,y_click,x_click;。
int v;
x_click = x;
y_click = y;
y_move = 400;。
v = 3;
int r,g,b;
while(y_move > y_click)。
{
g1.setColor(Color.black);。
g1.fillOval(x_click,y_move,5,5);。
y_move -= 5;。
r = (((int)Math.round(Math.random()*4321))%200)+55;。
g = (((int)Math.round(Math.random()*4321))%200)+55;。
b = (((int)Math.round(Math.random()*4321))%200)+55;。
g1.setColor(new Color(r,g,b));。
g1.fillOval(x_click,y_move,5,5);。
for(int j = 0 ;j<=10;j++)。
{
if(r>55) r -= 20;。
if(g>55) g -= 20;。
if(b>55) b -=20;。
g1.setColor(new Color(r,g,b));。
g1.fillOval(x_click,y_move+j*5,5,5);。
}
g1.setColor(Color.black);。
g1.fillOval(x_click,y_move+5*10,5,5);。
try
{
Thread.currentThread().sleep(v++);。
} catch (InterruptedException e) {}。
}
for(int j=12;j>=0;j--)。
{
g1.setColor(Color.black);。
g1.fillOval(x_click,y_move+(j*5),5,5);。
try
{
Thread.currentThread().sleep((v++)/3);。
} catch (InterruptedException e) {}。
}
y_move = 400;。
g1.setColor(Color.black);。
while(y_move > y_click)。
{
g1.fillOval(x_click-2,y_move,9,5);。
y_move -= 5;。
}
v = 15;
for(int i=0;i<=25;i++)。
{
r = (((int)Math.round(Math.random()*4321))%200)+55;。
g = (((int)Math.round(Math.random()*4321))%200)+55;。
b = (((int)Math.round(Math.random()*4321))%200)+55;。
g1.setColor(new Color(r,g,b));。
g1.drawOval(x_click-3*i,y_click-3*i,6*i,6*i);。
if(i<23) 。
{
g1.drawOval(x_click-3*(i+1),y_click-3*(i+1),6*(i+1),6*(i+1));。
g1.drawOval(x_click-3*(i+2),y_click-3*(i+2),6*(i+2),6*(i+2));。
}
try
{
Thread.currentThread().sleep(v++);。
} catch (InterruptedException e) {}。
g1.setColor(Color.black);。
g1.drawOval(x_click-3*i,y_click-3*i,6*i,6*i);。
}
/**
*对鼠标事件进行监听。
*临听其鼠标按下事件。
*当按下鼠标时,产生一个新线程。
*/
public void mousePressed(MouseEvent e)。
{
x = e.getX();。
y = e.getY();。
Thread one;
one = new Thread(this);。
one.start();。
one = null;
}
/**
*实现MouseListener接中的方法。为一个空方法。
*/
public void mouseReleased(MouseEvent e)。
{
}
/**
*实现MouseListener接中的方法。为一个空方法。
*/
public void mouseEntered(MouseEvent e)。
{
}
/**
*实现MouseListener接中的方法。为一个空方法。
*/
public void mouseExited(MouseEvent e)。
{
}
/**
*实现MouseListener接中的方法。为一个空方法。
*/
public void mouseClicked(MouseEvent e)。
{
}
import java.util.Scanner;。
public class Wuziqi {。
/**
* 棋盘
*/
private final int[][] qipan;。
/**
* 步数
*/
private int bushu;。
/**
* 构造方法,设置棋盘规格。
* @param x
* @param y
*/
public Wuziqi(int x, int y) {。
if (x < 1 || y < 1) {。
System.out.println("棋盘规格应不小于1,使用默认规格");。
qipan = new int[9][9];。
} else {
qipan = new int[y][x];。
}
}
/**
* 游戏开始
*/
public void play() {。
int[] zuobiao = null;。
//如果游戏没有结束
while (!end(zuobiao)) {。
//落子,并取得坐标
zuobiao = luozi();。
//输出棋盘
out();
}
}
/**
* 输出棋盘和棋子
*/
private void out() {。
for (int i = 0; i < qipan.length; i++) {。
for (int j = 0; j < qipan[i].length; j++) {。
if (qipan[i][j] == 0) {。
System.out.print(" +");。
}else if (qipan[i][j] == -1) {。
System.out.print(" 白");。
}else if (qipan[i][j] == 1) {。
System.out.print(" 黑");。
}
}
System.out.println(" ");。
}
}
/**
* 落子
*/
private int[] luozi() {。
int[] zuobiao;。
bushu++;
if (bushu % 2 == 1) {。
System.out.println("请黑方落子");。
zuobiao = input();。
qipan[zuobiao[1]][zuobiao[0]] = 1;。
}else {
System.out.println("请白方落子");。
zuobiao = input();。
qipan[zuobiao[1]][zuobiao[0]] = -1;。
}
return zuobiao;。
}
/**
* 输入坐标
* @return
*/
private int[] input() {。
Scanner sc = new Scanner(System.in);。
System.out.println("请输入x轴坐标");。
String x = sc.next();。
System.out.println("请输入y轴坐标");。
String y = sc.next();。
//如果没有通过验证,则再次执行input(),递归算法。
if (!validate(x, y)) {。
return input();。
}
int int_x = Integer.valueOf(x);。
int int_y = Integer.valueOf(y);。
return new int[] {int_x, int_y};。
}
/**
* 校验数据
* @param x
* @param y
* @return
*/
private boolean validate(String x, String y) {。
Integer int_x = null;。
Integer int_y = null;。
//异常处理的方式判断字符串是否是一个整数。
try {
int_x = Integer.valueOf(x);。
int_y = Integer.valueOf(y);。
} catch (NumberFormatException e) {。
System.out.println("坐标格式错误,坐标应为整数");。
return false;。
}
if (int_x < 0 || int_y < 0 || int_x >= qipan[0].length || int_y >= qipan.length) {。
System.out.println("坐标越界");。
return false;。
}
if (qipan[int_y][int_x] == 0) {。
return true;。
} else {
System.out.println("坐标上已有棋子");。
}
return false;。
};
/**
* 结束条件
* @return
*/
private boolean end(int[] zuobiao) {。
if (zuobiao == null) {。
return false;。
}
//计数器
//表示棋盘上经过最近落子坐标的4条线上的连续(和最近落子颜色相同的)棋子的个数。
//如果某条线上连续的棋子大于等于4(加上最近落子本身,大于等于5),则游戏结束,符合五子棋规则。
int[] jieguo = new int[4];。
int x = zuobiao[0];。
int y = zuobiao[1];。
//定义八个方向
final int[][] fangxiang = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}};。
//最近落子的坐标上的棋子颜色。
int number = qipan[y][x];。
//搜索最近落子坐标为中心最远4的距离。
for (int i = 1; i <= 4; i++) {。
//每次搜索不同的距离都搜索八个方向。
for (int j = 0; j < fangxiang.length; j++) {。
//约定如果某个方向为null时,不再搜索这个方向。关键字continue是跳过本次(一次)循环的意思。
if (fangxiang[j] == null) {。
continue;
}
int mubiao_x = x + i * fangxiang[j][0];。
int mubiao_y = y + i * fangxiang[j][1];。
//如果搜索坐标相对于棋盘越界,则不再搜索这个方向。
if (mubiao_y >= qipan.length || mubiao_y < 0 || mubiao_x >= qipan[0].length || mubiao_x < 0) {。
fangxiang[j] = null;。
continue;
}
//如果最近落子坐标上的值等于目标坐标上的值(颜色相同),则计数器上某条线加1。
//否则认为这个方向没有棋子或有别的颜色的棋子,不再搜索这个方向。
if (number == qipan[mubiao_y][mubiao_x]) {。
jieguo[j % 4]++;。
}else {
fangxiang[j] = null;。
}
}
}
//查看计数器上是否有比3更大的数(查看是否有一方胜出)
for (int i : jieguo) {。
if (i > 3) {。
System.out.println("游戏结束");。
if (bushu % 2 == 1) {。
System.out.println("黑方胜");。
} else {
System.out.println("白方胜");。
}
return true;。
}
}
//没有胜出者的情况下,查看棋盘上是否还有空位置,如果有,则游戏可以继续。
for (int[] arr : qipan) {。
for (int i : arr) {。
if (i == 0) {。
return false;。
}
}
}
//如果没有空位置,则平局。
System.out.println("游戏结束,平局");。
return true;
}
表1. CheckerDrag.java 。
// CheckerDrag.javaimport java.awt.*;import java.awt.event.*;public class CheckerDrag extends java.applet.Applet{ // Dimension of checkerboard square. // 棋盘上每个小方格的尺寸 final static int SQUAREDIM = 40; // Dimension of checkerboard -- includes black outline. // 棋盘的尺寸 – 包括黑色的轮廓线 final static int BOARDDIM = 8 * SQUAREDIM + 2; // Dimension of checker -- 3/4 the dimension of a square. // 棋子的尺寸 – 方格尺寸的3/4 final static int CHECKERDIM = 3 * SQUAREDIM / 4; // Square colors are dark green or white. // 方格的颜色为深绿色或者白色 final static Color darkGreen = new Color (0, 128, 0); // Dragging flag -- set to true when user presses mouse button over checker // and cleared to false when user releases mouse button. // 拖动标记 --当用户在棋子上按下鼠标按键时设为true, // 释放鼠标按键时设为false boolean inDrag = false; // Left coordinate of checkerboard's upper-left corner. // 棋盘左上角的左方向坐标 int boardx; // Top coordinate of checkerboard's upper-left corner. //棋盘左上角的上方向坐标 int boardy; // Left coordinate of checker rectangle origin (upper-left corner). // 棋子矩形原点(左上角)的左方向坐标 int ox; // Top coordinate of checker rectangle origin (upper-left corner). // 棋子矩形原点(左上角)的上方向坐标 int oy; // Left displacement between mouse coordinates at time of press and checker // rectangle origin. // 在按键时的鼠标坐标与棋子矩形原点之间的左方向位移 int relx; // Top displacement between mouse coordinates at time of press and checker // rectangle origin. // 在按键时的鼠标坐标与棋子矩形原点之间的上方向位移 int rely; // Width of applet drawing area. // applet绘图区域的宽度 int width; // Height of applet drawing area. // applet绘图区域的高度 int height; // Image buffer. // 图像缓冲 Image imBuffer; // Graphics context associated with image buffer. // 图像缓冲相关联的图形背景 Graphics imG; public void init () { // Obtain the size of the applet's drawing area. // 获取applet绘图区域的尺寸 width = getSize ().width; height = getSize ().height; // Create image buffer. // 创建图像缓冲 imBuffer = createImage (width, height); // Retrieve graphics context associated with image buffer. // 取出图像缓冲相关联的图形背景 imG = imBuffer.getGraphics (); // Initialize checkerboard's origin, so that board is centered. // 初始化棋盘的原点,使棋盘在屏幕上居中 boardx = (width - BOARDDIM) / 2 + 1; boardy = (height - BOARDDIM) / 2 + 1; // Initialize checker's rectangle's starting origin so that checker is // centered in the square located in the top row and second column from // the left. // 初始化棋子矩形的起始原点,使得棋子在第一行左数第二列的方格里居中 ox = boardx + SQUAREDIM + (SQUAREDIM - CHECKERDIM) / 2 + 1; oy = boardy + (SQUAREDIM - CHECKERDIM) / 2 + 1; // Attach a mouse listener to the applet. That listener listens for // mouse-button press and mouse-button release events. // 向applet添加一个用来监听鼠标按键的按下和释放事件的鼠标监听器 addMouseListener (new MouseAdapter () { public void mousePressed (MouseEvent e) { // Obtain mouse coordinates at time of press. // 获取按键时的鼠标坐标 int x = e.getX (); int y = e.getY (); // If mouse is over draggable checker at time // of press (i.e., contains (x, y) returns // true), save distance between current mouse // coordinates and draggable checker origin // (which will always be positive) and set drag // flag to true (to indicate drag in progress). // 在按键时如果鼠标位于可拖动的棋子上方 // (也就是contains (x, y)返回true),则保存当前 // 鼠标坐标与棋子的原点之间的距离(始终为正值)并且 // 将拖动标志设为true(用来表明正处在拖动过程中) if (contains (x, y)) { relx = x - ox; rely = y - oy; inDrag = true; } } boolean contains (int x, int y) { // Calculate center of draggable checker. // 计算棋子的中心位置 int cox = ox + CHECKERDIM / 2; int coy = oy + CHECKERDIM / 2; // Return true if (x, y) locates with bounds // of draggable checker. CHECKERDIM / 2 is the // radius. // 如果(x, y)仍处于棋子范围内则返回true // CHECKERDIM / 2为半径 return (cox - x) * (cox - x) + (coy - y) * (coy - y) < CHECKERDIM / 2 * CHECKERDIM / 2; } public void mouseReleased (MouseEvent e) { // When mouse is released, clear inDrag (to // indicate no drag in progress) if inDrag is // already set. // 当鼠标按键被释放时,如果inDrag已经为true, // 则将其置为false(用来表明不在拖动过程中) if (inDrag) inDrag = false; } }); // Attach a mouse motion listener to the applet. That listener listens // for mouse drag events. //向applet添加一个用来监听鼠标拖动事件的鼠标运动监听器 addMouseMotionListener (new MouseMotionAdapter () { public void mouseDragged (MouseEvent e) { if (inDrag) { // Calculate draggable checker's new // origin (the upper-left corner of // the checker rectangle). // 计算棋子新的原点(棋子矩形的左上角) int tmpox = e.getX () - relx; int tmpoy = e.getY () - rely; // If the checker is not being moved // (at least partly) off board, // assign the previously calculated // origin (tmpox, tmpoy) as the // permanent origin (ox, oy), and // redraw the display area (with the // draggable checker at the new // coordinates). // 如果棋子(至少是棋子的一部分)没有被 // 移出棋盘,则将之前计算的原点 // (tmpox, tmpoy)赋值给永久性的原点(ox, oy), // 并且刷新显示区域(此时的棋子已经位于新坐标上) if (tmpox > boardx && tmpoy > boardy && tmpox + CHECKERDIM < boardx + BOARDDIM && tmpoy + CHECKERDIM < boardy + BOARDDIM) { ox = tmpox; oy = tmpoy; repaint (); } } } }); } public void paint (Graphics g) { // Paint the checkerboard over which the checker will be dragged. // 在棋子将要被拖动的位置上绘制棋盘 paintCheckerBoard (imG, boardx, boardy); // Paint the checker that will be dragged. // 绘制即将被拖动的棋子 paintChecker (imG, ox, oy); // Draw contents of image buffer. // 绘制图像缓冲的内容 g.drawImage (imBuffer, 0, 0, this); } void paintChecker (Graphics g, int x, int y) { // Set checker shadow color. // 设置棋子阴影的颜色 g.setColor (Color.black); // Paint checker shadow. // 绘制棋子的阴影 g.fillOval (x, y, CHECKERDIM, CHECKERDIM); // Set checker color. // 设置棋子颜色 g.setColor (Color.red); // Paint checker. // 绘制棋子 g.fillOval (x, y, CHECKERDIM - CHECKERDIM / 13, CHECKERDIM - CHECKERDIM / 13); } void paintCheckerBoard (Graphics g, int x, int y) { // Paint checkerboard outline. // 绘制棋盘轮廓线 g.setColor (Color.black); g.drawRect (x, y, 8 * SQUAREDIM + 1, 8 * SQUAREDIM + 1); // Paint checkerboard. // 绘制棋盘 for (int row = 0; row < 8; row++) { g.setColor (((row & 1) != 0) ? darkGreen : Color.white); for (int col = 0; col < 8; col++) { g.fillRect (x + 1 + col * SQUAREDIM, y + 1 + row * SQUAREDIM, SQUAREDIM, SQUAREDIM); g.setColor ((g.getColor () == darkGreen) ? Color.white : darkGreen); } } } // The AWT invokes the update() method in response to the repaint() method // calls that are made as a checker is dragged. The default implementation // of this method, which is inherited from the Container class, clears the // applet's drawing area to the background color prior to calling paint(). // This clearing followed by drawing causes flicker. CheckerDrag overrides // update() to prevent the background from being cleared, which eliminates // the flicker. // AWT调用了update()方法来响应拖动棋子时所调用的repaint()方法。该方法从 // Container类继承的默认实现会在调用paint()之前,将applet的绘图区域清除 // 为背景色,这种绘制之后的清除就导致了闪烁。CheckerDrag重写了update()来 // 防止背景被清除,从而消除了闪烁。 public void update (Graphics g) { paint (g); }}。