现在的位置: 首页 > 综合 > 正文

试着写了个Android贪吃蛇程序-代码分享

2017年12月18日 ⁄ 综合 ⁄ 共 11146字 ⁄ 字号 评论关闭

——前段时间和同学上java,在上课时提出一起写点小游戏,于是写了2048~然后自己又试着在android上重新写一个,发现挺好玩。

于是无聊想试着多接触实践Android的绘图功能,于是试着写了个安卓贪吃蛇程序。

代码不好的地方大家请原谅。

   先介绍一下玩法:

1、在电脑端模拟机打开的话,可以通过 w s a d 来控制上下左右。

2、在手机端通过方向感应器,手机角度的变化来控制贪吃蛇的运动。

3、试着添加了记录排名的功能,后来觉得挺简单,但是有点冗杂,所以很粗糙的弄了个得分记录。供大家参考。

       还有一点就是,蛇身的点点都是固定大小,所以分辨率高的手机看到的蛇会小很多,怪我懒,不想去改了,大家可以通过获取屏幕宽度然后按比例来设置点点的大小。

代码的大部分的地方我也尽可能的注释了,方便大家参考。觉得有时候试着编个小游戏挺能鼓励自己的~哈哈哈。

首先要创建一个类来存放坐标值:

package com.snakemy;

public class xymark {
	private int xmark;
	private int ymark;
	public int getXmark() {
		return xmark;
	}
	public void setXmark(int xmark) {
		this.xmark = xmark;
	}
	public int getYmark() {
		return ymark;
	}
	public void setYmark(int ymark) {
		this.ymark = ymark;
	}

	
}

游戏界面的代码(View):

package com.snakemy;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class GameView extends View {
	
	private int ranx, rany;//随机点坐标。
	List<xymark> xymark = new ArrayList<xymark>();//蛇身。
//	private Canvas canvasout;
	private Paint paint;
	private int tarflag = 2;//蛇运动方向标志。
	private boolean randomflag = true;//创造随机点的标志。


	{	//初始化第一个点。
		xymark firstXymark = new xymark();
		firstXymark.setXmark(10);firstXymark.setYmark(10);
		xymark.add(firstXymark);
	}
	
	public GameView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public GameView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public GameView(Context context) {
		super(context);
	}
	
	@Override
	protected void onDraw(Canvas canvas) {// 如何在外部调用这个Canvas画布。?
		super.onDraw(canvas);
//		canvasout = canvas;		原本打算通过canvasout全局量在ondraw以外的其他函数中控制canvas的,然而发现不行,所以直接用canvas就好了。
		paint = new Paint();
		if (randomflag)
			randompoint();
		paint.setColor(Color.RED);
		canvas.drawCircle(ranx, rany, 5, paint);//随机点。
		
		//填充空心风格,加入矩形边框。
		paint.setStyle(Paint.Style.STROKE);
		paint.setColor(Color.BLUE);
		canvas.drawRect(5,5,this.getWidth()-5,this.getHeight()-5, paint);
		
		
		paint.setStyle(Paint.Style.FILL);
		paint.setColor(Color.BLACK);

		//接触红点后,蛇身集合增长。
		if ((xymark.get(0).getXmark() == ranx) &&(xymark.get(0).getYmark() == rany)) {
			xymark nextXYmark = new xymark();	
			if(xymark.size()==1)//判断是否只有一个点。
			{
				switch (tarflag) {
				case 1:
					nextXYmark.setYmark(xymark.get(0).getYmark()+10);
					nextXYmark.setXmark(xymark.get(0).getXmark());
					break;
				case 2:
					nextXYmark.setYmark(xymark.get(0).getYmark()-10);
					nextXYmark.setXmark(xymark.get(0).getXmark());
					break;
				case 3:
					nextXYmark.setYmark(xymark.get(0).getYmark());
					nextXYmark.setXmark(xymark.get(0).getXmark()+10);
					break;	
				case 4:
					nextXYmark.setYmark(xymark.get(0).getYmark());
					nextXYmark.setXmark(xymark.get(0).getXmark()-10);
					break;	
				default:
					break;
				}
			}else {//大于一个点。
				int lenth = xymark.size()-1; //get( 0 ~ lenth );
				int x_cha = xymark.get(lenth-1).getXmark() - xymark.get(lenth).getXmark();
				int y_cha = xymark.get(lenth-1).getYmark() - xymark.get(lenth).getYmark();
				if (x_cha == 10) {
					nextXYmark.setYmark(xymark.get(lenth).getYmark());
					nextXYmark.setXmark(xymark.get(lenth).getXmark() - 10);
				} else if (x_cha == (-10)) {
					nextXYmark.setYmark(xymark.get(lenth).getYmark());
					nextXYmark.setXmark(xymark.get(lenth).getXmark() + 10);
				}
				if (y_cha == 10) {
					nextXYmark.setXmark(xymark.get(lenth).getXmark());
					nextXYmark.setYmark(xymark.get(lenth).getYmark() - 10);
				} else if (y_cha == (-10)) {
					nextXYmark.setXmark(xymark.get(lenth).getXmark());
					nextXYmark.setYmark(xymark.get(lenth).getYmark() + 10);
				}
			}
			
			
			randomflag = true;
			xymark.add(nextXYmark);
		}
		
		//绘制蛇身。
		 for(int m = 0;m < xymark.size();m++){
			 canvas.drawCircle(xymark.get(m).getXmark(),xymark.get(m).getYmark(),5, paint);
		 }
	}

	public int getTarflag() {
		return tarflag;
	}

	public void setTarflag(int tarflag) {
		this.tarflag = tarflag;
	}

	public void randompoint() {
		int width = (this.getWidth()-10)/10;
		int height = (this.getHeight()-10)/10;
		Random random = new Random();
		ranx = random.nextInt(width) * 10+10;
		rany = random.nextInt(height) * 10+10;
		randomflag = false;
	}
}

主程序代码(控制部分):

package com.snakemy;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;


@SuppressWarnings("deprecation") //强迫症。
public class MainActivity extends Activity implements SensorEventListener {
	
//	private Button changeButton;
	private boolean deathflag = false;
	private Timer timer = new Timer();
	private GameView gameView;
	private LinearLayout layout;
	private TextView textView;
	
	//加入方向感应来控制(虚拟机上用wsad控制,手机上用方向感应角度控制)。
	//顺便提醒一下自己。之所以不用重力感应控制,是因为,比如你在做公交或地铁时,加速度就会被影响到游戏控制。
	private SensorManager mSensorManager;//
	private Sensor mGyroscope;//并不是用陀螺仪喔。
	float[] gyroscope=new float[3];
	
	//存入数据。
	private SharedPreferences preferences;
	private SharedPreferences.Editor editor;
	
	
	private Handler handler = new Handler(){

		@Override
		public void handleMessage(Message msg) {
			//蛇的整体移动控制。
			//#对于第二个点开始的蛇身变化调整。
		for (int m = gameView.xymark.size()-1; m > 0; m--) {
			int x_cha = gameView.xymark.get(m).getXmark() - gameView.xymark.get(m - 1).getXmark();
			int y_cha = gameView.xymark.get(m).getYmark() - gameView.xymark.get(m - 1).getYmark();
			if (x_cha == 10) {
				gameView.xymark.get(m).setXmark(gameView.xymark.get(m).getXmark() - 10);
			} else if (x_cha == (-10)) {
				gameView.xymark.get(m).setXmark(gameView.xymark.get(m).getXmark() + 10);
			}
			if (y_cha == 10) {
				gameView.xymark.get(m).setYmark(gameView.xymark.get(m).getYmark() - 10);
			} else if (y_cha == (-10)) {
				gameView.xymark.get(m).setYmark(gameView.xymark.get(m).getYmark() + 10);
			}
		}
		//#对于第一个点的变化调整。
		switch (gameView.getTarflag()) {
		case 1: gameView.xymark.get(0).setYmark(gameView.xymark.get(0).getYmark()-10);
			break;
		case 2:gameView.xymark.get(0).setYmark(gameView.xymark.get(0).getYmark()+10);
			break;
		case 3:gameView.xymark.get(0).setXmark(gameView.xymark.get(0).getXmark()-10);
			break;
		case 4:gameView.xymark.get(0).setXmark(gameView.xymark.get(0).getXmark()+10);
			break;
		default:
			break;
		}
		
			//先刷新界面 后判断。
			gameView.invalidate();
			//判断是否出界。
			ifgameover();
			
			textView.setText("蛇身长度:" + gameView.xymark.size());
			super.handleMessage(msg);
		}
		
	};
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		init();
		getgameview();
		Log.e("test3", "test3");
		timer.schedule(new TimerTask() {
			
			@Override
			public void run() {
					if(!deathflag)
					handler.sendEmptyMessage(gameView.getTarflag());
			}
		}, 500,500);
		
	}	


	private void init() {
		layout = (LinearLayout) this.findViewById(R.id.root);
		textView = (TextView)this.findViewById(R.id.textview);
		
		mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
		mGyroscope    =   mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);//方向传感器。
		
		mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_UI);
		preferences = getSharedPreferences("SaveMark", Context.MODE_PRIVATE);
		editor = preferences.edit();
	}
	
	private void getgameview(){
		gameView = new GameView(this);
		layout.addView(gameView);
		gameView.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				handler.sendEmptyMessage(gameView.getTarflag());//点击屏幕时加速。
				return false;
			}
		});
		
		//为什么不能通过这里设置keydown达到点击屏幕时一直加速的目的。
//		gameView.setOnKeyListener(new OnKeyListener() {
//			
//			@Override
//			public boolean onKey(View v, int keyCode, KeyEvent event) {
//				Log.e("a", "b");
//				return false;
//			}
//		});
	}
	
	private void ifgameover(){
		//判断是否出界。
		if(gameView.xymark.get(0).getXmark()>gameView.getWidth()-5||
				gameView.xymark.get(0).getXmark()<5||
				gameView.xymark.get(0).getYmark()>gameView.getHeight()-5||
				gameView.xymark.get(0).getYmark()<5)
			gameover();
		
		//判断是否撞到自己。
		for(int i = 1; i< gameView.xymark.size();i++){
			if(gameView.xymark.get(0).getXmark()==gameView.xymark.get(i).getXmark()&&
					gameView.xymark.get(0).getYmark()==gameView.xymark.get(i).getYmark())//好像不能用equal。
				gameover();
		}
	}
	
	private void gameover(){
//		timer.cancel();
		deathflag = true;
		AlertDialog.Builder builder  = new Builder(MainActivity.this);
		builder.setCancelable(false);
		builder.setTitle("游戏提示" ) ;
		builder.setMessage("碰壁了\n"+"失败鸟~!\n"+" ——您的分数是"+gameView.xymark.size()+"分") ; 
		builder.setPositiveButton("重新开始",new OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				layout.removeView(gameView);
				getgameview();
				deathflag = false;
			}
		} );
		
		//查看分数排行及计入排行。(比较粗糙,因为不想花太多时间在这个处理上,这部分可以删去。)
		builder.setNegativeButton("进入排行", new OnClickListener() { 
			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				  final EditText savemark = new EditText(MainActivity.this); 
				  AlertDialog.Builder builder = new Builder(MainActivity.this);
				  builder.setCancelable(false);
				  builder.setTitle("分数记录:"+gameView.xymark.size());
				  builder.setMessage(preferences.getAll().toString().substring(1,preferences.getAll().toString().length()-2));
//				  builder.setIcon(R.drawable.ic_launcher);
				  builder.setView(savemark);
				  builder.setPositiveButton("存入记录" ,  new OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						editor.putString(savemark.getText().toString(), gameView.xymark.size()+"分\n");//存入。
						editor.commit();
						layout.removeView(gameView);
						getgameview();
						deathflag = false;
					}
				} );
				  builder.setNegativeButton("取消", new OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						layout.removeView(gameView);
						getgameview();
						deathflag = false;						
					}
				});
				  builder.show();
			}
		});
		builder.show();
	}

	// ww== 51 s== 47 a== 29 d== 32
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		//蛇的方向控制
//		Log.e("2", keyCode + "");
		if(!deathflag)
		switch (keyCode) {
			case 51:if(gameView.getTarflag()!=2){
				gameView.setTarflag(1);handler.sendEmptyMessage(gameView.getTarflag()); 
			}break;
			case 47:if(gameView.getTarflag()!=1){
				gameView.setTarflag(2);handler.sendEmptyMessage(gameView.getTarflag());
			}break;
			case 29:if(gameView.getTarflag()!=4){
				gameView.setTarflag(3);handler.sendEmptyMessage(gameView.getTarflag());			
			}break;	
			case 32:if(gameView.getTarflag()!=3){
				gameView.setTarflag(4);handler.sendEmptyMessage(gameView.getTarflag());		
			}break;	
		default:
			break;
		}
		return super.onKeyDown(keyCode, event);
	}
	
	


	@Override
	public void onSensorChanged(SensorEvent event) {
		if(event.sensor.getType() == Sensor.TYPE_ORIENTATION && (!deathflag))
			Fun_GYROSCOPE(event);
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// TODO Auto-generated method stub
	}

	//用方向感应器控制。
	float axisZ;
	float axisY;
	private void Fun_GYROSCOPE(SensorEvent event) {
//		float axisX = event.values[0];//这个值不用,具体参考方向传感器的使用。
		axisY = event.values[1];
		axisZ = event.values[2];
		if (axisY > 15 && gameView.getTarflag()!=2) {	
			gameView.setTarflag(1);return;
		} else if (axisY < -15 && gameView.getTarflag()!=1) {
			gameView.setTarflag(2);return;
		} else if (axisZ > 15 && gameView.getTarflag()!=4) {
			gameView.setTarflag(3);return;
		} else if (axisZ < -15 && gameView.getTarflag()!=3) {
			gameView.setTarflag(4);return;
		}
	}
	
	
}

layout文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}"
   	android:id="@+id/root"
   	android:orientation="vertical" >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/point" 
        android:textSize="26sp"
        android:id="@+id/textview"/>

</LinearLayout>

通过手机端操作的代码安全性不好,建议大家自己写手机端的控制,比如可以通过滑屏来控制,我就不去写啦~睡觉

直接复制上面的代码就可以用~

或者等我把代码包上传了再把下载地址补上给大家哈~

抱歉!评论已关闭.