android扫雷

本文将指导您如何使用Android平台开发扫雷游戏,包括界面设计、逻辑实现、按钮交互和游戏规则等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近练手android,准备编一系列的小游戏,第一个:扫雷。
思路:
1
、点击开始按钮生成雷区。(使用按钮控件就足够了,还可以方便的监听点击事件)
2
、点击雷区的按钮开始判断是否有雷,点中地雷游戏结束,点中空地则检查四周的雷的数量并显示出来。
3
、空地全部点开以后游戏胜利。

首先要确定雷区的大小,因为手机屏幕较小,所以选择8*8的小雷区。
<wbr><wbr><wbr> intMAX_ROW=8;//8</wbr></wbr></wbr>

<wbr><wbr><wbr> intMAX_C=8;//8</wbr></wbr></wbr>

然后设置雷的数量。
<wbr><wbr><wbr> intMAX_BOOM=16;//</wbr></wbr></wbr>
雷的数量
然后计算出需要点开多少空地。
<wbr><wbr><wbr> intSHOULD_FIND=MAX_ROW*MAX_C-MAX_BOOM;//</wbr></wbr></wbr>
应该点开的按钮数量
<wbr><wbr><wbr> int find =0;//</wbr></wbr></wbr>
已经找到的不是雷的数量
声明各种数组。l是布局里面的一行,b是雷区的按钮,date保存雷的位置。
<wbr><wbr><wbr> LinearLayoutl[]=new LinearLayout[MAX_ROW];<br><wbr><wbr><wbr> Buttonb[][]=new Button[MAX_ROW][MAX_C];<br><wbr><wbr><wbr> intdate[][]= newint[MAX_ROW][MAX_C];<br></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
加入开始退出的按钮。
<wbr><wbr><wbr> ButtonstartButton;<br><wbr><wbr><wbr> ButtonexitButton;<br></wbr></wbr></wbr></wbr></wbr></wbr>
因为android的界面跟逻辑是分离的,所以需要把逻辑里的对象跟界面的对象联系起来
for(int i=0; i<MAX_ROW; i++){
<wbr><wbr><wbr><wbr><wbr><wbr>l[i]=(LinearLayout)findViewById(R.id.linearLayout1+i);<br> }<br></wbr></wbr></wbr></wbr></wbr></wbr>
同过id来找寻到对象,对象的id是一个整数,同类型的id是连续的,所以我们可以用每次加1来循环,这样的话以后需要更改雷区大小,只用改变MAX_ROWMAX_C的值,不用动别的代码。
exitButton=(Button)findViewById(R.id.button2);
startButton=(Button)findViewById(R.id.button1);
同理,把两个按钮的也找到。

这样,基本的准备工作就做完了。


接着我们为关闭按钮添加功能。设置一个点击事件的监听器,这个按钮被点击后会调用onClick里的东西。onClick里我们彻底的关闭了本程序的进程。

exitButton.setOnClickListener(new OnClickListener(){

@Override

publicvoid onClick(View v) {

<wbr><wbr><wbr> finish();</wbr></wbr></wbr>

<wbr><wbr>android.os.Process.killProcess(android.os.Process.myPid());</wbr></wbr>

<wbr><wbr><wbr>System.exit(0);</wbr></wbr></wbr>

}

});

然后是开始按钮。点击以后判断状态,如果开始按钮上的字是重新开始,那么证明游戏已经开始了,雷区有按钮,所以我们先调用rmButton来清除雷区的按钮,再开始新的游戏,如果开始按钮上的字是别的,那就直接开始游戏。

startButton.setOnClickListener(new OnClickListener(){

@Override

publicvoid onClick(View v) {

<wbr><wbr><wbr></wbr></wbr></wbr> if(startButton.getText()=="重新开始"){

<wbr><wbr><wbr></wbr></wbr></wbr> <wbr><wbr><wbr></wbr></wbr></wbr> rmButton();

<wbr><wbr><wbr></wbr></wbr></wbr> <wbr><wbr><wbr></wbr></wbr></wbr> startgame();

<wbr><wbr><wbr></wbr></wbr></wbr> }else{

<wbr><wbr><wbr></wbr></wbr></wbr> <wbr><wbr><wbr></wbr></wbr></wbr><wbr><wbr><wbr></wbr></wbr></wbr> startButton.setText("重新开始");

<wbr><wbr><wbr></wbr></wbr></wbr> <wbr><wbr><wbr></wbr></wbr></wbr><wbr><wbr><wbr></wbr></wbr></wbr> startgame();

<wbr><wbr><wbr></wbr></wbr></wbr> <wbr><wbr><wbr></wbr></wbr></wbr> }

<wbr><wbr><wbr></wbr></wbr></wbr> }

});



我们先来看看rmButton这个简单的函数。在这个函数里,遍历行跟列,把按钮数组设置为null(意思是什么也没有)。然后用removeAllViews把每一行的东西都给移除。

publicvoid rmButton(){

<wbr><wbr><wbr></wbr></wbr></wbr> for(int i=0;i<MAX_ROW;i++){

<wbr><wbr><wbr></wbr></wbr></wbr> <wbr><wbr><wbr></wbr></wbr></wbr> for(int j=0;j<MAX_C;j++){

<wbr><wbr><wbr></wbr></wbr></wbr><wbr><wbr><wbr></wbr></wbr></wbr> b[i][j]=null;

<wbr><wbr><wbr></wbr></wbr></wbr> }

<wbr><wbr><wbr></wbr></wbr></wbr> l[i].removeAllViews();

<wbr><wbr><wbr></wbr></wbr></wbr> }

}



接着就是开始游戏的函数了。首先初始化找到的地雷数量,一会会用这个值来判断游戏是否获胜。接着调用loadBoom随机生成雷的数组。注释掉的logBoom是调试时用来在LOG中显示雷的数组的值的函数,没问题了就不需要了。最后调用addButton来在布局里添加雷区的按钮。

public void startgame(){

find = 0;//初始化找到的为0

loadBoom();

//logBoom();

addButton();

}



最开始设计时我是先用固定的雷区数组,主要把精力放在了点击后的逻辑上,随机生成地雷是后面加入的功能。做游戏要分清主次,首先把最难得部分做完,剩下的就好办了。先用系统当前的时间做种子,来生成随机数。随机数就跟树一样,从一个种子发芽成长,要是种子一样,那么长出来的东西一样,因为随机数其实也是一个固定的算法。比如第一次生成1(种子生成),753,以后还是会生成一样的1,7,5,3。所以我们要给他一个不一样的种子,而系统时间正好是时刻变化的。

接着调用了clearDate,这个函数把date中的数据全部变成0

最后得到207的随机数,如果这2个随机数指的位置没有雷的话,那么放上一个雷,如果已经有雷了,那就把i1,表示失败,重新再来。

public void loadBoom(){

Random r=newRandom(System.currentTimeMillis());

clearDate();

for(int i = 0; i < MAX_BOOM;i++){

<wbr><wbr><wbr></wbr></wbr></wbr> int x = abs(r.nextInt()%8);

<wbr><wbr><wbr></wbr></wbr></wbr> int y = abs(r.nextInt()%8);

<wbr><wbr><wbr></wbr></wbr></wbr> if(date[x][y]!=1){

<wbr><wbr><wbr></wbr></wbr></wbr> date[x][y]=1;

}

else{

<wbr><wbr><wbr></wbr></wbr></wbr> i--;

}

}

}

以下就是clearDate

public void clearDate(){

for(int i=0;i<MAX_ROW;i++){

<wbr><wbr><wbr></wbr></wbr></wbr> for(int j=0;j<MAX_C;j++){

<wbr><wbr><wbr></wbr></wbr></wbr> <wbr><wbr><wbr></wbr></wbr></wbr> date[i][j] = 0;

<wbr><wbr><wbr></wbr></wbr></wbr> }

}

}

最后是最重要的addButton函数,这个函数不光添加了按钮,还给每个按钮添加了不同的监听事件。(从windows弄到ubuntu来贴出来格式不对)


下面就是addButton

通过MAX_ROWMAX_C来生成按钮的二维数组,前面一个数字是行号,后面一个是在这一行中的第几个。然后设置按钮的长,宽,按钮上的文字。下面添加点击事件监听时需要使用到当前的行列值,但是ij是局部变量,不能引用,于是我们声明2final型的临时变量来存放ij的值。然后添加监听,监听时判断当前位置的date数组(雷的位置的数组)的值,如果是0,那就代表点击中了没有雷的按钮,那么找到的不是雷的计数器加一,加一后如果已经找出了所有的雷,那么执行游戏胜利的win。如果没有找出全部的雷,那么把按钮设置为不可用,并调用check把周围的雷的数量找出来显示在按钮上。如果,点击的位置相对的date里为1,那么代表踩到了地雷,则把踩中地雷的图像显示在按钮上,并运行gameover

接下来添加长时间按住按钮的监听。如果长时间按住按钮,那么把按钮的文字设置为B代表标记地雷,并且禁止按钮的使用。

最后把按钮加到相应的行里面。

public void addButton(){

for(int i=0;i<MAX_ROW;i++){

for(int j=0;j<MAX_C;j++){

b[i][j]=new Button(this);

b[i][j].setHeight(60);

b[i][j].setWidth(60);

b[i][j].setText("");

final int ti=i;

final int tj=j;

//点击按钮

b[i][j].setOnClickListener(new OnClickListener(){

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

if(date[ti][tj]==0){//没有地雷

find += 1;

if(find==SHOULD_FIND){win();}

else{

b[ti][tj].setEnabled(false);

b[ti][tj].setText(check(ti,tj));//把周围的雷数量显示在按钮上

}

}

else{

b[ti][tj].setBackgroundDrawable(getResources().getDrawable(R.drawable.wrong));

gameover();

}

}

});

//长按按钮

b[i][j].setOnCreateContextMenuLi<wbr>stener(newOnCreateContextMenuListe<wbr>ner() {</wbr></wbr>

@Override

public void onCreateContextMenu(ContextMenu menu, Viewv,

ContextMenuInfo menuInfo) {

// TODO Auto-generated method stub

menu.setHeaderTitle("地雷标记");

if(b[ti][tj].isEnabled()){

b[ti][tj].setText("B");

b[ti][tj].setEnabled(false);

}

}

});

l[i].addView(b[i][j]);//把按钮加入布局

}

}

}


这是最后一部分了。

下面就是四周雷的算法,需要注意按钮在边上,角上的边界问题,否则容易出现运行时数组访问越界问题。

//判断四周有没有雷

public String check(int i, int j){

int sum = 0;

<wbr></wbr>

if(i>0){

if(j<MAX_C-1){

if(date[i-1][j+1]!=0){sum++;}

}

if(date[i-1][j]!=0){sum++;}

}

if(j>0){

if(date[i][j-1]!=0){sum++;}

if(i<MAX_ROW-1){

if(date[i+1][j-1]!=0){sum++;}

}

}

if(i>0&&j>0){

if(date[i-1][j-1]!=0){sum++;}

}

if(i<MAX_ROW-1){

if(date[i+1][j]!=0){sum++;}

}

if(j<MAX_C-1){

if(date[i][j+1]!=0){sum++;}

}

if(i<(MAX_ROW-1)&&j<(MAX_C-1)){

if(date[i+1][j+1]!=0){sum++;}

}

return ""+sum;

}

<wbr></wbr>

//把所有的雷显示出来

public void showAllBoom(){

for(int i=0;i<MAX_ROW;i++){

for(int j=0;j<MAX_C;j++){

b[i][j].setEnabled(false);

if(date[i][j]!=0){

b[i][j].setBackgroundDrawable(getResources().getDrawable(R.drawable.wrong));//素材自己画了放到drawable里。

}

}

}

}



public void gameover(){

mvibrator.vibrate(pattern_Over, -1);

Toast.makeText(this, "gameover!!!!!!!!!",Toast.LENGTH_LONG).show();

showAllBoom();//把所有的雷显示出来

<wbr></wbr>

}

<wbr></wbr>

public void win(){

mvibrator.vibrate(pattern_Win, -1);

Toast.makeText(this, "you win!!!!!!!!!",Toast.LENGTH_LONG).show();

showAllBoom();//把所有的雷显示出来

}


还有第一下点击必不为雷,雷区大小,雷的数量等调整难度的就不做了,无非也就改改参数。下一个是俄罗斯方块。已经完成了,分批发上来。正在制作rpg中。


安卓 扫雷源码 添加重新开始按钮支持 Android studio ====================================== Risky Project Location: ----------------------- The tools *should* handle project locations in any directory. However, due to bugs, placing projects in directories containing spaces in the path, or characters like ", &#39; and &, have had issues. We&#39;re working to eliminate these bugs, but to save yourself headaches you may want to move your project to a location where this is not a problem. D:\Program Files\android_s_workplace\terrysaolei - Ignored Files: -------------- The following files were *not* copied into the new Gradle project; you should evaluate whether these are still needed in your project and if so manually move them: * ic_launcher-web.png * proguard-project.txt Moved Files: ------------ Android Gradle projects use a different directory structure than ADT Eclipse projects. Here&#39;s how the projects were restructured: * AndroidManifest.xml => app\src\main\AndroidManifest.xml * assets\ => app\src\main\assets * res\ => app\src\main\res\ * src\ => app\src\main\java\ Next Steps: ----------- You can now build the project. The Gradle project needs network connectivity to download dependencies. Bugs: ----- If for some reason your project does not build, and you determine that it is due to a bug or limitation of the Eclipse to Gradle importer, please file a bug at http://b.android.com with category Component-Tools. (This import summary is for your information only, and can be deleted after import once you are satisfied with the results.)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值