首页 > 代码库 > android 小游戏 ---- 数独(四)
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
android 小游戏 ---- 数独(四)