热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android游戏之数独游戏开发

这篇文章主要为大家详细介绍了Android游戏之数独游戏开发的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

 数独游戏是一种源自18世纪末的瑞士的游戏,后在美国发展、并在日本得以发扬光大的数学智力拼图游戏。在每一个小九宫格中,分别填上1至9的数字,让整个大九宫格每一列、每一行的数字都不重复。 数独的玩法逻辑简单,数字排列方式千变万化,是锻炼脑筋的好方法。

本文实现简单的数独游戏,通过mars的视频教程完成编程
1.自定义View:

package com.example.administrator.shudugame;

/**
 * Created by Administrator on 2016/9/19.
 */

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class MyView extends View{

  public MyView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }
  //方格长宽
  float width;
  float height;
  //选定的坐标
  int selectX;
  int selectY;
  MyGame mGame=new MyGame();

  //获得屏幕尺寸
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    //每一个小格的长宽
    this.width=w/9f;
    this.height=h/9f*2/3;
  }


  //绘图函数
  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //画背景
    Paint bgPaint=new Paint();
    bgPaint.setColor(getResources().getColor(R.color.bg));
    canvas.drawRect(0,0,getWidth(),getHeight()*2/3f, bgPaint);
    //线条画笔
    Paint darkPaint =new Paint();
    darkPaint.setColor(getResources().getColor(R.color.dark));
    Paint hilitePaint =new Paint();
    hilitePaint.setColor(getResources().getColor(R.color.hilite));
    Paint lightPaint =new Paint();
    lightPaint.setColor(getResources().getColor(R.color.light));
    //绘制线条
    for(int i=0;i<9;i++){
      canvas.drawLine(0, i*height,getWidth(),i*height,lightPaint);
      canvas.drawLine(0, i*height+1,getWidth(),i*height+1,hilitePaint);
      canvas.drawLine(i*width, 0,i*width,getWidth()+width*0.4f,lightPaint);
      canvas.drawLine(i*width+1,0,i*width+1,getWidth()+width*0.4f,hilitePaint);
      if(i%3==0){
        canvas.drawLine(0, i*height,getWidth(),i*height,darkPaint);
        canvas.drawLine(0, i*height+3,getWidth(),i*height+3,hilitePaint);
        canvas.drawLine(i*width, 0,i*width,getWidth()+width*0.4f,darkPaint);
        canvas.drawLine(i*width+3, 0,i*width+3,getWidth()+width*0.4f,hilitePaint);
      }
    }
    //绘制数字
    Paint numberPaint =new Paint();
    numberPaint.setColor(Color.BLACK);
    numberPaint.setStyle(Paint.Style.STROKE);
    numberPaint.setTextSize(height*0.75f);
    numberPaint.setTextAlign(Align.CENTER);

    //调节文字居中
    FontMetrics fMetrics=numberPaint.getFontMetrics();
    float x=width/2;
    float y=height/2-(fMetrics.ascent+fMetrics.descent)/2;
    for(int i=0;i<9;i++)
    {
      for(int j=0;j<9;j++)
      {
        canvas.drawText(mGame.getNumber(i+1, j+1), i*width+x, y+j*height, numberPaint);
      }
    }

  }
  //触摸事件
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    int x=(int)(event.getX()/width);
    int y=(int)(event.getY()/height);
    if(x<=8 && y<=8){ //判断点击的是否是游戏界面
      int []t=mGame.getUsed(x, y);
      selectX=x;
      selectY=y;
      MyDialog mDialog=new MyDialog(getContext(), t, this); //调用自定义Dialog
      mDialog.show();
    }
    return super.onTouchEvent(event);
  }
  public void setTitle(int i){
    mGame.setTitle(i,selectX,selectY);
    invalidate(); //每次填写一个数 都要重新进行绘制
    mGame.youWin();
  }
}

2.新建MyGame类:

package com.example.administrator.shudugame;

import android.content.Context;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;

/**
 * Created by Administrator on 2016/9/19.
 */
public class MyGame {

  Context context;
  String data="008309100" +
      "900060004" +
      "007504800" +
      "036000540" +
      "001000600" +
      "042000970" +
      "005907300" +
      "600010008" +
      "004608200";
  int numbers[][] =new int[9][9];
  public MyGame(){
    //初始化data
    for(int i=0;i<9;i++)
      for(int j=0;j<9;j++)
      {
        numbers[i][j]=data.charAt(i+j*9)-'0'; //字符转化为整形
      }
  }
  //得到值
  public String getNumber(int x,int y){
    if(numbers[x-1][y-1]==0)
      return "";
    else
      return ""+numbers[x-1][y-1];
  }
  //算出已经被用的数字
  public int[] getUsed(int x,int y){
    int c[]=new int[9];
    //x列
    for(int i=0;i<9;i++)
    {
      if(numbers[x][i]!=0)
      {
        c[numbers[x][i]-1]=numbers[x][i];
      }
    }
    //y排
    for(int i=0;i<9;i++)
    {
      if(numbers[i][y]!=0)
      {
        c[numbers[i][y]-1]=numbers[i][y];
      }
    }
    //小九宫格
    x=(x/3)*3;
    y=(y/3)*3;
    for(int i=0;i<9;i++)
    {
      if(numbers[x+i%3][y+i/3]!=0)
      {
        c[numbers[x+i%3][y+i/3]-1]=numbers[x+i%3][y+i/3];
      }
    }
    return c;
  }
  //设置选定的数字
  public void setTitle(int i,int x,int y){
    numbers[x][y]=i;
  }
  //判断游戏结束
  public void youWin(){
    int t=0;
    for (int i=0;i<9;i++){
      for (int j=0;j<9;j++){
        if (numbers[i][j]!=0){
           t++;
        }
      }
    }
    if (t==81){
      AlertDialog.Builder builder=new AlertDialog.Builder(context);
      builder.setTitle("Tips")
          .setMessage("You Win !")
          .setPositiveButton("Restart", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
          })
          .setNegativeButton("Exit", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
              System.exit(0);
            }
          }).show();
    }
  }
}

3.自定义Dialog类:

package com.example.administrator.shudugame;

/**
 * Created by Administrator on 2016/9/19.
 */
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;

public class MyDialog extends Dialog{

  MyView mView;
  View keys[]=new View[9];
  int []used=new int[9];

  //传入已经使用过的数字
  public MyDialog(Context context, int[] useed, MyView m) {
    super(context);
    this.mView=m;
    this.used=useed;

  }
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //设置标题
    setTitle("可选数字");
    //设置布局文件
    setContentView(R.layout.table);
    int id[]=new int[]{R.id.bt1,R.id.bt2,R.id.bt3,R.id.bt4,
        R.id.bt5,R.id.bt6,R.id.bt7,R.id.bt8,R.id.bt9};
    for(int i=0;i<9;i++)
    {
      final int t=i+1;
      keys[i]=findViewById(id[i]);
      keys[i].setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
          mView.setTitle(t);
          dismiss(); //取消对话框
        }
      });
    }
    for(int i=0;i<9;i++)
    {
      if(used[i]!=0)
        keys[used[i]-1].setVisibility(View.INVISIBLE); //将不可使用的数字对应的Button设置为隐藏
    }
  }
}

4.在MainActivity中,在onCreate()方法: 更改:setContentView(R.layout.activity_main); 为 setContentView(new MyView(this,attrs));

5.新建table.xml:

<&#63;xml version="1.0" encoding="utf-8"&#63;>


  



    

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 本文介绍如何使用布局文件在Android应用中排列多行TextView和Button,使其占据屏幕的特定比例,并提供示例代码以帮助理解和实现。 ... [详细]
  • 国内BI工具迎战国际巨头Tableau,稳步崛起
    尽管商业智能(BI)工具在中国的普及程度尚不及国际市场,但近年来,随着本土企业的持续创新和市场推广,国内主流BI工具正逐渐崭露头角。面对国际品牌如Tableau的强大竞争,国内BI工具通过不断优化产品和技术,赢得了越来越多用户的认可。 ... [详细]
  • 将Web服务部署到Tomcat
    本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • 本文介绍如何在 Unity 的 XML 配置文件中,将参数传递给自定义生命周期管理器的构造函数。我们将详细探讨 CustomLifetimeManager 类的实现及其配置方法。 ... [详细]
  • 本文详细介绍了 Java 中 org.apache.xmlbeans.SchemaType 类的 getBaseEnumType() 方法,提供了多个代码示例,并解释了其在不同场景下的使用方法。 ... [详细]
  • 本文详细介绍了如何解决MyBatis中常见的BindingException错误,提供了多种排查和修复方法,确保Mapper接口与XML文件的正确配置。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 本文探讨了在通过 API 端点调用时,使用猫鼬(Mongoose)的 findOne 方法总是返回 null 的问题,并提供了详细的解决方案和建议。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 本文探讨了在Windows Server 2008环境下配置Tomcat使用80端口时遇到的问题,包括端口被占用、多项目访问失败等,并提供详细的解决方法和配置建议。 ... [详细]
author-avatar
报告大王报报报报告大王
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有