diff --git a/app/build.gradle b/app/build.gradle index a33aa16..046a855 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,4 +26,5 @@ dependencies { }) compile 'com.android.support:appcompat-v7:25.1.0' testCompile 'junit:junit:4.12' + testCompile 'org.mockito:mockito-all:1.9.5' } diff --git a/app/src/androidTest/java/com/acme/tictactoe/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/acme/tictactoe/ExampleInstrumentedTest.java index d0f80f0..2f86848 100644 --- a/app/src/androidTest/java/com/acme/tictactoe/ExampleInstrumentedTest.java +++ b/app/src/androidTest/java/com/acme/tictactoe/ExampleInstrumentedTest.java @@ -7,7 +7,7 @@ import org.junit.Test; import org.junit.runner.RunWith; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; /** * Instrumentation test, which will execute on an Android device. diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6ae66cc..e9f394d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,10 +8,9 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> - + - diff --git a/app/src/main/java/com/acme/tictactoe/controller/TicTacToeActivity.java b/app/src/main/java/com/acme/tictactoe/controller/TicTacToeActivity.java deleted file mode 100644 index 84ba558..0000000 --- a/app/src/main/java/com/acme/tictactoe/controller/TicTacToeActivity.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.acme.tictactoe.controller; - -import android.support.v7.app.AppCompatActivity; -import android.os.Bundle; - -import com.acme.tictactoe.R; - -public class TicTacToeActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.tictactoe); - } -} diff --git a/app/src/main/java/com/acme/tictactoe/model/Board.java b/app/src/main/java/com/acme/tictactoe/model/Board.java index e65bab0..c87a16e 100644 --- a/app/src/main/java/com/acme/tictactoe/model/Board.java +++ b/app/src/main/java/com/acme/tictactoe/model/Board.java @@ -22,6 +22,7 @@ public Board() { */ public void restart() { clearCells(); + winner = null; currentTurn = Player.X; state = GameState.IN_PROGRESS; } @@ -33,11 +34,17 @@ public void restart() { * * @param row 0..2 * @param col 0..2 + * @return the player that moved or null if we did not move anything. * */ - public void mark( int row, int col ) { + public Player mark( int row, int col ) { + + Player playerThatMoved = null; + if(isValid(row, col)) { + cells[row][col].setValue(currentTurn); + playerThatMoved = currentTurn; if(isWinningMoveByPlayer(currentTurn, row, col)) { state = GameState.FINISHED; @@ -48,6 +55,8 @@ public void mark( int row, int col ) { flipCurrentTurn(); } } + + return playerThatMoved; } public Player getWinner() { diff --git a/app/src/main/java/com/acme/tictactoe/model/Player.java b/app/src/main/java/com/acme/tictactoe/model/Player.java index 73130f8..3be3b79 100644 --- a/app/src/main/java/com/acme/tictactoe/model/Player.java +++ b/app/src/main/java/com/acme/tictactoe/model/Player.java @@ -1,3 +1,3 @@ package com.acme.tictactoe.model; -enum Player { X , O } +public enum Player { X , O } diff --git a/app/src/main/java/com/acme/tictactoe/presenter/Presenter.java b/app/src/main/java/com/acme/tictactoe/presenter/Presenter.java new file mode 100644 index 0000000..b748ceb --- /dev/null +++ b/app/src/main/java/com/acme/tictactoe/presenter/Presenter.java @@ -0,0 +1,11 @@ +package com.acme.tictactoe.presenter; + + +public interface Presenter { + + void onCreate(); + void onPause(); + void onResume(); + void onDestroy(); + +} diff --git a/app/src/main/java/com/acme/tictactoe/presenter/TicTacToePresenter.java b/app/src/main/java/com/acme/tictactoe/presenter/TicTacToePresenter.java new file mode 100644 index 0000000..3cfe0fb --- /dev/null +++ b/app/src/main/java/com/acme/tictactoe/presenter/TicTacToePresenter.java @@ -0,0 +1,56 @@ +package com.acme.tictactoe.presenter; + +import com.acme.tictactoe.model.Board; +import com.acme.tictactoe.model.Player; +import com.acme.tictactoe.view.TicTacToeView; + +public class TicTacToePresenter implements Presenter { + + private TicTacToeView view; + private Board model; + + public TicTacToePresenter(TicTacToeView view) { + this.view = view; + this.model = new Board(); + } + + @Override + public void onCreate() { + model = new Board(); + } + + @Override + public void onPause() { + + } + + @Override + public void onResume() { + + } + + @Override + public void onDestroy() { + + } + + public void onButtonSelected(int row, int col) { + Player playerThatMoved = model.mark(row, col); + + if(playerThatMoved != null) { + view.setButtonText(row, col, playerThatMoved.toString()); + + if (model.getWinner() != null) { + view.showWinner(playerThatMoved.toString()); + } + } + } + + public void onResetSelected() { + view.clearWinnerDisplay(); + view.clearButtons(); + model.restart(); + } + + +} diff --git a/app/src/main/java/com/acme/tictactoe/view/TicTacToeActivity.java b/app/src/main/java/com/acme/tictactoe/view/TicTacToeActivity.java new file mode 100644 index 0000000..259016b --- /dev/null +++ b/app/src/main/java/com/acme/tictactoe/view/TicTacToeActivity.java @@ -0,0 +1,107 @@ +package com.acme.tictactoe.view; + +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import com.acme.tictactoe.R; +import com.acme.tictactoe.presenter.TicTacToePresenter; + +public class TicTacToeActivity extends AppCompatActivity implements TicTacToeView { + + private static String TAG = TicTacToeActivity.class.getName(); + + private ViewGroup buttonGrid; + private View winnerPlayerViewGroup; + private TextView winnerPlayerLabel; + + TicTacToePresenter presenter = new TicTacToePresenter(this); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.tictactoe); + winnerPlayerLabel = (TextView) findViewById(R.id.winnerPlayerLabel); + winnerPlayerViewGroup = findViewById(R.id.winnerPlayerViewGroup); + buttonGrid = (ViewGroup) findViewById(R.id.buttonGrid); + presenter.onCreate(); + } + + @Override + protected void onPause() { + super.onPause(); + presenter.onPause(); + } + + @Override + protected void onResume() { + super.onResume(); + presenter.onResume(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + presenter.onDestroy(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.menu_tictactoe, menu); + return true; + } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_reset: + presenter.onResetSelected(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + public void onCellClicked(View v) { + + Button button = (Button) v; + String tag = button.getTag().toString(); + int row = Integer.valueOf(tag.substring(0,1)); + int col = Integer.valueOf(tag.substring(1,2)); + Log.i(TAG, "Click Row: [" + row + "," + col + "]"); + + presenter.onButtonSelected(row, col); + + } + + @Override + public void setButtonText(int row, int col, String text) { + Button btn = (Button) buttonGrid.findViewWithTag("" + row + col); + if(btn != null) { + btn.setText(text); + } + } + + public void clearButtons() { + for( int i = 0; i < buttonGrid.getChildCount(); i++ ) { + ((Button) buttonGrid.getChildAt(i)).setText(""); + } + } + + public void showWinner(String winningPlayerDisplayLabel) { + winnerPlayerLabel.setText(winningPlayerDisplayLabel); + winnerPlayerViewGroup.setVisibility(View.VISIBLE); + } + + public void clearWinnerDisplay() { + winnerPlayerViewGroup.setVisibility(View.GONE); + winnerPlayerLabel.setText(""); + } +} diff --git a/app/src/main/java/com/acme/tictactoe/view/TicTacToeView.java b/app/src/main/java/com/acme/tictactoe/view/TicTacToeView.java new file mode 100644 index 0000000..3bd704e --- /dev/null +++ b/app/src/main/java/com/acme/tictactoe/view/TicTacToeView.java @@ -0,0 +1,8 @@ +package com.acme.tictactoe.view; + +public interface TicTacToeView { + void showWinner(String winningPlayerDisplayLabel); + void clearWinnerDisplay(); + void clearButtons(); + void setButtonText(int row, int col, String text); +} diff --git a/app/src/main/res/layout/tictactoe.xml b/app/src/main/res/layout/tictactoe.xml index d97f0f8..a53d3b4 100644 --- a/app/src/main/res/layout/tictactoe.xml +++ b/app/src/main/res/layout/tictactoe.xml @@ -1,17 +1,104 @@ - + android:gravity="center_horizontal" + tools:context="com.acme.tictactoe.view.TicTacToeActivity"> - - + android:columnCount="3" + android:rowCount="3"> + +