最终效果:
AndroidManifest.xml
xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.caobotao.crazycat" > <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> intent-filter> activity> application> manifest>
MainActivity.java
package com.example.caobotao.crazycat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new PlayGround(this)); } }
Dot.java
package com.example.caobotao.crazycat; /** * Created by caobotao on 15/11/9. */ public class Dot { private int x; private int y; private int status; static final int STATUS_ON = 1;//障碍的圆圈状态 static final int STATUS_OFF = 0;//可点击的圆圈状态 static final int STATUS_IN = 9;//猫所在的圆圈状态 public Dot(){} //实例化时每个圆圈都是可点击的状态 public Dot(int x,int y){ this.x = x; this.y = y; status = STATUS_OFF; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public void setXY(int x,int y){ this.x = x; this.y = y; } }
PlayGround.java
package com.example.caobotao.crazycat; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; import android.view.View.OnTouchListener; import android.widget.Toast; import java.util.HashMap; import java.util.Vector; /** * Created by caobotao on 15/11/9. */ public class PlayGround extends SurfaceView implements OnTouchListener{ private static int WIDTH = 45;//圆圈宽度 private static final int ROW = 10;//每行显示的圆圈数 private static final int COL = 10;//每列显示的圆圈数 private static final int Blocks = 13;//初始化障碍的个数 private Dot matrix[][]; private Dot cat; public PlayGround(Context context) { super(context); getHolder().addCallback(callback); //声明ROW x COL的圆圈矩阵并初始化 matrix = new Dot[ROW][COL]; for (int i = 0;i < ROW;i ++){ for (int j = 0;j < ROW;j ++){ matrix[i][j] = new Dot(j,i); } } initGame(); setOnTouchListener(this); } private void redraw(){ //初始化画板 Canvas canvas = getHolder().lockCanvas(); // Log.i("info", "222222"); //设置画板背景色 canvas.drawColor(Color.LTGRAY); Paint p = new Paint(); p.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 ++){ Dot one = getDot(j, i); switch (one.getStatus()){ case Dot.STATUS_OFF: p.setColor(0xFFEEEEEE); break; case Dot.STATUS_ON: p.setColor(0xFFFFAA00); break; case Dot.STATUS_IN: p.setColor(0xFFFF0000); break; } RectF rectF = new RectF(one.getX() * WIDTH + offset, one.getY() * WIDTH, (one.getX() + 1) * WIDTH + offset, (one.getY() + 1) * WIDTH);; // if(i % 2 ==0) { // rectF = new RectF((one.getX() + 1) * WIDTH, (one.getY() + 2) * WIDTH, (one.getX() + 2) * WIDTH, (one.getY() + 2) * WIDTH); // } canvas.drawOval(rectF,p); } } getHolder().unlockCanvasAndPost(canvas); } private void initGame(){ //将每个圆圈初始化为可点击状态 for (int i = 0;i < ROW;i ++){ for (int j = 0;j < ROW;j ++){ matrix[i][j].setStatus(Dot.STATUS_OFF); } } //将(4,5)设置初始化为猫所在的圆圈,并将状态设置为猫所在 cat = getDot(4,5); cat.setStatus(Dot.STATUS_IN); //随机设置Blocks个障碍 for (int i = 0 ;i < Blocks;){ int x = (int) ((Math.random() * 1000)%COL); int y = (int) ((Math.random() * 1000)%ROW); if(getDot(x,y).getStatus() == Dot.STATUS_OFF){ getDot(x,y).setStatus(Dot.STATUS_ON); i ++; } } } private boolean isAtEdge(Dot dot){ //判断某个圆圈是否在边缘 if(dot.getX() * dot.getY() == 0 || dot.getX()+1 == ROW || dot.getY() + 1 == COL){ return true; } return false; } //获取某个圆圈的左起1,2,3,4,5,6方向的相邻的圆圈 private Dot neighbour(Dot dot,int dir){ int x = -1; int y = -1; switch (dir){ case 1: //return getDot(dot.getX()-1,dot.getY()); x = dot.getX()-1; y = dot.getY(); break; case 2: if(dot.getY() % 2 == 0){ x = dot.getX() - 1; y = dot.getY() - 1; } else { x = dot.getX(); y = dot.getY() - 1; } break; case 3: if(dot.getY() % 2 == 0){ x = dot.getX() ; y = dot.getY() - 1; } else { x = dot.getX() + 1; y = dot.getY() - 1; } break; case 4: x = dot.getX() + 1; y = dot.getY(); break; case 5: if(dot.getY() % 2 == 0){ x = dot.getX() ; y = dot.getY() + 1; } else { x = dot.getX() + 1; y = dot.getY() + 1; } break; case 6: if(dot.getY() % 2 == 0){ x = dot.getX() - 1; y = dot.getY() + 1; } else { x = dot.getX(); y = dot.getY() + 1; } break; } if (x != -1 || y != -1){ return getDot(x,y); } return null; } //获取某个圆圈在某个方向到矩阵边缘或到障碍的距离,如果是到边缘,返回正值,如果是到障碍,返回负值 private int getDistance(Dot dot,int dir){ int distance = 0; if (isAtEdge(dot)){ return 1; } Dot ori = dot; Dot next; while (true){ next = neighbour(ori,dir); if (next.getStatus() == Dot.STATUS_ON){ return distance * -1; } if (isAtEdge(next)){ distance ++; return distance; } distance ++; ori = next; } } //将猫移动到某个圆圈 private void moveTo(Dot dot){ Dot temp = new Dot(); temp = dot; dot = cat; cat = temp; cat.setStatus(Dot.STATUS_IN); dot.setStatus(Dot.STATUS_OFF); //如果移动后猫已在矩阵边缘,则游戏失败 if (isAtEdge(cat)){ lose(); } // getDot(cat.getX(),cat.getY()).setStatus(Dot.STATUS_OFF); // dot.setStatus(Dot.STATUS_IN); // cat.setXY(dot.getX(), dot.getY()); } private Dot getDot(int x,int y){ return matrix[y][x]; } Callback callback = new 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) { } }; @Override public boolean onTouch(View v, MotionEvent event) { // Log.i("info","33333"); if (event.getAction() == MotionEvent.ACTION_UP){ // Log.i("info", "44444"); // Toast.makeText(getContext(),event.getX() + ":" + event.getY(),Toast.LENGTH_SHORT).show(); 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){ initGame(); } //否则如果点击的圆圈的状态是可点击的,就将此圆圈的状态设置为障碍,并将猫进行移动 else if (getDot(x,y).getStatus() == Dot.STATUS_OFF){ getDot(x,y).setStatus(Dot.STATUS_ON); move(); } redraw(); // } return true; } private void move() { //如果猫已在矩阵边缘,则游戏失败 if (isAtEdge(cat)){ lose(); return; } //猫可以移动的圆圈 Vectoravailable = new Vector (); //猫可以移动的到矩阵边缘没有障碍的圆圈 Vector positive = new Vector (); HashMap al = new HashMap (); for (int i =1;i<7;i++){ Dot n = neighbour(cat,i); if(n.getStatus() == Dot.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{ Dot best = null; //如果存在可以直接到达屏幕边缘的走向 if (positive.size() != 0){ System.out.println("向前进"); int min = 999; 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); } } } //所有路径均有路障 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 = k; best = available.get(i); } } } if(best != null) { moveTo(best); } else{ moveTo(available.get(0)); } // Dot d = available.get(0); // for (int i = 1;i // if ( Math.min(available.get(i).getX(), available.get(i).getY()) < Math.min(d.getX(),d.getY()) ){ // d = available.get(i); // } // } // moveTo(d); } } //赢得游戏 private void win() { Toast.makeText(getContext(),"YOU HAVE WON THE GAME!",Toast.LENGTH_SHORT).show(); } //游戏失败 private void lose() { Toast.makeText(getContext(),"YOU HAVE LOST THE GAME!",Toast.LENGTH_SHORT).show(); } }
注:由于本项目只是用于简单学习交流,代码中难免会有bug出现,请自行调试修改。
作者: caobotao
出处: http://www.cnblogs.com/caobotao/p/4966663.html
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。