Sudoku (tiếng Nhật: 数独 sūdoku; còn được viết Su Doku; âm Hán Việt là "số độc") là một loại trò chơi lôgic và cách chơi là điền số từ 1 đến 9 vào những ô trống sao cho mỗi cột dọc, mỗi hàng ngang, mỗi phân vùng nhỏ (ô 3x3) có đủ các số từ 1 đến 9 mà không được lặp lại.
Bảng câu đố hình vuông, mỗi chiều có 9 ô nhỏ, hợp thành 9 cột, 9 hàng và được chia thành 9 ô lớn 3x3. Một vài ô nhỏ được đánh số, đó là những manh mối duy nhất để bạn tìm lời giải. Tuỳ theo mức độ nhiều hay ít của các manh mối, các câu đố được xếp loại dễ, trung bình, khó hay cực khó. Ngoài ra, còn những bảng như 16x16, 25x25 hay thậm chí 100x100.
Khởi đầu
Sudoku là một từ Nhật, có thể dịch tạm là con số độc nhất, (Thật ra nó có nguồn gốc từ Mỹ với tên gọi là "đặt con số vào vị trí đúng"). ở Anh, trong vòng có vài tháng, từ chỗ không mấy người biết đến, nó đã tạo nên một cơn lốc, khiến cho khách đi tàu phải lỡ ga còn học sinh thì quên làm bài tập.
Người mang trò chơi này đến Anh là một vị thẩm phán về hưu từng làm việc ở Hong Kong tên là Wayne Gould. Ông tìm thấy một tạp chí Sudoku trong chuyến nghỉ hè ở Nhật. Mặc dù không biết tiếng Nhật, song ông rất tò mò về trò chơi. Gould mày mò ra cách chơi khi so sánh câu đố với lời giải được in ở cuối quyển tạp chí. Sau đó, ông say mê nó đến mức dùng khả năng lập trình máy tính để viết chương trình và tạo ra vô số các câu đố khác nhau.
"Tôi có hai mục tiêu. Một là làm cho người ta biết nhiều hơn đến trò chơi này. Thật là đáng kinh ngạc khi Sudoku là loại hình giải trí phổ thông ở Nhật đến thế, trong khi những nước trên thế giới hình như không biết gì đến nó. Hai là tôi muốn chứng minh một ông thẩm phán cũng có khả năng lập nên một chương trình phần mềm và kiếm ra tiền từ việc đó."
Mục tiêu đầu tiên mà Gould nhằm tới là tờ báo nổi tiếng Times của Anh, nhưng ông biết việc này không dễ dàng gì: "Nếu bạn gọi điện cho một ai đó ở tờ Times và nói, này tôi có câu đố cho các anh xem, hẳn bạn sẽ nghe từ bên kia những tiếng thở dài não nuột", ông tâm sự. Nhưng tôi chuẩn bị rất kỹ về chuyện trông câu đố sẽ như thế nào trên mặt báo. Vì vậy vị biên tập viên khi nghe tôi phát biểu hiểu ngay tôi muốn nói gì.
Trào lưu
Tờ Times bắt đầu đăng tải trò chơi trên số báo ngày 12/11/2002. Và cuộc chạy đua bắt đầu. Ba ngày sau, tờ Mail tung ra bản Sudoku của riêng mình, và chả bao lâu sau tất cả các nhật báo phát hành trên toàn nước Anh đã kịp ăn theo, ngoại trừ tờ chuyên về tài chính Financial Times. Ai nấy đều khẳng định câu đố của họ mới là hay nhất. Chẳng hạn, tờ Guardian có lần chạy một câu đố Sudoku trên mỗi trang của phần phụ san và tuyên bố họ là tờ báo duy nhất có các câu đố được viết tay trên núi Phú Sĩ.
Sukodu có sẵn trên Internet và có thể download xuống điện thoại di động. Một số tờ báo còn mở các cuộc thi trên toàn quốc, và mốt chơi Sudoku đang lan từ Anh tới Australia, Nam Phi và Mỹ. Một số báo dùng chương trình của Gould, số khác tự tạo ra các câu đố của riêng mình, thuê các công ty hay mua lại chúng từ các nhà xuất bản Nhật.
Nguồn gốc
Tim Preston, giám đốc Puzzler Media - nhà xuất bản các tạp chí và sách câu đố lớn nhất của Anh, cho rằng Sudoku thực ra là phát minh của nhà toán học thế kỷ 18 Leonhard Euler. Là người gốc Basel (Thuỵ Sĩ), nhưng phần lớn cuộc đời mình, ông phục vụ hoàng gia Nga ở Sankt-Peterburg. Euler và có thú vui đưa ra các câu đố. Trong số các trò chơi ông nghĩ ra có Hình vuông Latinh. Đó là sự sắp xếp các con số sao cho chúng không trùng lặp theo chiều ngang lẫn chiều dọc. Euler thông minh đến mức ông có thể thực hiện những phép tính phức tạp và xây dựng các công thức hoàn toàn bằng trí nhớ, sau khi ông đã bị mù.
Trong nhiều năm, chỉ có giới toán học biết đến Hình vuông Latinh. Đến thập kỷ 1970, nhà xuất bản Dell của Mỹ đưa nó vào những tập sách đố, và đặt tên cho nó là Vị trí con số.
Với một cái tên chán ngắt như thế, chả mấy chốc nó đã rơi vào lãng quên, Preston bình luận. Nhưng may mắn là trò chơi được đưa tới Nhật và một nhà xuất bản có tên là Nikoli đổi tên nó thành Sudoku.
ở Nhật, tất cả các câu đố Sudoku đều được viết tay. Preston cho đó là một điều lạ lùng: Họ có rất nhiều tác giả. Ai mà có câu đố được đăng trên một trong các tạp chí của Nikoli coi đó một vinh dự lớn. Bạn có thể nghĩ rằng một nước công nghệ cao như Nhật phải nghĩ ra những chương trình máy tính để làm những câu đố này... Nhưng họ khẳng định các câu đố viết tay hay hơn nhiều.
Puzzler Media trước đây từng mua các Sudoku của Nikoli và in chúng trong các quyển sách đố, nhưng chỉ đến khi Gould tung nó lên trên mặt báo, Sudoku mới trở thành trào lưu.
Các bước tạo chương trình Sudoku Pro:
Bước 1: Viết giao diện cho nó
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/background"
android:padding="20dip">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingLeft="20dip"
android:paddingRight="20dip">
<TextView
android:text="@string/hello"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="20dip"
android:textSize="20sp"
android:textStyle="italic"
android:textColor="@color/title_color" android:gravity="center"/>
<TableLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:stretchColumns="*">
<TableRow>
<Button
android:id="@+id/continue_button"
android:text="@string/continue_label" />
<Button
android:id="@+id/new_game_button"
android:text="@string/new_game_label" />
</TableRow>
<TableRow>
<Button
android:id="@+id/about_button"
android:text="@string/about_label" />
<Button
android:id="@+id/exit_button"
android:text="@string/exit_label" />
</TableRow>
</TableLayout>
</LinearLayout>
</LinearLayout>
Bước 2: Thiết kế giao diện giới thiệu bản thân chứ hè
about.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">
<!-- Get text content from values strings.xml -->
<TextView
android:id="@+id/about_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/about_text" />
</ScrollView>
Bước 3: Thiết kế giao diện cho trang 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>
Bước 4: Tạo chuỗi thiết lập(settings.xml)
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="music"
android:title="@string/music_title"
android:summary="@string/music_summary"
android:defaultValue="true" />
<CheckBoxPreference
android:key="hints"
android:title="@string/hints_title"
android:summary="@string/hints_summary"
android:defaultValue="true" />
</PreferenceScreen>
Bước 5: Tạo lớp Settings
package quangit.Sudoku;
import quangit.Sudoku.R;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class Settings extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings); // Call settings.xml
}
}
Bước 6: Tạo lớp PuzzleView
package quangit.Sudoku;
import quangit.Sudoku.R;
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.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
public class PuzzleView extends View {
private static final String TAG = "Sudoku" ;
private final Game game;
private float width; // width of one tile
private float height; // height of one tile
private int selX; // X index of selection
private int selY; // Y index of selection
private final Rect selRect = new Rect();
public PuzzleView(Context context) {
super(context);
this.game = (Game) context;
setFocusable(true);
setFocusableInTouchMode(true);
}
@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) {
// Draw the background...
Paint background = new Paint();
background.setColor(getResources().getColor(
R.color.puzzle_background));
canvas.drawRect(0, 0, getWidth(), getHeight(), background);
// * Draw the board...
// Draw the board...
// Define colors for the grid lines
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 the 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(),
light);
canvas.drawLine(i * width + 1, 0, i * width + 1,
getHeight(), hilite);
}
// Draw the 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 the numbers...
// Draw the numbers...
// Define color and style for numbers
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);
// Draw the number in the center of the tile
FontMetrics fm = foreground.getFontMetrics();
// Centering in X: use alignment (and X at midpoint)
float x = width / 2;
// Centering in Y: measure ascent/descent first
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);
}
}
// * Draw the hints...
// Draw the hints...
// Pick a hint color based on #moves left
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);
}
}
}
// * Draw the selection...
// Draw the selection...
Log.d(TAG, "selRect=" + selRect);
Paint selected = new Paint();
selected.setColor(getResources().getColor(
R.color.puzzle_selected));
canvas.drawRect(selRect, selected);
// ...
}
@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;
default:
return super.onKeyDown(keyCode, event);
}
return true;
}
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));
}
@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;
}
public void setSelectedTile(int tile) {
if (game.setTileIfValid(selX, selY, tile)) {
invalidate();// may change hints
} else {
// Number is not valid for this tile
// Number is not valid for this tile
Log.d(TAG, "setSelectedTile: invalid: " + tile);
startAnimation(AnimationUtils.loadAnimation(game,R.anim.shake));
Log.d(TAG, "setSelectedTile: invalid: " + tile);
}
}
}
Bước 7: Tạo lớp Keypad
package quangit.Sudoku;
import quangit.Sudoku.R;
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 PuzzleView puzzleView;
public Keypad(Context context, int useds[], PuzzleView puzzleView) {
super(context);
this.useds = useds;
this.puzzleView = puzzleView;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.keypad);
findViews();
for (int element : useds) {
if (element != 0)
keys[element - 1].setVisibility(View.INVISIBLE);
}
setListeners();
}
// ...
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);
}});
}
@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;
}
private boolean isValid(int tile) {
for (int t : useds) {
if (tile == t)
return false;
}
return true;
}
private void returnResult(int tile) {
puzzleView.setSelectedTile(tile);
dismiss();
}
}
Bước 8: Tạo lớp About để giới thiệu @@
package quangit.Sudoku;
import quangit.Sudoku.R;
import android.app.Activity;
import android.os.Bundle;
public class About extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.about); // Call layout about.xml
}
}
Bước 9: Tạo lớp Game
package quangit.Sudoku;
import quangit.Sudoku.R;
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 = "org.example.sudoku.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 final String easyPuzzle =
"360000000004230800000004200" +
"070460003820000014500013020" +
"001900000007048300000000045" ;
private final String mediumPuzzle =
"650000070000506000014000005" +
"007009000002314700000700800" +
"500000630000201000030000097" ;
private final String hardPuzzle =
"009000000080605020501078000" +
"000000700706040102004000000" +
"000720903090301080000000600" ;
@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 PuzzleView(this);
setContentView(puzzleView);
puzzleView.requestFocus();
}
// ...
protected void showKeypadOrError(int x, int y) {
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.CENTER, 0, 0);
toast.show();
}
else {
Log.d(TAG, "showKeypad: used=" + toPuzzleString(tiles));
Dialog v = new Keypad(this, tiles, puzzleView);
v.show();
}
}
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;
}
/** Cache of used tiles */
private final int used[][][] = new int[9][9][];
/** Return cached used tiles visible from the given coords */
protected int[] getUsedTiles(int x, int y) {
return used[x][y];
}
/** Compute the two dimensional array of used tiles */
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]));
}
}
}
//--------
/** Compute the used tiles visible from this position */
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;
}
// 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 = getTile(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;
}
//~~~~~~~~~~
/** Given a difficulty level, come up with a new puzzle */
private int[] getPuzzle(int diff) {
String puz;
// TODO: Continue last game
switch (diff) {
case DIFFICULTY_HARD:
puz = hardPuzzle;
break;
case DIFFICULTY_MEDIUM:
puz = mediumPuzzle;
break;
case DIFFICULTY_EASY:
default:
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 into an 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;
}
/** Return the tile at the given coordinates */
private int getTile(int x, int y) {
return puzzle[y * 9 + x];
}
/** Change the tile at the given coordinates */
private void setTile(int x, int y, int value) {
puzzle[y * 9 + x] = value;
}
/** Return a string for the tile at the given coordinates */
protected String getTileString(int x, int y) {
int v = getTile(x, y);
if (v == 0)
return "" ;
else
return String.valueOf(v);
}
}
Bước 10: Tạo lớp Sudoku
package quangit.Sudoku;
import quangit.Sudoku.R;
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" ;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); // Call layout main.xml (first layout for application)
// Search & Setup click listeners for all the buttons
View continueButton = this.findViewById(R.id.continue_button);
View newGameButton = this.findViewById(R.id.new_game_button);
View aboutButton = this.findViewById(R.id.about_button);
View exitButton = this.findViewById(R.id.exit_button);
continueButton.setOnClickListener(this);
newGameButton.setOnClickListener(this);
aboutButton.setOnClickListener(this);
exitButton.setOnClickListener(this);
}
// method implement the OnClickListener interface
public void onClick(View v) {
switch (v.getId()) {
case R.id.continue_button:
break;
case R.id.new_game_button:
openNewGameDialog();
break;
case R.id.about_button:
Intent i_about = new Intent(this, About.class);
startActivity(i_about); //Set activity for class About.java
break;
case R.id.exit_button:
//finish();
Intent i_exit = new Intent(Intent.ACTION_MAIN);
i_exit.addCategory(Intent.CATEGORY_HOME);
i_exit.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i_exit);
break;
}
}
/** Ask the user what difficulty level they want */
private void openNewGameDialog() {
new AlertDialog.Builder(this)
.setTitle(R.string.new_game_title)
//???
.setItems(R.array.difficulty,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface, int i){
startGame(i);
}
}
)
//---?
.show();
}
/** Start a new game with the given difficulty level */
private void startGame(int i) {
//???
Log.d(TAG, "clicked on " + i);
//---?
Intent intent = new Intent(Sudoku.this, Game.class);// Call class Game.java
intent.putExtra(Game.KEY_DIFFICULTY, i); // Set difficulty
startActivity(intent);
}
// Create menu
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu); // Set menu.xml for this activity
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.settings:
startActivity(new Intent(this, Settings.class)); // Call class Settings.java
return true;
}
return false;
}
}