Continuing from the previous article, the previous article completed the timing in the game and the automatic random arrangement of the program fragments. This article will complete the remaining parts (the movement of the fragments and the success logic of the puzzle)
The implementation process is roughly: the last photo is not displayed by default, but it actually exists. Click the adjacent picture in the blank area (only the picture in the blank area is clicked and valid) and then realize the movement of the picture after clicking and the exchange of the blank area. After the second move, if the combination of the final total picture is the same as the given final picture, a prompt box showing the success of the puzzle will pop up!
In fact, the summary is an array of knowledge. Use the coordinate value exchange of the array to show the exchange of pictures, and use the picture movement several times (the exchange of the number of arrays) to see if it is the same as the imported final designated picture (specified numerical order)!
The specific implementation method: (the code comments are already very detailed, and are commented step by step according to the logic, which is easy to understand)
If you don’t understand something in the comment area, you can leave a message or private message me. If the article has code, logic, or inaccurate writing errors, please correct me. I will correct and learn in time, thank you!
To achieve the effect of clicking on the fragments:
//Represents the function of moving the button at the specified position, exchanging the picture with the blank area private void move(int imagebuttonId, int site) { //Judging which row and column the selected picture is in, the judgment method is through the method of finding the remainder int sitex=site/imageX; int sitey=site%imageY; // Get the coordinates of the blank area int blankx=blankSwap/imageX; int blanky=blankSwap%imageY; //Two conditions for the image to move //1. In the same row, the absolute value of the subtraction of the number of columns is 1; 2. In the same column, the absolute value of the subtraction of the number of rows is 1 int x=Math.abs(sitex-blankx); int y=Math.abs(sitey-blanky); if((x == 0&&y==1)||(y==0&&x==1)){ // Find this movable button by id ImageButton clickButton=findViewById(imagebuttonId); clickButton.setVisibility(View.INVISIBLE); // button to view the blank area ImageButton blackButton=findViewById(blankImgid); //Set the blank area to the image blackButton.setImageResource(image[imageIndex[site]]); //Invisible between movements, after movement, set the control to be visible blackButton.setVisibility(View.VISIBLE); //Record the process of changing the corner mark into the array that stores the image location swap(site,blankSwap); //The position of the new blank area is updated to be equal to the position of the incoming click button blankSwap=site; blankImgid=imagebuttonId; }
Realize the logical effect of judging whether the debris moves successfully after several times:
/ / Determine whether the puzzle is successful private void judgeGameOver() { boolean loop=true;//Define flag bit for(int i=0;i<imageIndex.length;i++) { if (imageIndex[i] != i) { loop = false; break; } } if(loop){ //Puzzle is successful, stop timing handler.removeMessages(1); // After the puzzle is successful, the player is prohibited from continuing to move the button ib00.setClickable(false); ib01.setClickable(false); ib02.setClickable(false); ib10.setClickable(false); ib11.setClickable(false); ib12.setClickable(false); ib20.setClickable(false); ib21.setClickable(false); ib22.setClickable(false); ib22.setImageResource(image[8]); ib22.setVisibility(View.VISIBLE); //Pop up the user success dialog box AlertDialog.Builder builder=new AlertDialog.Builder(this); builder.setMessage("Congratulations, the puzzle is successful! Your time is "+time+"seconds").setPositiveButton("Confirm",null); builder.create().show(); }
Java total code:
package com.example.jigsaw; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint; import android.media.Image; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.AlteredCharSequence; import android.view.View; import android.widget.Button; import android.widget.ImageButton; import android.widget.TextView; public class MainActivity extends AppCompatActivity { ImageButton ib00,ib01,ib02,ib10,ib11,ib12,ib20,ib21,ib22; Button restartBtn; TextView timeTv; //Define the number of pictures in each row and column private int imageX=3; private int imageY=3; //Total number of pictures private int imgCount=imageX*imageY; //position of blank space private int blankSwap=imgCount-1; //Initialize the button id of the blank area private int blankImgid=R.id.pt_id_02x02; //Define time variables int time = 0; //Store the array of fragments for unified management private int[]image={R.drawable.pt_id_00x00,R.drawable.pt_id_00x01,R.drawable.pt_id_00x02, R.drawable.pt_tv_01x00,R.drawable.pt_tv_01x01,R.drawable.pt_tv_01x02,R.drawable.p1,R.drawable.p2,R.drawable.p3}; // Declare an array of subscripts for an image array, and randomly arrange the array private int[]imageIndex=new int[image.length]; Handler handler=new Handler(){ @Override public void handleMessage(@NonNull Message msg) { if (msg.what==1){ time++; timeTv.setText("Time: "+time+" seconds"); handler.sendEmptyMessageDelayed(1,1000); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); //scramble fragments disruptRandpm(); handler.sendEmptyMessageDelayed(1,1000); } // randomly shuffle the irregular private void disruptRandpm() { for(int i=0;i<imageIndex.length;i++){ imageIndex[i]=i; } //Specify 20 times, randomly select the values corresponding to the two subscripts to exchange int rand1,rand2; for(int j=0;j<20;j++){ // Randomly generate a corner mark, the value of 0-8 rand1=(int)(Math.random()*(imageIndex.length-1)); //The second randomly generated corner mark cannot be the same as the first time do{ rand2=(int)(Math.random()*(imageIndex.length-1)); if(rand1!=rand2){ break; } }while (true); //Exchange the corresponding values on the two corner marks swap(rand1,rand2); } //Randomly arranged on the specified control ib00.setImageResource(image[imageIndex[0]]); ib01.setImageResource(image[imageIndex[1]]); ib02.setImageResource(image[imageIndex[2]]); ib10.setImageResource(image[imageIndex[3]]); ib11.setImageResource(image[imageIndex[4]]); ib12.setImageResource(image[imageIndex[5]]); ib20.setImageResource(image[imageIndex[6]]); ib21.setImageResource(image[imageIndex[7]]); ib22.setImageResource(image[imageIndex[8]]); } //exchange private void swap(int rand1, int rand2) { int temp=imageIndex[rand1]; imageIndex[rand1]=imageIndex[rand2]; imageIndex[rand2]=temp; } private void initView() { ib00=findViewById(R.id.pt_id_00x00); ib01=findViewById(R.id.pt_id_00x01); ib02=findViewById(R.id.pt_id_00x02); ib10=findViewById(R.id.pt_id_01x00); ib11=findViewById(R.id.pt_id_01x01); ib12=findViewById(R.id.pt_id_01x02); ib20=findViewById(R.id.pt_id_02x00); ib21=findViewById(R.id.pt_id_02x01); ib22=findViewById(R.id.pt_id_02x02); timeTv=findViewById(R.id.pt_tv_time); restartBtn=findViewById(R.id.pt_btn_restart); } public void onClick(View view) { int id=view.getId(); switch (id){ case R.id.pt_id_00x00: move(R.id.pt_id_00x00,0); break; case R.id.pt_id_00x01: move(R.id.pt_id_00x01,1); break; case R.id.pt_id_00x02: move(R.id.pt_id_00x02,2); break; case R.id.pt_id_01x00: move(R.id.pt_id_01x00,3); break; case R.id.pt_id_01x01: move(R.id.pt_id_01x01,4); break; case R.id.pt_id_01x02: move(R.id.pt_id_01x02,5); break; case R.id.pt_id_02x00: move(R.id.pt_id_02x00,6); break; case R.id.pt_id_02x01: move(R.id.pt_id_02x01,7); break; case R.id.pt_id_02x02: move(R.id.pt_id_02x02,8); break; } } //Represents the function of moving the button at the specified position, exchanging the picture with the blank area private void move(int imagebuttonId, int site) { //Judging which row and column the selected picture is in, the judgment method is through the method of finding the remainder int sitex=site/imageX; int sitey=site%imageY; // Get the coordinates of the blank area int blankx=blankSwap/imageX; int blanky=blankSwap%imageY; //Two conditions for the image to move //1. In the same row, the absolute value of the subtraction of the number of columns is 1; 2. In the same column, the absolute value of the subtraction of the number of rows is 1 int x=Math.abs(sitex-blankx); int y=Math.abs(sitey-blanky); if((x == 0&&y==1)||(y==0&&x==1)){ // Find this movable button by id ImageButton clickButton=findViewById(imagebuttonId); clickButton.setVisibility(View.INVISIBLE); // button to view the blank area ImageButton blackButton=findViewById(blankImgid); //Set the blank area to the image blackButton.setImageResource(image[imageIndex[site]]); //Invisible between movements, after movement, set the control to be visible blackButton.setVisibility(View.VISIBLE); //Record the process of changing the corner mark into the array that stores the image location swap(site,blankSwap); //The position of the new blank area is updated to be equal to the position of the incoming click button blankSwap=site; blankImgid=imagebuttonId; } //Judge whether the jigsaw puzzle is completed after this move is completed judgeGameOver(); } / / Determine whether the puzzle is successful private void judgeGameOver() { boolean loop=true;//Define flag bit for(int i=0;i<imageIndex.length;i++) { if (imageIndex[i] != i) { loop = false; break; } } if(loop){ //Puzzle is successful, stop timing handler.removeMessages(1); // After the puzzle is successful, the player is prohibited from continuing to move the button ib00.setClickable(false); ib01.setClickable(false); ib02.setClickable(false); ib10.setClickable(false); ib11.setClickable(false); ib12.setClickable(false); ib20.setClickable(false); ib21.setClickable(false); ib22.setClickable(false); ib22.setImageResource(image[8]); ib22.setVisibility(View.VISIBLE); //Pop up the user success dialog box AlertDialog.Builder builder=new AlertDialog.Builder(this); builder.setMessage("Congratulations, the puzzle is successful! Your time is "+time+"seconds").setPositiveButton("Confirm",null); builder.create().show(); } // } } // jigsaw puzzle restart public void restart(View view) { // The jigsaw puzzle restarts, allowing the player to move pieces ib00.setClickable(true); ib01.setClickable(true); ib02.setClickable(true); ib10.setClickable(true); ib11.setClickable(true); ib12.setClickable(true); ib20.setClickable(true); ib21.setClickable(true); ib22.setClickable(true); // jigsaw puzzle disruptRandpm(); handler.removeMessages(1); //The time returns to 0, and re-⏲ time=0; timeTv.setText("Time: "+time+" seconds"); handler.sendEmptyMessageDelayed(1,1000); } } Screenshot effect: