偶尔帮同学作一个拼图游戏要求多加注释实现后加了这么多注释直接删掉太可惜了
不如拿出来共享一下其实有些注释就是废话不过先讲一下原理方始读者了然不惑 :)
主要利用了Graphics中的
public abstract boolean drawImage(Image img
int dx
int dy
int dx
int dy
int sx
int sy
int sx
int sy
Color bgcolor
ImageObserver observer)
方法(Draws as much of the specified area of the specified image as is currently available scaling it on the fly tofit inside the specified area of the destination drawable surface)大意是把 img 中由 (sx sy)(sx sy)指定的矩形区域画到 observer 中由(dx dy)(dx dy)指定的矩形区域内(如果两个指定的大小不同可能会依目的大小为准进行拉伸或压缩建议相同) 有了上面的方法就可以进行构思拼图游戏的具体实现了主要是计算上面的个值以下代码注释很详细(或说很罗嗦)有几点要指出 图片为随机打乱一个小子说块图片怎么随机打乱都能拼成结果有几次拼了多半个小时都不成(我不太擅长拼图)所以如果拼不出来请重新开始一下 最后的图片为拼图图片存为 bgjpg 放至同一文件夹下即可如要换图要改变窗口大小否则会变形 一直另我很郁闷的事情空白的一块始终颜色是黑色无论我加多少 setcolor语句还望各位大虾指教 显示时间未实现继承Runnable接口实现并不难但 显示正确图片继续游戏 相当于一个暂停按钮需要线程间的协作 唤醒等待恩不算太难有需要的就实现否则就掐表吧
import javaawt*;
import javaawtevent*;
import javaawtimageBufferedImage;
import javaio*;
import javaximageioImageIO;
import javautil*;
import javaxswing*;
public class Pintu extends JFrame{
private Image image buff; //原始图片缓存图片
private Point point = new Point( ); //记录第九块图片位置
private int[][] map = {{ }{ } { }}; //给破碎图片标号
private int sx sy; // 分割后每一个图片的宽度和高度
private Canvas canvas; //加载图片容器
private Graphics gs gb; //gs 画出Canvas gb画出buff图像
private boolean isRunning = false; //游戏是否正在进行
private JButton start = new JButton(开始新的游戏); // 按钮
private JButton show = new JButton(显示正确图片); //按钮
private JTextArea showTime = new JTextArea(显示时间);
private JTextArea showStep = new JTextArea(显示步骤);
private JPanel panel = new JPanel(); //装在上面个按钮
private int steps = ; // 记录移动的步骤
public Pintu(String title) { //构造方法
super(title);
try { //异常抛出
image = ImageIOread(new File(bgjpg)); //装载图片
} catch (IOException ex) {
exprintStackTrace();
}
initScreen(); //初始化canvas由于canvas 初始化较复杂所以单独写一个方法
buff = new BufferedImage( BufferedImageTYPE_INT_BGR);//三原色加载
gb = buffgetGraphics();
sx = imagegetWidth(this) / ;
sy = imagegetHeight(this) / ;
setLayout(new BorderLayout());
add(panel BorderLayoutSOUTH);
add(canvas BorderLayoutCENTER);
panelsetLayout(new GridLayout( ));
paneladd(start);
paneladd(show);
paneladd(showTime);
paneladd(showStep);
showTimesetEditable(false);
showStepsetEditable(false);
showTimesetFont(new Font(黑体 FontPLAIN ));
showStepsetFont(new Font(黑体 FontPLAIN ));
setSize( );
setResizable(false);
setDefaultCloseOperation(JFrameEXIT_ON_CLOSE);
}
void initScreen() {
canvas = new Canvas() {
public void paint(Graphics g) { //覆写canvas的paint 方法
gs = getGraphics(); //得到Canvas的Graphics
if (isRunning) {
drawScreen();
} else {
gdrawImage(image this);
gsetColor(Colorgray);
}
}
};
canvasaddMouseListener(new MouseAdapter() {
//覆写mousePressed 方法实现鼠标点击时图片移动
public void mousePressed(MouseEvent me) {
if (!isRunning) return; // 如果未运行说明图片未分割直接返回
int x = megetX() / sx y = megetY() / sy;//判断鼠标点击的图片在map中的编号
int fx = (int) pointgetX() fy = (int) pointgetY();//记录第九块图片(未显示图片)的位置
int canMove = Mathabs(fx x) + Mathabs(fy y); // 如鼠标点击位置与第九块图片(可移动的位置)相邻则canMove 必为
if (canMove != ) return; // canMove 不为不能移动图片
map[fx][fy] = map[x][y]; //点击图片坐标 赋给第九块图片
map[x][y] = ; //第九块图片给掉 点击图片
pointsetLocation(x y); //point 坐标改变
drawScreen(); //重绘屏幕实现图片移动
showStepsetText(移动步骤 + ++steps); //步骤加一
}
});
//为Start按钮添加事件
startaddActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
initMap();
drawScreen();
isRunning = true;
steps = ;
showStepsetText(移动步骤 + steps);
showsetLabel(显示正确图片);
}
});
//为show按钮添加事件
showaddActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (showgetLabel()equals(继续游戏)) {
drawScreen();
isRunning = true;
showsetLabel(显示正确图片);
} else {
gsdrawImage(image canvas);
isRunning = false;
showsetLabel(继续游戏);
}
}
});
}
void initMap() {
long time = SystemnanoTime();//得到系统当前时间 作为随机数种子
javautilRandom rnd = new javautilRandom(time);
int temp x y x y;
//随机交换图片
for (int i = ; i < ; i++) {
x = rndnextInt();
x = rndnextInt();
y = rndnextInt();
y = rndnextInt();
temp = map[x][y];
map[x][y] = map[x][y];
map[x][y] = temp;
}
//标记号图片(即空白图片)
outer:
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
if (map[i][j] == ) {
pointsetLocation(i j);
break outer;
}
}
void drawScreen() {
int sx sy sx sy dx dy dx dy;
int t t;
gbsetColor(Colorwhite);
gbclearRect( sx * sy * );//清空整个缓沖去图片
for (int x = ; x < ; x++)
for (int y = ; y < ; y++)
if(map[x][y] != ) {
// 目的地址
dx = x * sx; dy = y * sy; // 移动的左上角坐标
dx = dx + sx ; dy = dy + sy ; // 移动的右下角坐标
// 源地址
t = map[x][y] % ; t = map[x][y] / ;
sx = t * sx; sy = t * sy; // 移动的左上角图标
sx = sx + sx ; sy = sy + sy ; // 移动的右下角坐标
gbdrawImage(image dx dy dx dy sx sy sx sy Colorwhite canvas);//绘制缓沖区图片
}
gsdrawImage(buff canvas);//将缓沖区图片绘制到 canvas 上
}
public static void main(String[] args) {
Pintu pintu = new Pintu(拼图);
new Thread(pintu)start();
pintusetVisible(true);
}
}