android 小游戏 ---- 数独(四)

segment 4

android 小游戏 ----  数独(四)

好的,棋盘绘制出来了。那么我们如何在空白方格中填写数字呢?

这时按钮就发挥出来它的作用了。

我们在控制器类game中设置一个标志,标示当前用户想要填写的数字,

可以通过监听器监听当前用户点击是哪个按钮,然后用game的set方法设置一下。

首先在MainActivity.java 中设置一下监听器。

public class MainActivity extends Activity {

    private Game game;
    private Button btn_1;
    private Button btn_2;
    private Button btn_3;
    private Button btn_4;
    private Button btn_5;
    private Button btn_6;
    private Button btn_7;
    private Button btn_8;
    private Button btn_9;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        game = Game.getGameInstance();

        //取得View
        findButtonViewById();
        //设置监听器
        setButtonOnClickListener();

    }

    private void setButtonOnClickListener() {
        btn_1.setOnClickListener(new OnBtnClickListener(1));
        btn_2.setOnClickListener(new OnBtnClickListener(2));
        btn_3.setOnClickListener(new OnBtnClickListener(3));
        btn_4.setOnClickListener(new OnBtnClickListener(4));
        btn_5.setOnClickListener(new OnBtnClickListener(5));
        btn_6.setOnClickListener(new OnBtnClickListener(6));
        btn_7.setOnClickListener(new OnBtnClickListener(7));
        btn_8.setOnClickListener(new OnBtnClickListener(8));
        btn_9.setOnClickListener(new OnBtnClickListener(9));
    }

    private void findButtonViewById() {
        btn_1 = (Button)findViewById(R.id.num_1);
        btn_2 = (Button)findViewById(R.id.num_2);
        btn_3 = (Button)findViewById(R.id.num_3);
        btn_4 = (Button)findViewById(R.id.num_4);
        btn_5 = (Button)findViewById(R.id.num_5);
        btn_6 = (Button)findViewById(R.id.num_6);
        btn_7 = (Button)findViewById(R.id.num_7);
        btn_8 = (Button)findViewById(R.id.num_8);
        btn_9 = (Button)findViewById(R.id.num_9);
    }

    class OnBtnClickListener implements OnClickListener{

        //以id标识按下的是哪一个数字键盘按钮
        int id;

        public OnBtnClickListener(int id){
            this.id = id;
        }
        @Override
        public void onClick(View view) {
            game.setSelectCurNumber(this.id);
        }

    }
}

监听器类使用内部类实现,我们重写监听器类的构造方法,给按钮设置监听器时传一个id参数作为标示。

然后如何在棋盘中绘制呢,其实每绘制一个数字,surfaceview都会重绘,只不过速度很快,且我们控制

其他重绘的部分都不变,所以在视觉效果上就造成了只绘制一个数字的效果。

想象我们绘制数字的过程,是把int数组一一取出来在棋盘上对应的方格内绘制,那么我们要绘制新的数字

也可以这么来。

为了区分初始化数组,我们设置一个临时数组,用于保存游戏中的数据

//临时数组 存储游戏中的棋盘对应值
    private int[] temp_sudoku = new int[9*9];

当然 他需要初始化,初始化所需数据和棋盘的初始化数据一样,

public Game(){
        sudoku = fromPuzzleString(init_str);
        temp_sudoku = fromPuzzleString(init_str);

    }
/**
     *根据一个字符串数据 生成一个整形数组 数独游戏的初始化数据
     */
    protected int[] fromPuzzleString(String str){
        int[] sudo =  new int[str.length()];
        for(int i=0;i<sudo.length;i++){
            //charAt()返回指定索引处的 char值    分解字符串填充到数组
            //减去0 做类型转换 使之成为int类型
            sudo[i]=str.charAt(i)-‘0‘;
        }
        return sudo;
    }

好的,接下我们就可以在用户填写数字点击方格时,计算出来当前的坐标,并更新临时数组中的数据,

再用临时数组中的数据在棋盘上重绘以到达填充数据的效果。

@Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction() != MotionEvent.ACTION_DOWN){
            return super.onTouchEvent(event);
        }
        clicked = true;
        //用户点击的屏幕的坐标点
        selectedX = (int)(event.getX() / width);
        selectedY = (int)(event.getY() / height);

        //超出棋盘的点击 无效  直接返回
        if(!game.isVaildClick(selectedX, selectedY)){
            return super.onTouchEvent(event);
        }

        //不超出棋盘 点击初始化已经存在的数字 直接返回
        if(!game.getTileString(selectedX, selectedY).equals("")){
            return super.onTouchEvent(event);
        }
        game.setNewTileString(selectedX, selectedY, game.getSelectCurNumber());
        //显示选中方格的相对坐标
        //Toast.makeText(getContext(), "("+selectedX+","+selectedY+")", Toast.LENGTH_SHORT).show();
        draw();
        number++;
        if(game.isWin()){
            showWinDialog();
            //Toast.makeText(getContext(), "恭喜你完成了!!", Toast.LENGTH_LONG).show();
        }
        return true;
    }
/**
     * 绘制新填入的数据
     * @param canvas
     * @param paint
     */
    private void inflateNewNum(Canvas canvas, Paint paint) {
        setFontStyle(paint);
        //设置数字在单元格里显示居中
        FontMetrics fm = paint.getFontMetrics();
        float x = width/2;
        float y = height/2-(fm.ascent+fm.descent)/2;
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                canvas.drawText(game.getNewTileString(i, j), i*width+x, j*height+y, paint);
            }
        }
    }

什么时候才计算用户是否完成了游戏呢,

/**
     * 判断是否成功完成数独
     * 只要临时数组中还有0
     * 则一定是未完成棋盘的填充
     * 判断临时数组不含0时 与正确字符串相匹配
     * 相同则为完成
     */
    public boolean isWin(){
        for (int i = 0 ; i < temp_sudoku.length ; i++) {
            if(0 == temp_sudoku[i]){
                return false;
            }
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < temp_sudoku.length; i++) {
            sb.append(temp_sudoku[i]);
        }
        if(sb.toString().equals(correct_str)){
            return true;
        }
        return false;
    }

每次填充判断一次,直到完成游戏。

游戏中还针对操作步数做了计算,即重绘棋盘的次数。

菜单中有开启辅助条的功能,可以凸显横竖9个数字,这里就不在详述了。

   

源码中有关于数据库的类,这里希望从数据库中读取初始数据字符串和正确数据字符串,并能在退出时保存临时数据字符串,时间有限并未完成.按钮区域的undo按钮本意是要执行撤销操作的,也没有实现。可以自行添加这些功能。

这里使用的完整数据如下

以上仅供参考。

附上源码:

http://pan.baidu.com/s/1gdJ3TKJ

附上apk(bin目录下的,未签名):

http://pan.baidu.com/s/1qWPrlNm

时间: 2024-08-28 21:46:46

android 小游戏 ---- 数独(四)的相关文章

android 小游戏 ---- 数独(一)

segment 1 android 小游戏 ----  数独(一) 规则:在9X9的棋盘中,每个横行和竖列中的9个格子都包含数字1至9,不重复, 且每个黑色粗实线围住的9个格子都包含数字1至9,不重复. 既然涉及到棋盘,那就少不了绘图,我们知道在android中绘图的工作是由UI线程完成的, 一般是指主线程,而android系统设定UI绘图线程超过5秒不响应就会报异常,所以一般在 子线程中进行数据的计算,然后将消息发给UI线程,使之更新界面. 在Java中我们可以通过View来绘图,在默认情况下

android 小游戏 ---- 数独(三)

segment 3 android 小游戏 ----  数独(三) 好的,既然要把数独棋盘中初始提示数字绘制出来,我们就要先了解数独的一些特点. 数独棋盘中总共是81个数字,那我们是否可以用一个数组来代表整个棋盘对应的数字呢想象我们初始化一个9x9的数组,private int[] sudoku = new int[9*9] //初始化数据 private int[] sudoku = new int[9*9]; 这里使用一维数组,当然使用二维数组更加明了直接,这个随个人喜好. 那么我们可以让

android 小游戏 ---- 数独(二)

> 首先创建一个自己的View类 -->继承SurfaceView并实现SurfaceHolder.Callback接口 --> SurfaceView.getHolder()获得SurfaceHolder对象 -->SurfaceHolder.addCallback(callback) 添加回调函数 -->SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布 --> Canvas绘画 -->SurfaceHolder.unlockC

android小游戏模版—重力感应

好久没更新博客了,今天来谈谈android小游戏---重力感应,一般在游戏里运用的比较多,比如这类游戏有:神庙逃亡,极品飞车,平衡球,三围重力迷宫,重力赛车等. 首先什么是重力感应,重力感应是指现在手机中常用的一个器件,及加速度传感器.当手机静止时,加速度就是重力,所以一般也叫做重力传感器.这个硬件可以感应加速度的变化,转化为数据提供给系统.还有一种传感器是陀螺仪,检测围绕某轴的旋转动作,是利用有质量的刚体的在做旋转或震动时,如果发生垂直于旋转或震动轴的旋转,因为惯性会产生垂直于旋转或震动轴的柯

Android开发系列(十六):【Android小游戏成语连连看】第二篇

写的晚了,在分工个Z市高中的一个成绩查询的系统,原系统竟然是用VB写的,我不得不佩服原本写系统的那位哥们真能耐得住. 明天搭建下SVN就等着先发工程款然后开始项目了,想想有工资进账,心里也为我那干瘪的钱包小兴奋了一把. 闲话不多说了,今天我们来分析下这个小游戏的工作原理以及核心代码的解析: 工作原理: "主界面"以及"关卡界面"不多说了,这两个是直接写了xml文件, 然后,我们在"游戏界面"的搭建是: 用java代码动态生成了这个界面,在界面中通

软件工程 Android小游戏 猜拳大战

一.前言 最近学校举办的大学生程序设计竞赛,自己利用课余时间写了一个小游戏,最近一直在忙这个写这个小游戏,参加比赛,最终是老师说自己写的简单,可以做的更复杂的点的.加油 二.内容简介 自己玩过Android系统下的节奏大师,自己也就考虑做一个类似的,然后自己写技术水平有限,还是在学习Android阶段,自己就想到可以写一个猜拳的比较小游戏. 这是一款基于Android平台小游戏—猜拳大战,简单,易操作,趣味强,训练反应速度,内存小,没有广告,安全. 最大的特点:训练人的反应速度. 游戏规则:在3

介绍一款Android小游戏--交互式人机对战五子棋

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6589025 学习Android系统开发之余,编写了一个小游戏--交互式人机对战五子棋,自娱自乐.之所以称之为交互式人机对战五子棋,一是因为在进入人机对战模式这前,你可以任意设置好开局,同时,在对战过程中,你可以看到机器的思考过程,还可以标识出每一个落子点的优劣势:二是因为可以为机器增加游戏经验,使得机器越来越聪明.希望喜欢五子棋的同学能够喜欢,

Android开发系列(十五):【Android小游戏成语连连看】第一篇

学了一个多月安卓,因为暑假的时候要给朋友说写个小游戏,而且也想检测下自己的能力,所以说从7号开始就着手写这个小游戏了,前前后后带上课到今天总算是写完了,但是写的这个小游戏还是有很多问题,但是还好,勉强能跑起来,一些瑕疵就不要在乎太多了,毕竟咱又不准备发布供别人下载. APK安装包下载链接(我给放在百度云盘了,可以直接点击下载):http://pan.baidu.com/s/1bnxpQrH 代码文件下载:(放在CSDN的下载那里了,不需要积分):http://download.csdn.net/

Python编写微信打飞机小游戏(四)

之前的工作已经基本上将我方飞机的图形显示工作做的差不多了,这篇博客中我们将开始添加敌方飞机——小型敌机.中型敌机(直升机)和大型敌机(坦克).新建一个enemy.py文件,导入pygame和random模块,开始编写吧(还是要注意文件编码问题,以后就不再啰嗦了). 敌方飞机类与我方飞机模块有一定的相似性,但不会左右移动,不会发射子弹等等.小型敌机是敌方飞机中最基本的类型,一击毙命,没有血量.没有出场音效.中型敌机有一定血量,损毁时附带特殊音效.大型敌机血量最多,出场和损毁时都有特殊音效,游戏中中