Android应用实践之数独游戏开发

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

数独游戏是一种源自18世纪末的瑞士的游戏,后在美国发展、并在日本得以发扬光大的数学智力拼图游戏。拼图是九宫格(即3格宽×3格高)的正方形状,每一格又细分为一个九宫格。在每一个小九宫格中,分别填上1至9的数字,让整个大九宫格每一列、每一行的数字都不重复。

数独的玩法逻辑简单,数字排列方式千变万化。不少教育者认为数独是锻炼脑筋的好方法,上外语阅读课的时候外教老师就很喜欢带我们玩这个,乐此不疲,老外的教学方式还是很受欢迎的。但是每次玩这个游戏的时候都要发一张数独游戏卡,嫌麻烦,就想着写一个demo放自己手机上,想想那个时候真是好奇心爆棚,碰上很火爆的小游戏都想整一个DIY的Demo,叨叨够了,哈哈,上源码。

一、界面布局

1.主界面

    

2.数字键盘布局

    

3.游戏提示布局

   

二、游戏提示类

 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;i
 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;i

五、背景音乐

 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

七、游戏设置

 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); } } 


以上就是Android应用实践之数独游戏开发的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » 移动