SlideShare a Scribd company logo
1 of 22
Download to read offline
UNIVERSITAS GUNADARMA
FAKULTAS TEKNOLOGI INDUSTRI
MANUAL BOOK PERMAINAN SIMPLY SUDOKU
Disusun Oleh :
Nama : Bagus Prayogo
NPM : 51412349
Kelas : 3IA24
Jurusan : Teknik Informatika
Dosen : Anita Sari Apriliani
Ditulis sebagai salah satu syarat kelulusan Mata Kuliah
Softskill “Pengantar Teknologi Game”
LABORATORIUM INFORMATIKA
UNIVERSITAS GUNADARMA
2015
Untuk membuat game, yang dilakukan pertama adalah menjalankan eclipse. Pastikan sudah
menginstal android sdk yang dibutuhkan untuk membuat program android dan pada eclipse
sudah terinstal ADT(Android Development Tools). Kita bisa memulainya dengan klik file -
new – android application project , lalu tentukan nama aplikasi, nama project, nama
package, serta minimum required, target sdk, sdk untuk mengcompile serta tema aplikasi.
Jika sudah, tekan next saja hingga finish.
Berikut File – File yang di butuhkan program permainan simply sudoku :
Game.java
package bagus.map.v2;
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";
public static final String KEY_DIFFICULTY =
"my.difficulty";
private static final String PREF_PUZZLE = "puzzle" ;
public static final int DIFFICULTY_EASY = 0;
public static final int DIFFICULTY_MEDIUM = 1;
public static final int DIFFICULTY_HARD = 2;
protected static final int DIFFICULTY_CONTINUE = -1;
private int puzzle[] = new int[9 * 9];
// ini adalah nilai dari blok 9 x 9, edit dengan sangat hati-hati
private final String easyPuzzle =
"360000000004230800000004200" +
"070460003820000014500013020" +
"001900000007048300000000045";
private final String mediumPuzzle =
"650000070000506000014000005" +
"007009000002314700000700800" +
"500000630000201000030000097";
private final String hardPuzzle =
"009000000080605020501078000" +
"000000700706040102004000000" +
"000720903090301080000000600";
private Puzzle puzzleView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
int diff = getIntent().getIntExtra(KEY_DIFFICULTY,
DIFFICULTY_EASY);
puzzle = getPuzzle(diff);
calculateUsedTiles();
puzzleView = new Puzzle(this);
setContentView(puzzleView);
puzzleView.requestFocus();
// Jika activity di-restart, maka akan dilanjutkan sesuai dengan activity terakhir
getIntent().putExtra(KEY_DIFFICULTY, DIFFICULTY_CONTINUE);
}
@Override
protected void onResume() {
super.onResume();
Musik.play(this, R.raw.game);
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause");
Musik.stop(this);
// ini adalah untuk menyimpan sususan puzzle
getPreferences(MODE_PRIVATE).edit().putString(PREF_PUZZLE,
toPuzzleString(puzzle)).commit();
}
// ini adalah blok kondisi permainan sudoku
private int[] getPuzzle(int diff) {
String puz;
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:
default:
puz = easyPuzzle;
break;
}
return fromPuzzleString(puz);
}
// ini blok yang akan mengkonversi nilai array ke dalam string puzzle
static private String toPuzzleString(int[] puz) {
StringBuilder buf = new StringBuilder();
for (int element : puz) {
buf.append(element);
}
return buf.toString();
}
// ini blok yang akan mengkonversi value dari string puzzle ke dalam array
static protected int[] fromPuzzleString(String string) {
int[] puz = new int[string.length()];
for (int i = 0; i < puz.length; i++) {
puz[i] = string.charAt(i) - '0';
}
return puz;
}
// mengembalikan nilai pada tiap tile sesuai dengan nilai koordinat
private int getTile(int x, int y) {
return puzzle[y * 9 + x];
}
// merubah tile berdasarkan koordinat
private void setTile(int x, int y, int value) {
puzzle[y * 9 + x] = value;
}
// mengembalikan string untuk tile berdasarkan koordinat
protected String getTileString(int x, int y) {
int v = getTile(x, y);
if (v == 0)
return "";
else
return String.valueOf(v);
}
// mengganti tile jika movement benar
protected boolean setTileIfValid(int x, int y, int value) {
int tiles[] = getUsedTiles(x, y);
if (value != 0) {
for (int tile : tiles) {
if (tile == value)
return false;
}
}
setTile(x, y, value);
calculateUsedTiles();
return true;
}
// membuka popup keypad jika values isian pada tile koordinat benar
protected void showKeypadOrError(int x, int y) {
int tiles[] = getUsedTiles(x, y);
if (tiles.length == 9) {
Toast toast = Toast.makeText(this,
R.string.lblCobaLagi, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
} else {
Log.d(TAG, "showKeypad: used=" + toPuzzleString(tiles));
Dialog v = new Keypad(this, tiles, puzzleView);
v.show();
}
}
// simpan cache tile
private final int used[][][] = new int[9][9][];
// mengembalikan cache tile berdasarkan koordinat
protected int[] getUsedTiles(int x, int y) {
return used[x][y];
}
private void calculateUsedTiles() {
for (int x = 0; x < 9; x++) {
for (int y = 0; y < 9; y++) {
used[x][y] = calculateUsedTiles(x, y);
// Log.d(TAG, "used[" + x + "][" + y + "] = "
// + toPuzzleString(used[x][y]));
}
}
}
private int[] calculateUsedTiles(int x, int y) {
int c[] = new int[9];
// horizontal
for (int i = 0; i < 9; i++) {
if (i == y)
continue;
int t = getTile(x, i);
if (t != 0)
c[t - 1] = t;
}
// vertical
for (int i = 0; i < 9; i++) {
if (i == x)
continue;
int t = getTile(i, y);
if (t != 0)
c[t - 1] = t;
}
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 = getTile(i, j);
if (t != 0)
c[t - 1] = t;
}
}
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;
}
}
Merupakan file java yang menyimpan code program untuk mendefinisikan sudoku dengan
blok 9x9 beserta fungsinya. Kelas ini yang juga menentukan tingkat kesulitan sudoku.
Keypad.java
package bagus.map.v2;
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 final Puzzle puzzleView;
public Keypad(Context context, int useds[], Puzzle puzzleView) {
super(context);
this.useds = useds;
this.puzzleView = puzzleView;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.lblKeypad);
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) {
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;
}
// mengembalikan tile berdasakan parameter yang dipanggil
private void returnResult(int tile) {
puzzleView.setSelectedTile(tile);
dismiss();
}
private boolean isValid(int tile) {
for (int t : useds) {
if (tile == t)
return false;
}
return true;
}
private void findViews() {
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(){
public void onClick(View v) {
returnResult(t);
}});
}
keypad.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
returnResult(0);
}});
}
}
Merupakan file java yang menyimpan code program untuk mendefinisikan keypad yang di
gunakan user untuk menginput nilai pada grid – grid yang kosong.
Musik.java
package bagus.map.v2;
import android.content.Context;
import android.media.MediaPlayer;
public class Musik {
private static MediaPlayer mp = null;
// stop musik dan mulai memainkan musik baru (bila di resource lebih dari satu)
public static void play(Context context, int resource) {
stop(context);
// play musik jika pada preferences tidak disabled
if (Prefs.getMusic(context)) {
mp = MediaPlayer.create(context, resource);
mp.setLooping(true);
mp.start();
}
}
// stop musik
public static void stop(Context context) {
if (mp != null) {
mp.stop();
mp.release();
mp = null;
}
}
}
Merupakan file java yang menyimpan code program untuk memainkan musik ketika
memasuki mode permainan.
package bagus.map.v2;
import android.content.Context;
import android.content.SharedPreferences;
public class Pengaturan {
private static final String SUDOKU_OPTIONS = Sudoku.class.getName();
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;
private static SharedPreferences getSudokuPreferences(
Context context) {
return context.getSharedPreferences(SUDOKU_OPTIONS,
Context.MODE_PRIVATE);
}
public static boolean getMusic(Context context) {
return getSudokuPreferences(context).getBoolean(
OPT_MUSIC, OPT_MUSIC_DEF);
}
public static boolean getHints(Context context) {
return getSudokuPreferences(context).getBoolean(
OPT_HINTS, OPT_HINTS_DEF);
}
public static boolean putMusic(Context context, boolean value) {
return getSudokuPreferences(context)
.edit()
.putBoolean(OPT_MUSIC, value)
.commit();
}
public static boolean putHints(Context context, boolean value) {
return getSudokuPreferences(context)
.edit()
.putBoolean(OPT_HINTS, value)
.commit();
}
}
Merupakan file java yang menyimpan code program untuk pengaturan musik.
Prefs.java
package bagus.map.v2;
import android.content.Context;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
public class Prefs extends PreferenceActivity {
// opsi dan default values
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
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pengaturan);
}
// fungsi untuk mengambil value dari musik
public static boolean getMusic(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(OPT_MUSIC, OPT_MUSIC_DEF);
}
// fungsi untuk mengambil value dari hints
public static boolean getHints(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(OPT_HINTS, OPT_HINTS_DEF);
}
}
Merupakan kelas dengan fungsi untuk mengambil value dari musik dan hints
Puzzle.java
package bagus.map.v2;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
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;
public class Puzzle extends View {
private static final String TAG = "Sudoku";
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;
private float width;
private float height;
private int selX;
private int selY;
private final Rect selRect = new Rect();
private final Game game;
public Puzzle(Context context) {
super(context);
this.game = (Game) context;
setFocusable(true);
setFocusableInTouchMode(true);
// ...
setId(ID);
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable p = super.onSaveInstanceState();
Log.d(TAG, "onSaveInstanceState");
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) {
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 onSizeChanged(int w, int h, int oldw, int oldh) {
width = w / 9f;
height = h / 9f;
getRect(selX, selY, selRect);
Log.d(TAG, "onSizeChanged: width " + width + ", height "
+ height);
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
// gambar background
Paint background = new Paint();
background.setColor(getResources().getColor(
R.color.puzzle_background));
canvas.drawRect(0, 0, getWidth(), getHeight(), background);
// Gambar board...
// mendefinisikan warna untuk setiap grid
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));
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(),
light);
canvas.drawLine(i * width + 1, 0, i * width + 1,
getHeight(), hilite);
}
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);
}
// gambar angka...
// mendefinisikan warna dan style untuk setiap angka
Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
foreground.setColor(getResources().getColor(
R.color.puzzle_foreground));
foreground.setStyle(Style.FILL);
foreground.setTextSize(height * 0.75f);
foreground.setTextScaleX(width / height);
foreground.setTextAlign(Paint.Align.CENTER);
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.getTileString(i, j), i
* width + x, j * height + y, foreground);
}
}
if (Prefs.getHints(getContext())) {
// gambar hints
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);
}
}
}
}
Log.d(TAG, "selRect=" + selRect);
Paint selected = new Paint();
selected.setColor(getResources().getColor(
R.color.puzzle_selected));
canvas.drawRect(selRect, selected);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
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;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
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);
break;
default:
return super.onKeyDown(keyCode, event);
}
return true;
}
public void setSelectedTile(int tile) {
if (game.setTileIfValid(selX, selY, tile)) {
invalidate();
} else {
Log.d(TAG, "setSelectedTile: invalid: " + tile);
startAnimation(AnimationUtils.loadAnimation(game,
R.anim.shake));
}
}
private void select(int x, int y) {
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) {
rect.set((int) (x * width), (int) (y * height), (int) (x
* width + width), (int) (y * height + height));
}
// ...
}
Merupakan file java yang menyimpan code program untuk mendefinisikan gambar board,
warna untuk setiap grid. Gambar angka, warna dan style untuk setiap angka. Dan juga
gambar hints.
Sudoku.java
package bagus.map.v2;
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";
// panggil activity saat pertama kali running
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
View continueButton = findViewById(R.id.continue_button);
continueButton.setOnClickListener(this);
View newButton = findViewById(R.id.new_button);
newButton.setOnClickListener(this);
View aboutButton = findViewById(R.id.about_button);
aboutButton.setOnClickListener(this);
View exitButton = findViewById(R.id.exit_button);
exitButton.setOnClickListener(this);
}
@Override
protected void onResume() {
super.onResume();
/**Music.play(this, R.raw.main);**/
}
@Override
protected void onPause() {
super.onPause();
Musik.stop(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.continue_button:
startGame(Game.DIFFICULTY_CONTINUE);
break;
// ...
case R.id.about_button:
Intent i = new Intent(this, Tentang.class);
startActivity(i);
break;
case R.id.new_button:
openNewGameDialog();
break;
case R.id.exit_button:
finish();
break;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.settings:
startActivity(new Intent(this, Prefs.class));
return true;
}
return false;
}
private void openNewGameDialog() {
new AlertDialog.Builder(this)
.setTitle(R.string.lblMulaiBaruLevel)
.setItems(R.array.difficulty,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface,
int i) {
startGame(i);
}
})
.show();
}
private void startGame(int i) {
Log.d(TAG, "clicked on " + i);
Intent intent = new Intent(Sudoku.this, Game.class);
intent.putExtra(Game.KEY_DIFFICULTY, i);
startActivity(intent);
}
}
Merupakan file java yang menyimpan code program untuk mendefinisikan button pada
layout utama seperti “Lanjutkan”, “Mulai Baru”, “Tentang”, “Keluar”. Button “Lanjutkan”
akan melanjutkan program dengan mode permainan yang sudah ditentukan ketika pertama
memulai game. Button “Mulai Baru” akan mengarahkan user pada mode permainan awal
yang juga menentukan tingkat kesulitan sudoku. Button “Tentang” akan menampilkan
layout tentang game dan pembuatnya. Button “Keluar” akan mengarahkan user keluar dari
game.
keypad.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keypad"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:stretchColumns="*">
<TableRow>
<Button android:id="@+id/keypad_1"
android:text="1">
</Button>
<Button android:id="@+id/keypad_2"
android:text="2">
</Button>
<Button android:id="@+id/keypad_3"
android:text="3">
</Button>
</TableRow>
<TableRow>
<Button android:id="@+id/keypad_4"
android:text="4">
</Button>
<Button android:id="@+id/keypad_5"
android:text="5">
</Button>
<Button android:id="@+id/keypad_6"
android:text="6">
</Button>
</TableRow>
<TableRow>
<Button android:id="@+id/keypad_7"
android:text="7">
</Button>
<Button android:id="@+id/keypad_8"
android:text="8">
</Button>
<Button android:id="@+id/keypad_9"
android:text="9">
</Button>
</TableRow>
</TableLayout>
File ini menyimpan informasi mengenai pembuatan keypad sudoku
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/depan"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:padding="30dip"
android:orientation="horizontal">
<LinearLayout
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_gravity="center">
<TextView
android:text="@string/mainApp"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="165dip"
android:textSize="24.5sp" />
<Button
android:id="@+id/continue_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/lblLanjutkan" />
<Button
android:id="@+id/new_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/lblMulaiBaru" />
<Button
android:id="@+id/about_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/lblTentang" />
<Button
android:id="@+id/exit_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/lblKeluar" />
</LinearLayout>
</LinearLayout>
File ini menyimpan informasi mengenai pembuatan layout utama pada program.
Tentang.xml
<?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="117dp"
android:text="@string/lblTentangStr" />
</ScrollView>
File yang menyimpan informasi penentuan tampilan apa yang akan ditampilkan ketika user
menekan button “Tentang”.
Output :
Layout utama
Layout tentang permainan
Tampilan pilihan tingkatan ketika memulai game
Tampilan permainan sudoku tingkat mudah
Tampilan ketika permainan sudoku tingkat mudah berhasil di selesaikan
Sekian. Untuk lebih jelasnya, saya sertakan juga source code dari game ini.

More Related Content

What's hot

Quicksort: illustrated step-by-step walk through
Quicksort: illustrated step-by-step walk throughQuicksort: illustrated step-by-step walk through
Quicksort: illustrated step-by-step walk throughYoshi Watanabe
 
Www.mathvn.com bt-mu logarit-mathvn.com
Www.mathvn.com bt-mu logarit-mathvn.comWww.mathvn.com bt-mu logarit-mathvn.com
Www.mathvn.com bt-mu logarit-mathvn.comhao5433
 
Handbook - From jQuery to YUI 3
Handbook - From jQuery to YUI 3Handbook - From jQuery to YUI 3
Handbook - From jQuery to YUI 3Ying-Hsiang Liao
 
Pogram menghitung bangun datar dan ruang dengan java
Pogram menghitung bangun datar dan ruang dengan javaPogram menghitung bangun datar dan ruang dengan java
Pogram menghitung bangun datar dan ruang dengan javaLendra Susanto
 
Informática ii ejercicios resueltos - practica 3
Informática ii   ejercicios resueltos - practica 3Informática ii   ejercicios resueltos - practica 3
Informática ii ejercicios resueltos - practica 3Alvin Jacobs
 
ゲーム理論BASIC 第28回 - 交渉ゲーム : 4つの公理とナッシュ交渉解-
ゲーム理論BASIC 第28回 - 交渉ゲーム : 4つの公理とナッシュ交渉解-ゲーム理論BASIC 第28回 - 交渉ゲーム : 4つの公理とナッシュ交渉解-
ゲーム理論BASIC 第28回 - 交渉ゲーム : 4つの公理とナッシュ交渉解-ssusere0a682
 
Sistema de ecuaciones no lineales
Sistema de ecuaciones no linealesSistema de ecuaciones no lineales
Sistema de ecuaciones no linealeselizabethzuniga1
 
Bai tap tham khao CSPE
Bai tap tham khao CSPEBai tap tham khao CSPE
Bai tap tham khao CSPEmrcoffee282
 
Вы ещё пишете код руками? Тогда мы идём к вам! - Сергей Садовников
Вы ещё пишете код руками? Тогда мы идём к вам! - Сергей СадовниковВы ещё пишете код руками? Тогда мы идём к вам! - Сергей Садовников
Вы ещё пишете код руками? Тогда мы идём к вам! - Сергей Садовниковcorehard_by
 
Toan 1 bai_05_đạo hàm - bookbooming
Toan 1 bai_05_đạo hàm - bookboomingToan 1 bai_05_đạo hàm - bookbooming
Toan 1 bai_05_đạo hàm - bookboomingbookbooming
 
Luonggiac chuong3
Luonggiac chuong3Luonggiac chuong3
Luonggiac chuong3Huynh ICT
 
Baitap ktlt code
Baitap ktlt codeBaitap ktlt code
Baitap ktlt codeHồ Lợi
 
Luonggiac chuong4
Luonggiac chuong4Luonggiac chuong4
Luonggiac chuong4Huynh ICT
 

What's hot (15)

Quicksort: illustrated step-by-step walk through
Quicksort: illustrated step-by-step walk throughQuicksort: illustrated step-by-step walk through
Quicksort: illustrated step-by-step walk through
 
Www.mathvn.com bt-mu logarit-mathvn.com
Www.mathvn.com bt-mu logarit-mathvn.comWww.mathvn.com bt-mu logarit-mathvn.com
Www.mathvn.com bt-mu logarit-mathvn.com
 
Handbook - From jQuery to YUI 3
Handbook - From jQuery to YUI 3Handbook - From jQuery to YUI 3
Handbook - From jQuery to YUI 3
 
Pogram menghitung bangun datar dan ruang dengan java
Pogram menghitung bangun datar dan ruang dengan javaPogram menghitung bangun datar dan ruang dengan java
Pogram menghitung bangun datar dan ruang dengan java
 
Informática ii ejercicios resueltos - practica 3
Informática ii   ejercicios resueltos - practica 3Informática ii   ejercicios resueltos - practica 3
Informática ii ejercicios resueltos - practica 3
 
Juego del gato
Juego del gatoJuego del gato
Juego del gato
 
ゲーム理論BASIC 第28回 - 交渉ゲーム : 4つの公理とナッシュ交渉解-
ゲーム理論BASIC 第28回 - 交渉ゲーム : 4つの公理とナッシュ交渉解-ゲーム理論BASIC 第28回 - 交渉ゲーム : 4つの公理とナッシュ交渉解-
ゲーム理論BASIC 第28回 - 交渉ゲーム : 4つの公理とナッシュ交渉解-
 
Sistema de ecuaciones no lineales
Sistema de ecuaciones no linealesSistema de ecuaciones no lineales
Sistema de ecuaciones no lineales
 
Chuong13
Chuong13Chuong13
Chuong13
 
Bai tap tham khao CSPE
Bai tap tham khao CSPEBai tap tham khao CSPE
Bai tap tham khao CSPE
 
Вы ещё пишете код руками? Тогда мы идём к вам! - Сергей Садовников
Вы ещё пишете код руками? Тогда мы идём к вам! - Сергей СадовниковВы ещё пишете код руками? Тогда мы идём к вам! - Сергей Садовников
Вы ещё пишете код руками? Тогда мы идём к вам! - Сергей Садовников
 
Toan 1 bai_05_đạo hàm - bookbooming
Toan 1 bai_05_đạo hàm - bookboomingToan 1 bai_05_đạo hàm - bookbooming
Toan 1 bai_05_đạo hàm - bookbooming
 
Luonggiac chuong3
Luonggiac chuong3Luonggiac chuong3
Luonggiac chuong3
 
Baitap ktlt code
Baitap ktlt codeBaitap ktlt code
Baitap ktlt code
 
Luonggiac chuong4
Luonggiac chuong4Luonggiac chuong4
Luonggiac chuong4
 

Viewers also liked

Mural Art Presentation
Mural Art PresentationMural Art Presentation
Mural Art PresentationFarah Sham
 
RESUME_PINKESH_ANAND
RESUME_PINKESH_ANANDRESUME_PINKESH_ANAND
RESUME_PINKESH_ANANDPINKESH ANAND
 
COMPARATIVE ANALYSIS OF 2 BUSINESS
COMPARATIVE ANALYSIS OF 2 BUSINESSCOMPARATIVE ANALYSIS OF 2 BUSINESS
COMPARATIVE ANALYSIS OF 2 BUSINESSFarah Sham
 
Business report (Charity Drive)
Business report (Charity Drive)Business report (Charity Drive)
Business report (Charity Drive)Farah Sham
 
Psychology journal
Psychology journalPsychology journal
Psychology journalFarah Sham
 
COMPARATIVE ANALYSIS OF 2 RESTAURANTS REPORT
COMPARATIVE ANALYSIS OF 2 RESTAURANTS REPORTCOMPARATIVE ANALYSIS OF 2 RESTAURANTS REPORT
COMPARATIVE ANALYSIS OF 2 RESTAURANTS REPORTFarah Sham
 
Financial Ratio Analysis
Financial Ratio AnalysisFinancial Ratio Analysis
Financial Ratio AnalysisFarah Sham
 
English 2 Compare and Contrast Essay
English 2 Compare and Contrast EssayEnglish 2 Compare and Contrast Essay
English 2 Compare and Contrast EssayFarah Sham
 
Business Plan Presentation
Business Plan Presentation Business Plan Presentation
Business Plan Presentation Farah Sham
 
SUSTAINABLE WASTE WATER TREATMENT
SUSTAINABLE WASTE WATER TREATMENTSUSTAINABLE WASTE WATER TREATMENT
SUSTAINABLE WASTE WATER TREATMENTFarah Sham
 

Viewers also liked (13)

Mural Art Presentation
Mural Art PresentationMural Art Presentation
Mural Art Presentation
 
RESUME_PINKESH_ANAND
RESUME_PINKESH_ANANDRESUME_PINKESH_ANAND
RESUME_PINKESH_ANAND
 
Are Saunas Good for You?
Are Saunas Good for You?Are Saunas Good for You?
Are Saunas Good for You?
 
GPC presentation
GPC presentationGPC presentation
GPC presentation
 
COMPARATIVE ANALYSIS OF 2 BUSINESS
COMPARATIVE ANALYSIS OF 2 BUSINESSCOMPARATIVE ANALYSIS OF 2 BUSINESS
COMPARATIVE ANALYSIS OF 2 BUSINESS
 
Business report (Charity Drive)
Business report (Charity Drive)Business report (Charity Drive)
Business report (Charity Drive)
 
Instructable
InstructableInstructable
Instructable
 
Psychology journal
Psychology journalPsychology journal
Psychology journal
 
COMPARATIVE ANALYSIS OF 2 RESTAURANTS REPORT
COMPARATIVE ANALYSIS OF 2 RESTAURANTS REPORTCOMPARATIVE ANALYSIS OF 2 RESTAURANTS REPORT
COMPARATIVE ANALYSIS OF 2 RESTAURANTS REPORT
 
Financial Ratio Analysis
Financial Ratio AnalysisFinancial Ratio Analysis
Financial Ratio Analysis
 
English 2 Compare and Contrast Essay
English 2 Compare and Contrast EssayEnglish 2 Compare and Contrast Essay
English 2 Compare and Contrast Essay
 
Business Plan Presentation
Business Plan Presentation Business Plan Presentation
Business Plan Presentation
 
SUSTAINABLE WASTE WATER TREATMENT
SUSTAINABLE WASTE WATER TREATMENTSUSTAINABLE WASTE WATER TREATMENT
SUSTAINABLE WASTE WATER TREATMENT
 

Makalah game sudoku

  • 1. UNIVERSITAS GUNADARMA FAKULTAS TEKNOLOGI INDUSTRI MANUAL BOOK PERMAINAN SIMPLY SUDOKU Disusun Oleh : Nama : Bagus Prayogo NPM : 51412349 Kelas : 3IA24 Jurusan : Teknik Informatika Dosen : Anita Sari Apriliani Ditulis sebagai salah satu syarat kelulusan Mata Kuliah Softskill “Pengantar Teknologi Game” LABORATORIUM INFORMATIKA UNIVERSITAS GUNADARMA 2015
  • 2. Untuk membuat game, yang dilakukan pertama adalah menjalankan eclipse. Pastikan sudah menginstal android sdk yang dibutuhkan untuk membuat program android dan pada eclipse sudah terinstal ADT(Android Development Tools). Kita bisa memulainya dengan klik file - new – android application project , lalu tentukan nama aplikasi, nama project, nama package, serta minimum required, target sdk, sdk untuk mengcompile serta tema aplikasi. Jika sudah, tekan next saja hingga finish. Berikut File – File yang di butuhkan program permainan simply sudoku : Game.java package bagus.map.v2; 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"; public static final String KEY_DIFFICULTY = "my.difficulty"; private static final String PREF_PUZZLE = "puzzle" ; public static final int DIFFICULTY_EASY = 0; public static final int DIFFICULTY_MEDIUM = 1; public static final int DIFFICULTY_HARD = 2; protected static final int DIFFICULTY_CONTINUE = -1; private int puzzle[] = new int[9 * 9]; // ini adalah nilai dari blok 9 x 9, edit dengan sangat hati-hati private final String easyPuzzle = "360000000004230800000004200" + "070460003820000014500013020" + "001900000007048300000000045"; private final String mediumPuzzle = "650000070000506000014000005" + "007009000002314700000700800" + "500000630000201000030000097"; private final String hardPuzzle = "009000000080605020501078000" + "000000700706040102004000000" + "000720903090301080000000600"; private Puzzle puzzleView;
  • 3. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "onCreate"); int diff = getIntent().getIntExtra(KEY_DIFFICULTY, DIFFICULTY_EASY); puzzle = getPuzzle(diff); calculateUsedTiles(); puzzleView = new Puzzle(this); setContentView(puzzleView); puzzleView.requestFocus(); // Jika activity di-restart, maka akan dilanjutkan sesuai dengan activity terakhir getIntent().putExtra(KEY_DIFFICULTY, DIFFICULTY_CONTINUE); } @Override protected void onResume() { super.onResume(); Musik.play(this, R.raw.game); } @Override protected void onPause() { super.onPause(); Log.d(TAG, "onPause"); Musik.stop(this); // ini adalah untuk menyimpan sususan puzzle getPreferences(MODE_PRIVATE).edit().putString(PREF_PUZZLE, toPuzzleString(puzzle)).commit(); } // ini adalah blok kondisi permainan sudoku private int[] getPuzzle(int diff) { String puz; 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: default: puz = easyPuzzle; break;
  • 4. } return fromPuzzleString(puz); } // ini blok yang akan mengkonversi nilai array ke dalam string puzzle static private String toPuzzleString(int[] puz) { StringBuilder buf = new StringBuilder(); for (int element : puz) { buf.append(element); } return buf.toString(); } // ini blok yang akan mengkonversi value dari string puzzle ke dalam array static protected int[] fromPuzzleString(String string) { int[] puz = new int[string.length()]; for (int i = 0; i < puz.length; i++) { puz[i] = string.charAt(i) - '0'; } return puz; } // mengembalikan nilai pada tiap tile sesuai dengan nilai koordinat private int getTile(int x, int y) { return puzzle[y * 9 + x]; } // merubah tile berdasarkan koordinat private void setTile(int x, int y, int value) { puzzle[y * 9 + x] = value; } // mengembalikan string untuk tile berdasarkan koordinat protected String getTileString(int x, int y) { int v = getTile(x, y); if (v == 0) return ""; else return String.valueOf(v); } // mengganti tile jika movement benar protected boolean setTileIfValid(int x, int y, int value) { int tiles[] = getUsedTiles(x, y); if (value != 0) { for (int tile : tiles) { if (tile == value) return false; } } setTile(x, y, value); calculateUsedTiles(); return true; } // membuka popup keypad jika values isian pada tile koordinat benar protected void showKeypadOrError(int x, int y) { int tiles[] = getUsedTiles(x, y); if (tiles.length == 9) { Toast toast = Toast.makeText(this, R.string.lblCobaLagi, Toast.LENGTH_SHORT);
  • 5. toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); } else { Log.d(TAG, "showKeypad: used=" + toPuzzleString(tiles)); Dialog v = new Keypad(this, tiles, puzzleView); v.show(); } } // simpan cache tile private final int used[][][] = new int[9][9][]; // mengembalikan cache tile berdasarkan koordinat protected int[] getUsedTiles(int x, int y) { return used[x][y]; } private void calculateUsedTiles() { for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { used[x][y] = calculateUsedTiles(x, y); // Log.d(TAG, "used[" + x + "][" + y + "] = " // + toPuzzleString(used[x][y])); } } } private int[] calculateUsedTiles(int x, int y) { int c[] = new int[9]; // horizontal for (int i = 0; i < 9; i++) { if (i == y) continue; int t = getTile(x, i); if (t != 0) c[t - 1] = t; } // vertical for (int i = 0; i < 9; i++) { if (i == x) continue; int t = getTile(i, y); if (t != 0) c[t - 1] = t; } 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 = getTile(i, j); if (t != 0) c[t - 1] = t; } } int nused = 0; for (int t : c) { if (t != 0) nused++; } int c1[] = new int[nused];
  • 6. nused = 0; for (int t : c) { if (t != 0) c1[nused++] = t; } return c1; } } Merupakan file java yang menyimpan code program untuk mendefinisikan sudoku dengan blok 9x9 beserta fungsinya. Kelas ini yang juga menentukan tingkat kesulitan sudoku. Keypad.java package bagus.map.v2; 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 final Puzzle puzzleView; public Keypad(Context context, int useds[], Puzzle puzzleView) { super(context); this.useds = useds; this.puzzleView = puzzleView; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setTitle(R.string.lblKeypad); 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) { int tile = 0; switch (keyCode) { case KeyEvent.KEYCODE_0: case KeyEvent.KEYCODE_SPACE: tile = 0; break; case KeyEvent.KEYCODE_1: tile = 1; break;
  • 7. 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; } // mengembalikan tile berdasakan parameter yang dipanggil private void returnResult(int tile) { puzzleView.setSelectedTile(tile); dismiss(); } private boolean isValid(int tile) { for (int t : useds) { if (tile == t) return false; } return true; } private void findViews() { 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(){ public void onClick(View v) { returnResult(t); }}); } keypad.setOnClickListener(new View.OnClickListener(){ public void onClick(View v) { returnResult(0); }}); } } Merupakan file java yang menyimpan code program untuk mendefinisikan keypad yang di gunakan user untuk menginput nilai pada grid – grid yang kosong.
  • 8. Musik.java package bagus.map.v2; import android.content.Context; import android.media.MediaPlayer; public class Musik { private static MediaPlayer mp = null; // stop musik dan mulai memainkan musik baru (bila di resource lebih dari satu) public static void play(Context context, int resource) { stop(context); // play musik jika pada preferences tidak disabled if (Prefs.getMusic(context)) { mp = MediaPlayer.create(context, resource); mp.setLooping(true); mp.start(); } } // stop musik public static void stop(Context context) { if (mp != null) { mp.stop(); mp.release(); mp = null; } } } Merupakan file java yang menyimpan code program untuk memainkan musik ketika memasuki mode permainan. package bagus.map.v2; import android.content.Context; import android.content.SharedPreferences; public class Pengaturan { private static final String SUDOKU_OPTIONS = Sudoku.class.getName(); private static final String OPT_MUSIC = "music"; private static final boolean OPT_MUSIC_DEF = true;
  • 9. private static final String OPT_HINTS = "hints"; private static final boolean OPT_HINTS_DEF = true; private static SharedPreferences getSudokuPreferences( Context context) { return context.getSharedPreferences(SUDOKU_OPTIONS, Context.MODE_PRIVATE); } public static boolean getMusic(Context context) { return getSudokuPreferences(context).getBoolean( OPT_MUSIC, OPT_MUSIC_DEF); } public static boolean getHints(Context context) { return getSudokuPreferences(context).getBoolean( OPT_HINTS, OPT_HINTS_DEF); } public static boolean putMusic(Context context, boolean value) { return getSudokuPreferences(context) .edit() .putBoolean(OPT_MUSIC, value) .commit(); } public static boolean putHints(Context context, boolean value) { return getSudokuPreferences(context) .edit() .putBoolean(OPT_HINTS, value) .commit(); } } Merupakan file java yang menyimpan code program untuk pengaturan musik. Prefs.java package bagus.map.v2; import android.content.Context; import android.os.Bundle; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; public class Prefs extends PreferenceActivity { // opsi dan default values 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 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pengaturan); }
  • 10. // fungsi untuk mengambil value dari musik public static boolean getMusic(Context context) { return PreferenceManager.getDefaultSharedPreferences(context) .getBoolean(OPT_MUSIC, OPT_MUSIC_DEF); } // fungsi untuk mengambil value dari hints public static boolean getHints(Context context) { return PreferenceManager.getDefaultSharedPreferences(context) .getBoolean(OPT_HINTS, OPT_HINTS_DEF); } } Merupakan kelas dengan fungsi untuk mengambil value dari musik dan hints Puzzle.java package bagus.map.v2; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Paint.FontMetrics; import android.graphics.Paint.Style; 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; public class Puzzle extends View { private static final String TAG = "Sudoku"; 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; private float width; private float height; private int selX; private int selY; private final Rect selRect = new Rect(); private final Game game; public Puzzle(Context context) { super(context);
  • 11. this.game = (Game) context; setFocusable(true); setFocusableInTouchMode(true); // ... setId(ID); } @Override protected Parcelable onSaveInstanceState() { Parcelable p = super.onSaveInstanceState(); Log.d(TAG, "onSaveInstanceState"); 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) { 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 onSizeChanged(int w, int h, int oldw, int oldh) { width = w / 9f; height = h / 9f; getRect(selX, selY, selRect); Log.d(TAG, "onSizeChanged: width " + width + ", height " + height); super.onSizeChanged(w, h, oldw, oldh); } @Override protected void onDraw(Canvas canvas) { // gambar background Paint background = new Paint(); background.setColor(getResources().getColor( R.color.puzzle_background)); canvas.drawRect(0, 0, getWidth(), getHeight(), background); // Gambar board... // mendefinisikan warna untuk setiap grid 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)); for (int i = 0; i < 9; i++) { canvas.drawLine(0, i * height, getWidth(), i * height, light);
  • 12. canvas.drawLine(0, i * height + 1, getWidth(), i * height + 1, hilite); canvas.drawLine(i * width, 0, i * width, getHeight(), light); canvas.drawLine(i * width + 1, 0, i * width + 1, getHeight(), hilite); } 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); } // gambar angka... // mendefinisikan warna dan style untuk setiap angka Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG); foreground.setColor(getResources().getColor( R.color.puzzle_foreground)); foreground.setStyle(Style.FILL); foreground.setTextSize(height * 0.75f); foreground.setTextScaleX(width / height); foreground.setTextAlign(Paint.Align.CENTER); 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.getTileString(i, j), i * width + x, j * height + y, foreground); } } if (Prefs.getHints(getContext())) { // gambar hints 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); } } } }
  • 13. Log.d(TAG, "selRect=" + selRect); Paint selected = new Paint(); selected.setColor(getResources().getColor( R.color.puzzle_selected)); canvas.drawRect(selRect, selected); } @Override public boolean onTouchEvent(MotionEvent event) { 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; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { 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); break; default: return super.onKeyDown(keyCode, event); } return true; } public void setSelectedTile(int tile) { if (game.setTileIfValid(selX, selY, tile)) { invalidate(); } else { Log.d(TAG, "setSelectedTile: invalid: " + tile);
  • 14. startAnimation(AnimationUtils.loadAnimation(game, R.anim.shake)); } } private void select(int x, int y) { 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) { rect.set((int) (x * width), (int) (y * height), (int) (x * width + width), (int) (y * height + height)); } // ... } Merupakan file java yang menyimpan code program untuk mendefinisikan gambar board, warna untuk setiap grid. Gambar angka, warna dan style untuk setiap angka. Dan juga gambar hints. Sudoku.java package bagus.map.v2; 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"; // panggil activity saat pertama kali running @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); View continueButton = findViewById(R.id.continue_button); continueButton.setOnClickListener(this); View newButton = findViewById(R.id.new_button); newButton.setOnClickListener(this); View aboutButton = findViewById(R.id.about_button); aboutButton.setOnClickListener(this); View exitButton = findViewById(R.id.exit_button);
  • 15. exitButton.setOnClickListener(this); } @Override protected void onResume() { super.onResume(); /**Music.play(this, R.raw.main);**/ } @Override protected void onPause() { super.onPause(); Musik.stop(this); } public void onClick(View v) { switch (v.getId()) { case R.id.continue_button: startGame(Game.DIFFICULTY_CONTINUE); break; // ... case R.id.about_button: Intent i = new Intent(this, Tentang.class); startActivity(i); break; case R.id.new_button: openNewGameDialog(); break; case R.id.exit_button: finish(); break; } } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.settings: startActivity(new Intent(this, Prefs.class)); return true; } return false; } private void openNewGameDialog() { new AlertDialog.Builder(this) .setTitle(R.string.lblMulaiBaruLevel) .setItems(R.array.difficulty,
  • 16. new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialoginterface, int i) { startGame(i); } }) .show(); } private void startGame(int i) { Log.d(TAG, "clicked on " + i); Intent intent = new Intent(Sudoku.this, Game.class); intent.putExtra(Game.KEY_DIFFICULTY, i); startActivity(intent); } } Merupakan file java yang menyimpan code program untuk mendefinisikan button pada layout utama seperti “Lanjutkan”, “Mulai Baru”, “Tentang”, “Keluar”. Button “Lanjutkan” akan melanjutkan program dengan mode permainan yang sudah ditentukan ketika pertama memulai game. Button “Mulai Baru” akan mengarahkan user pada mode permainan awal yang juga menentukan tingkat kesulitan sudoku. Button “Tentang” akan menampilkan layout tentang game dan pembuatnya. Button “Keluar” akan mengarahkan user keluar dari game. keypad.xml <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/keypad" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:stretchColumns="*"> <TableRow> <Button android:id="@+id/keypad_1" android:text="1"> </Button> <Button android:id="@+id/keypad_2" android:text="2"> </Button> <Button android:id="@+id/keypad_3" android:text="3"> </Button> </TableRow> <TableRow> <Button android:id="@+id/keypad_4" android:text="4"> </Button> <Button android:id="@+id/keypad_5" android:text="5"> </Button> <Button android:id="@+id/keypad_6" android:text="6"> </Button> </TableRow> <TableRow> <Button android:id="@+id/keypad_7" android:text="7"> </Button> <Button android:id="@+id/keypad_8"
  • 17. android:text="8"> </Button> <Button android:id="@+id/keypad_9" android:text="9"> </Button> </TableRow> </TableLayout> File ini menyimpan informasi mengenai pembuatan keypad sudoku main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="@drawable/depan" android:layout_height="fill_parent" android:layout_width="fill_parent" android:padding="30dip" android:orientation="horizontal"> <LinearLayout android:orientation="vertical" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_gravity="center"> <TextView android:text="@string/mainApp" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_gravity="center" android:layout_marginTop="165dip" android:textSize="24.5sp" /> <Button android:id="@+id/continue_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/lblLanjutkan" /> <Button android:id="@+id/new_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/lblMulaiBaru" /> <Button android:id="@+id/about_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/lblTentang" /> <Button android:id="@+id/exit_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/lblKeluar" /> </LinearLayout> </LinearLayout> File ini menyimpan informasi mengenai pembuatan layout utama pada program. Tentang.xml <?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"
  • 18. android:layout_height="117dp" android:text="@string/lblTentangStr" /> </ScrollView> File yang menyimpan informasi penentuan tampilan apa yang akan ditampilkan ketika user menekan button “Tentang”. Output : Layout utama
  • 20. Tampilan pilihan tingkatan ketika memulai game
  • 21. Tampilan permainan sudoku tingkat mudah
  • 22. Tampilan ketika permainan sudoku tingkat mudah berhasil di selesaikan Sekian. Untuk lebih jelasnya, saya sertakan juga source code dari game ini.