我的第2个JAVA作品----扫雷游戏
发表于:2007-07-04来源:作者:点击数:
标签:
***************************编程思路******************************* 这个 游戏 大煎都很熟悉的,鼠标不断的点击雷盒,如果是雷,满盘皆输,如果不是雷 则打开当前雷盒,显示出周围雷的个数。如果这个雷盒周围一圈都不是雷,则应该将 周围的雷盒都打开,并依
***************************编程思路*******************************
这个
游戏大煎都很熟悉的,鼠标不断的点击雷盒,如果是雷,满盘皆输,如果不是雷
则打开当前雷盒,显示出周围雷的个数。如果这个雷盒周围一圈都不是雷,则应该将
周围的雷盒都打开,并依次按照上面的规则迭代循环下去,这个循环应该结束在遇到
含有雷的雷盒那里,或者所有的雷盒都已经探测完,编程的难点也就在这里,大家多
留意下bones_box类的鼠标左键点击事件和bones_triggers()过程,特别要注意
is_clicked这个布尔值,正是由于他的使用才使得迭代得以顺利进行
至于布雷,我是采用随即的方式,有人说微软的布雷很有讲究的,那个算法我就不知
道了,好象还是个很高深的数学难题,你们谁吃饱了没事就研究下吧
*******************************************************************/
import
java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.*;
public class bones_game //游戏主类,初始化界面,生成雷区
{
public static int clicked_counter = 450;//计数器,减至0时表示扫雷成功结束
JFrame MainFrame;//主窗体
JButton button_refresh;
bones_box bones_box[];//雷盒
public bones_game()//构造方法
{
int i;
bones_box = new bones_box[450];
button_refresh = new JButton("重新开始游戏");
MainFrame = new JFrame("扫雷游戏");
MainFrame.getContentPane().setLayout(new BorderLayout());
Container box_grid = new Container();
box_grid.setLayout(new GridLayout(15,30));
for (i = 0;i < 450;i++)//画出所有雷盒
{
bones_box[i] = new bones_box(i,this);
box_grid.add(bones_box[i]);
}
bones_sts_refresh();//刷新信息
MainFrame.getContentPane().add(button_refresh,BorderLayout.NORTH);
MainFrame.getContentPane().add(box_grid,BorderLayout.CENTER);
MainFrame.pack();
MainFrame.show();
MainFrame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
button_refresh.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
bones_sts_refresh();
}
});
}
public static void main(String[] argus)
{
new bones_game();//启动游戏
}
public void bones_sts_refresh()//刷新所有雷盒,布置信息
{
int i,j;
clicked_counter = 450;
for (i = 0;i < 450;i++)
{
bones_box[i].setEnabled(true);
bones_box[i].is_clicked = false;
bones_box[i].setVisible(true);
bones_box[i].is_bone = false;
bones_box[i].number_of_real_bone = 0;
bones_box[i].flag = "";
bones_box[i].setText(" ");
bones_box[i].setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED,Color.white,Color.black));//初始状态为突起
bones_box[i].setBackground(Color.gray);
}
for (i = 0;i < 90;i++)//随机布雷
{
bones_box[(int)(Math.random() * 449)].is_bone = true;
}
for (i = 0;i < 450;i++)//依次统计每个雷盒周围雷的个数
{
if (bones_box[i].is_bone)//雷盒中有雷,不参与叠带,计数器自减
{
bones_game.clicked_counter--;
}
for (j = 0;j < 8;j++)
{
if (bones_box[i].bones_around[j] == 777)
{
continue;
}
if (bones_box[bones_box][i].bones_around[j]].is_bone)
{
bones_box[i].number_of_real_bone++;
}
}
//打开此代码,可以看看雷的分布情况
//if (bones_box[i].is_bone)
//{
// bones_box[i].setText("●");
//}
}
}
public void game_lose()
{
int type,k;
for (k = 0;k < 450;k++)
{
if (bones_box[k].is_bone)
{
bones_box[k].setText("●");
}
}
type=JOptionPane.INFORMATION_MESSAGE;
JOptionPane.showMessageDialog(MainFrame,"很抱歉,你输了,谢谢!!!","提示信息",type);
bones_sts_refresh();
}
public void game_win()
{
int type;
type=JOptionPane.INFORMATION_MESSAGE;
JOptionPane.showMessageDialog(MainFrame,"严重恭喜,你赢了,傻鸟!!!","提示信息",type);
bones_sts_refresh();
}
}
class bones_box extends JTextField//雷盒类
{
public boolean is_clicked = false;//是否检查标志
public boolean is_bone = false;//是否是雷
public int bone_id;//雷盒标识号
public int[] bones_around;//周围雷盒的BONE_ID,以数组形式记录
public bones_game frame_handle;//游戏主类句柄
public int number_of_real_bone;//周围一圈雷的总数目
public String flag;//右键点击标识 "↑":标识为雷 "?":不确定状态 "":空
public bones_box(int i,bones_game handle)//构造方法
{
super();
this.bone_id = i;
//this.setEnabled(false);
this.frame_handle = handle;
this.setCursor(frame_handle.MainFrame.getCursor());
this.setForeground(Color.cyan);
this.bones_around = find_bones_around();//获取周围雷盒的ID,存入bones_around数组
this.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
int j;
/*-------------------双键齐下----------------------
捕捉效果很差,稍有偏差就会引发下面的左键或右键事件,不知道大家
有没有比较好的能精确的捕捉这个事件的办法,象微软的那样,就算
指头没有同时击键,也能捕捉得到,如果找到,可以封装下面代码,并
在DEV上告诉我一声
{
int k,li_num;
if (is_clicked)
{
for(k = 0,k < 8,k++)
{
if (frame_handle.bones_box[bones_around][k]].flag == "↑")
{
li_num++;
}
}
if (li_num == number_of_real_bone)
{
for (k = 0,k < 8,k++)
{
if (frame_handle.bones_box[bones_around][k]].flag == "↑")
{
continue;
}
if (frame_handle.bones_box[bones_around][k]].is_clicked)
{
continue;
}
if (frame_handle.bones_box[bones_around][k]].is_bone)//失败
{
frame_handle.game_lose();
return;
}
frame_handle.bones_box[bones_around][k]].setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED,Color.white,Color.black));//雷盒凹下显示
frame_handle.bones_box[bones_around][k]].setBackground(Color.WHITE);
frame_handle.bones_box[bones_around][k]].setEnabled(false);
frame_handle.bones_box[bones_around][k]].setText(Integer.toString(frame_handle.bones_box[bones_around][k]].number_of_real_bone));//提示周围有多少个雷
frame_handle.bones_box[bones_around][k]].is_clicked = true;//标记本雷盒以探测过,避免以后相互迭带产生无限循环
bones_game.clicked_counter--;
}
}
}
else
{
}
}
----------------------------------------------------*/
if(e.getButton()==e.BUTTON1)//左键点击
{
if (is_clicked)
{
return;
}
if(flag == "↑")//标识号为雷,点击直接返回
{
return;
}
if (is_bone)//是雷,提示游戏失败
{
frame_handle.game_lose();
return;
}
setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED,Color.white,Color.black));//雷盒凹下显示
setBackground(Color.WHITE);
setEnabled(false);
setText(Integer.toString(number_of_real_bone));//提示周围有多少个雷
is_clicked = true;//标记本雷盒以探测过,避免以后相互迭带产生无限循环
bones_game.clicked_counter--;
bones_triggers();//触发过程
if (bones_game.clicked_counter <= 0)
{
frame_handle.game_win();
}
}
if(e.getButton()==e.BUTTON3)//右键
{
if (is_clicked)
{
return;
}
if (flag == "")
{
setText("↑");
flag = "↑";
return;
}
if (flag == "↑")
{
setText("?");
flag = "?";
return;
}
if (flag == "?")
{
setText("");
flag = "";
return;
}
}
}
});
}
public int[] find_bones_around()//根据自己的BONE_ID,找出周围一圈雷盒的ID
{
int[] bones_around = new int[8];
int i,li_row,li_column;
li_row = bone_id / 30;
li_column = bone_id -li_row * 30;
bones_around[0] = li_column - 1 + (li_row - 1) * 30;
bones_around[1] = li_column + (li_row - 1) * 30;
bones_around[2] = li_column + 1 + (li_row - 1) * 30;
bones_around[3] = li_column + 1 + li_row * 30;
bones_around[4] = li_column + 1 + (li_row + 1) * 30;
bones_around[5] = li_column + (li_row + 1) * 30;
bones_around[6] = li_column - 1 + (li_row + 1) * 30;
bones_around[7] = li_column - 1 + li_row * 30;
if (li_column == 0)//第一列的特殊处理,因为他的左边为空,在此一律标记为777
{
bones_around[0] =777;
bones_around[6] = 777;
bones_around[7] = 777;
}
if (li_column == 29)//最后一列特殊处理,因为他的右边为空
{
bones_around[2] = 777;
bones_around[3] = 777;
bones_around[4] = 777;
}
for (i = 0;i < bones_around.length;i++)
{
if (bones_around[i] < 0 | bones_around[i] > 449)
{
bones_around[i] = 777;
}
}
return bones_around;
}
public void bones_triggers()//触发过程
{
int k;
boolean is_all_free = true;
for (k = 0;k < 8;k++)
{
if (bones_around[k] == 777)
{
continue;
}
if (frame_handle.bones_box[bones_around][k]].is_bone)
//判断周围是否全部不是雷,如果条件不成立,就没有自动触发周围雷盒的必要,留给玩家自己去踩
{
is_all_free = false;
break;
}
}
if (is_all_free)//条件成立,开始自动探测周围雷盒
{
for (k = 0;k < 8;k++)
{
if (bones_around[k] == 777)
{
continue;
}
if (frame_handle.bones_box[bones_around][k]].flag == "↑")//已标记为雷,跳过
{
continue;
}
if (frame_handle.bones_box[bones_around][k]].is_clicked)//已探测,跳过
{
continue;
}
bones_game.clicked_counter--;
frame_handle.bones_box[bones_around][k]].setEnabled(false);
frame_handle.bones_box[bones_around][k]].setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED,Color.white,Color.black));
frame_handle.bones_box[bones_around][k]].setBackground(Color.WHITE);
frame_handle.bones_box[bones_around][k]].setText(Integer.toString(frame_handle.bones_box[bones_around][k]].number_of_real_bone));
frame_handle.bones_box[bones_around][k]].is_clicked = true;
frame_handle.bones_box[bones_around][k]].bones_triggers();//迭代触发下去
}
}
}
}
/*------------------------------edited by 八神苍月 tools: EditPlus + JDK1.4.2-------------------------------*/
原文转自:http://www.ltesting.net