初级贪食蛇

文章目录

  • 初级贪食蛇
    • 效果展示:
    • 界面设计
    • 算法设计
      • 游戏面板类
      • 蛇身类
      • 蛇类
      • 方向类
      • 主函数类

效果展示:

界面设计

游戏界面的设计布局我们采用“相对布局中嵌套线性布局”这样做的好处是界面整体对称性更强,游戏体验更佳。
用相对布局将游戏界面分成两部分,一部分为游戏展示界面,一部分为按钮控制界面。
这里的界面设计着重是按钮布局的界面,游戏展示界面将在算法设计中的游戏面板类中展开。
游戏展示界面我们需要调用游戏面板类的内容:

    <com.example.sqltext.GamePanelandroid:id="@+id/gamePanel"android:layout_width="match_parent"android:layout_height="500dp" />

按钮控制界面则采用线性布局和相对布局相辅相成,使得整个界面规整,对称。我们将按钮控制界面分为三个部分,将开始游戏和结束游戏放于左边,方向控制居中处理,暂停和继续放于右边。

 <LinearLayoutandroid:layout_below="@+id/gamePanel"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><LinearLayoutandroid:orientation="vertical"android:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"><Buttonandroid:id="@+id/start"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="开始游戏" /><Buttonandroid:id="@+id/back"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="退出游戏" /></LinearLayout><RelativeLayoutandroid:layout_width="0dp"android:layout_weight="3"android:layout_height="match_parent"><Buttonandroid:id="@+id/up"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="上"android:textStyle="bold" /><Buttonandroid:id="@+id/left"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="左"android:layout_below="@+id/up"android:layout_toLeftOf="@+id/down"android:textStyle="bold" /><Buttonandroid:id="@+id/right"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="右"android:layout_below="@+id/up"android:layout_toRightOf="@+id/down"android:textStyle="bold" /><Buttonandroid:id="@+id/down"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:layout_below="@+id/up"android:text="下"android:textStyle="bold" /></RelativeLayout><LinearLayoutandroid:orientation="vertical"android:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"><Buttonandroid:id="@+id/Continue"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="继续游戏" /><Buttonandroid:id="@+id/Stop"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="暂停" /></LinearLayout></LinearLayout>

将按钮的布置尽量美观并且符合玩家习惯。
布局效果展示:

算法设计

界面的设计完成过后,现在需要进行算法的更新以及按钮的适配。
由繁入简,我们需要先将游戏面板的内容完善,再逐渐布局“贪食蛇”

游戏面板类

在这个类里,我们需要完成定义界面高度和宽度,蛇身的类调用,分数,速度,开始游戏,格子大小,活动范围,蛇长算法,食物坐标,方向,食物与蛇身重叠,蛇头位置,按键过快导致BUG等问题。
首先完成声明定义:

class GamePanel  extends View implements View.OnTouchListener {public int wid,hei;//获得View的宽和高public ArrayList<SnackBody> body = new ArrayList<SnackBody>(); //蛇身public  int score;//分数public  int  speed;//速度public boolean start;//开始游戏private static final int MAX_Height = 20;private  static  final  int MAX_Width = 20; //活动范围20*20private int rectSize; //每一格子大小private  int snackLength ;//蛇长private int foodX,foodY;//食物坐标private Random random;private Paint paint;private int direction; //方向private int eatSign; // 用于判断刷新下一个食物是否和蛇身重叠private Snack snack;private DirectiomThread left = new DirectiomThread(this,1);private DirectiomThread up = new DirectiomThread(this,2);private DirectiomThread right = new DirectiomThread(this,3);private DirectiomThread down = new DirectiomThread(this,4);private int itemX,itemY; //判断蛇头位置public int lastDirection;//限制过于快速按键吃掉自己BUGpublic GamePanel(Context context) { super(context); }public GamePanel(Context context, AttributeSet attributeSet){super(context,attributeSet);}

其次是初始化定义,将分数设为0,速度为100,蛇头方向,食物方向,蛇身长度都完成初始化定义。

 public void init(){rectSize = wid/MAX_Width;  score = 0;   speed = 100;itemX = -1;itemY = -1;body.clear();snackLength= 0;random = new Random();paint = new Paint();paint.setAntiAlias(true);direction  =3;lastDirection = 3;this.setWillNotDraw(false);}

然后完成画布的颜色分类,前期的准备工作就基本完成了:

protected void onDraw(Canvas canvas){//画布if (start){paint.setColor(Color.YELLOW);   //食物颜色canvas.drawRect(foodX*rectSize,foodY*rectSize,foodX*rectSize+rectSize,foodY*rectSize+rectSize,paint);if (body.size()>0){paint.setColor(Color.BLUE);   //头部颜色canvas.drawRect(body.get(0).getX()*rectSize,body.get(0).getY()*rectSize,body.get(0).getX()*rectSize+rectSize,body.get(0).getY()*rectSize+rectSize,paint);paint.setColor(Color.GREEN);    //身体颜色for (int i=1;i<body.size();i++){canvas.drawRect(body.get(i).getX()*rectSize,body.get(i).getY()*rectSize,body.get(i).getX()*rectSize+rectSize,body.get(i).getY()*rectSize+rectSize,paint);}paint.setColor(Color.RED);paint.setTextSize(50);canvas.drawText("分数:" + score, wid-300, wid-20, paint); //分数}}}

如图,蓝色为蛇头,绿色为蛇身,黄色为食物,红色为分数提示。

为了后续蛇身移动,定义方向,还需要一个大小更改的定义:

 protected void onSizeChanged(int w,int h,int oldw,int oldh){super.onSizeChanged(w,h,oldw,oldh);wid = w;hei = h;}

完成这些设置之后,我们开始写点击开始游戏后的算法:
点击开始游戏后,会自动向右边移动,蛇身位置会从newBody到newBody2;

public void startGame(){   //开始游戏init();start = true;SnackBody newBody = new SnackBody();newBody.setX(MAX_Width/2);newBody.setY(MAX_Height/2);SnackBody newBody2 = new SnackBody();newBody2.setX(MAX_Width/2-1);newBody2.setY(MAX_Width/2);body.add(newBody);body.add(newBody2);do {foodX = random.nextInt(MAX_Width-1);foodY = random.nextInt(MAX_Height-1);}while (foodX == newBody.getX() && foodY == newBody.getY());snack = new Snack(this);snack.start();}

游戏开始后,蛇体可由玩家控制,我们需要完成一个移动的算法:

 public void move(int x,int y){   //移动itemX = body.get(0).getX()+x;itemY = body.get(0).getY()+y;if (itemX == foodX && itemY == foodY){eat();for (int i = body.size()-2;i>0;i--){body.get(i).setX(body.get(i-1).getX());body.get(i).setY(body.get(i-1).getY());}}else {for (int i = body.size() - 1; i > 0; i--) {body.get(i).setX(body.get(i - 1).getX());body.get(i).setY(body.get(i - 1).getY());}}body.get(0).setX(body.get(0).getX() + x);body.get(0).setY(body.get(0).getY() + y);}

贪食蛇的重点在于吃,吃了以后身体会加长:
每吃到一个食物,身体就会张长。将身体张长的数据增加到growbody数据类中。

 public void eat(){    //吃score = score+10;snackLength++;do {eatSign = 0;foodX = random.nextInt(MAX_Height-1);foodY = random.nextInt(MAX_Width-1);for (int i = 0; i<body.size();i++){if (foodX == body.get(i).getX() && foodY == body.get(i).getY()){eatSign++;}}if (foodX == itemX  && foodY == itemY)eatSign++;}while (eatSign>0);SnackBody growBody = new SnackBody();growBody.setX(body.get(body.size()-1).getX());growBody.setY(body.get(body.size()-1).getY());body.add(growBody);}

贪食蛇的死亡判定为撞到边界或者自己身体,此时游戏会结束。

 public boolean hitOrBite(){    //碰到边界if (body.get(0).getX() < 0 || body.get(0).getX() >= 20|| body.get(0).getY() < 0 || body.get(0).getY() >= 20)return true;else {for (int i = body.size() - 1; i > 2; i--) {if (body.get(0).getX() == body.get(i).getX()&& body.get(0).getY() == body.get(i).getY())return true;}}return false;}public void dead() { }public int getDirection(){return direction;}public void setDirection(int direction) {this.direction = direction;}public int getScore() {return score;}

完成上面的算法,我们仅仅完成了游戏展示界面以及其算法。下面我们还要继续完善按钮控制的算法。
为防止BUG冲突,例如蛇头突然180°转头导致游戏结束。设置了以下规则:当蛇头为左边时候,不难按下右键,以此类推。

@Overridepublic boolean onTouch(View v, MotionEvent event) {if (v.getId() == R.id.left && event.getAction() == MotionEvent.ACTION_DOWN){if (lastDirection !=3 ){left = new DirectiomThread(this,1);up.canRun = false;right.canRun = false;down.canRun = false;left.canRun = true;left.start();}}else if (v.getId() == R.id.left && event.getAction() == MotionEvent.ACTION_UP){left.canRun = false;}if (v.getId() == R.id.up && event.getAction() == MotionEvent.ACTION_DOWN){if (lastDirection !=4 ){up = new DirectiomThread(this,2);up.canRun = true;right.canRun = false;down.canRun = false;left.canRun = false;up.start();}}else if (v.getId() == R.id.up && event.getAction() == MotionEvent.ACTION_UP){up.canRun = false;}if (v.getId() == R.id.right && event.getAction() == MotionEvent.ACTION_DOWN){if (lastDirection !=1 ){right = new DirectiomThread(this,3);up.canRun = false;right.canRun = true;down.canRun = false;left.canRun = false;right.start();}}else if (v.getId() == R.id.right && event.getAction() == MotionEvent.ACTION_UP){right.canRun = false;}if (v.getId() == R.id.down && event.getAction() == MotionEvent.ACTION_DOWN){if (lastDirection !=2 ){down = new DirectiomThread(this,4);up.canRun = false;right.canRun = false;down.canRun = true;left.canRun = false;down.start();}}else if (v.getId() == R.id.right && event.getAction() == MotionEvent.ACTION_UP){down.canRun = false;}

规范了游戏规则后,还需设定开始游戏以及暂停,继续游戏的算法:

if (v.getId() == R.id.start && event.getAction() == MotionEvent.ACTION_UP && start==false){this.startGame();}if (v.getId() == R.id.Continue && event.getAction() == MotionEvent.ACTION_UP && start ==false){start = true;snack = new Snack(this);snack.start();}if (v.getId() == R.id.Stop && event.getAction() == MotionEvent.ACTION_UP){start = false;}return false;

如此,游戏面板类的内容大致完成,接下面是完善蛇身类,方向类,蛇类定义以及最后的主函数使用。
接下来这三类均为游戏面板类线程的子线程,为方便修改。

蛇身类

此类用来定义蛇身的位置信息:
自动完善get和set方法。

class SnackBody {private int x,y;public int getX() {return x;}public int getY() {return y;}public void setX(int x) {this.x = x;}public void setY(int y) {this.y = y;}
}

蛇类

此类用来定义蛇体本身的跟踪,调用游戏面板类的算法集合。

class Snack extends  Thread {private GamePanel gamePanel;   //声明地图public Snack(GamePanel gamePanel){this.gamePanel= gamePanel;}  //声明蛇存在地图public void run(){   //处理的逻辑while (gamePanel.start){   //当点击开始try {long before = System.currentTimeMillis();  //开始前时间gamePanel.postInvalidate();   //调用gamePanellong after= System.currentTimeMillis();   //结束时间Thread.sleep((int)((20000/gamePanel.speed)-(after-before)));  //蛇移动速度}catch (InterruptedException e){   //中断异常e.printStackTrace();    //追踪}switch (gamePanel.getDirection()){case 1:                             //选择左gamePanel.move(-1,0);            //X轴向左移动一个像素,y轴不变gamePanel.lastDirection = 1;    //最后一个位置为:左break;case 2:                           //选择上gamePanel.move(0,-1);           // X轴不变,y轴向上移动一个像素gamePanel.lastDirection = 2;    //最后一个位置为:上break;case 3:                             //选择右gamePanel.move(1,0);               //X轴向右移动一个像素,y轴不变gamePanel.lastDirection = 3;      //最后一个位置为:右break;case 4:                             //选择右gamePanel.move(0,1);                // X轴不变,y轴向下移动一个像素gamePanel.lastDirection = 4;          //最后一个位置为:下break;}if (gamePanel.hitOrBite()){    //撞到墙壁gamePanel.start = false;   //结束游戏gamePanel.dead();      //蛇死亡continue;}}}
}

方向类

此类用来定义蛇的方向条件以及蛇的速度:

class DirectiomThread  extends  Thread{private GamePanel gamePanel;private int direction;public  boolean canRun;public DirectiomThread(GamePanel gamePanel,int direction){this.gamePanel = gamePanel;this.direction = direction;}public void run(){while (canRun){gamePanel.setDirection(direction);try {Thread.sleep(10);}catch (InterruptedException e){e.printStackTrace();}}}
}

主函数类

在主函数中需要添加一段重要代码,该代码为调用游戏面板类进行游戏展示:

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)gamePanel.getLayoutParams();gamePanel.setLayoutParams(params);params.width = width;params.height = width;

如此就能够完成贪食蛇的游戏展示
主函数完全代码:

public class game extends AppCompatActivity {private Button up,left,right,down;private Button start,back,Continue,Stop;private GamePanel gamePanel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_game);getSupportActionBar().hide();//隐藏标题栏getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//隐藏状态栏up = findViewById(R.id.up);left = findViewById(R.id.left);right = findViewById(R.id.right);down = findViewById(R.id.down);start = findViewById(R.id.start);back = findViewById(R.id.back);Continue = findViewById(R.id.Continue);Stop = findViewById(R.id.Stop);DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);int width = metrics.widthPixels;int height  = metrics.heightPixels;gamePanel = findViewById(R.id.gamePanel);gamePanel.setBackgroundColor(Color.LTGRAY);RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)gamePanel.getLayoutParams();gamePanel.setLayoutParams(params);params.width = width;params.height = width;start.setOnTouchListener(gamePanel);Continue.setOnTouchListener(gamePanel);back.setOnTouchListener(gamePanel);Stop.setOnTouchListener(gamePanel);left.setOnTouchListener(gamePanel);right.setOnTouchListener(gamePanel);up.setOnTouchListener(gamePanel);down.setOnTouchListener(gamePanel);back.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(game.this,Main2.class);startActivity(intent);finish();}});}protected void onStart(){super.onStart();}protected void onStop(){super.onStop();}protected  void onPause(){super.onPause();gamePanel.start = false;}protected void onResume() {super.onResume();}protected void onRestart() {super.onRestart();}protected void onDestroy() {super.onDestroy();}
}

大家也可以一起尝试开发出自己的贪食蛇小游戏哟

Android 贪食蛇相关推荐

  1. android贪食蛇详细教程实现加源码

    转载请注明出处:http://blog.csdn.net/b2569449528/article/details/78475327 工作需要开发了一个贪食蛇apk预装到公司产品,共10关.包含了游戏得 ...

  2. 一个完整的嵌入式程序_【荐读】贪食蛇游戏的Android嵌入式系统设计

    贪食蛇游戏的Android嵌入式系统设计 Design of Android Embedded-System for Greedy Snake Game 作者: 韩 中, 苟和平, 李 援:琼台师范学 ...

  3. linux终端贪吃蛇,分享|nSnake: 在Linux的终端上玩经典的贪食蛇游戏

    你知道20世纪末的那些古老的诺基亚手机上最棒的东西是什么吗? 贪食蛇! 我以前在这个看似无聊但却让人上瘾的游戏上花费了大把的时间.在古老的诺基亚手机被智能手机取代的同时,贪食蛇也被另外的无聊但却令人上 ...

  4. [原]Console小技巧——Console版贪食蛇

    这一篇是我的Console小技巧的最后一篇文章,以下是索引: 1.[原]Console小技巧--七彩输出 2.[原]Console小技巧--字符涂鸦 3.[原]Console小技巧--Console版 ...

  5. tomcat websock html5,websocket实战(4) websocket版贪食蛇游戏(tomcat官方自带)

    通过前面3篇的阐述,相信可以构建一个简单的socket应用了.当然,也会遗漏了许多知识点,相信会在以后分享的实例中捎带说明下. 本文的主要是分析下tomcat官方自带的贪食蛇游戏.为什么选择分析这个项 ...

  6. java小程序贪吃蛇代码_微信小程序Demo之贪食蛇

    原标题:微信小程序Demo之贪食蛇 差不多大半年前,笔者发布了一篇关于OC版贪食蛇开发的文章,时隔多月,微信小程序横空出世,于是闲来无事的我又写了一个小程序版. 01页面布局 关于小程序笔者就不做介绍 ...

  7. 【第三篇:利用ChatGPT编写贪食蛇小游戏】

    好像现在最近对ChatGPT讨论越来越热,ChatGPT的出现应该会引发"一次新的社会变革",未来很多码农会失业啊!与其坐着被改变,不如尝试主动改变,我今天就利用ChatGPT编写 ...

  8. 原生js实现贪食蛇小游戏

    先不多说先上图 下面是代码部分(这里你可以根据需要改变蛇头和身体还有食物的图片,然后默认的样式是使用纯颜色的如果没有更改我的背景图片的话------改这些图开始是想搞笑一下朋友哈哈哈,请不要在意哈), ...

  9. 使用C++设计贪食蛇小游戏

    说明:所有代码均可在Visual Studio 2013上编译执行.并未测试在其它编译器上编译情况. 游戏规则 贪食蛇游戏要求玩家控制方向键(或WSAD键)来控制小蛇的前进方向,以使蛇吃掉面板上随即位 ...

最新文章

  1. vs连接mysql建一个表并增删查改_VS连接SQL Server数据库,增删改查详细教程(C#代码)...
  2. 使用VC++6.0创建MFC对话框程序
  3. php javabean对象,Struts2 bean标签:创建并示例化一个JavaBean对象
  4. 局部特征(3)——SURF特征总结
  5. python输出字母金字塔可以输入字母和行数的_python实现输入任意一个大写字母生成金字塔的示例...
  6. [ActiveRecord] 之ActiveRecordMediator
  7. 法国 计算机 转专业,在法国留学怎样换专业
  8. android屏幕适配教程,Android屏幕适配方案,android屏幕适配
  9. 计算机组成原理 第七章 输入输出系统
  10. React Native悬浮效果组件
  11. 堆——神奇的优先队列(上)
  12. Eclipse—在Eclipse中如何发布创建的JavaWeb工程
  13. C#中各种字符类型的转化
  14. python字典快速一览
  15. python 导出依赖包
  16. 制作Win10PE启动盘
  17. lvgl 主要文件目录树
  18. 2008最火爆的十大网络流行语
  19. 变限积分性质的总结笔记
  20. DELL G7 重装win10系统

热门文章

  1. 【php】PHP数据库访问
  2. Opencv 基础(三):使用OpenCV裁剪图像
  3. 2008年GCT考试真题A卷
  4. QCM2290 充电指示灯 —— CHG_LED_SINK
  5. 人工智能行业岗位有哪些?
  6. 安卓:三分钟实现物流配送页面(时间轴效果)
  7. docker版mongodb数据同步到elasticsearch
  8. mysql 查询dual报错_MYSQL基础02(查询)
  9. mac macbook应用清单
  10. 安卓开发新手入门教程!Android学习路线指南,复习指南