主类——————Game.java
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;public class Game extends JFrame {
private GameCanvas canvas=new GameCanvas();
private GameTip tip=new GameTip();
private GameBlock block;
private boolean isPlaying=true;
//定义菜单栏
private JMenuBar menuBar = new JMenuBar();
private JMenu mGame = new JMenu("游戏"),
mSetting = new JMenu("颜色"),
mStyle = new JMenu("风格"),
mHelp = new JMenu("帮助");private JMenuItem mNewGame = new JMenuItem("新游戏"),
mPlay = new JMenuItem("开始"),
mPause = new JMenuItem("暂停"),
mResume = new JMenuItem("继续"),
mHero=new JMenuItem("英雄榜"),
mExit = new JMenuItem("退出");private JMenuItem mSetBlockColor = new JMenuItem("设置方块颜色"),
mSetBackgroundColor=new JMenuItem("设置背景颜色"),
mInitializeColor=new JMenuItem("还原为初始颜色");private JCheckBoxMenuItem
mWindows = new JCheckBoxMenuItem("Windows"),
mMotif = new JCheckBoxMenuItem("Motif"),
mMetal = new JCheckBoxMenuItem("Metal", true);private JMenuItem mReadme=new JMenuItem("说明"),
mAbout=new JMenuItem("关于");//构造函数
public Game() {//设置标题,窗口的大小和起始坐标
super("俄罗斯方块");
setSize(330, 422);
setLocation((Toolkit.getDefaultToolkit().getScreenSize().width - getSize().width) / 2,
(Toolkit.getDefaultToolkit().getScreenSize().height - getSize().height) / 2);
//布局管理器
Container container = getContentPane();
container.setLayout(new BorderLayout(2, 0));
getContentPane().add(canvas,BorderLayout.CENTER);
getContentPane().add(tip,BorderLayout.EAST); //添加菜单栏
menuBar.add(mGame);
menuBar.add(mSetting);
menuBar.add(mStyle);
menuBar.add(mHelp); mGame.add(mPlay);
mGame.add(mPause);
mGame.add(mResume);
mGame.add(mNewGame);
mGame.addSeparator();
mGame.add(mHero);
mGame.addSeparator();
mGame.add(mExit); mSetting.add(mSetBlockColor);
mSetting.add(mSetBackgroundColor);
mSetting.addSeparator();
mSetting.add(mInitializeColor); mStyle.add(mWindows);
mStyle.add(mMotif);
mStyle.add(mMetal); mHelp.add(mReadme);
mHelp.add(mAbout); setJMenuBar(menuBar); //添加监听器
addKeyListener(new KeyListener()); mNewGame.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
}
});
mPlay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
mPlay.setEnabled(false);
Thread thread=new Thread(new GameRun());
thread.start();
}
});
mPause.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
}
});
mResume.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
}
});
mHero.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
}
});
mExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
System.exit(0);
}
});
mSetBlockColor.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
Color newBlockColor = JColorChooser.showDialog(
Game.this,"设置方块颜色",
canvas.getBlockColor());
if (newBlockColor != null)
canvas.setBlockColor(newBlockColor);
}
});
mSetBackgroundColor.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
Color newBackgroundColor = JColorChooser.showDialog(
Game.this, "设置方块颜色",
canvas.getBackgroundColor());
if (newBackgroundColor != null)
canvas.setBackgroundColor(newBackgroundColor);
}
});
mInitializeColor.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
canvas.setBackgroundColor(Color.darkGray);
canvas .setBlockColor(Color.orange);
}
});
mWindows.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
setStyle("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
canvas.adjust();
mWindows.setState(true);
mMetal.setState(false);
mMotif.setState(false);
}
});
mMotif.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
setStyle("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
canvas.adjust();
mWindows.setState(false);
mMetal.setState(false);
mMotif.setState(true);
}
});
mMetal.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
setStyle("javax.swing.plaf.metal.MetalLookAndFeel");
canvas.adjust();
mWindows.setState(false);
mMetal.setState(true);
mMotif.setState(false);
}
});
mReadme.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
}
});
mAbout.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
}
});
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent ce) {
canvas.adjust();
}
});
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
setVisible(true);
canvas.adjust();
}public void setStyle(String style) {
try {
UIManager.setLookAndFeel(style);
SwingUtilities.updateComponentTreeUI(this);
} catch (Exception e) {
}
}//内部类——游戏运行过程
private class GameRun implements Runnable {
public void run() {
int style = GameBlock.STYLES[(int) (Math.random() * 7)][(int) (Math.random() * 4)];
while (isPlaying) {
if (block != null) { //第一次循环时,block为空
if (block.isAlive()) {
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
continue;
}
} checkFullLine(); if (isGameOver()) { //检查游戏是否应该结束了
reportGameOver();
return;
} block = new GameBlock(style, canvas);
block.start();
style = GameBlock.STYLES[(int) (Math.random() * 7)][(int) (Math.random() * 4)];
tip.setStyle(style);
}
}// 检测是否存在满行,若存在,则清除
public void checkFullLine(){
for (int i = 0; i < canvas.getCanvasRows(); i++) {
int row = -1;
boolean fullLine = true;
for (int j = 0; j < canvas.getCanvasCols(); j++) {
if (!canvas.getBox(i,j).getBoxColor()) {
fullLine = false;
break;
}
}
if (fullLine) {
row = i;
canvas.clearLine(row);
}
}
}
//判断游戏是否结束
private boolean isGameOver() {
for (int i = 0; i < canvas.getCanvasCols(); i++) {
GameBox box = canvas.getBox(0, i);
if (box.getBoxColor()) return true;
}
return false;
}}//报告游戏结束
public void reportGameOver(){
JOptionPane.showMessageDialog(this, "Game Over!");
}//内部类——键盘适配器
private class KeyListener extends KeyAdapter {
public void keyPressed(KeyEvent ke) {
if(isPlaying==false)
return;
switch (ke.getKeyCode()) {
case KeyEvent.VK_DOWN:
block.moveDown();
break;
case KeyEvent.VK_LEFT:
block.moveLeft();
break;
case KeyEvent.VK_RIGHT:
block.moveRight();
break;
case KeyEvent.VK_UP:
block.turnNext();
break;
case KeyEvent.VK_SPACE:
while(block.moveDown())
{
}
break;
default:
break;
}
}
}public static void main(String[] args) {
new Game();
}
}
上面是部分代码,因为字数限制,下面再接着发代码,谢谢!问题:
1、类Game中的内部类GameRun,if (block != null) { if (block.isAlive())……}}的作用是什么?
2、问题1中,currentThread()指的是哪儿个线程?thread,block?
3、第1个方块后,接着出现第2个方块,那么第1个方块的对象是否还存在?若存在,在消行后还存在否?
4、设置颜色的菜单项不能独占进程?在设置颜色时,游戏结束,产生无法关闭对话框的问题。
5、在游戏没有开始的时候,先改变背景颜色,然后还原初始颜色,画布颜色不能瞬间还原,只能开始游戏才能还原,如何解决这个缺点?
5、为什么添加了GameTip面板,键盘就不能控制方块了?而不添加GameTip,就能控制方块
6、为什么TipCancas定义的tipcanvas不能定义为static?
类——GameBox.java
import java.awt.Dimension;
public class GameBox implements Cloneable {
private boolean iscolor;
private Dimension size = new Dimension();/*
* 构造函数
*/
public GameBox(boolean iscolor) {
this.iscolor = iscolor;
}/*
* 判断方格是前景色还是背景色,true表示前景色,false表示背景色
*/
public boolean getBoxColor() {
return iscolor;
}/*
* 设置方格颜色
*/
public void setBoxColor(boolean iscolor) {
this.iscolor = iscolor;
}/*
* 获取方格的尺寸
*/
public Dimension getBoxSize() {
return size;
}/*
* 设置方格尺寸
*/
public void setSize(Dimension size) {
this.size = size;
}
public Object clone() {
Object cloned = null;
try {
cloned = super.clone();
} catch (Exception exception) {
exception.printStackTrace();
}return cloned;
}
}类——GameCanvas.java
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.*;
import javax.swing.border.EtchedBorder;public class GameCanvas extends JPanel {
private Color backgroundColor = Color.darkGray, //背景颜色
blockColor = Color.orange; //方块颜色
private int boxWidth=18,//方块的边长(宽)
boxHeight=18, //方块的边长(高)
ROWS=20, //画布的行数
COLS=12; //画布的列数private GameBox[][] boxes=new GameBox[ROWS][COLS];
// 构造函数
public GameCanvas() {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
boxes[i][j] = new GameBox(false);
}
}
setBorder(new EtchedBorder(
EtchedBorder.RAISED, Color.white, new Color(148, 145, 140)));
}//获取方格,若超界,返回null
public GameBox getBox(int row, int col) {
if (row < 0 || row > boxes.length - 1
|| col < 0 || col > boxes[0].length - 1)
return null;
return (boxes[row][col]);
}//获取画布的行数
public int getCanvasRows(){
return ROWS;
}//获取画布的列数
public int getCanvasCols(){
return COLS;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
g.setColor(boxes[i][j].getBoxColor() ? blockColor : backgroundColor);
g.fill3DRect(j * boxWidth, i * boxHeight,
boxWidth, boxHeight, true);
}
}
}
//清除一行,并将该行的上面一行克隆到被消的一行
public synchronized void clearLine(int row) {
for (int i = row; i > 0; i--) {
for (int j = 0; j < COLS; j++)
boxes[i][j] = (GameBox) boxes[i - 1][j].clone();
}
repaint();
} //调整画布的大小
public void adjust(){
boxHeight = getSize().height/ROWS;
boxWidth = getSize().width/COLS;
}//获取方块颜色
public Color getBlockColor(){
return blockColor;
}
//设置方块颜色
public void setBlockColor(Color blockcolor){
blockColor=blockcolor;
}
//获取背景颜色
public Color getBackgroundColor(){
return backgroundColor;
}
//设置背景颜色
public void setBackgroundColor(Color backgroundcolor){
backgroundColor=backgroundcolor;
}
}public class GameBlock extends Thread {
public final static int[][] STYLES = {
{0x0f00, 0x4444, 0x0f00, 0x4444}, // 长条型
{0x0660, 0x0660, 0x0660, 0x0660}, // 方块
{0x04e0, 0x0464, 0x00e4, 0x04c4}, // 'T'型
{0x2640, 0xc600, 0x2640, 0xc600}, // 'Z'型
{0x4620, 0x6c00, 0x4620, 0x6c00}, // 反'Z'型
{0x6220, 0x1700, 0x2230, 0x0740}, // '7'型
{0x6440, 0x0e20, 0x44c0, 0x8e00}, // 反'7'型
};
private GameCanvas canvas;
private GameBox[][] boxes = new GameBox[4][4];
private int style, //方块的类型
y=-1, //纵坐标位置
x=5; //横坐标位置
private boolean moving=true,
pausing=false;
public GameBlock(int style,GameCanvas canvas) {
this.style = style;
this.canvas = canvas;int key = 0x8000;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
boolean isColor = ((style & key) != 0);
boxes[i][j] = new GameBox(isColor);
key >>= 1;
}
}
display();
}
//清除方块
private void earse() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (boxes[i][j].getBoxColor()) {
GameBox box = canvas.getBox(i + y, j + x);
if (box == null) continue;
box.setBoxColor(false);
}
}
}
}
//显示方块
private void display() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (boxes[i][j].getBoxColor()) {
GameBox box = canvas.getBox(y + i, x + j);
if (box == null) continue;
box.setBoxColor(true);
}
}
}
}
public void moveLeft() {
moveTo(y, x - 1);
}
//块向右移动一格
public void moveRight() {
moveTo(y, x + 1);
}//块向下落一格
public boolean moveDown() {
if(moveTo(y + 1, x))
return true;
else
return false;
}
// 块变型
public void turnNext() {
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 4; j++) {
if (STYLES[i][j] == style) {
int newStyle = STYLES[i][(j + 1) % 4];
turnTo(newStyle);
return;
}
}
}
}//判断是否可以移动
private boolean isMoveAble(int newRow, int newCol) {
earse();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (boxes[i][j].getBoxColor()) {
GameBox box = canvas.getBox(newRow + i, newCol + j);
if (box == null || (box.getBoxColor())) {
display();
return false;
}
}
}
}
display();
return true;
}//移动
private synchronized boolean moveTo(int newRow, int newCol) {
if (!isMoveAble(newRow, newCol) || !moving) return false;earse();
y = newRow;
x = newCol;display();
canvas.repaint();return true;
} //是否可以变换类型
private boolean isTurnAble(int newStyle) {
int key = 0x8000;
earse();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if ((newStyle & key) != 0) {
GameBox box = canvas.getBox(y + i, x + j);
if (box == null || box.getBoxColor()) {
display();
return false;
}
}
key >>= 1;
}
}
display();
return true;
} /*
* 变型
*/
private boolean turnTo(int newStyle) {
if (!isTurnAble(newStyle) || !moving) return false;
earse();
int key = 0x8000;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
boolean isColor = ((newStyle & key) != 0);
boxes[i][j].setBoxColor(isColor);
key >>= 1;
}
}
style = newStyle;
display();
canvas.repaint();
return true;
}
public void run(){
while(moving)
{
try
{
sleep(500);
if(pausing==false)
moving = ( moveTo(y + 1,x) && moving );
}catch(InterruptedException e)
{
e.printStackTrace();
}
}
}}PS:在Game类中,下列两段代码是加颜色的,在代码中不能加颜色,所以直接复制调试会发生错误,也是我所咨询的第1、2、6问题的所在位置getContentPane().add(tip,BorderLayout.EAST);
if (block != null) { //第一次循环时,block为空
if (block.isAlive()) {
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
continue;
}
backgroundColor = backgroundcolor;
this.repaint();
}
我最后修改为:
mInitializeColor.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
canvas.setBackgroundColor(Color.darkGray);
canvas .setBlockColor(Color.orange);
canvas.repaint();
}
});谢谢你的帮助,我已经解决了这个问题,添加repaint(),让画布重新绘制一遍,呵呵;下过了,看了,他做得好复杂啊我编的这个也是从网上下的,然后自己学着编写的代码,除了引用了几个重要的算法,其他的几乎都不一样了,可问题就随即出现了。不好意思,代码不全,少发了一个类
类——GameTip.javaimport java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EtchedBorder;public class GameTip extends JPanel{
//定义4个面板:提示面板,信息面板,按钮面板,提示画布
private JPanel pTip=new JPanel(new BorderLayout());
private static JPanel pInfo = new JPanel(new GridLayout(6, 1));
private JPanel pButton = new JPanel(new GridLayout(5, 1));
private TipCanvas tipcanvas=new TipCanvas();
//定义文本框和按钮
private JTextField tLevel = new JTextField("1"),
tScore = new JTextField("0"),
tFloor = new JTextField("0");
private JButton bPlay = new JButton("开始"),
bPause = new JButton("暂停"),
bUp=new JButton("增加难度"),
bDown=new JButton("降低难度"),
bExit = new JButton("退出");
//定义引用
private Game game;
//构造函数
GameTip(){
setLayout(new GridLayout(3,1));
add(pTip);
add(pInfo);
add(pButton);
pTip.add(new JLabel("下一个方块"),BorderLayout.NORTH);
pTip.add(tipcanvas,BorderLayout.CENTER);
pInfo.add(new JLabel("难度"));
pInfo.add(tLevel);
pInfo.add(new JLabel("得分"));
pInfo.add(tScore);
pInfo.add(new JLabel("层数"));
pInfo.add(tFloor);
pInfo.setBorder(new EtchedBorder( EtchedBorder.LOWERED,Color.white,
new Color(148, 145, 140) ));
tLevel.setEditable(false);
tScore.setEditable(false);
tFloor.setEditable(false);
pButton.add(bPlay);
pButton.add(bPause);
pButton.add(bUp);
pButton.add(bDown);
pButton.add(bExit);
pButton.setBorder(new EtchedBorder( EtchedBorder.LOWERED,Color.white,
new Color(148, 145, 140) ));
bPlay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
}
});
bPause.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
}
});
bUp.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
}
});
bDown.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
}
});
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent ce) {
}
});
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent ce) {
tipcanvas.adjust();
}
});
}
public void setStyle(int style) {
tipcanvas.setStyle(style);
}
//内部类——提示面板画布
private class TipCanvas extends JPanel{
private Color backgroundColor = Color.darkGray, //背景颜色
blockColor = Color.orange; //方块颜色
private int boxWidth=18, //方块的边长(宽)
boxHeight=18, //方块的边长(高)
style;
private GameBox[][] boxes=new GameBox[4][4];
//构造函数
TipCanvas(){
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
boxes[i][j] = new GameBox(false);
}
}
setBorder(new EtchedBorder(
EtchedBorder.RAISED, Color.white, new Color(148, 145, 140)));
}
//设置提示面板的方块类型
public void setStyle(int style) {
this.style = style;
repaint();
}
//调整提示面板画布的大小
public void adjust() {
boxWidth = getSize().width / 4;
boxHeight = getSize().height / 4;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int key = 0x8000;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
g.setColor((((key & style) != 0) ? blockColor : backgroundColor));
g.fill3DRect(j * boxWidth, i * boxHeight,
boxWidth, boxHeight, true);
key >>= 1;
}
}
}
}}
1、类Game中的内部类GameRun,if (block != null) { if (block.isAlive())……}}中Thread.currentThread().sleep(100);
如果没有在类Game中添加了GameTip面板,并对sleep(100)修改为sleep(10000),会有明显的变化,也就是在出现第2个方块的时候,会延迟10秒钟,但如果在类Game中添加了GameTip面板的话,即使修改了,也没有变化,这是什么原因造成的?
2、问题1中,currentThread()指的是哪儿个线程?thread,block?
GameBlock extends Thread;同时
类Game的菜单项“开始”——
mPlay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
mPlay.setEnabled(false);
Thread thread=new Thread(new GameRun());
thread.start();
}
});)
3、用类GameBlock新建一个方块,以什么来判断该方块的存亡?
4、设置颜色的菜单项不能独占进程?在设置颜色时,游戏结束,产生无法关闭对话框的问题。如果解决该问题?
5、为什么在类Game中添加了GameTip面板,键盘就不能控制方块了?而不添加GameTip,就能控制方块。
为什么键盘监控事件没有响应????????????????????????????????????????????????????????????????????????
“5、为什么在类Game中添加了GameTip面板,键盘就不能控制方块了?而不添加GameTip,就能控制方块。 ”
1、类Game中的内部类GameRun,if (block != null) { if (block.isAlive())……}}中Thread.currentThread().sleep(100);
如果没有在类Game中添加了GameTip面板,并对sleep(100)修改为sleep(10000),会有明显的变化,也就是在出现第2个方块的时候,会延迟10秒钟,但如果在类Game中添加了GameTip面板的话,即使修改了,也没有变化,这是什么原因造成的?
2、问题1中,currentThread()指的是哪儿个线程?thread,block?
GameBlock extends Thread;同时
类Game的菜单项“开始”——
mPlay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
mPlay.setEnabled(false);
Thread thread=new Thread(new GameRun());
thread.start();
}
});)
3、用类GameBlock新建一个方块,以什么来判断该方块的存亡?
4、设置颜色的菜单项不能独占进程,在设置颜色时,游戏结束,产生无法关闭对话框的问题。如果解决该问题?
if (block.isAlive()) {
try {
Thread.currentThread().sleep(100);
} catch (Exception ie) {
ie.printStackTrace();
}
continue;
}
}
既然已经进到while里面了,当前的thread指的就是GameRun的就是你说的thread,block中的thread
try {
Thread.currentThread().sleep(10000);
} catch (Exception ie) {
ie.printStackTrace();
}
continue;
}
thread线程是判断block是否活动,如果不在活动状态,则新建一个block(当方块移动到不能再移动的时候,它就会销毁【while (moving)里的moving==false】),否则等100s以后再判断,这个跟有没有GameTip好像没有关系
for (int j = 0; j < 4; j++) {
if (boxes[i][j].getBoxColor()) {
GameBox box = canvas.getBox(newRow + i, newCol + j);
if (box == null || (box.getBoxColor())) {
display();
return false;
}
}
}
}
当方块要移动到目标地时,它就会判断将要移动到的那个区域是否有方块(box.getBoxColor()==true)或是否到底部了(box==null),满足一个条件就说明方块不能再移动了,就返回false,此时有moving = (moveTo(y + 1, x) && moving);所以moving=false;block进程就结束了(while(moving)),这时方块也没了,就要在thread里被重新初始化(block = new GameBlock(style, canvas);