您好,登錄后才能下訂單哦!
這篇“Android怎么實現數獨游戲開發”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Android怎么實現數獨游戲開發”文章吧。
一、界面布局
1.主界面
<?xml version="1.0" encoding="utf-8"?> <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.數字鍵盤布局
<?xml version="1.0" encoding="utf-8"?> <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.游戲提示布局
<?xml version="1.0" encoding="utf-8"?> <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;i<startx+3;i++){ for(int j=starty;j<starty+3;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;i<keys.length;i++){ final 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<c.length){ getRect(i, j, r); hint.setColor(c[movesleft]); canvas.drawRect(r, hint); } } } } } @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); } }
以上就是關于“Android怎么實現數獨游戲開發”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。