总体思路:
1.创建游戏工程 (sufaceView的使用)callback方法和自定义的redraw方法
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new Playground(this)); //setContentView(R.layout.activity_main); }
SurfaceHolder.Callback callback=new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { redraw(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { WIDTH=width/(COL+1); redraw(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { } };
2.神经猫游戏元素的建立 Dog(此处利用到矩阵matrix 的使用)还有状态常量的定义 以及 设置路障和定义中心点为Cat
注意:行列 X,Y 和matrix中X,Y的倒置关系
private Dog cat; private static final int ROW=10; private static final int COL=10; private static final int BLOCK=15; private Dog matrix[][];
private void initsGame() { for (int i=0;i<ROW;i++){ for (int j=0;j<COL;j++){ matrix[i][j].setStatus(Dog.STATUS_OFF); } } cat=new Dog(4,5); getDog(4,5).setStatus(Dog.STATUS_IN); for (int i=0;i<BLOCK;){ int x= (int) ((Math.random()*1000)%COL); int y=(int) ((Math.random()*1000)%ROW); if(getDog(x,y).getStatus()==Dog.STATUS_OFF){ getDog(x,y).setStatus(Dog.STATUS_ON); i++; Log.d("HH", "BLOCK +" +i); } } }3.游戏场景的绘制 (Paint和Canvas)
public void redraw(){ Canvas c=getHolder().lockCanvas(); c.drawColor(Color.LTGRAY); Paint paint=new Paint(); paint.setFlags(Paint.ANTI_ALIAS_FLAG); for (int i=0;i<ROW;i++) { int offset=0; if (i%2!=0){ offset=WIDTH/2; } for (int j = 0; j < COL; j++) { Dog one=getDog(j,i); switch (one.getStatus()){ case Dog.STATUS_OFF: paint.setColor(0xFFEEEEEE); break; case Dog.STATUS_ON: paint.setColor(0xFFFFAA00); break; case Dog.STATUS_IN: paint.setColor(0xFFFF0000); break; default: break; } c.drawOval(new RectF(one.getX()*WIDTH+offset,one.getY()*WIDTH ,(one.getX()+1)*WIDTH+offset,(one.getY()+1)*WIDTH),paint); } } getHolder().unlockCanvasAndPost(c); }此处应该注意的点是 width的选择 利用callback接口中sufaceChanged的方法传入的width参数 来计算 WIDTH=width/COT;
4.定义触摸事件
public boolean onTouch(View v, MotionEvent event) { if(event.getAction()==MotionEvent.ACTION_UP){ int x,y; y= (int) (event.getY()/WIDTH); if(y%2==0){ x= (int) (event.getX()/WIDTH); }else{ x= (int) ((event.getX()-WIDTH/2)/WIDTH); } if ((x+1)>COL||(y+1)>ROW){ initsGame(); }else if(getDog(x,y).getStatus()==Dog.STATUS_OFF){ getDog(x,y).setStatus(Dog.STATUS_ON); move(); } redraw(); } return true; }
注意:当发生越界情况时,应该有相应的操作,否则会系统崩溃,此处设为初始化游戏;
*5.四个功能函数的实现
private boolean isAtEdge(Dog d){ if(d.getX()*d.getY()==0||d.getX()+1==COL||d.getY()+1==ROW){ return true; } return false; } private Dog getNeighbour(Dog one,int dir){ switch (dir){ case 1: return getDog(one.getX()-1,one.getY()); case 2: if(one.getY()%2==0){ return getDog(one.getX()-1,one.getY()-1); }else{ return getDog(one.getX(),one.getY()-1); } case 3: if(one.getY()%2==0){ return getDog(one.getX(),one.getY()-1); }else{ return getDog(one.getX()+1,one.getY()-1); } case 4: return getDog(one.getX()+1,one.getY()); case 5: if(one.getY()%2==0){ return getDog(one.getX(),one.getY()+1); }else{ return getDog(one.getX()+1,one.getY()+1); } case 6: if(one.getY()%2==0){ return getDog(one.getX()-1,one.getY()+1); }else{ return getDog(one.getX(),one.getY()+1); } default: break; } return null; } private int getDistance(Dog one,int dir){ int distance=0; if(isAtEdge(one)){ return 1; } Dog ori=one,next; while(true){ next=getNeighbour(ori,dir); if (next.getStatus()==Dog.STATUS_ON){ return distance*-1; } if(isAtEdge(next)){ distance++; return distance; } distance++; ori=next; } } private void MoveTo(Dog one){ one.setStatus(Dog.STATUS_IN); getDog(cat.getX(),cat.getY()).setStatus(Dog.STATUS_OFF); cat.setXY(one.getX(),one.getY()); }6.移动策略以及优化
private void move() { if(isAtEdge(cat)){ lose(); return; } Vector<Dog>available=new Vector<>(); Vector<Dog>positive=new Vector<>(); HashMap<Dog,Integer>al=new HashMap<Dog,Integer>(); for (int i=1;i<7;i++){ Dog n=getNeighbour(cat,i); if(n.getStatus()==Dog.STATUS_OFF){ available.add(n); al.put(n,i); if(getDistance(n,i)>0){ positive.add(n); } } } if(available.size()==0){ win(); }else if (available.size()==1){ MoveTo(available.get(0)); }else{ Dog best=null; if (positive.size()!=0) {//有可以直接到达边缘的路径 System.out.println("找路径"); int min=99; for (int i = 0; i < positive.size();i++) { int a =getDistance(positive.get(i),al.get(positive.get(i))); if (a<min){ min=a; best=positive.get(i); } } MoveTo(best); }else{//所有方向都有路障 System.out.println("躲路障"); int max=0; for (int i = 0; i < available.size();i++) { int k =getDistance(available.get(i),al.get(available.get(i))); if (k<=max){//此处务必要<=max !!!否则当出现等于0的情况时系统将会崩溃 max=k; best=available.get(i); } } MoveTo(best); } } } private void lose(){ Toast.makeText(getContext(),"You lose",Toast.LENGTH_SHORT).show(); } private void win(){ Toast.makeText(getContext(),"You win,业诚真帅",Toast.LENGTH_SHORT).show(); } }