어릴때 많이 가지고 놀던 숫자 퍼즐게임인데...
인터넷 돌아다니다 우현히 보게되서...
어떻게 만들었을까 고민 시작 하기도 전에 코딩해봤습니다...
안드로이드에서 기본 제공하는 버튼과 기본 레이아웃을 사용. 소스는 아래와 같습니다.
gradientbox3.xml (버튼 그라디언트 주기위해)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="20dp"/>
<gradient
android:startColor="#FFAAAAFF"
android:endColor="#FFffffff"
android:angle="90" />
<padding
android:left="5dp"
android:top="5dp"
android:right="5dp"
android:bottom="5dp" />
<stroke
android:width="4dp"
android:color="#99232323" />
</shape>
다음은 기본으로 생성되는 엑티비디에 전체 소스를 쑤셔 넣었어요.......
package com.example.mygame001;
import java.util.Random;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.RelativeLayout;
public class MainActivity extends Activity {
private int[][] cellData;
private int BtnWidth;
private RelativeLayout cv;
private Button startBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
super.onCreate(savedInstanceState);
RelativeLayout gameView = new RelativeLayout(this);
setContentView(gameView);
cv = new RelativeLayout(this);
cv.setBackgroundColor(Color.argb(180, 0, 0, 0));
gameView.addView(cv);
int sw = getWindow().getWindowManager().getDefaultDisplay().getWidth();
int nb = 3;
BtnWidth = sw / nb;
int indexBtn = 0;
cellData = new int[nb][nb];
Button mb = null;
RelativeLayout.LayoutParams lp = null;
for(int ny=0; ny<nb; ny++){
for(int nx=0; nx<nb; nx++){
mb = new Button(this);
lp = new RelativeLayout.LayoutParams(BtnWidth,BtnWidth);
lp.leftMargin = nx * BtnWidth;
lp.topMargin = ny * BtnWidth;
mb.setLayoutParams(lp);
mb.setBackgroundResource(R.drawable.gradientbox3);
mb.setTextSize(72);
mb.setText(String.valueOf(++indexBtn));
mb.setOnClickListener(BtnClick);
cv.addView(mb);
cellData[ny][nx] = 1;
}
}
cv.removeViewAt(nb*nb-1);
cellData[nb-1][nb-1] = 0;
startBtn = new Button(this);
lp = new RelativeLayout.LayoutParams(sw, 120);
lp.topMargin = BtnWidth * nb;
startBtn.setLayoutParams(lp);
startBtn.setTextSize(32);
startBtn.setText("START GAME");
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
shufflePosition();
}
});
gameView.addView(startBtn);
}
private View.OnClickListener BtnClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
moveButton(v, getEmptyCell(v));
if( isCompleteGame() && timeCount != 0){
startBtn.setText("COMPLETE GAME "+String.valueOf(timeCount));
}
int nb=3;
Log.d("++GAME","--------------------");
for(int ny=0; ny<nb; ny++){
Log.d("++GAME", String.valueOf(cellData[ny][0])+","+String.valueOf(cellData[ny][1])+","+String.valueOf(cellData[ny][2]));
}
}
};
private int getEmptyCell(View v){
RelativeLayout.LayoutParams rp = (RelativeLayout.LayoutParams)v.getLayoutParams();
int ny = Integer.valueOf(rp.topMargin / BtnWidth);
int nx = Integer.valueOf(rp.leftMargin / BtnWidth);
int result = (nx-1>=0 && cellData[ny][nx-1] == 0)? 1:
(nx+1<=2 && cellData[ny][nx+1] == 0)? 2:
(ny-1>=0 && cellData[ny-1][nx] == 0)? 3:
(ny+1<= 2 && cellData[ny+1][nx] == 0)? 4:0;
return result;
}
private void moveButton(View v, int dir){
RelativeLayout.LayoutParams rp = (RelativeLayout.LayoutParams)v.getLayoutParams();
int ny = Integer.valueOf(rp.topMargin / BtnWidth);
int nx = Integer.valueOf(rp.leftMargin / BtnWidth);
switch(dir){
case 1: rp.leftMargin -= BtnWidth; cellData[ny][nx] = 0; cellData[ny][nx-1] = 1;break;
case 2: rp.leftMargin += BtnWidth; cellData[ny][nx] = 0; cellData[ny][nx+1] = 1;break;
case 3: rp.topMargin -= BtnWidth; cellData[ny][nx] = 0; cellData[ny-1][nx] = 1;break;
case 4: rp.topMargin += BtnWidth; cellData[ny][nx] = 0; cellData[ny+1][nx] = 1;break;
}
v.setLayoutParams(rp);
}
private boolean isCompleteGame(){
boolean result = true;
for(int i=cv.getChildCount()-1; i>0; i--){
Button btn = (Button)cv.getChildAt(i);
RelativeLayout.LayoutParams rp = (RelativeLayout.LayoutParams)btn.getLayoutParams();
int ny = Integer.valueOf(rp.topMargin / BtnWidth);
int nx = Integer.valueOf(rp.leftMargin / BtnWidth);
int id = Integer.valueOf(btn.getText().toString());
if(
(ny==0 && nx+1==id) ||
(ny==1 && nx+4==id) ||
(ny==2 && nx+7==id)
){}else{
result = false;
break;
}
}
return result;
}
private void shufflePosition(){
Random rnd = new Random();
for(int i=cv.getChildCount()-1; i>0; i--){
int index = rnd.nextInt(i+1);
RelativeLayout.LayoutParams first = (RelativeLayout.LayoutParams)((Button)cv.getChildAt(index)).getLayoutParams();
RelativeLayout.LayoutParams next = (RelativeLayout.LayoutParams)((Button)cv.getChildAt(i)).getLayoutParams();
((Button)cv.getChildAt(index)).setLayoutParams(next);
((Button)cv.getChildAt(i)).setLayoutParams(first);
}
timeCount = 0;
if(handler==null){
handler = new Handler();
checkTime();
}
}
private void shuffleLable(){
Random rnd = new Random();
for(int i=cv.getChildCount()-1; i>0; i--){
int index = rnd.nextInt(i+1);
String lbl = ((Button)cv.getChildAt(index)).getText().toString();
String tmp = ((Button)cv.getChildAt(i)).getText().toString();
((Button)cv.getChildAt(index)).setText(tmp);
((Button)cv.getChildAt(i)).setText(lbl);
}
}
private int timeCount=0;
Handler handler;
private void checkTime(){
handler.postDelayed(new Runnable(){
public void run(){
timeCount++;
checkTime();
if(timeCount<60){
startBtn.setText(String.valueOf(timeCount)+" 초 경과.");
}else{
int m = timeCount/60;
int s = timeCount-(m*60);
startBtn.setText(String.valueOf(m)+"분 "+String.valueOf(s)+"초 경과.");
}
}
}, 1000);
}
}
위소스를 실행한 화면은 아래와 같습니다...
기획도 없고, 설계도 없고, 머리에 그려지는 대로 코딩해서, 주석도 없습니다.
우선 onCreate() 속에 있는 nb 를 전역 변수로 만드시고,
moveButton() 의 int nx = .... 아래부분에 Log.d("++game",String.valueOf(ny)+" / "+String.valueOf(nx)+" / "+String.valueOf(dir)); 를 추가해서
로그를 찍어보시면 dir 가 어떤 버튼을 눌러도 0 이 나올겁니다. 해서 움직이지 않는거구요...
자 그럼 getEmptyCell() 에서 문제가 있는거죠...
int result =
(nx-1>=0 && cellData[ny][nx-1]==0)? 1: // 좌
(nx+1<nb && cellData[ny][nx+1]==0)? 2: // 우
(ny-1>=0 && cellData[ny-1][nx]==0)? 3: // 상
(ny+1<nb && cellData[ny+1][nx]==0)? 4: 0; // 하
요렇게 수정해서 로그를 찍어보면 이동이 가능한 버튼은 움직일 방향이 0 이 나오지 않게 되고.
다음으로 수정해야 할 부분은 BtnClick() 내부에 int nb=3; 요걸 삭제 하시구요.
다음은 게임 완료 여부 isComplete 부분에
if (
(ny==0 && nx+1==id) ||
(ny==1 && nx+4==id) ||
(ny==2 && nx+7==id)
요 조건식을 수정하셔야 합니다... 이건 숙제 입니다. 본인 스스로 해결하시기 바랍니다.
예를 들어 7 * 7일경우에는 nb 만 7로 바꿔주면 될줄알았는데
onclik listener가 먹히지 않고 문제점이 어딘지 찾을수 없어서
이렇게 질문 올렸습니다.
추가적으로 바뀌어야할 구문이 있다면 어디인지 알고 싶습니다