TicTacToe Game
//
//src\com\example\android\tictactoe\library\GameActivity.java
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.tictactoe.library;
import java.util.Random;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Handler.Callback;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.example.android.tictactoe.library.GameView.ICellListener;
import com.example.android.tictactoe.library.GameView.State;
public class GameActivity extends Activity {
/** Start player. Must be 1 or 2. Default is 1. */
public static final String EXTRA_START_PLAYER =
"com.example.android.tictactoe.library.GameActivity.EXTRA_START_PLAYER";
private static final int MSG_COMPUTER_TURN = 1;
private static final long COMPUTER_DELAY_MS = 500;
private Handler mHandler = new Handler(new MyHandlerCallback());
private Random mRnd = new Random();
private GameView mGameView;
private TextView mInfoView;
private Button mButtonNext;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
/*
* IMPORTANT: all resource IDs from this library will eventually be merged
* with the resources from the main project that will use the library.
*
* If the main project and the libraries define the same resource IDs,
* the application project will always have priority and override library resources
* and IDs defined in multiple libraries are resolved based on the libraries priority
* defined in the main project.
*
* An intentional consequence is that the main project can override some resources
* from the library.
* (TODO insert example).
*
* To avoid potential conflicts, it is suggested to add a prefix to the
* library resource names.
*/
setContentView(R.layout.lib_game);
mGameView = (GameView) findViewById(R.id.game_view);
mInfoView = (TextView) findViewById(R.id.info_turn);
mButtonNext = (Button) findViewById(R.id.next_turn);
mGameView.setFocusable(true);
mGameView.setFocusableInTouchMode(true);
mGameView.setCellListener(new MyCellListener());
mButtonNext.setOnClickListener(new MyButtonListener());
}
@Override
protected void onResume() {
super.onResume();
State player = mGameView.getCurrentPlayer();
if (player == State.UNKNOWN) {
player = State.fromInt(getIntent().getIntExtra(EXTRA_START_PLAYER, 1));
if (!checkGameFinished(player)) {
selectTurn(player);
}
}
if (player == State.PLAYER2) {
mHandler.sendEmptyMessageDelayed(MSG_COMPUTER_TURN, COMPUTER_DELAY_MS);
}
if (player == State.WIN) {
setWinState(mGameView.getWinner());
}
}
private State selectTurn(State player) {
mGameView.setCurrentPlayer(player);
mButtonNext.setEnabled(false);
if (player == State.PLAYER1) {
mInfoView.setText(R.string.player1_turn);
mGameView.setEnabled(true);
} else if (player == State.PLAYER2) {
mInfoView.setText(R.string.player2_turn);
mGameView.setEnabled(false);
}
return player;
}
private class MyCellListener implements ICellListener {
public void onCellSelected() {
if (mGameView.getCurrentPlayer() == State.PLAYER1) {
int cell = mGameView.getSelection();
mButtonNext.setEnabled(cell >= 0);
}
}
}
private class MyButtonListener implements OnClickListener {
public void onClick(View v) {
State player = mGameView.getCurrentPlayer();
if (player == State.WIN) {
GameActivity.this.finish();
} else if (player == State.PLAYER1) {
int cell = mGameView.getSelection();
if (cell >= 0) {
mGameView.stopBlink();
mGameView.setCell(cell, player);
finishTurn();
}
}
}
}
private class MyHandlerCallback implements Callback {
public boolean handleMessage(Message msg) {
if (msg.what == MSG_COMPUTER_TURN) {
// Pick a non-used cell at random. That's about all the AI you need for this game.
State[] data = mGameView.getData();
int used = 0;
while (used != 0x1F) {
int index = mRnd.nextInt(9);
if (((used >> index) & 1) == 0) {
used |= 1 << index;
if (data[index] == State.EMPTY) {
mGameView.setCell(index, mGameView.getCurrentPlayer());
break;
}
}
}
finishTurn();
return true;
}
return false;
}
}
private State getOtherPlayer(State player) {
return player == State.PLAYER1 ? State.PLAYER2 : State.PLAYER1;
}
private void finishTurn() {
State player = mGameView.getCurrentPlayer();
if (!checkGameFinished(player)) {
player = selectTurn(getOtherPlayer(player));
if (player == State.PLAYER2) {
mHandler.sendEmptyMessageDelayed(MSG_COMPUTER_TURN, COMPUTER_DELAY_MS);
}
}
}
public boolean checkGameFinished(State player) {
State[] data = mGameView.getData();
boolean full = true;
int col = -1;
int row = -1;
int diag = -1;
// check rows
for (int j = 0, k = 0; j < 3; j++, k += 3) {
if (data[k] != State.EMPTY && data[k] == data[k+1] && data[k] == data[k+2]) {
row = j;
}
if (full && (data[k] == State.EMPTY ||
data[k+1] == State.EMPTY ||
data[k+2] == State.EMPTY)) {
full = false;
}
}
// check columns
for (int i = 0; i < 3; i++) {
if (data[i] != State.EMPTY && data[i] == data[i+3] && data[i] == data[i+6]) {
col = i;
}
}
// check diagonals
if (data[0] != State.EMPTY && data[0] == data[1+3] && data[0] == data[2+6]) {
diag = 0;
} else if (data[2] != State.EMPTY && data[2] == data[1+3] && data[2] == data[0+6]) {
diag = 1;
}
if (col != -1 || row != -1 || diag != -1) {
setFinished(player, col, row, diag);
return true;
}
// if we get here, there's no winner but the board is full.
if (full) {
setFinished(State.EMPTY, -1, -1, -1);
return true;
}
return false;
}
private void setFinished(State player, int col, int row, int diagonal) {
mGameView.setCurrentPlayer(State.WIN);
mGameView.setWinner(player);
mGameView.setEnabled(false);
mGameView.setFinished(col, row, diagonal);
setWinState(player);
}
private void setWinState(State player) {
mButtonNext.setEnabled(true);
mButtonNext.setText("Back");
String text;
if (player == State.EMPTY) {
text = getString(R.string.tie);
} else if (player == State.PLAYER1) {
text = getString(R.string.player1_win);
} else {
text = getString(R.string.player2_win);
}
mInfoView.setText(text);
}
}
//src\com\example\android\tictactoe\library\GameView.java
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.tictactoe.library;
import java.util.Random;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory.Options;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.os.Handler.Callback;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
//-----------------------------------------------
public class GameView extends View {
public static final long FPS_MS = 1000/2;
public enum State {
UNKNOWN(-3),
WIN(-2),
EMPTY(0),
PLAYER1(1),
PLAYER2(2);
private int mValue;
private State(int value) {
mValue = value;
}
public int getValue() {
return mValue;
}
public static State fromInt(int i) {
for (State s : values()) {
if (s.getValue() == i) {
return s;
}
}
return EMPTY;
}
}
private static final int MARGIN = 4;
private static final int MSG_BLINK = 1;
private final Handler mHandler = new Handler(new MyHandler());
private final Rect mSrcRect = new Rect();
private final Rect mDstRect = new Rect();
private int mSxy;
private int mOffetX;
private int mOffetY;
private Paint mWinPaint;
private Paint mLinePaint;
private Paint mBmpPaint;
private Bitmap mBmpPlayer1;
private Bitmap mBmpPlayer2;
private Drawable mDrawableBg;
private ICellListener mCellListener;
/** Contains one of {@link State#EMPTY}, {@link State#PLAYER1} or {@link State#PLAYER2}. */
private final State[] mData = new State[9];
private int mSelectedCell = -1;
private State mSelectedValue = State.EMPTY;
private State mCurrentPlayer = State.UNKNOWN;
private State mWinner = State.EMPTY;
private int mWinCol = -1;
private int mWinRow = -1;
private int mWinDiag = -1;
private boolean mBlinkDisplayOff;
private final Rect mBlinkRect = new Rect();
public interface ICellListener {
abstract void onCellSelected();
}
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
requestFocus();
mDrawableBg = getResources().getDrawable(R.drawable.lib_bg);
setBackgroundDrawable(mDrawableBg);
mBmpPlayer1 = getResBitmap(R.drawable.lib_cross);
mBmpPlayer2 = getResBitmap(R.drawable.lib_circle);
if (mBmpPlayer1 != null) {
mSrcRect.set(0, 0, mBmpPlayer1.getWidth() -1, mBmpPlayer1.getHeight() - 1);
}
mBmpPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mLinePaint = new Paint();
mLinePaint.setColor(0xFFFFFFFF);
mLinePaint.setStrokeWidth(5);
mLinePaint.setStyle(Style.STROKE);
mWinPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mWinPaint.setColor(0xFFFF0000);
mWinPaint.setStrokeWidth(10);
mWinPaint.setStyle(Style.STROKE);
for (int i = 0; i < mData.length; i++) {
mData[i] = State.EMPTY;
}
if (isInEditMode()) {
// In edit mode (e.g. in the Eclipse ADT graphical layout editor)
// we'll use some random data to display the state.
Random rnd = new Random();
for (int i = 0; i < mData.length; i++) {
mData[i] = State.fromInt(rnd.nextInt(3));
}
}
}
public State[] getData() {
return mData;
}
public void setCell(int cellIndex, State value) {
mData[cellIndex] = value;
invalidate();
}
public void setCellListener(ICellListener cellListener) {
mCellListener = cellListener;
}
public int getSelection() {
if (mSelectedValue == mCurrentPlayer) {
return mSelectedCell;
}
return -1;
}
public State getCurrentPlayer() {
return mCurrentPlayer;
}
public void setCurrentPlayer(State player) {
mCurrentPlayer = player;
mSelectedCell = -1;
}
public State getWinner() {
return mWinner;
}
public void setWinner(State winner) {
mWinner = winner;
}
/** Sets winning mark on specified column or row (0..2) or diagonal (0..1). */
public void setFinished(int col, int row, int diagonal) {
mWinCol = col;
mWinRow = row;
mWinDiag = diagonal;
}
//-----------------------------------------
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int sxy = mSxy;
int s3 = sxy * 3;
int x7 = mOffetX;
int y7 = mOffetY;
for (int i = 0, k = sxy; i < 2; i++, k += sxy) {
canvas.drawLine(x7 , y7 + k, x7 + s3 - 1, y7 + k , mLinePaint);
canvas.drawLine(x7 + k, y7 , x7 + k , y7 + s3 - 1, mLinePaint);
}
for (int j = 0, k = 0, y = y7; j < 3; j++, y += sxy) {
for (int i = 0, x = x7; i < 3; i++, k++, x += sxy) {
mDstRect.offsetTo(MARGIN+x, MARGIN+y);
State v;
if (mSelectedCell == k) {
if (mBlinkDisplayOff) {
continue;
}
v = mSelectedValue;
} else {
v = mData[k];
}
switch(v) {
case PLAYER1:
if (mBmpPlayer1 != null) {
canvas.drawBitmap(mBmpPlayer1, mSrcRect, mDstRect, mBmpPaint);
}
break;
case PLAYER2:
if (mBmpPlayer2 != null) {
canvas.drawBitmap(mBmpPlayer2, mSrcRect, mDstRect, mBmpPaint);
}
break;
}
}
}
if (mWinRow >= 0) {
int y = y7 + mWinRow * sxy + sxy / 2;
canvas.drawLine(x7 + MARGIN, y, x7 + s3 - 1 - MARGIN, y, mWinPaint);
} else if (mWinCol >= 0) {
int x = x7 + mWinCol * sxy + sxy / 2;
canvas.drawLine(x, y7 + MARGIN, x, y7 + s3 - 1 - MARGIN, mWinPaint);
} else if (mWinDiag == 0) {
// diagonal 0 is from (0,0) to (2,2)
canvas.drawLine(x7 + MARGIN, y7 + MARGIN,
x7 + s3 - 1 - MARGIN, y7 + s3 - 1 - MARGIN, mWinPaint);
} else if (mWinDiag == 1) {
// diagonal 1 is from (0,2) to (2,0)
canvas.drawLine(x7 + MARGIN, y7 + s3 - 1 - MARGIN,
x7 + s3 - 1 - MARGIN, y7 + MARGIN, mWinPaint);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Keep the view squared
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = MeasureSpec.getSize(heightMeasureSpec);
int d = w == 0 ? h : h == 0 ? w : w < h ? w : h;
setMeasuredDimension(d, d);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
int sx = (w - 2 * MARGIN) / 3;
int sy = (h - 2 * MARGIN) / 3;
int size = sx < sy ? sx : sy;
mSxy = size;
mOffetX = (w - 3 * size) / 2;
mOffetY = (h - 3 * size) / 2;
mDstRect.set(MARGIN, MARGIN, size - MARGIN, size - MARGIN);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
return true;
} else if (action == MotionEvent.ACTION_UP) {
int x = (int) event.getX();
int y = (int) event.getY();
int sxy = mSxy;
x = (x - MARGIN) / sxy;
y = (y - MARGIN) / sxy;
if (isEnabled() && x >= 0 && x < 3 && y >= 0 & y < 3) {
int cell = x + 3 * y;
State state = cell == mSelectedCell ? mSelectedValue : mData[cell];
state = state == State.EMPTY ? mCurrentPlayer : State.EMPTY;
stopBlink();
mSelectedCell = cell;
mSelectedValue = state;
mBlinkDisplayOff = false;
mBlinkRect.set(MARGIN + x * sxy, MARGIN + y * sxy,
MARGIN + (x + 1) * sxy, MARGIN + (y + 1) * sxy);
if (state != State.EMPTY) {
// Start the blinker
mHandler.sendEmptyMessageDelayed(MSG_BLINK, FPS_MS);
}
if (mCellListener != null) {
mCellListener.onCellSelected();
}
}
return true;
}
return false;
}
public void stopBlink() {
boolean hadSelection = mSelectedCell != -1 && mSelectedValue != State.EMPTY;
mSelectedCell = -1;
mSelectedValue = State.EMPTY;
if (!mBlinkRect.isEmpty()) {
invalidate(mBlinkRect);
}
mBlinkDisplayOff = false;
mBlinkRect.setEmpty();
mHandler.removeMessages(MSG_BLINK);
if (hadSelection && mCellListener != null) {
mCellListener.onCellSelected();
}
}
@Override
protected Parcelable onSaveInstanceState() {
Bundle b = new Bundle();
Parcelable s = super.onSaveInstanceState();
b.putParcelable("gv_super_state", s);
b.putBoolean("gv_en", isEnabled());
int[] data = new int[mData.length];
for (int i = 0; i < data.length; i++) {
data[i] = mData[i].getValue();
}
b.putIntArray("gv_data", data);
b.putInt("gv_sel_cell", mSelectedCell);
b.putInt("gv_sel_val", mSelectedValue.getValue());
b.putInt("gv_curr_play", mCurrentPlayer.getValue());
b.putInt("gv_winner", mWinner.getValue());
b.putInt("gv_win_col", mWinCol);
b.putInt("gv_win_row", mWinRow);
b.putInt("gv_win_diag", mWinDiag);
b.putBoolean("gv_blink_off", mBlinkDisplayOff);
b.putParcelable("gv_blink_rect", mBlinkRect);
return b;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof Bundle)) {
// Not supposed to happen.
super.onRestoreInstanceState(state);
return;
}
Bundle b = (Bundle) state;
Parcelable superState = b.getParcelable("gv_super_state");
setEnabled(b.getBoolean("gv_en", true));
int[] data = b.getIntArray("gv_data");
if (data != null && data.length == mData.length) {
for (int i = 0; i < data.length; i++) {
mData[i] = State.fromInt(data[i]);
}
}
mSelectedCell = b.getInt("gv_sel_cell", -1);
mSelectedValue = State.fromInt(b.getInt("gv_sel_val", State.EMPTY.getValue()));
mCurrentPlayer = State.fromInt(b.getInt("gv_curr_play", State.EMPTY.getValue()));
mWinner = State.fromInt(b.getInt("gv_winner", State.EMPTY.getValue()));
mWinCol = b.getInt("gv_win_col", -1);
mWinRow = b.getInt("gv_win_row", -1);
mWinDiag = b.getInt("gv_win_diag", -1);
mBlinkDisplayOff = b.getBoolean("gv_blink_off", false);
Rect r = b.getParcelable("gv_blink_rect");
if (r != null) {
mBlinkRect.set(r);
}
// let the blink handler decide if it should blink or not
mHandler.sendEmptyMessage(MSG_BLINK);
super.onRestoreInstanceState(superState);
}
//-----
private class MyHandler implements Callback {
public boolean handleMessage(Message msg) {
if (msg.what == MSG_BLINK) {
if (mSelectedCell >= 0 && mSelectedValue != State.EMPTY && mBlinkRect.top != 0) {
mBlinkDisplayOff = !mBlinkDisplayOff;
invalidate(mBlinkRect);
if (!mHandler.hasMessages(MSG_BLINK)) {
mHandler.sendEmptyMessageDelayed(MSG_BLINK, FPS_MS);
}
}
return true;
}
return false;
}
}
private Bitmap getResBitmap(int bmpResId) {
Options opts = new Options();
opts.inDither = false;
Resources res = getResources();
Bitmap bmp = BitmapFactory.decodeResource(res, bmpResId, opts);
if (bmp == null && isInEditMode()) {
// BitmapFactory.decodeResource doesn't work from the rendering
// library in Eclipse's Graphical Layout Editor. Use this workaround instead.
Drawable d = res.getDrawable(bmpResId);
int w = d.getIntrinsicWidth();
int h = d.getIntrinsicHeight();
bmp = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas c = new Canvas(bmp);
d.setBounds(0, 0, w - 1, h - 1);
d.draw(c);
}
return bmp;
}
}
//
//res\layout\lib_game.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
>
<com.example.android.tictactoe.library.GameView
android:id="@+id/game_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dip"
android:layout_weight="1"
/>
<TextView
android:id="@+id/info_turn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_marginBottom="10dip"
/>
<Button
android:id="@+id/next_turn"
android:text="I'm done"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
/>
</LinearLayout>
//
//res\layout-land\lib_game.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical|center_horizontal"
>
<com.example.android.tictactoe.library.GameView
android:id="@+id/game_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="20dip"
/>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
>
<TextView
android:id="@+id/info_turn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_marginBottom="10dip"
/>
<Button
android:id="@+id/next_turn"
android:text="I'm done"
android:minEms="10"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
/>
</LinearLayout>
</LinearLayout>
//
//res\values\strings.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<resources>
<string name="player2_win">Player 2 (computer) wins!</string>
<string name="player1_win">Player 1 (you) wins!</string>
<string name="tie">This is a tie! No one wins!</string>
<string name="player2_turn">Player 2\'s turn (that\'s the computer)</string>
<string name="player1_turn">Player 1\'s turn -- that\'s you!</string>
</resources>
//
C:\Java_Dev\sdk\Android\android-sdk\samples\android-13\TicTacToeMain\src\com\example\android\tictactoe\MainActivity.java
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.tictactoe;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import com.example.android.tictactoe.library.GameActivity;
import com.example.android.tictactoe.library.GameView.State;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.start_player).setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
startGame(true);
}
});
findViewById(R.id.start_comp).setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
startGame(false);
}
});
}
private void startGame(boolean startWithHuman) {
Intent i = new Intent(this, GameActivity.class);
i.putExtra(GameActivity.EXTRA_START_PLAYER,
startWithHuman ? State.PLAYER1.getValue() : State.PLAYER2.getValue());
startActivity(i);
}
}
//
C:\Java_Dev\sdk\Android\android-sdk\samples\android-13\TicTacToeMain\res\layout\main.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_marginTop="20dip"
android:layout_marginBottom="5dip"
android:text="@string/welcome"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_marginBottom="5dip"
android:text="@string/explain2"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_marginBottom="20dip"
android:text="@string/explain1"
/>
<Button
android:id="@+id/start_player"
android:text="@string/start_player"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/start_comp"
android:text="@string/start_comp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dip"
/>
<ImageView
android:id="@+id/ImageView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon"
/>
</LinearLayout>
//
C:\Java_Dev\sdk\Android\android-sdk\samples\android-13\TicTacToeMain\res\values\strings.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<resources>
<string name="start_comp">Start -- Computer goes first</string>
<string name="start_player">Start -- Player goes first</string>
<string name="welcome"><b>Welcome to the Tic-Tac-Toe Sample!</b></string>
<string name="explain1">This sample code demonstrates how to split an application in multiple projects by using the \'project library\' available in the Froyo SDK Tools.</string>
<string name="explain2">This activity is defined in one project. The second activity, launched by one of the buttons below, is located in another project which is a \"library\" to the main one and merged in the same APK.</string>
<string name="app_name">Tic-Tac-Toe Sample</string>
</resources>
Related examples in the same category