从蓝杰做完总结,突然感觉生活平静了下来,但是要是学完了不去运用,慢慢地就全会忘记,所以大家在家也要加油哦!
上面这都是题外话,今天我们来做的是最近网上很火的手机游戏——POPSTAR。
游戏规则自然不用多说,只需点击两个或两个以上颜色相同的方块即可消除,没有时间限制。每次消除的砖块越多,所得到的分也越多。到最后如果剩下10个以下的砖块,还会有额外加分。
下面我们开始写程序:
首先我们建立一个常量接口来存储信息:
/**
* 常量接口
* @author Administrator
*
*/
public interface Config {
int SIZE = 30;// 砖块大小
int X = 10;// 砖块横向的个数
int Y = 10;// 砖块纵向的个数
int[][] array = new int[X][Y];// 砖块数组
// 红1 -1
// 黄2 -2
// 蓝3 -3
// 绿4 -4
// 桃5 -5
// 无0
JLabel[][] jparray = new JLabel[X][Y];// 面板数组
JTextField jtfscore = new JTextField("0", 5);//分数文本框
JTextField jtmax = new JTextField("0", 5);//最高分文本框
}
然后我们建立主窗体:
/**
* 主界面
*
* @author Administrator
*
*/
public class MainFrame extends JPanel implements Config {
private Random r = new Random();// 实例化随机数对象
private GameRule gr = new GameRule();// 实例化游戏规则对象
public static void main(String[] args) {
MainFrame mf = new MainFrame();
mf.initGUI();
}
/**
* 实例化窗体
*/
public void initGUI() {
final JFrame jf = new JFrame("POPSTAR");// 创建一个窗体
jf.setSize(new Dimension(400, 400));// 设置窗体大小
jf.setResizable(false);// 设置窗体不可调节
jf.setLocationRelativeTo(null);// 设置窗体位置居中
jf.setDefaultCloseOperation(3);// 设置窗体关闭按钮
jf.setIconImage(new ImageIcon("assets/icon36.png").getImage());// 设置窗体的图标
this.setLayout(null);// 设置面板布局为空
BrickListener bl = new BrickListener(this);// 实例化监听器
// 循环给面板添加标签
for (int i = 0; i < X; i++) {
for (int j = 0; j < Y; j++) {
jparray[i][j] = new JLabel() // 给标签设置重绘方法
{
public void paint(Graphics g) {
super.paint(g);
drawbricks(g);// 画砖块的方法
}
};
jparray[i][j].setBounds(i * SIZE, 72 + j * SIZE, SIZE, SIZE);// 给标签设置绝对位置
jparray[i][j].setOpaque(true);// 设置标签透明
jparray[i][j].addMouseListener(bl);// 给标签添加鼠标监听器
this.add(jparray[i][j]);// 将标签添加到面板上
}
}
this.setBackground(Color.black);// 设置面板背景为黑色
jf.add(this, BorderLayout.CENTER);// 将面板添加到窗体中部
JPanel jpeast = new JPanel();// 创建东边面板
jpeast.setLayout(new FlowLayout(FlowLayout.CENTER, 50, 20));// 设置布局为流式布局
jpeast.setBackground(Color.black);// 设置背景为黑色
jpeast.setPreferredSize(new Dimension(94, 0));// 设置东部面板的大小
JButton jbustart = new JButton("开始");// 实例化开始按钮
// 给西部面板添加监听器
jbustart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jtfscore.setText("0");// 初始化分数
for (int i = 0; i < X; i++) {
for (int j = 0; j < Y; j++) {
array[i][j] = r.nextInt(4) + 1;// 随机给标签添加颜色
}
jf.repaint();// 重回面板
}
}
});
JLabel jlscore = new JLabel("当前分数");// 实例化分数标签
jlscore.setFont(new Font("微软雅黑", Font.BOLD, 12));// 设置标签字体
jlscore.setForeground(Color.white);// 设置字体颜色
JLabel jlmax = new JLabel("最高分");// 实例化最高分标签
jlmax.setFont(new Font("微软雅黑", Font.BOLD, 12));// 设置字体属性
jlmax.setForeground(Color.white);// 设置字体颜色
jtfscore.setEditable(false);// 设置分数标签不可编辑
jtfscore.setHorizontalAlignment(JTextField.CENTER);// 设置水平居中
jtfscore.setOpaque(false);// 设置透明
jtfscore.setBorder(null);// 设置无边框
jtfscore.setForeground(Color.white);// 设置字体为白色
jtfscore.setFont(new Font("微软雅黑", Font.BOLD, 12));// 设置字体属性
jtmax.setEditable(false);// 设置分数标签不可编辑
jtmax.setOpaque(false);// 设置透明
jtmax.setBorder(null);// 设置无边框
jtmax.setHorizontalAlignment(JTextField.CENTER);// 设置水平居中
jtmax.setText(gr.getmaxscore() + "");// 设置内容
jtmax.setFont(new Font("微软雅黑", Font.BOLD, 12));// 设置字体属性
jtmax.setForeground(Color.white);// 设置字体为白色
// 将组件加到容器上
jpeast.add(jbustart);
jpeast.add(jlscore);
jpeast.add(jtfscore);
jpeast.add(jlmax);
jpeast.add(jtmax);
jf.add(jpeast, BorderLayout.EAST);// 将东部面板添加到窗体上
jf.setVisible(true);// 设置窗体可见
}
/**
* 画砖块的方法
*
* @param g
*/
private void drawbricks(Graphics g) {
for (int i = 0; i < X; i++) {
for (int j = 0; j < Y; j++) {
if (array[i][j] != 0) {
jparray[i][j].setIcon(new ImageIcon("image/" + array[i][j]
+ ".png"));
} else if (array[i][j] == 0) {
jparray[i][j].setIcon(null);
jparray[i][j].setBackground(Color.black);
}
}
}
}
}
下面我们给星星面板添加监听器:
/**
* 星星面板监听器
*
* @author Administrator
*
*/
public class BrickListener extends MouseAdapter implements Config {
private GameRule gr = new GameRule();// 实例化游戏规则对象
private MainFrame mf;// 声明窗体对象
private AudioClip audio;// 生命声音对象
/**
* 构造方法
*
* @param mf主面板
*/
public BrickListener(MainFrame mf) {
this.mf = mf;
}
/**
* 鼠标按下监听器
*/
public void mousePressed(MouseEvent e) {
JLabel jl = (JLabel) e.getSource();// 实例化标签
int x0 = jl.getBounds().x / SIZE;// 得到标签的x坐标
int y0 = (jl.getBounds().y - 72) / SIZE;// 得到标签的y坐标
if (array[x0][y0] < 0) // 如果已经被选中
{
int score = (int) (5 * Math.pow(gr.getscore(x0, y0), 2));// 得到此方块的分数
gr.clean();// 将方块清除并落下
mf.repaint();// 重回面板
// 播放方块破裂的声音
try {
audio = Applet.newAudioClip(new File("assets/broken.wav")
.toURL());
audio.play();
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
jtfscore.setText(Integer.parseInt(jtfscore.getText()) + score + "");// 记录分数文本框
if (Integer.parseInt(jtfscore.getText()) > Integer.parseInt(jtmax
.getText())) // 如果此时分数大于最高分
{
gr.savamaxscore();// 保存最高分到文件
jtmax.setText(Integer.parseInt(jtfscore.getText()) + "");// 设置当前分数到最高分
}
if (gr.judge()) // 如果游戏结束
{
jtfscore.setText(Integer.parseInt(jtfscore.getText())
+ gr.getresidue() + "");// 添加附加分数
if (Integer.parseInt(jtfscore.getText()) > Integer
.parseInt(jtmax.getText())) // 如果此时分数大于最高分
{
gr.savamaxscore();// 保存最高分到文件
jtmax.setText(Integer.parseInt(jtfscore.getText()) + "");// 设置最高分
}
// 播放游戏结束声音
try {
audio = Applet.newAudioClip(new File("assets/win.wav")
.toURL());
audio.play();
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
JOptionPane.showMessageDialog(null, "游戏结束!");// 弹出游戏结束对话框
}
} else if (array[x0][y0] > 0)// 如果该标签没有被选中
{
gr.returnback();// 重置被选中的标签
// 播放选择声音
try {
audio = Applet.newAudioClip(new File("assets/select.wav")
.toURL());
audio.play();
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
// 如果该标签只连接一个
if (gr.find(array[x0][y0], x0, y0) == 1) {
gr.returnback();// 重置被选中标签
}
}
}
}
最后,也是最重要的一步,就是建立游戏规则,我们建立游戏规则类:
/**
* 记录游戏规则
* @author Administrator
*
*/
public class GameRule implements Config {
/**
* 自动掉落
*/
public void drop() {
for (int i = 0; i < X; i++) {
for (int j = 1; j < Y; j++) {
// 如果上一行有空格
if (array[i][j] == 0) {
// 把那一列向下移空格数
for (int k = j; k > 0; k--) {
array[i][k] = array[i][k - 1];
}
array[i][0] = 0;
}
}
}
turnleft();
}
/**
* 右边的自动左移
*/
public void turnleft() {
for (int i = 0; i < X - 1; i++) {
if (sumline(i) == 0) {
int line = 1;
for (int k = i + 1; k < X; k++) {
if (sumline(k) == 0) {
line++;
} else {
break;
}
}
for (int k = i; k < X - line; k++) {
for (int j = 0; j < Y; j++) {
array[k][j] = array[k + line][j];
}
}
for (int j = 0; j < Y; j++) {
array[X - 1][j] = 0;
}
}
}
}
/**
* 求第i列的和
*
* @param i列数
* @return
*/
public int sumline(int i) {
int sum = 0;
for (int j = 0; j < Y; j++) {
sum += array[i][j];
}
return sum;
}
/**
* 得到这个砖块的个数
*
* @param x
* @param y
* @return
*/
public int getscore(int x, int y) {
int count = 0;
for (int i = 0; i < X; i++) {
for (int j = 0; j < Y; j++) {
if (array[i][j] < 0) {
count++;
}
}
}
return count;
}
/**
* 根据颜色将砖块及周围的都变成相反数
*
* @param color
* @param x
* @param y
* @return
*/
public int find(int color, int x, int y) {
int count = 0;
if (array[x][y] == color) {
count++;
array[x][y] = -array[x][y];
} else {
return 0;
}
if (x >= 1) {
count += find(color, x - 1, y);
}
if (x < X - 1) {
count += find(color, x + 1, y);
}
if (y >= 1) {
count += find(color, x, y - 1);
}
if (y < Y - 1) {
count += find(color, x, y + 1);
}
return count;
}
/**
* 判断输赢
*
* @return
*/
public boolean judge() {
for (int i = 0; i < X; i++) {
for (int j = 0; j < Y; j++) {
if (array[i][j] != 0) {
if (i >= 1) {
if (array[i - 1][j] == array[i][j]) {
return false;
}
}
if (j >= 1) {
if (array[i][j - 1] == array[i][j]) {
return false;
}
}
if (i < X - 1) {
if (array[i + 1][j] == array[i][j]) {
return false;
}
}
if (j < Y - 1) {
if (array[i][j + 1] == array[i][j]) {
return false;
}
}
}
}
}
return true;
}
/**
* 保存最高分到文件
*
* @throws Exception
*/
public void savamaxscore() {
try {
File file = new File("src/bricks/save");
if (!file.exists()) {
file.createNewFile();
}
OutputStream os = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(os);
dos.writeInt(Integer.parseInt(jtfscore.getText()));
dos.flush();
os.close();
} catch (Exception e) {
}
}
/**
* 从文件中读取最高分
*
* @return 最高分
* @throws Exception
*/
public int getmaxscore() {
try {
File file = new File("src/bricks/save");
if (!file.exists()) {
file.createNewFile();
}
InputStream is = new FileInputStream(file);
DataInputStream dis = new DataInputStream(is);
int score = dis.readInt();
jtmax.setText(score + "");
dis.close();
is.close();
return score;
} catch (Exception e) {
}
return 0;
}
/**
* 将选中的砖块清除
*/
public void clean() {
for (int i = 0; i < X; i++) {
for (int j = 0; j < Y; j++) {
if (array[i][j] < 0) {
array[i][j] = 0;
}
}
}
drop();
}
/**
* 将选中的砖块还原
*/
public void returnback() {
for (int i = 0; i < X; i++) {
for (int j = 0; j < Y; j++) {
if (array[i][j] < 0) {
array[i][j] = -array[i][j];
}
}
}
}
/**
* 得到最后要加的分数
*
* @return 最后要加的分数
*/
public int getresidue() {
int count = 0;
for (int i = 0; i < X; i++) {
for (int j = 0; j < Y; j++) {
if (array[i][j] > 0) {
count++;
}
}
}
int a[] = { 2000, 1980, 1920, 1820, 1680, 1500, 1280, 1020, 720, 380 };
if (count < 10) {
return a[count];
}
return 0;
}
}
这样,我们做的简单的POPSTAR就完成了!声音和图片我都在附件中给出,大家自己动手做一做吧~