数独游戏是一种源自18世纪末的瑞士的游戏,后在美国发展、并在日本得以发扬光大的数学智力拼图游戏。拼图是九宫格(即3格宽×3格高)的正方形状,每一格又细分为一个九宫格。在每一个小九宫格中,分别填上1至9的数字,让整个大九宫格每一列、每一行的数字都不重复。
数独的玩法逻辑简单,数字排列方式千变万化。不少教育者认为数独是锻炼脑筋的好方法,上外语阅读课的时候外教老师就很喜欢带我们玩这个,乐此不疲,老外的教学方式还是很受欢迎的。但是每次玩这个游戏的时候都要发一张数独游戏卡,嫌麻烦,就想着写一个demo放自己手机上,想想那个时候真是好奇心爆棚,碰上很火爆的小游戏都想整一个DIY的Demo,叨叨够了,哈哈,上源码。
一、界面布局
1.主界面
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@color/background"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:padding="30dip"
android:orientation="horizontal">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="25dip"
android:text="@string/main_title"
android:textSize="24sp" />
<Button
android:id="@+id/continue_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/continue_label" />
<Button
android:id="@+id/new_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/new_game_label" />
<Button
android:id="@+id/about_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/about_label" />
<Button
android:id="@+id/exit_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/exit_label" />
LinearLayout>
LinearLayout>
2.数字键盘布局
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keypad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@color/puzzle_background"
android:stretchColumns="*" >
<TableRow >
<Button
android:id="@+id/keypad_1"
android:text="@string/keypad_1" />
<Button
android:id="@+id/keypad_2"
android:text="@string/keypad_2" />
<Button
android:id="@+id/keypad_3"
android:text="@string/keypad_3" />
TableRow>
<TableRow >
<Button
android:id="@+id/keypad_4"
android:text="@string/keypad_4" />
<Button
android:id="@+id/keypad_5"
android:text="@string/keypad_5" />
<Button
android:id="@+id/keypad_6"
android:text="@string/keypad_6" />
TableRow>
<TableRow >
<Button
android:id="@+id/keypad_7"
android:text="@string/keypad_7" />
<Button
android:id="@+id/keypad_8"
android:text="@string/keypad_8" />
<Button
android:id="@+id/keypad_9"
android:text="@string/keypad_9" />
TableRow>
TableLayout>
3.游戏提示布局
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip">
<TextView
android:id="@+id/about_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/about_text"/>
ScrollView>
二、游戏提示类
package com.dw.gamesuduku;
import android.app.Activity;
import android.os.Bundle;
public class About extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.about);
}
}
三、逻辑实现1
package com.dw.gamesuduku;
import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.widget.Toast;
public class Game extends Activity {
private static final String TAG="Sudoku";
private static final String PREF_PUZZLE="puzzle";
protected static final int DIFFICULTY_CONTINUE=-1;
public static final String KEY_DIFFICULTY="difficulty";
public static final int DIFFICULTY_EASY=0;
public static final int DIFFICULTY_MEDIUM=1;
public static final int DIFFICULTY_HARD=2;
private int puzzle[]=new int[9*9];
private PuzzleView puzzleView;
//三种游戏模式
private static final String easyPuzzle="360000000004230800000004200"+
"070460003820000014500013010"+
"001900000007048300000000045";
private static final String mediumPuzzle="650000070000506000014000005"+
"007009000002314700000700800"+
"500000630000201000030000097";
private static final String hardPuzzle="009000000080605020501078000"+
"000000700706040102004000000"+
"000720903090301080000000600";
private final int used[][][]=new int[9][9][];
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Log.e(TAG, "onCreate");
int diff=getIntent().getIntExtra(KEY_DIFFICULTY, DIFFICULTY_EASY);
puzzle=getPuzzle(diff);
calculateUsedTiles();
puzzleView=new PuzzleView(this);
setContentView(puzzleView);
puzzleView.requestFocus();
//if the activity is restarted ,do a continue next time
getIntent().putExtra(KEY_DIFFICULTY, DIFFICULTY_CONTINUE);
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
Music.stop(this);
//Save the current puzzle
getPreferences(MODE_PRIVATE).edit().putString(PREF_PUZZLE, toPuzzleString(puzzle)).commit();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Music.play(this, R.raw.game);
}
protected int[] getUsedTiles(int x,int y){
return used[x][y];
}
private void calculateUsedTiles() {
// TODO Auto-generated method stub
for (int x = 0; x < 9; x++) {
for (int y = 0; y < 9; y++) {
used[x][y]=calculateUsedTiles(x,y);
}
}
}
private int[] calculateUsedTiles(int x, int y) {
// TODO Auto-generated method stub
int c[]=new int[9];
//horizontal
for(int i=0;i<9;i++){
if(i==y)
continue;
int t=getTitle(x, i);
if(t!=0)
c[t-1]=t;
}
//vertical
for(int i=0;i<9;i++){
if(i==x)
continue;
int t=getTitle(i, y);
if(t!=0)
c[t-1]=t;
}
//same cell block
int startx=(x/3)*3;
int starty=(y/3)*3;
for(int i=startx;i3;i++){
for(int j=starty;j3;j++){
if(i==x&&j==y)
continue;
int t=getTitle(i, j);
if(t!=0)
c[t-1]=t;
}
}
//compress
int nused=0;
for (int t : c) {
if(t!=0)
nused++;
}
int c1[]=new int[nused];
nused=0;
for (int t : c) {
if(t!=0)
c1[nused++]=t;
}
return c1;
}
//give a difficulty level
private int[] getPuzzle(int diff) {
// TODO Auto-generated method stub
String puz = null;
switch (diff) {
case DIFFICULTY_CONTINUE:
puz=getPreferences(MODE_PRIVATE).getString(PREF_PUZZLE, easyPuzzle);
break;
case DIFFICULTY_HARD:
puz=hardPuzzle;
break;
case DIFFICULTY_MEDIUM:
puz=mediumPuzzle;
break;
case DIFFICULTY_EASY:
puz=easyPuzzle;
break;
}
return fromPuzzleString(puz);
}
//convert an array into a puzzle string
static private String toPuzzleString(int[] puz){
StringBuilder buf=new StringBuilder();
for (int element : puz) {
buf.append(element);
}
return buf.toString();
}
//convert a puzzle string to an array
static protected int[] fromPuzzleString(String string) {
// TODO Auto-generated method stub
int[] puz=new int[string.length()];
for (int i = 0; i < puz.length; i++) {
puz[i]=string.charAt(i)-'0';
}
return puz;
}
public String getTitleString(int x, int y) {
// TODO Auto-generated method stub
int v=getTitle(x,y);
if(v==0)
return "";
else
return String.valueOf(v);
}
private int getTitle(int x, int y) {
// TODO Auto-generated method stub
return puzzle[y*9+x];
}
private void setTitle(int x,int y,int value){
puzzle[y*9+x]=value;
}
//change the tile only if it's a valid move
protected boolean setTileIfValid(int x, int y, int value) {
// TODO Auto-generated method stub
int tiles[]=getUsedTiles(x, y);
if(value!=0){
for (int tile : tiles) {
if(tile==value)
return false;
}
}
setTitle(x, y, value);
calculateUsedTiles();
return true;
}
//open the keypad if there are any valid moves
protected void showKeypadOrError(int x, int y) {
// TODO Auto-generated method stub
int tiles[]=getUsedTiles(x, y);
if(tiles.length==9){
Toast toast=Toast.makeText(this, R.string.no_moves_label, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.BOTTOM, 0, 0);
toast.show();
}else{
Log.d(TAG, "showKeypad:used="+toPuzzleString(tiles));
Dialog v=new Keypad(this,tiles,puzzleView);
v.show();
}
}
}
四、数字键盘
package com.dw.gamesuduku;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
public class Keypad extends Dialog {
protected static final String TAG="Sudoku";
private final View keys[]=new View[9];
private View keypad;
private final int useds[];
private PuzzleView puzzleView;
public Keypad(Context context,int useds[],PuzzleView puzzleView){
super(context);
this.useds=useds;
this.puzzleView=puzzleView;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.keypad);
findViews();
for (int element : useds) {
if(element!=0){
keys[element-1].setVisibility(View.INVISIBLE);
}
setListeners();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
int tile=0;
switch (keyCode) {
case KeyEvent.KEYCODE_0:
case KeyEvent.KEYCODE_SPACE:tile=0;break;
case KeyEvent.KEYCODE_1:tile=1;break;
case KeyEvent.KEYCODE_2:tile=2;break;
case KeyEvent.KEYCODE_3:tile=3;break;
case KeyEvent.KEYCODE_4:tile=4;break;
case KeyEvent.KEYCODE_5:tile=5;break;
case KeyEvent.KEYCODE_6:tile=6;break;
case KeyEvent.KEYCODE_7:tile=7;break;
case KeyEvent.KEYCODE_8:tile=8;break;
case KeyEvent.KEYCODE_9:tile=9;break;
default:
return super.onKeyDown(keyCode, event);
}
if(isValid(tile)){
returnResult(tile);
}
return true;
}
private boolean isValid(int tile) {
// TODO Auto-generated method stub
for (int t : useds) {
if(tile==t)
return false;
}
return true;
}
private void findViews() {
// TODO Auto-generated method stub
keypad=findViewById(R.id.keypad);
keys[0]=findViewById(R.id.keypad_1);
keys[1]=findViewById(R.id.keypad_2);
keys[2]=findViewById(R.id.keypad_3);
keys[3]=findViewById(R.id.keypad_4);
keys[4]=findViewById(R.id.keypad_5);
keys[5]=findViewById(R.id.keypad_6);
keys[6]=findViewById(R.id.keypad_7);
keys[7]=findViewById(R.id.keypad_8);
keys[8]=findViewById(R.id.keypad_9);
}
private void setListeners(){
for(int i=0;ifinal int t=i+1;
keys[i].setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
returnResult(t);
}
});
}
keypad.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
returnResult(0);
}
});
}
private void returnResult(int tile) {
// TODO Auto-generated method stub
puzzleView.setSelectedTile(tile);
dismiss();
}
}
五、背景音乐
package com.dw.gamesuduku;
import android.content.Context;
import android.media.MediaPlayer;
public class Music {
private static MediaPlayer mp=null;
//stop old song and start a new song
public static void play(Context context,int resource){
stop(context);
if(Settings.getMusic(context)){
mp=MediaPlayer.create(context, resource);
mp.setLooping(true);
mp.start();
}
}
//stop the music
public static void stop(Context context) {
// TODO Auto-generated method stub
if(mp!=null){
mp.stop();
mp.release();
mp=null;
}
}
}
六、逻辑实现2
package com.dw.gamesuduku;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
@SuppressLint("DrawAllocation")
public class PuzzleView extends View {
private static final String TAG = "Sudoku";
private final Game game;
private float width;
private float height;
private int selX;
private int selY;
private final Rect selRect = new Rect();
private static final String SELX="selX";
private static final String SELY="selY";
private static final String VIEW_STATE="viewState";
private static final int ID=42;//any positive int num
public PuzzleView(Context context) {
super(context);
this.game = (Game) context;
setFocusable(true);
setFocusableInTouchMode(true);
setId(ID);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
width = w / 9f;
height = h / 9f;
getRect(selX, selY, selRect);
Log.d(TAG, "onSizeChanged:width" + width + ",height" + height);
super.onSizeChanged(w, h, oldw, oldh);
}
//实例状态保存在bundle中,保存当前游戏状态
@Override
protected Parcelable onSaveInstanceState() {
// TODO Auto-generated method stub
Parcelable p=super.onSaveInstanceState();
Log.d(TAG, "onSavedInstanceState");
Bundle bundle=new Bundle();
bundle.putInt(SELX, selX);
bundle.putInt(SELY, selY);
bundle.putParcelable(VIEW_STATE, p);
return bundle;
}
//恢复已经保存的信息
@Override
protected void onRestoreInstanceState(Parcelable state) {
// TODO Auto-generated method stub
Log.d(TAG, "onRestoreInstanceState");
Bundle bundle=(Bundle) state;
select(bundle.getInt(SELX),bundle.getInt(SELY));
super.onRestoreInstanceState(bundle.getParcelable(VIEW_STATE));
return;
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
// draw background
Paint background = new Paint();
background.setColor(getResources().getColor(R.color.puzzle_background));
canvas.drawRect(0, 0, getWidth(), getHeight(), background);
// draw board
Paint dark = new Paint();
dark.setColor(getResources().getColor(R.color.puzzle_dark));
Paint hilite = new Paint();
hilite.setColor(getResources().getColor(R.color.puzzle_hilite));
Paint light = new Paint();
light.setColor(getResources().getColor(R.color.puzzle_light));
// draw minor grid lines
for (int i = 0; i < 9; i++) {
canvas.drawLine(0, i * height, getWidth(), i * height, light);
canvas.drawLine(0, i * height + 1, getWidth(), i * height + 1,
hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(), dark);
canvas.drawLine(i * width + 1, 0, i * width + 1, getHeight(),
hilite);
}
// draw major grid lines
for (int i = 0; i < 9; i++) {
if (i % 3 != 0)
continue;
canvas.drawLine(0, i * height, getWidth(), i * height, dark);
canvas.drawLine(0, i * height + 1, getWidth(), i * height + 1,
hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(), dark);
canvas.drawLine(i * width + 1, 0, i * width + 1, getHeight(),
hilite);
}
// draw numbers
Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
foreground.setColor(getResources().getColor(R.color.puzzle_foregroud));
foreground.setStyle(Style.FILL);
foreground.setTextSize(height * 0.75f);
foreground.setTextScaleX(width / height);
foreground.setTextAlign(Paint.Align.CENTER);
// draw num in the center of the tile
FontMetrics fm = foreground.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(this.game.getTitleString(i, j), i * width + x,
j * height + y, foreground);
}
}
// draw the selection
Log.e(TAG, "selRect=" + selRect);
Paint selected = new Paint();
selected.setColor(getResources().getColor(R.color.puzzle_selected));
canvas.drawRect(selRect, selected);
//draw the hints pick a hint color based on moves left
//根据每个单元格可填的数目给出不同颜色的提示
if(Settings.getHints(getContext())){
Paint hint=new Paint();
int c[]={getResources().getColor(R.color.puzzle_hint_0),
getResources().getColor(R.color.puzzle_hint_1),
getResources().getColor(R.color.puzzle_hint_2),};
Rect r=new Rect();
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int movesleft=9-game.getUsedTiles(i, j).length;
if(movesleft@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
Log.d(TAG, "onKeyDown:keycode=" + keyCode + ",event=" + event);
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
select(selX, selY - 1);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
select(selX, selY + 1);
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
select(selX - 1, selY);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
select(selX + 1, selY);
break;
case KeyEvent.KEYCODE_0:
case KeyEvent.KEYCODE_SPACE:
setSelectedTile(0);
break;
case KeyEvent.KEYCODE_1:
setSelectedTile(1);
break;
case KeyEvent.KEYCODE_2:
setSelectedTile(2);
break;
case KeyEvent.KEYCODE_3:
setSelectedTile(3);
break;
case KeyEvent.KEYCODE_4:
setSelectedTile(4);
break;
case KeyEvent.KEYCODE_5:
setSelectedTile(5);
break;
case KeyEvent.KEYCODE_6:
setSelectedTile(6);
break;
case KeyEvent.KEYCODE_7:
setSelectedTile(7);
break;
case KeyEvent.KEYCODE_8:
setSelectedTile(8);
break;
case KeyEvent.KEYCODE_9:
setSelectedTile(9);
break;
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_DPAD_CENTER:
game.showKeypadOrError(selX, selY);
default:
return super.onKeyDown(keyCode, event);
}
return true;
}
//显示软键盘
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction()!=MotionEvent.ACTION_DOWN)
return super.onTouchEvent(event);
select((int)(event.getX()/width),(int)(event.getY()/height));
game.showKeypadOrError(selX, selY);
Log.d(TAG, "onTouchEvent:x"+selX+",y"+selY);
return true;
}
public void setSelectedTile(int tile) {
// TODO Auto-generated method stub
//num is not valid for this tile
Log.d(TAG, "selectedTile:invalid:"+tile);
// startAnimation(AnimationUtils.loadAnimation(game, R.aims.shake));
if (game.setTileIfValid(selX, selY, tile)) {
invalidate();
} else {
// num is not invalid for this tile
Log.d(TAG, "setSelectedTile:invalid " + tile);
}
}
// 首先计算选定区域的x,y坐标,然后再次调用getRect方法计算新的选择矩形
private void select(int x, int y) {
// TODO Auto-generated method stub
invalidate(selRect);// 第一次调用通知原选择的区域需要重绘
selX = Math.min(Math.max(x, 0), 8);
selY = Math.min(Math.max(y, 0), 8);
getRect(selX, selY, selRect);
invalidate(selRect);// 第二次调用通知新选择的区域也需要重绘
}
private void getRect(int x, int y, Rect rect) {
// TODO Auto-generated method stub
rect.set((int) (x * width), (int) (y * height),
(int) (x * width + width), (int) (y * height + height));
}
}
七、游戏设置
package com.dw.gamesuduku;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
public class Settings extends Activity {
private static final String OPT_MUSIC="music";
private static final boolean OPT_MUSIC_DEF=true;
private static final String OPT_HINTS="hints";
private static final boolean OPT_HINTS_DEF=true;
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new PrefsFragement()).commit();
}
public static class PrefsFragement extends PreferenceFragment{
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
}
}
//get the current music option
public static boolean getMusic(Context context){
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(OPT_MUSIC,OPT_MUSIC_DEF);
}
//get the current music option
public static boolean getHints(Context context){
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(OPT_HINTS,OPT_HINTS_DEF);
}
}
八、游戏入口
package com.dw.gamesuduku;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
public class Sudoku extends Activity implements OnClickListener {
private static final String TAG = "Sudoku";
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View continueButton = this.findViewById(R.id.continue_button);
continueButton.setOnClickListener(this);
View newButton = this.findViewById(R.id.new_button);
newButton.setOnClickListener(this);
View aboutButton = this.findViewById(R.id.about_button);
aboutButton.setOnClickListener(this);
View exitButton = this.findViewById(R.id.exit_button);
exitButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.continue_button:
startGame(Game.DIFFICULTY_CONTINUE);
case R.id.about_button:
Intent i = new Intent(this, About.class);
startActivity(i);
break;
case R.id.new_button:
openNewGameDialog();
break;
case R.id.exit_button:
finish();
break;
}
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Music.play(this, R.raw.welcome);
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
Music.stop(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.settings:
startActivity(new Intent(this, Settings.class));
return true;
}
return false;
}
private void openNewGameDialog() {
// TODO Auto-generated method stub
new AlertDialog.Builder(this).setTitle(R.string.new_game_title)
.setItems(R.array.difficulty,
new DialogInterface.OnClickListener() {
@Override
public void onClick(
DialogInterface dialoginterface, int i) {
// TODO Auto-generated method stub
startGame(i);
}
}).show();
}
protected void startGame(int i) {
// TODO Auto-generated method stub
Log.i(TAG, "clicked on"+i);
Intent intent=new Intent(Sudoku.this,Game.class);
intent.putExtra(Game.KEY_DIFFICULTY, i);
startActivity(intent);
}
}