From 56496d5a40dacc1ae771e952fc6027494a8e71b1 Mon Sep 17 00:00:00 2001 From: Natanel Rudyuklakir Date: Sun, 1 Jan 2023 14:07:10 +0200 Subject: [PATCH] linked the android part to the code with basic graphics --- .idea/misc.xml | 2 + .idea/vcs.xml | 6 + app/build.gradle | 4 +- app/google-services.json | 1 + app/src/main/AndroidManifest.xml | 5 +- .../example/chessfirebase/GameAvtivity.java | 71 ++++- .../example/chessfirebase/MainActivity.java | 30 ++- .../com/example/chessfirebase/RoomBrowse.java | 86 +++++- .../chessfirebase/chessClasses/Bishop.java | 56 ++++ .../chessfirebase/chessClasses/Board.java | 237 +++++++++++++++++ .../chessfirebase/chessClasses/BoardCell.java | 62 +++++ .../chessfirebase/chessClasses/King.java | 96 +++++++ .../chessfirebase/chessClasses/Knight.java | 34 +++ .../chessfirebase/chessClasses/Pawn.java | 56 ++++ .../chessfirebase/chessClasses/Piece.java | 117 ++++++++ .../chessfirebase/chessClasses/Queen.java | 39 +++ .../chessfirebase/chessClasses/Rook.java | 52 ++++ .../example/chessfirebase/customGameView.java | 50 ++++ .../example/chessfirebase/socketPlayer.java | 250 ++++++++++++++++++ app/src/main/res/drawable/black_bishop.png | Bin 0 -> 1260 bytes app/src/main/res/drawable/black_king.png | Bin 0 -> 2485 bytes app/src/main/res/drawable/black_knight.png | Bin 0 -> 1516 bytes app/src/main/res/drawable/black_pawn.png | Bin 0 -> 797 bytes app/src/main/res/drawable/black_queen.png | Bin 0 -> 2267 bytes app/src/main/res/drawable/black_rook.png | Bin 0 -> 725 bytes app/src/main/res/drawable/white_bishop.png | Bin 0 -> 1944 bytes app/src/main/res/drawable/white_king.png | Bin 0 -> 2279 bytes app/src/main/res/drawable/white_knight.png | Bin 0 -> 1878 bytes app/src/main/res/drawable/white_pawn.png | Bin 0 -> 1294 bytes app/src/main/res/drawable/white_queen.png | Bin 0 -> 2637 bytes app/src/main/res/drawable/white_rook.png | Bin 0 -> 933 bytes .../res/layout/activity_game_avtivity.xml | 63 +++++ app/src/main/res/layout/sample_game_view.xml | 16 ++ app/src/main/res/values-night/styles.xml | 7 + app/src/main/res/values/attrs_game_view.xml | 8 + app/src/main/res/values/colors.xml | 4 + app/src/main/res/values/styles.xml | 7 + 37 files changed, 1343 insertions(+), 16 deletions(-) create mode 100644 .idea/vcs.xml create mode 100644 app/src/main/java/com/example/chessfirebase/chessClasses/Bishop.java create mode 100644 app/src/main/java/com/example/chessfirebase/chessClasses/Board.java create mode 100644 app/src/main/java/com/example/chessfirebase/chessClasses/BoardCell.java create mode 100644 app/src/main/java/com/example/chessfirebase/chessClasses/King.java create mode 100644 app/src/main/java/com/example/chessfirebase/chessClasses/Knight.java create mode 100644 app/src/main/java/com/example/chessfirebase/chessClasses/Pawn.java create mode 100644 app/src/main/java/com/example/chessfirebase/chessClasses/Piece.java create mode 100644 app/src/main/java/com/example/chessfirebase/chessClasses/Queen.java create mode 100644 app/src/main/java/com/example/chessfirebase/chessClasses/Rook.java create mode 100644 app/src/main/java/com/example/chessfirebase/customGameView.java create mode 100644 app/src/main/java/com/example/chessfirebase/socketPlayer.java create mode 100644 app/src/main/res/drawable/black_bishop.png create mode 100644 app/src/main/res/drawable/black_king.png create mode 100644 app/src/main/res/drawable/black_knight.png create mode 100644 app/src/main/res/drawable/black_pawn.png create mode 100644 app/src/main/res/drawable/black_queen.png create mode 100644 app/src/main/res/drawable/black_rook.png create mode 100644 app/src/main/res/drawable/white_bishop.png create mode 100644 app/src/main/res/drawable/white_king.png create mode 100644 app/src/main/res/drawable/white_knight.png create mode 100644 app/src/main/res/drawable/white_pawn.png create mode 100644 app/src/main/res/drawable/white_queen.png create mode 100644 app/src/main/res/drawable/white_rook.png create mode 100644 app/src/main/res/layout/sample_game_view.xml create mode 100644 app/src/main/res/values-night/styles.xml create mode 100644 app/src/main/res/values/attrs_game_view.xml create mode 100644 app/src/main/res/values/styles.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index 4927dd7..6f7009d 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,11 +3,13 @@ diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index f41536b..0ddc7f1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,8 +23,8 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 } } diff --git a/app/google-services.json b/app/google-services.json index 247d516..c98edda 100644 --- a/app/google-services.json +++ b/app/google-services.json @@ -1,6 +1,7 @@ { "project_info": { "project_number": "786174912789", + "firebase_url": "https://chess-firebase-711c4-default-rtdb.europe-west1.firebasedatabase.app", "project_id": "chess-firebase-711c4", "storage_bucket": "chess-firebase-711c4.appspot.com" }, diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bc7c2b0..54e358b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,7 +2,8 @@ - + + + tools:targetApi="29"> diff --git a/app/src/main/java/com/example/chessfirebase/GameAvtivity.java b/app/src/main/java/com/example/chessfirebase/GameAvtivity.java index c2eeffb..895292b 100644 --- a/app/src/main/java/com/example/chessfirebase/GameAvtivity.java +++ b/app/src/main/java/com/example/chessfirebase/GameAvtivity.java @@ -1,14 +1,83 @@ package com.example.chessfirebase; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.os.Bundle; +import android.os.StrictMode; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.widget.Button; +import android.widget.FrameLayout; -public class GameAvtivity extends AppCompatActivity { +import com.example.chessfirebase.chessClasses.BoardCell; +import com.example.chessfirebase.chessClasses.Piece; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +public class GameAvtivity extends AppCompatActivity { + private static final int REQUEST_READ_PHONE_STATE = 1; + String roomName; + private FirebaseAuth mAuth; + private FirebaseDatabase database; + private boolean firebaseConn = false; + private DatabaseReference player; + FrameLayout frmview; + customGameView cgv; + socketPlayer p; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_game_avtivity); + StrictMode.ThreadPolicy gfgPolicy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); + StrictMode.setThreadPolicy(gfgPolicy); + Intent i=getIntent(); + mAuth=FirebaseAuth.getInstance(); + frmview = findViewById(R.id.cgv); + + cgv = new customGameView(GameAvtivity.this, frmview.getWidth(), frmview.getHeight()); + frmview.addView(cgv); + Piece.size=1080.0f/8.0f; + BoardCell.size=Piece.size; + if(i.getBooleanExtra("FireBase",false)) { + firebaseConn = true; + roomName = i.getExtras().getString("roomName"); + //create a firebasePlayer + }else{ + p=new socketPlayer(); + Thread th=new Thread(p); + th.start(); + + try { + Thread.sleep(250); + } catch (InterruptedException e) { + e.printStackTrace(); + } + cgv.start(p.getBoard()); + cgv.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + p.getBoard().psuedoClickListener(event.getX(),event.getY()); + return false; + } + }); + } + + + } + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + if ( cgv == null && hasFocus) { + cgv = new customGameView(GameAvtivity.this, frmview.getWidth(), frmview.getHeight()); + frmview.addView(cgv); + cgv.start(p.getBoard()); + } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/chessfirebase/MainActivity.java b/app/src/main/java/com/example/chessfirebase/MainActivity.java index df7b73a..e8899ba 100644 --- a/app/src/main/java/com/example/chessfirebase/MainActivity.java +++ b/app/src/main/java/com/example/chessfirebase/MainActivity.java @@ -10,8 +10,10 @@ import android.preference.PreferenceManager; import android.util.Log; import android.view.View; +import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; +import android.widget.Toast; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.database.DataSnapshot; @@ -31,7 +33,7 @@ public class MainActivity extends AppCompatActivity { private TextView tvName; private TextView tvElo; private FirebaseAuth mAuth; - private Button btRooms; + private Button btRooms,btQPair; private FirebaseDatabase database; private DatabaseReference player; @Override @@ -43,23 +45,32 @@ protected void onCreate(Bundle savedInstanceState) {//TODO: add all the buttons tvName=findViewById(R.id.tvName); tvElo=findViewById(R.id.tvElo); btRooms=findViewById(R.id.btBrowseRooms); + btQPair=findViewById(R.id.btQuickPair); String name=FirebaseAuth.getInstance().getCurrentUser().getDisplayName(); tvName.setText(name); tvElo.setText(sharedPreferences.getInt("Elo",800)+""); mAuth = FirebaseAuth.getInstance(); database=FirebaseDatabase.getInstance(); - player= database.getReference("players/"+name); - player.setValue(name+":"+sharedPreferences.getInt("Elo",800));//set the value by default to the name and rating so that we read + player= database.getReference("players/"+mAuth.getUid()+":"+name); + player.setValue(sharedPreferences.getInt("Elo",800));//set the value by default to the name and rating so that we read //it at the start and know what to display - btRooms.setOnClickListener(new View.OnClickListener() { + btRooms.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { + btRooms.setEnabled(false); startActivity(new Intent(MainActivity.this,RoomBrowse.class)); - readFromDB(); MainActivity.this.finish(); } }); - //readFromDB(); + btQPair.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent u=new Intent(MainActivity.this,GameAvtivity.class); + u.putExtra("Firebase",false); + startActivity(u); + MainActivity.this.finish(); + } + }); } private String readFromFile(Context context, String fileName) { @@ -107,11 +118,12 @@ public void signOut(View v){ this.finish(); } - public void readFromDB(){ + public void checkForFailure(){ player.addValueEventListener(new ValueEventListener() { @Override - public void onDataChange(@NonNull DataSnapshot snapshot) {//occurs when another player joins the room + public void onDataChange(@NonNull DataSnapshot snapshot) { //start an activity to roomBrowse + startActivity(new Intent(MainActivity.this,RoomBrowse.class)); MainActivity.this.finish(); } @@ -120,6 +132,8 @@ public void onDataChange(@NonNull DataSnapshot snapshot) {//occurs when another public void onCancelled(@NonNull DatabaseError error) { //error //TODO: try and handle the error (think about how to handle) + btRooms.setEnabled(true); + Toast.makeText(MainActivity.this,"Error creating player",Toast.LENGTH_LONG).show(); } }); } diff --git a/app/src/main/java/com/example/chessfirebase/RoomBrowse.java b/app/src/main/java/com/example/chessfirebase/RoomBrowse.java index 54855f5..419a41d 100644 --- a/app/src/main/java/com/example/chessfirebase/RoomBrowse.java +++ b/app/src/main/java/com/example/chessfirebase/RoomBrowse.java @@ -1,19 +1,29 @@ package com.example.chessfirebase; +import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; import android.os.Bundle; +import android.preference.PreferenceManager; import android.text.InputType; import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; +import android.widget.Toast; import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; import java.util.ArrayList; import java.util.List; @@ -28,6 +38,7 @@ public class RoomBrowse extends AppCompatActivity { FirebaseDatabase db; DatabaseReference roomRef; + DatabaseReference player; FirebaseAuth mAuth; @Override protected void onCreate(Bundle savedInstanceState) { @@ -36,14 +47,13 @@ protected void onCreate(Bundle savedInstanceState) { mAuth=FirebaseAuth.getInstance(); db=FirebaseDatabase.getInstance(); - + player=db.getReference(mAuth.getUid()); name=mAuth.getCurrentUser().getDisplayName(); - + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); lv=findViewById(R.id.lvRoomView); btCreateRoom=findViewById(R.id.btCreateRoom); roomList=new ArrayList<>(); - btCreateRoom.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -56,17 +66,87 @@ public void onClick(View v) { @Override public void onClick(DialogInterface dialog, int which) { roomName=et.getText().toString(); + btCreateRoom.setEnabled(false); } }); bldr.setNegativeButton("Cancel" ,new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); + btCreateRoom.setEnabled(true); } }); bldr.show(); roomRef=db.getReference("rooms/"+roomName+"/white"); + readFromDB(); + roomRef.setValue(mAuth.getCurrentUser().getDisplayName()+":"+sharedPreferences.getInt("Elo",-100)); + } + }); + lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + roomName=roomList.get(position); + roomRef=db.getReference("rooms/"+roomName+"/black"); + readFromDB(); + roomRef.setValue(mAuth.getCurrentUser().getDisplayName()+":"+sharedPreferences.getInt("Elo",-100)); + //possible to add random color pick for the room creation + /*roomRef.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot snapshot) { + if(snapshot.hasChild("/white")){ + roomRef=db.getReference("rooms/"+roomName+"/black"); + } + + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + + } + });*/ } }); + updateRoomList(); } + + + public void readFromDB(){//constant;y read from db to update the list + roomRef.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot snapshot) {//occurs when another player joins the room + // + //start an activity to roomBrowse + startActivity(new Intent(getApplicationContext(),GameAvtivity.class).putExtra("roomName",roomName)); + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + //error + //TODO: try and handle the error (think about how to handle) + Toast.makeText(getApplicationContext(),"error",Toast.LENGTH_LONG).show(); + btCreateRoom.setEnabled(true); + } + }); + } + public void updateRoomList(){ + roomRef=db.getReference("rooms"); + roomRef.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot snapshot) { + roomList.clear(); + Iterable it=snapshot.getChildren(); + for(DataSnapshot sn:it){ + roomList.add(sn.getKey()); + ArrayAdapter adapter=new ArrayAdapter<>(RoomBrowse.this, android.R.layout.simple_list_item_1); + lv.setAdapter(adapter); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + + } + }); + } + } \ No newline at end of file diff --git a/app/src/main/java/com/example/chessfirebase/chessClasses/Bishop.java b/app/src/main/java/com/example/chessfirebase/chessClasses/Bishop.java new file mode 100644 index 0000000..8d6e6c7 --- /dev/null +++ b/app/src/main/java/com/example/chessfirebase/chessClasses/Bishop.java @@ -0,0 +1,56 @@ +package com.example.chessfirebase.chessClasses; + +//imports------- + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import com.example.chessfirebase.R; +import com.example.chessfirebase.customGameView; + +import java.util.*; + + + +public class Bishop extends Piece{ + + public Bishop(int row,int col,boolean isWhite) { + super(row, col, isWhite); + this.img = BitmapFactory.decodeResource(customGameView.context.getResources(), isWhite ? R.drawable.white_bishop : R.drawable.black_bishop); + this.img= Bitmap.createScaledBitmap(this.img,(int)this.size,(int)this.size,true); + } + + //calculateing the moves using bfs + + public void calculateMoves(Board b){ + int[][] dir={{-1,-1},{-1,1},{1,-1},{-1,-1}}; + //top left, top right, bottom left, bottom right + + for(int i=0;i=0 && c>=0 && r<8 && c<8;r+=dir[i][0], c+=dir[i][1]){ + //if first time we dont check curr pos,(possible not to add this cond) + //Delete if needed + if(r==this.row && c==this.col){ + continue; + } + if(b.getCell(r,c).getPiece()==null){ + super.possibleMoves.add(new int[] {r,c}); + }else{ + if(b.getCell(r, c).getPiece().isWhite==this.isWhite){ + break; + }else{ + super.possibleMoves.add(new int[] {r,c}); + break; + } + } + } + } + validateMoves(b); + } + + @Override + public char toChar() { + return this.isWhite ? 'B' : 'b'; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/chessfirebase/chessClasses/Board.java b/app/src/main/java/com/example/chessfirebase/chessClasses/Board.java new file mode 100644 index 0000000..474f08e --- /dev/null +++ b/app/src/main/java/com/example/chessfirebase/chessClasses/Board.java @@ -0,0 +1,237 @@ +package com.example.chessfirebase.chessClasses; + +//---------------imports------------------- + + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.util.Log; + +import com.example.chessfirebase.socketPlayer; + +public class Board{//add the tap listener later in android studio + //variables + private BoardCell[][] board; + private King wk; + private King bk; + public Piece remove; + public boolean isFirstClick; + int[] from; + private socketPlayer player; + + public Board(boolean isWhite,socketPlayer p){ + this.player=p; + board=new BoardCell[8][8]; + for(int i=0;i=0 && this.col+d[1]<8 && this.col+d[1]>=0 && (b.getCell(this.row+d[0],this.col+d[1]).getPiece()==null || b.getCell(this.row+d[0],this.col+d[1]).getPiece().getIsWhite()!=this.isWhite)){ + super.possibleMoves.add(new int[] {this.row+d[0], this.col+d[1]}); + } + } + validateMoves(b); + } + + public boolean isCheck(Board b){ + //no need for that!!! + //run BFS to check if its check+ 8 moves for Knight and 2 for pawns. + //checking for top checks + //a=0 if vert/horiz , a=1 if diag a=2 if horse, a=3 if pawn + //a[0] is row a[1] is col a[2] is kind (diag/horiz/vert/horse/pawn) + int[][] dir={{-1,-1},{-1,1},{1,-1},{-1,-1},{1,0},{0,1},{-1,0},{0,-1}}; + //first diagonal then vertical + Piece p; + for(int i=0;i=0 && c<8 && c>=0;r+=dir[i][0],c+=dir[i][1]){ + if((p=b.getCell(r,c).getPiece())!=null){ + if(p.isWhite!=this.isWhite){//check if not our color + if(i<=3){ + if(p instanceof Queen || p instanceof Bishop){ + return true; + } + }else{ + if(p instanceof Queen || p instanceof Rook){ + return true; + } + } + }else{ + //we can break cuz it blocks + break; + } + } + } + } + //check for knight and pawn checks: + + //knight: + + int[][] moves={{2,1},{2,-1},{-2,1},{-2,-1},{1,2},{-1,2},{1,-2},{-1,-2}};//taken from the knight class + //exact same algorithm, just reusing differently + for(int[] mov:moves){ + if(this.row+mov[0]>=0 && this.row+mov[0]<8 && this.col+mov[1]>=0 && this.col+mov[1]<8){//checking if inside the board + if(b.getCell(this.row+mov[0],this.col+mov[1]).getPiece()!=null && //if there is a piece there + b.getCell(this.row+mov[0],this.col+mov[1]).getPiece() instanceof Knight &&//is this piece a Knight + b.getCell(this.row+mov[0], this.col+mov[1]).getPiece().getIsWhite() != this.isWhite){ + return true; + } + } + } + + //pawn: + if(this.row-1>=0 && this.col+1<8 && b.getCell(this.row-1, this.col+1).getPiece()!=null){//checking if there is a pawn infront on the right of the king + if(b.getCell(this.row-1, this.col+1).getPiece() instanceof Pawn && b.getCell(this.row-1, this.col+1).getPiece().getIsWhite() != this.isWhite){ + return true; + } + } + if(this.row-1>=0 && this.col-1>=0 && b.getCell(this.row-1, this.col-1).getPiece()!=null){//checking if there is a pawn infront on the left of the king + if(b.getCell(this.row-1, this.col+1).getPiece() instanceof Pawn && b.getCell(this.row-1, this.col+1).getPiece().getIsWhite() != this.isWhite){ + return true; + } + } + + //if no checks found we return false. + return false; + } + + @Override + public char toChar() { + return this.isWhite ? 'K' : 'k'; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/chessfirebase/chessClasses/Knight.java b/app/src/main/java/com/example/chessfirebase/chessClasses/Knight.java new file mode 100644 index 0000000..7006c75 --- /dev/null +++ b/app/src/main/java/com/example/chessfirebase/chessClasses/Knight.java @@ -0,0 +1,34 @@ +package com.example.chessfirebase.chessClasses; + +//imports------ + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import com.example.chessfirebase.R; +import com.example.chessfirebase.customGameView; + +public class Knight extends Piece{ + + public Knight(int row, int col,boolean isWhite){ + super(row, col, isWhite); + this.img = BitmapFactory.decodeResource(customGameView.context.getResources(),isWhite ? R.drawable.white_knight : R.drawable.black_knight); + this.img= Bitmap.createScaledBitmap(this.img,(int)this.size,(int)this.size,true); + } + + public void calculateMoves(Board b){ + int[][] moves={{2,1},{2,-1},{-2,1},{-2,-1},{1,2},{-1,2},{1,-2},{-1,-2}};//the possible 8 moves. + for(int[] mov:moves){ + if(this.row+mov[0]<8 && this.row+mov[0]>=0 && this.col+mov[1]<8 && this.col+mov[1]>=0 && (b.getCell(this.row+mov[0],this.col+mov[1]).getPiece()==null || b.getCell(this.row+mov[0],this.col+mov[1]).getPiece().getIsWhite()!=this.isWhite)){ + super.possibleMoves.add(new int[]{mov[0]+this.row,mov[1]+this.col}); + } + } + validateMoves(b); + } + + @Override + public char toChar() { + return this.isWhite ? 'N' : 'n'; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/chessfirebase/chessClasses/Pawn.java b/app/src/main/java/com/example/chessfirebase/chessClasses/Pawn.java new file mode 100644 index 0000000..0d48bd0 --- /dev/null +++ b/app/src/main/java/com/example/chessfirebase/chessClasses/Pawn.java @@ -0,0 +1,56 @@ +package com.example.chessfirebase.chessClasses; + +//imports: +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import com.example.chessfirebase.R; +import com.example.chessfirebase.customGameView; + +import java.util.*; + + + + +public class Pawn extends Piece{ + //variables + public boolean isFirstMove=true; + + + + public Pawn(int row, int col, boolean isWhite) { + super(row, col, isWhite); + this.img = BitmapFactory.decodeResource(customGameView.context.getResources(), isWhite ? R.drawable.white_pawn : R.drawable.black_pawn); + this.img= Bitmap.createScaledBitmap(this.img,(int) this.size,(int) this.size,true); + } + + //methods: + public void calculateMoves(Board b){ + //change to check the moves better - we dont have a check checker + if (this.row-1>=0 && b.getCell(this.row-1,this.col).getPiece()==null){ + if(isFirstMove && this.row-2>=0 && b.getCell(this.row-2,this.col).getPiece()==null){ + super.possibleMoves.add(new int[] {this.row-2,this.col}); + } + isFirstMove = false; + super.possibleMoves.add(new int[] {this.row-1,this.col}); + } + if(row-1>=0 && col+1<8 && b.getCell(row-1, col+1).getPiece()!=null) + super.possibleMoves.add(new int[] {row-1,col+1}); + + + if(row-1>=0 && col-1>=0 && b.getCell(row-1, col-1).getPiece()!=null) + super.possibleMoves.add(new int[] {row-1,col-1}); + + validateMoves(b); + } + + public List getMoves(Board b) { + calculateMoves(b); + return this.possibleMoves; + } + + @Override + public char toChar() { + return this.isWhite ? 'P':'p'; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/chessfirebase/chessClasses/Piece.java b/app/src/main/java/com/example/chessfirebase/chessClasses/Piece.java new file mode 100644 index 0000000..ce335d1 --- /dev/null +++ b/app/src/main/java/com/example/chessfirebase/chessClasses/Piece.java @@ -0,0 +1,117 @@ +package com.example.chessfirebase.chessClasses; + +//---------------------------imports-------------------------------- + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.util.Log; + +import java.util.*; + + +//------------------------class + methods-------------------------------- +public abstract class Piece{ + + //---------------------------position handling-------------------------------- + protected int col; + protected int row; + public final boolean isWhite; + public List possibleMoves; + public boolean isSelected;//if piece is tapped we set it to true and calc moves and display validated moves + //if 1 piece is selected change all other are to not selected + + //------------------------GUI handling-------------------------------- + public static float size; + public Bitmap img; + //------------------------methods-------------------------------- + + public Piece(int row, int col, boolean isWhite){ + this.row = row; + this.col = col; + this.isWhite = isWhite; + this.isSelected=false; + this.possibleMoves=new ArrayList(); + } + //returns position of the piece assuming 0,0 is the start of the board + public float[] getPos(){ + return new float[] {(col)*size,(row)*size};//returns {x,y} + } + + public int[] getRawPos(){ + return new int[]{row,col}; + } + + public int getCol() { + return this.col; + } + + public int getRow() { + return this.row; + } + + public boolean getIsWhite() { + return this.isWhite; + } + + public List getMoves() { + //removed the board and the calc moves because thy happen before every move. + return this.possibleMoves; + } + + public void setMoves(List possibleMoves){ + this.possibleMoves= possibleMoves; + } + + public void validateMoves(Board b){ + //checking for pinned pieces + List moves=this.possibleMoves; + List remove=new ArrayList<>(); + int[] currPos; + //check what moves to remove: + for(int i=0;i=0 && c>=0 && r<8 && c<8;r+=d[0],c+=d[1]){ + if(b.getCell(r,c).getPiece()==null){ + super.possibleMoves.add(new int[] {r,c}); + }else{ + if(b.getCell(r,c).getPiece().isWhite==this.isWhite){ + break; + }else{ + super.possibleMoves.add(new int[] {r,c}); + break; + } + } + } + } + validateMoves(b); + } + @Override + public char toChar() { + return this.isWhite ? 'Q' : 'q'; + } +} diff --git a/app/src/main/java/com/example/chessfirebase/chessClasses/Rook.java b/app/src/main/java/com/example/chessfirebase/chessClasses/Rook.java new file mode 100644 index 0000000..f845bcd --- /dev/null +++ b/app/src/main/java/com/example/chessfirebase/chessClasses/Rook.java @@ -0,0 +1,52 @@ +package com.example.chessfirebase.chessClasses; + +//imports +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import com.example.chessfirebase.R; +import com.example.chessfirebase.customGameView; + +import java.util.*; + + + +public class Rook extends Piece{ + + public Rook(int row, int col, boolean isWhite) { + super(row, col, isWhite); + + this.img = BitmapFactory.decodeResource(customGameView.context.getResources(), isWhite ? R.drawable.white_rook : R.drawable.black_rook); + this.img= Bitmap.createScaledBitmap(this.img,(int) size,(int) size,true); + } + + //methods + + public void calculateMoves(Board b){ + + int[][] dir={{1,0},{0,1},{-1,0},{0,-1}}; + //down right up left + + for(int[] mov:dir){ + for(int r=this.row+mov[0],c=this.col+mov[1]; r<8 && c<8 && r>=0 && c>=0; r+=mov[0],c+=mov[1]){ + if(b.getCell(r,c).getPiece()==null){ + this.possibleMoves.add(new int[]{r,c}); + }else{ + if(b.getCell(r,c).getPiece().getIsWhite() != b.getCell(this.row, this.col).getPiece().getIsWhite()){ + this.possibleMoves.add(new int[]{r,c}); + break; + }else{ + break; + } + } + } + } + validateMoves(b); + } + + @Override + public char toChar() { + return this.isWhite ? 'R':'r'; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/chessfirebase/customGameView.java b/app/src/main/java/com/example/chessfirebase/customGameView.java new file mode 100644 index 0000000..3ad6688 --- /dev/null +++ b/app/src/main/java/com/example/chessfirebase/customGameView.java @@ -0,0 +1,50 @@ +package com.example.chessfirebase; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +import com.example.chessfirebase.chessClasses.Board; +import com.example.chessfirebase.chessClasses.BoardCell; +import com.example.chessfirebase.chessClasses.Piece; + +public class customGameView extends SurfaceView implements Runnable { + public static Context context; + private float width,height; + private SurfaceHolder holder; + private Board b; + public customGameView(Context context, float width, float height) { + super(context); + this.context = context; + this.width = width; + this.height = height; + holder = getHolder(); + } + public void start(Board b){ + this.b=b; + Thread t=new Thread(this); + t.start(); + } + public void drawBoard(){ + if(holder.getSurface().isValid()){ + Canvas canvas = holder.lockCanvas(); + canvas.drawColor(context.getResources().getColor(androidx.cardview.R.color.cardview_dark_background)); + b.draw(canvas); + holder.unlockCanvasAndPost(canvas); + } + } + + @Override + public void run() { + while (true){ + drawBoard(); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { e.printStackTrace();} + } + } +} diff --git a/app/src/main/java/com/example/chessfirebase/socketPlayer.java b/app/src/main/java/com/example/chessfirebase/socketPlayer.java new file mode 100644 index 0000000..581b6ff --- /dev/null +++ b/app/src/main/java/com/example/chessfirebase/socketPlayer.java @@ -0,0 +1,250 @@ +package com.example.chessfirebase; + +//imports +import com.example.chessfirebase.chessClasses.Bishop; +import com.example.chessfirebase.chessClasses.Board; +import com.example.chessfirebase.chessClasses.King; +import com.example.chessfirebase.chessClasses.Knight; +import com.example.chessfirebase.chessClasses.Pawn; +import com.example.chessfirebase.chessClasses.Piece; + +import java.io.*; +import java.net.Socket; +import java.util.*; + + +public class socketPlayer implements Runnable{ + private Board board;//think about how move mechanism will work (almost done) + public boolean isWhite; + public boolean ourTurn; + public List pieces; + public ConnectionHandler ch; + String host="10.0.2.2"; + + int port = 8888; + + public socketPlayer(){ + this.pieces=new ArrayList(); + this.ch=new ConnectionHandler(host,port); + } + + public Board getBoard() {return board;} + + public ConnectionHandler getConnectionHandler(){ + return this.ch; + } + @Override + public void run(){ + try { + playerSetup(this.ch.getIsWhite()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + calculateMoves(); + Thread t=new Thread(this.ch); + t.start(); + } + + public void playerSetup(boolean isWhite) throws InterruptedException{ + this.board=new Board(isWhite, this); + this.isWhite=isWhite; + this.ourTurn=this.isWhite; + } + + //add a check for what pieces there are to know if its draw!. + public boolean checkPossibleMoves(){ + boolean bishop=false,knight=false; + if(pieces.size()==1)return true;//only a king left + for(Piece p : pieces){ + if(p instanceof Bishop || p instanceof Knight || p instanceof King){ + bishop=p instanceof Bishop; + knight=p instanceof Knight; + } + + if(p.possibleMoves.size()>0 && pieces.size()>1){ + return false; + } + } + if(bishop^knight){ + // only the bishop or the knight is left or both kings + return true; + } + + return true ; + } + + public void calculateMoves(){ + for(int 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 S+beef0000}!$9&8%1e zBftZ|7R4-Z1y~(jgGy~JB^?It1A|Kpn*k1)+4rbAirmAJ27wza4GS;|T#c-y)S@*B z?5a5SoTPnGg_Ht55ESpNC@KRpJHo7t>qO<^6DGyqIf4;J7kjqRqZ!a6MJ3~)2k z<`=Nt%sxAm1jOFM7acs-0OuWi78C+3X#;S;$?k-c4-nVks{7_D+U@8S2E5JDYgm%J z%%XtbI(p5R@US}7_Jsi)g zBVe~W!Zza;^DjDW1q`eQUOB@y<62t*0|UUrAlPP1v=i`DFs#uy?;2}4FpX1EMy7 z<}NN-S-_G;2>kH1jK=FE<#zaBW`2%FC9O+MTFJnxfc>dSxxk~D`MFA-KNol?Ge1|! z^Y?%gwK+3CSIP6&2A=;qn7m3lD|tJc^XuUpt$PMH^({4_*q?aqqOSX!wg=ql>H&AU bx(@gc{sH)y$U_yZ00000NkvXXu0mjfw8>#< literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/black_queen.png b/app/src/main/res/drawable/black_queen.png new file mode 100644 index 0000000000000000000000000000000000000000..0d94a1c29a50896a6fbe017e1eeda9b5a42fe0a4 GIT binary patch literal 2267 zcmV<12qgE3P)(5~dA8 zrJ=07jv?R&VRuhI+}&mOdhXp9F%|HauI}v2|DHK#&YYRKGj~N*d6F>cQ7bUfcxv$D zj;97c?kJnc%0y%;unkxO^aJmyYIs6*D0NyAkuLyCf!V+%RXyjxdjU8F)MsQX@TRK1 zP6#(TXKeO0w& zgToF+ylvo~ci<}UJsWp6aL2$)0L`W7T=bwNBGZA8L-7v`d1Ef(>}B5trkbh+*5_2t z1&#)bNP~#HDk3XIWQu{}bCLVJ;hDcUa0h{t1;{p*<)Nh4&)n!PBVk zI1j7pHDCeo2Ox7Pcg3ZZ%Wc13bKu!Mxsl1zUFybt^Y_?eNN zV}N;y>?y=)RQ(Rwt$QEv8+d-w8Bj z{I)yCh++(`0uJP%5M(RwWboY7+E+woVvYEAWXTtig}`zxzIMPw4zs65$Fu9!p5 zz|1jGCnxs}IKPqn8|VG1)HR%=JOPa4;QYd+>~cPK7+((^44#`qnb92O594yH z&Ua7ia?%4%cqUIdrNFI@yhdoq^W;HQgwX| zUDIL@aNh4WqM*Yx5qSgH4=`uW99mjhXlZF76beyWTbsol8yib|FcOJmrK8a(9*-yO zai7nJ-|tVStE#H7R+(-7mvpo92{g| zU|`&pT4{N`UgKpS^+!fV(mml~~w6ye?7Ca+ANKHb$Tg&@z~^2UUC zxV*gl#{T{L>*Db^ot>S8!(ndSx@F=~Q&WT2>m7HmuC8WeWQ1rmN;Dcxdp&i(eS7@U zSVWjVe?G0PtpoxA4j(@JaYskT%z~7M!aZDHU;jZY7E6007K>?5Pmk`}wM(0uo3)~% z;-QVmvu4fGjT<*=dwaV^B9W|KaOlvX!HJ6Dz@kNq{<>z(n#$JJR+cYcPDRCoZRz3R zVY<4yxO(*}H*ek~5{VFrM6%Mu!^2FPG>Mv;8ft56@%#Pw{r+^iwzig~OPA8v*qBxK z_3PKuYwV*(k8T?p8Zv&e_)tBZY@jBrec&;V$D^xPuhzYL_v+cRXY-2P;o)J;>?KYZ z8XD4$jt#Yd{0?e2(Bkj4=`)(@j z@pwoi5)2Lwrr(uQ-cO}3Uc5+eZ*M#vkDmcLu|9L`Qq|#-^exrkaRRO5kPy&-^%afR zcCYYwJlwl?k9a(;Si2|#Sf3N8?l*xCfcI6^ajT;!{T{Z#IV%)-4yeZ3SRYW;*o4+U p(FQ+iJaK;kcxv$DjwjCG{{ez+xA)Q`_t5|V002ovPDHLkV1l?JR_*`* literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/black_rook.png b/app/src/main/res/drawable/black_rook.png new file mode 100644 index 0000000000000000000000000000000000000000..b9748e87f29861cb4ca00c7ce03df54f3f6b35a0 GIT binary patch literal 725 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
    sH;c-=<)10)l{ab#=+m(2zX(=%YIJFBW6}1CY&| zH%llKlCG{U9UBC0x+;VL2XJc^{j-3qUAxvGymIAA-LNMu@W0bNrIgZf382{mI|Rrl zpL}ABy-IA(P zO4)!V02?=M)K4$78b>L$3~0$UpC(^u$4SlJBfz~P@>v=(N50vBMO?nihjV#&_3G6+ zcB=)Z36T2wdO3RZXx737><8qw+iuGh(qHFto*yU2q9iL}6X~dl^tx<>O)H|$EHE8_ zw70iQC=}AeFRgF^ULd5DlASwu<|6#I$+rEu_~d*&6p<<5r0LXNrBrz){KF4F%-p$i z0hTJInp4!v0G2IVhR5Tfv9S@7i;=}CxW@p`s#U9KXlTf2n^NlgK%425KL?$>--rER zdD3!CQv zdGNsp#qDkLdd92UFXZWJ!yRv>1#+oiX+S41Su z!+?uqO_7~DcgjZ}eWdF@&WlT)gl%ZyI6OQoKA+EQ=prk^;c!^IUaxMoufF=Ku752bE_sEtxl*4vae|hX7M^*OXHB)N9Jh%2>aCz5a6(DFsWHmKI}e(E|J!G8ZeQR1@%=&1Pf&{{1+ePW*nO zFz2k$I+=XE{AWP+?b|0JBB4;oyeQa4iibr+d_JG9zeGyG(q+${Jv!zKK+b)ii@lZzh(6_wLCz>do0~a(`ZOaWBUDsW z;PrZ^joIGb&I1oTaM_^Cw&Y%LXreUlv|}FFo06(6mWY!Sf|rTSy>q# zj|Y#(lh!XODIpSx5Q#(xhr@)!;c5M7G|JS}RKBL|5Ru>H11uz@0s4X4l~T-~KcBj~ zI_m4|(~k4!&&TO>7C3aegu`LZojXT&cQ2V4YX$BrGdO3*B$qod{(TG~EVwpLIM z11P2L1^x**4jw#6dwaW~OC%EX^z;x21c*kX#N%<|@i?(q%;@XC6Nv;amkXE6MQLfN z(KrA0dcD-v)>2tnIV~dF+S+*Mop&Hvoxd$2p}g%cl(0tnNnlS&NeOG#tRWZ-(%s!n zUtb@SlamFHmrKgZ%BZcarLL}y3l}cn^Z6jT74t0-IbD$L#SjKiO1(#NF=B|_Zl}7s znwpv#JRZ+9&!zSq4u@p~nERnnh_h$UGB7Y;Wx{ z0jjF1=)}K3fE;ThZ z)7qRla~K&JacI#smff@~9MYPH{{ zg$pS!FE>1v+8hpt;c>I)qtPglNQ8lb0eX9T>FMb)q9ziF=+j*!xs4Ji*zh7f+W<`1 z?RM$x?373(a-~u=tMvExOKWSZ?&V(>WqXl?e+kHj4I5^Ks96pjI;0bRuNd14{$rZ9 zA@)N^?lR1_xZQ5O+n|&xyyzBshk&(^+~kVIVzcI1U1G7A+;PVpx|cT;YJV|*Jsby^ zoSek(_nQmJRTmK<7!0y#(IWj+MWJI9^YY*X{)1_^V9uO5R99CUt*WYu%F0UPIcwGQ zrDZG@vuxpTnDgh)69@$8>+7ShuaExze#Xbg^=Zd}77_WpAOeMkgm!~&Ci&U+ED&cF zp24OT1U?7aim|=u=ddo?x2_7H8mQ7*HOXz0Qj6x&jt=c+#Y{(YivWW_AIUE*eL$ax vglA;$ObP$L$&G)+U+;2*@bxZVIl}(~G3Pqk!(KD#00000NkvXXu0mjfsr>;1 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/white_rook.png b/app/src/main/res/drawable/white_rook.png new file mode 100644 index 0000000000000000000000000000000000000000..a805de496f4d152dd02026bed09b45548b6e88d8 GIT binary patch literal 933 zcmV;W16urvP) zn!ERY_xs*^_wL^BS5ZpQNp!V4fSV=|>~{jeekTy@cLKqFM_aInSR(RXM3jRqiHNvp zuSDdFh}?F#&a{ZsTW#MIrIeNdV}QECVlLY&;HATL%5K^>GtW~xlgV6gI503^pL!x9 zPi+GpI<;3ykdU~)d z%Se321+TBKGdnv=yWs!tE;Q7 z`dF65;^Ly|P#p0rxLhu?wzg&>mX_Ju+tcstVU>PH^Huk{ZP{(yqMPv$kuZ=4?u5f( z#>dC$?d{d_)he}Gjm^zX4i66jegH#Cse&sfx+8pcqxyi)fJ!ElDxc4*>*DC>NR5n) z*dx0S+|`L$dxUL7q!0K2j3kpu=H})Ig^aI-EG#UrwY3HC6&O=W?d$mQEExWX{uGTy zhlYoT&wqRvp<1o7ySq!JQYiutbj1SRru1La`!S$0nT+x2oXuwKsr<@ooF;cmKMne7 zMAfTOSK5bSpX!G0$Y>~{jeey8IEo7}1Q0PO7SFflP<&@JS0Is0eCt1pv+ zp97@RX(lHp4Z4L$B*Mzd3Y;bmFDJI$U}*E70%~1dU21!K+js(?R4S=xG-@XS9(jq? z^9YNG1-t`7gM)(<3Iz%UcZtMS7#$sDV`BqgSw!wDrM_u7GBCOyx#4`YhK}5=c+0ud;;!3G + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/sample_game_view.xml b/app/src/main/res/layout/sample_game_view.xml new file mode 100644 index 0000000..9e7871e --- /dev/null +++ b/app/src/main/res/layout/sample_game_view.xml @@ -0,0 +1,16 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..af77b16 --- /dev/null +++ b/app/src/main/res/values-night/styles.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/attrs_game_view.xml b/app/src/main/res/values/attrs_game_view.xml new file mode 100644 index 0000000..ccfd390 --- /dev/null +++ b/app/src/main/res/values/attrs_game_view.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index f8c6127..66e3f6c 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -7,4 +7,8 @@ #FF018786 #FF000000 #FFFFFFFF + #FF29B6F6 + #FF039BE5 + #FFBDBDBD + #FF757575 \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..789b763 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file