Check the permitted movements for the human player.
authorGustavo Martin Morcuende <gu.martinm@gmail.com>
Wed, 29 Aug 2012 23:05:32 +0000 (01:05 +0200)
committerGustavo Martin Morcuende <gu.martinm@gmail.com>
Wed, 29 Aug 2012 23:05:32 +0000 (01:05 +0200)
AndroidManifest.xml
src/de/android/reversi/CheckMovement.java [new file with mode: 0644]
src/de/android/reversi/Movement.java [new file with mode: 0644]
src/de/android/reversi/Player.java
src/de/android/reversi/ReversiView.java
src/de/android/reversi/Square.java [new file with mode: 0644]

index be12a58..cc1f077 100644 (file)
@@ -5,7 +5,9 @@
 
     <uses-sdk
         android:minSdkVersion="15"
-        android:targetSdkVersion="15" android:maxSdkVersion="16"/>
+        android:targetSdkVersion="15" 
+        android:maxSdkVersion="16"/>
+    <uses-configuration android:reqTouchScreen="undefined"/>
 
     <application
         android:icon="@drawable/ic_launcher"
@@ -13,7 +15,8 @@
         android:theme="@style/AppTheme" >
         <activity
             android:name=".ReversiActivity"
-            android:label="@string/title_activity_reversi" >
+            android:label="@string/title_activity_reversi" 
+            android:screenOrientation="portrait">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
 
diff --git a/src/de/android/reversi/CheckMovement.java b/src/de/android/reversi/CheckMovement.java
new file mode 100644 (file)
index 0000000..c1dc0c0
--- /dev/null
@@ -0,0 +1,170 @@
+package de.android.reversi;
+
+public class CheckMovement {
+    public static boolean horizontal(Square gameBoard[][], short column, short row, Player player) {
+        return right(gameBoard, column, row, player) ||
+                left(gameBoard, column, row, player);
+    }
+
+    public static boolean vertical(Square gameBoard[][], short column, short row, Player player) {
+        return up(gameBoard, column, row, player) ||
+                down(gameBoard, column, row, player);
+    }
+
+    public static boolean diagonal(Square gameBoard[][], short column, short row, Player player) {
+        return diagonalLeftUp(gameBoard, column, row, player) ||
+                diagonalRightDown(gameBoard, column, row, player) ||
+                diagonalRightUp(gameBoard, column, row, player) ||
+                diagonalLeftDown(gameBoard, column, row, player);
+    }
+
+    private static boolean up (Square gameBoard[][], short column, short row, Player player) {
+
+        //Precondition 1.
+        if  (row <= 1) {
+            return false;
+        }
+
+        //Precondition 2.
+        if (gameBoard[column][row-1].getPlayer() == player) {
+            return false;
+        }
+
+        return outflank((short)0, (short)-1, gameBoard, player, (short)(row-2), column);
+    }
+
+    private static boolean down (Square gameBoard[][], short column, short row, Player player) {
+
+        //Precondition 1:
+        if  (row >= ReversiView.NUMBER_OF_ROWS -2) {
+            return false;
+        }
+
+        //Precondition 2.
+        if (gameBoard[column][row+1].getPlayer() == player) {
+            return false;
+        }
+
+        return outflank((short)0, (short)1, gameBoard, player, (short)(row+2), column);
+    }
+
+    private static boolean right (Square gameBoard[][], short column, short row, Player player) {
+
+        //Precondition 1:
+        if  (column >= ReversiView.NUMBER_OF_COLUMNS -2) {
+            return false;
+        }
+
+        //Precondition 2.
+        if (gameBoard[column+1][row].getPlayer() == player) {
+            return false;
+        }
+
+        return outflank((short)1, (short)0, gameBoard, player, row, (short)(column+2));
+    }
+
+    private static boolean left (Square gameBoard[][], short column, short row, Player player) {
+
+        //Precondition 1:
+        if  (column <= 1) {
+            return false;
+        }
+
+        //Precondition 2.
+        if (gameBoard[column-1][row].getPlayer() == player) {
+            return false;
+        }
+
+        return outflank((short)-1, (short)0, gameBoard, player, row, (short)(column-2));
+    }
+
+    private static boolean diagonalLeftUp (Square gameBoard[][], short column, short row,
+            Player player) {
+
+        //Precondition 1:
+        if  (column <= 1 && row <= 1) {
+            return false;
+        }
+
+        //Precondition 2.
+        if (gameBoard[column-1][row-1].getPlayer() == player) {
+            return false;
+        }
+
+        return outflank((short)-1, (short)-1, gameBoard, player, (short)(row-2),
+                (short)(column-2));
+    }
+
+    private static boolean diagonalRightDown (Square gameBoard[][], short column, short row,
+            Player player) {
+
+        //Precondition 1:
+        if  (column >= ReversiView.NUMBER_OF_COLUMNS -2 && row >= ReversiView.NUMBER_OF_ROWS -2) {
+            return false;
+        }
+
+        //Precondition 2.
+        if (gameBoard[column+1][row+1].getPlayer() == player) {
+            return false;
+        }
+
+        return outflank((short)1, (short)1, gameBoard, player, (short)(row+2),
+                (short)(column+2));
+    }
+
+    private static boolean diagonalLeftDown (Square gameBoard[][], short column, short row,
+            Player player) {
+
+        //Precondition 1:
+        if  (column <= 1 && row >= ReversiView.NUMBER_OF_ROWS -2) {
+            return false;
+        }
+
+        //Precondition 2.
+        if (gameBoard[column-1][row+1].getPlayer() == player) {
+            return false;
+        }
+
+        return outflank((short)1, (short)1, gameBoard, player, (short)(row+2),
+                (short)(column-2));
+    }
+
+    private static boolean diagonalRightUp (Square gameBoard[][], short column, short row,
+            Player player) {
+
+        //Precondition 1:
+        if  (row <= 1 && column >= ReversiView.NUMBER_OF_COLUMNS -2) {
+            return false;
+        }
+
+        //Precondition 2.
+        if (gameBoard[column+1][row-1].getPlayer() == player) {
+            return false;
+        }
+
+        return outflank((short)1, (short)1, gameBoard, player, (short)(row-2),
+                (short)(column+2));
+    }
+
+    public static boolean empty(Square gameBoard[][], short column, short row) {
+        if (gameBoard[column][row].getPlayer() == Player.NOPLAYER) {
+            return true;
+        }
+        return false;
+    }
+
+    private static boolean outflank(short moveX, short moveY, Square gameBoard[][], Player player,
+            short row, short column) {
+
+        do {
+            if (gameBoard[column][row].getPlayer() == player) {
+                return true;
+            }
+            row = (short)(row + moveX);
+            column = (short)(column + moveY);
+        }while (row > 0 && column >0 &&
+                row <= ReversiView.NUMBER_OF_ROWS && column <= ReversiView.NUMBER_OF_COLUMNS);
+
+        return false;
+    }
+}
diff --git a/src/de/android/reversi/Movement.java b/src/de/android/reversi/Movement.java
new file mode 100644 (file)
index 0000000..62d417f
--- /dev/null
@@ -0,0 +1,19 @@
+package de.android.reversi;
+
+public class Movement {
+    private final short row;
+    private final short column;
+
+    public Movement(short row, short column) {
+        this.row = row;
+        this.column = column;
+    }
+
+    public short getRow() {
+        return row;
+    }
+
+    public short getColumn() {
+        return column;
+    }
+}
index 904a380..a000c66 100644 (file)
@@ -1,54 +1,38 @@
 package de.android.reversi;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import android.graphics.Color;
 
 public enum Player {
-    PLAYER1(1) {
+    NOPLAYER {
+        @Override
+        int color() {
+            return 0;
+        }
+
+    },
+    PLAYER1 {
         @Override
         public int color() {
             return Color.BLACK;
 
         }
     },
-    PLAYER2(2) {
+    PLAYER2 {
         @Override
         int color() {
             return Color.WHITE;
         }
     };
 
-    private final int playerNumber;
     private final int color;
-    private static final Map<Integer, Player> playerMap = new HashMap<Integer, Player>();
-
 
-    static {
-        for (Player player : Player.values())
-        {
-            playerMap.put(player.playerNumber, player);
-        }
-    }
-
-    private Player (final int playerNumber) {
-        this.playerNumber = playerNumber;
+    private Player () {
         this.color = color();
     }
 
-    public int getPlayerNumber() {
-        return this.playerNumber;
-    }
-
     public int getColor() {
         return this.color;
     }
 
-    public static final Player getPlayer (final int playerNumber)
-    {
-        return playerMap.get(playerNumber);
-    }
-
     abstract int color();
 }
index 3bea3dc..e08247b 100644 (file)
@@ -1,5 +1,8 @@
 package de.android.reversi;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -11,47 +14,38 @@ import android.view.SurfaceView;
 
 
 public class ReversiView extends SurfaceView {
-    private static final String TAG = "GameBoard";
+    public static final short NUMBER_OF_COLUMNS = 8;
+    public static final short NUMBER_OF_ROWS = 8;
 
-    /**
-     * The number of columns of this board
-     */
-    private static int NUMBER_OF_COLUMNS = 8;
-
-    /**
-     * The number of rows of this board
-     */
-    private static int NUMBER_OF_ROWS = 8;
-
-    /**
-     * The top margin
-     */
-    private static int TOP_MARGIN = 0;
-
-    /**
-     * Vertical margin
-     */
-    private static int LEFT_MARGIN = 0;
+    private static final short TOP_MARGIN = 0;
+    private static final short LEFT_MARGIN = 0;
 
     private int squareWidth;
     private int squareHeight;
     private int canvasHeight;
     private int canvasWidth;
-    private final int gameBoard[][] = new int[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS];
+
+    private final Square gameBoard[][] = new Square[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS];
+    //¿Funciona bien volatile con enum? Ver mi codigo de Singletons y enums.
+    private volatile Player currentPlayer = Player.PLAYER1;
+    private volatile boolean isEnableUserTouch;
 
 
     public ReversiView(Context context) {
         super(context);
+        this.preInitBoard();
         this.initialize();
     }
 
     public ReversiView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        this.preInitBoard();
         this.initialize();
     }
 
     public ReversiView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
+        this.preInitBoard();
         this.initialize();
     }
 
@@ -123,12 +117,19 @@ public class ReversiView extends SurfaceView {
             @Override
             public void surfaceCreated(SurfaceHolder holder) {
                 //White
-                updateGrid(Player.PLAYER1.getPlayerNumber(), 3, 3);
-                updateGrid(Player.PLAYER1.getPlayerNumber(), 4, 4);
+                updateBoard(Player.PLAYER1, (short)3, (short)3);
+                updateBoard(Player.PLAYER1, (short)4, (short)4);
                 //Black
-                updateGrid(Player.PLAYER2.getPlayerNumber(), 4, 3);
-                updateGrid(Player.PLAYER2.getPlayerNumber(), 3, 4);
+                updateBoard(Player.PLAYER2, (short)4, (short)3);
+                updateBoard(Player.PLAYER2, (short)3, (short)4);
 
+                //AllowedMovements for Player
+                List<Movement> list = allowedMovements(currentPlayer);
+
+                //UpdateBoard with suggestions
+                for (Movement movement : list) {
+                    updateBoard(currentPlayer, movement.getColumn(), movement.getRow(), true);
+                }
             }
 
             @Override
@@ -136,6 +137,7 @@ public class ReversiView extends SurfaceView {
                     int width, int height) {
                 Canvas canvas = holder.lockCanvas();
                 calculateGraphicParameters(canvas, width, height);
+                updateSquareParameters();
                 drawGrid(canvas);
                 drawPositions(canvas);
                 holder.unlockCanvasAndPost(canvas);
@@ -150,12 +152,16 @@ public class ReversiView extends SurfaceView {
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
+        if (!this.isEnableUserTouch) {
+            return false;
+        }
+
         if (event.getAction() == MotionEvent.ACTION_DOWN) {
             // Hidden pointer
-            int column = transformCoordinateXInColumn(event.getX());
-            int row = transformCoordinateYInRow(event.getY());
+            short column = transformCoordinateXInColumn(event.getX());
+            short row = transformCoordinateYInRow(event.getY());
             if (row != -1 && column != -1 ) {
-                updateGrid(Player.PLAYER2.getPlayerNumber(), column, row);
+                updateBoard(this.currentPlayer, column, row);
                 Canvas canvas = getHolder().lockCanvas();
                 drawGrid(canvas);
                 drawPositions(canvas);
@@ -168,9 +174,9 @@ public class ReversiView extends SurfaceView {
         }
     }
 
-    private int transformCoordinateYInRow(float y) {
+    private short transformCoordinateYInRow(float y) {
 
-        int row = (int) ((y - TOP_MARGIN) / this.squareWidth);
+        short row = (short) ((y - TOP_MARGIN) / this.squareWidth);
 
         // if tapped outside the board
         if (row < 0 || row >= NUMBER_OF_ROWS) {
@@ -180,9 +186,9 @@ public class ReversiView extends SurfaceView {
         return row;
     }
 
-    private int transformCoordinateXInColumn(float x) {
+    private short transformCoordinateXInColumn(float x) {
 
-        int column = (int) ((x - LEFT_MARGIN) / this.squareWidth);
+        short column = (short) ((x - LEFT_MARGIN) / this.squareWidth);
 
         // if tapped outside the board
         if (column < 0 || column >= NUMBER_OF_COLUMNS) {
@@ -192,41 +198,131 @@ public class ReversiView extends SurfaceView {
         return column;
     }
 
-    private void drawChip(Canvas canvas, int player, int column, int row) {
-        if (player != 0) {
-            // calculating the center of the cell
-            int cellMediumX = (column * this.squareWidth + (column + 1) * this.squareWidth) / 2;
-            int cellMediumY = (row * this.squareHeight + (row + 1) * this.squareHeight) / 2;
+    private void drawDisk(Canvas canvas, Square square, short column, short row) {
+        this.drawCircle(canvas, square.getPlayer(), square.getSquareMediumX(),
+                square.getSquareMediumY(), square.getRadius(), square.isSuggestion());
+    }
+
+    private void drawCircle(Canvas canvas, Player player, int cx, int cy, int radius,
+            boolean isSolid) {
 
-            // applying the margins
-            int cx = cellMediumX + LEFT_MARGIN;
-            int cy = cellMediumY + TOP_MARGIN;
-            // now the radius
-            int radius = (this.squareWidth - 2) / 2 - 2;
+        Paint paint = new Paint();
+
+        paint.setAntiAlias(true);
+
+        //If not solid it is a suggestion.
+        if (!isSolid) {
+            paint.setAlpha(77);
+        }
 
-            this.drawCircle(canvas, player, cx, cy, radius);
+        switch (player){
+            case PLAYER1:
+                paint.setColor(player.getColor());
+                //paint.setAntiAlias(true);
+                canvas.drawCircle(cx, cy, radius, paint);
+                break;
+            case PLAYER2:
+                //border color
+                paint.setColor(Color.BLACK);
+                canvas.drawCircle(cx, cy, radius, paint);
+                //inside color
+                paint.setColor(player.getColor());
+                canvas.drawCircle(cx, cy, radius-2, paint);
+                break;
+            default:
+                break;
         }
     }
 
-    private void drawCircle(Canvas canvas, int player, int cx, int cy, int radius) {
+    private void updateBoard(Player player, short column, short row) {
+        this.updateBoard(player, column, row, false);
+    }
 
-        Paint paint = new Paint();
+    private void updateBoard(Player player, short column, short row, boolean suggestion) {
+        this.gameBoard[column][row].setPlayer(player);
+        this.gameBoard[column][row].setSuggestion(suggestion);
+    }
 
-        paint.setColor(Player.getPlayer(player).getColor());
-        //paint.setAntiAlias(true);
+    private void drawPositions(Canvas canvas) {
+        for (short column = 0; column < NUMBER_OF_COLUMNS; column++) {
+            for (short row = 0; row < NUMBER_OF_ROWS; row++) {
+                if (this.gameBoard[column][row].getPlayer() != Player.NOPLAYER) {
+                    drawDisk(canvas, this.gameBoard[column][row], column, row);
+                }
+            }
+        }
+    }
 
-        canvas.drawCircle(cx, cy, radius, paint);
+    private void preInitBoard() {
+        for (short column = 0; column < NUMBER_OF_COLUMNS; column++) {
+            for (short row = 0; row < NUMBER_OF_ROWS; row++) {
+                this.gameBoard[column][row] = new Square();;
+            }
+        }
     }
 
-    private void updateGrid(int player, int column, int row) {
-        this.gameBoard[column][row] = player;
+    private void updateSquareParameters() {
+        for (short column = 0; column < NUMBER_OF_COLUMNS; column++) {
+            for (short row = 0; row < NUMBER_OF_ROWS; row++) {
+
+                // calculating the square's center
+                int cellMediumX = (column * this.squareWidth + (column + 1) * this.squareWidth) / 2;
+                int cellMediumY = (row * this.squareHeight + (row + 1) * this.squareHeight) / 2;
+
+                // applying the margins
+                int cx = cellMediumX + LEFT_MARGIN;
+                int cy = cellMediumY + TOP_MARGIN;
+
+                // the radius
+                int radius = (this.squareWidth - 2) / 2 - 2;
+
+                //update squares
+                this.gameBoard[column][row].setRadius(radius);
+                this.gameBoard[column][row].setSquareMediumX(cx);
+                this.gameBoard[column][row].setSquareMediumY(cy);
+            }
+        }
     }
 
-    private void drawPositions(Canvas canvas) {
-        for (int column = 0; column < NUMBER_OF_COLUMNS; column++) {
-            for (int row = 0; row < NUMBER_OF_ROWS; row++) {
-                drawChip(canvas, this.gameBoard[column][row], column, row);
+    private void first() {
+        if (this.currentPlayer == Player.PLAYER1) {
+            //AllowedMovements for Player
+            List<Movement> list = allowedMovements(this.currentPlayer);
+
+            //UpdateBoard with suggestions
+            for (Movement movement : list) {
+                updateBoard(this.currentPlayer, movement.getColumn(), movement.getRow(), true);
+            }
+
+
+            //Draw board
+            Canvas canvas = getHolder().lockCanvas();
+            drawGrid(canvas);
+            drawPositions(canvas);
+            getHolder().unlockCanvasAndPost(canvas);
+
+            this.isEnableUserTouch = true;
+        }
+        else {
+            //The IA is always PLAYER2 ?
+            //Launch IA Thread.
+        }
+    }
+
+    private List<Movement> allowedMovements(Player player) {
+        List<Movement> list = new ArrayList<Movement>();
+
+        for (short column = 0; column < NUMBER_OF_COLUMNS; column++) {
+            for (short row = 0; row < NUMBER_OF_ROWS; row++) {
+                if (CheckMovement.empty(gameBoard, column, row) &&
+                        (CheckMovement.diagonal(gameBoard, column, row, player) ||
+                                CheckMovement.horizontal(gameBoard, column, row, player) ||
+                                CheckMovement.vertical(gameBoard, column, row, player))) {
+                    list.add(new Movement(row, column));
+                }
             }
         }
+
+        return list;
     }
 }
diff --git a/src/de/android/reversi/Square.java b/src/de/android/reversi/Square.java
new file mode 100644 (file)
index 0000000..f981bce
--- /dev/null
@@ -0,0 +1,54 @@
+package de.android.reversi;
+
+public class Square {
+    private Player player;
+    private boolean suggestion;
+    private int squareMediumX;
+    private int squareMediumY;
+    private int radius;
+
+    //Default constructor.
+    public Square () {
+        this.player = Player.NOPLAYER;
+    }
+
+    public boolean isSuggestion() {
+        return suggestion;
+    }
+
+    public void setSuggestion(boolean suggestion) {
+        this.suggestion = suggestion;
+    }
+
+    public int getSquareMediumX() {
+        return squareMediumX;
+    }
+
+    public void setSquareMediumX(int squareMediumX) {
+        this.squareMediumX = squareMediumX;
+    }
+
+    public int getSquareMediumY() {
+        return squareMediumY;
+    }
+
+    public void setSquareMediumY(int squareMediumY) {
+        this.squareMediumY = squareMediumY;
+    }
+
+    public void setPlayer (Player player) {
+        this.player = player;
+    }
+
+    public Player getPlayer() {
+        return player;
+    }
+
+    public void setRadius (int radius) {
+        this.radius = radius;
+    }
+
+    public int getRadius() {
+        return radius;
+    }
+}