import java.io.IOException;
import java.util.Random;
import java.lang.Math;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.Command.*;
import javax.microedition.lcdui.Displayable.*;
/**
* MineSweeper MIDlet Class
*/
public class MineSweeper extends MIDlet
{
Display display;
MineSweeperCanvas canvas;
public void startApp()
{
display = Display.getDisplay(this);
if (canvas==null)
{
canvas = new MineSweeperCanvas(this);
display.setCurrent(canvas);
} else
{
canvas.repaint();
}
}
public void pauseApp()
{
}
public void destroyApp(boolean unconditional)
{
canvas = null;
}
public void exit()
{
destroyApp(false);
notifyDestroyed();
}
}
class MineSweeperCanvas extends Canvas implements CommandListener
//소스분석 중인데요. 이부분에서 자꾸 에러가 걸리네요. 에러내용이 영어인데 대충 해석해 봐도 뭔말이지..
에러에 대한 내용은
MineSweeperCanvas is not abstract and does not override abstract method commandAction(Javax.microedition.lcdui.Command,
javax.microedition.lcdui.Diplayable) in javax.microedition.CommandListener//
이겁니다. 어떻게 하란 걸까요;;고수님의 해법을 기다립니다.ㅠㅠ
{
int messageX;
int messageY;
int fontHeight;
int offsetX;
int offsetY;
int selectedX;
int selectedY;
int selectedX_O;
int selectedY_O;
int fieldWidth;
int fieldHeight;
static final int GAME_READY = 0;
static final int GAME_PLAY = 1;
static final int GAME_REDRAW_ALL = 2;
static final int GAME_REDRAW_ONE = 3;
static final int GAME_END = 4;
static final int BLOCK_CLOSE = 0;
static final int BLOCK_OPEN = 1;
static final int BLOCK_FLAG = 2;
static final int IMAGE_WIDTH = 16;
static final int IMAGE_HEIGHT = 16;
static final int[] LEVEL_FACTOR = { 8, 6, 3 };
static Random random = new Random();
private Image[] imgOpen = new Image[6];
private Image imgClose;
private Image imgFlag;
private Image imgMine;
private Image imgBanner;
int[][] fieldStatus;
int[][] fieldValue;
int mineCount;
int flagCount;
int openCount;
String message;
int status;
private MineSweeper midlet;
private Command cmdFlag;
private Command cmdExit;
public MineSweeperCanvas(MineSweeper midlet)
{
this.midlet = midlet;
try
{
fontHeight = Font.getDefaultFont().getHeight();
imgBanner = Image.createImage("/banner.png");
for (int i=0;i<6;i++)
{
imgOpen[i] = Image.createImage("/open_"+i+".png");
}
imgClose = Image.createImage("/close.png");
imgFlag = Image.createImage("/flag.png");
imgMine = Image.createImage("/mine.png");
fieldWidth = getWidth() / IMAGE_WIDTH;
fieldHeight = (getHeight() - (imgBanner.getHeight() + fontHeight)) / IMAGE_HEIGHT;
fieldStatus = new int[fieldWidth][fieldHeight];
fieldValue = new int[fieldWidth][fieldHeight];
offsetX = (getWidth() - IMAGE_WIDTH * fieldWidth) / 2;
offsetY = (getHeight() - IMAGE_HEIGHT * fieldHeight - imgBanner.getHeight() - fontHeight) / 2 + imgBanner.getHeight();
messageX = 3;
messageY = getHeight() - fontHeight;
}catch (IOException e)
{
message = "Can't load image! :" + e.getMessage();
}
cmdExit = new Command("Exit",Command.EXIT,0);
cmdFlag = new Command("Flag",Command.SCREEN,1);
addCommand(cmdExit);
addCommand(cmdFlag);
setCommandListener(this);
startGame();
}
protected void startGame()
{
message = "Level? (1~3)";
selectedX = -1;
selectedY = -1;
status = GAME_READY;
for(int x =0; x < fieldWidth; ++x)
{for(int y =0;y < fieldHeight;++y)
{fieldStatus[x][y] = BLOCK_CLOSE;
fieldValue[x][y] = 0;
}
}
repaint();
}
protected void initField(int level)
{
selectedX = 0;
selectedY = 0;
selectedX_O = 0;
selectedY_O = 0;
mineCount = (fieldWidth*fieldHeight)*100/LEVEL_FACTOR[level]/100;
flagCount = 0;
openCount = 0;
message = "Remains : " + (mineCount-flagCount);
int i = 0;
while (i<mineCount)
{
int x = Math.abs(random.nextInt()) % fieldWidth;
int y = Math.abs(random.nextInt()) % fieldHeight;
if (fieldValue[x][y] == -1)
{
continue;
}
boolean exceed = false;
for (int x1 = x-1;x1 <= x+1;x1++)
{
for (int y1 = y-1;y1 <= y+1;y1++)
{
if (0<=x1 && x1<fieldWidth && 0<=y1 && y1<fieldHeight)
{
if (fieldValue[x1][y1]>=5)
{
exceed = true;
break;
}
}
}
if (exceed) break;
}
if (exceed) continue;
fieldValue[x][y] = -1;
for (int x1 = x-1;x1 <=x+1;x1++)
{
for(int y1 = y-1;y1 <= y+1;y1++)
{
if (0<=x1 && x1<fieldWidth && 0<=y1 && y1<fieldHeight && (fieldValue[x1][y1]!=-1))
{
fieldValue[x1][y1]++;
}
}
}
i++;
}
}
protected void openBlock(int x, int y)
{
if (fieldValue[x][y] == -1)
{
status= GAME_END;
message = "Bomb!";
for(int x1 = 0; x1 < fieldWidth; ++x1)
{
for(int y1 = 0; y1 < fieldHeight; ++y1)
{
if (fieldValue[x1][y1] == -1)
{
fieldStatus[x1][y1] = BLOCK_OPEN;
}
}
}
}
else if (fieldStatus[x][y] == BLOCK_CLOSE)
{
if (fieldValue[x][y]>0)
{
fieldValue[x][y] = BLOCK_OPEN;
openCount++;
status = GAME_REDRAW_ONE;
}
else
{
fillOpen(x,y);
status = GAME_REDRAW_ALL;
}
if (fieldWidth*fieldHeight == openCount + mineCount)
{
status = GAME_END;
message = "Well Done!";
}
}
}
protected void fillOpen(int x, int y)
{
if (x<0 || fieldWidth <=x || y<0 || fieldHeight <=y)
{
return;
}
if (fieldStatus[x][y] != BLOCK_CLOSE)
{
return;
}
fieldStatus[x][y] = BLOCK_OPEN;
openCount++;
if (fieldValue[x][y] == 0)
{
fillOpen(x - 1,y - 1);
fillOpen(x - 1,y );
fillOpen(x - 1,y + 1);
fillOpen(x ,y - 1);
fillOpen(x ,y + 1);
fillOpen(x + 1,y - 1);
fillOpen(x + 1,y);
fillOpen(x + 1,y + 1);
}
}
protected void ketPressed(int keyCode)
{
int param = getGameAction(keyCode);
switch (status)
{
case GAME_READY:
int level = -1;
switch (keyCode)
{
case KEY_NUM1:
level = 0;
break;
case KEY_NUM2:
level = 1;
break;
case KEY_NUM3:
level = 2;
}
if (level>=0)
{
initField(level);
status = GAME_PLAY;
repaint();
}
break;
case GAME_PLAY:
switch (param)
{
case UP:
selectedX_O = selectedX;
selectedY_O = selectedY;
selectedY = (selectedY - 1 + fieldHeight) % fieldHeight;
break;
case DOWN:
selectedX_O = selectedX;
selectedY_O = selectedY;
selectedY = (selectedY + 1) % fieldHeight;
break;
case LEFT:
selectedX_O = selectedX;
selectedY_O = selectedY;
selectedX = (selectedX - 1 + fieldWidth) % fieldWidth;
break;
case RIGHT:
selectedX_O = selectedX;
selectedY_O = selectedY;
selectedX = (selectedX + 1) % fieldWidth;
break;
case FIRE:
if (fieldStatus[selectedX][selectedY]==BLOCK_CLOSE)
{
openBlock(selectedX, selectedY);
}
break;
}
repaint();
break;
case GAME_END:
if (param==FIRE)
{
startGame();
}
}
}
public void paint(Graphics g)
{
switch (status)
{
case GAME_READY:
g.setColor(0x999999);
g.fillRect(0, 0, getWidth(), getHeight());
g.drawImage(imgBanner, 0, 0, g.TOP|g.LEFT);
for (int x=0; x<fieldWidth; x++)
{
for (int y=0; y<fieldHeight; y++)
{
paintBlock(g, x, y);
}
}
break;
case GAME_PLAY:
paintBlock(g, selectedX_O, selectedY_O);
paintBlock(g, selectedX, selectedY);
break;
case GAME_REDRAW_ALL:
for (int x=0; x<fieldWidth; x++)
{
for (int y=0; y<fieldHeight; y++)
{
paintBlock(g, x, y);
}
}
status = GAME_PLAY;
break;
case GAME_REDRAW_ONE:
paintBlock(g, selectedX, selectedY);
status = GAME_PLAY;
break;
case GAME_END:
for (int x=0; x<fieldWidth; x++)
{
for (int y=0; y<fieldHeight; y++)
{
paintBlock(g, x, y);
}
}
break;
}
if (message!=null)
{
g.setColor(0x999999);
g.fillRect(messageX, messageY, getWidth(), fontHeight);
g.setColor(0xFF0000);
g.drawString(message, messageX, messageY, g.TOP|g.LEFT);
message = null;
}
}
protected void paintBlock(Graphics g, int x, int y)
{
int screenX = offsetX + IMAGE_WIDTH * x;
int screenY = offsetY + IMAGE_HEIGHT * y;
if (fieldStatus[x][y]==BLOCK_CLOSE)
{
g.drawImage(imgClose, screenX, screenY, g.TOP|g.LEFT);
}
else if (fieldStatus[x][y]==BLOCK_FLAG)
{
g.drawImage(imgFlag, screenX, screenY, g.TOP|g.LEFT);
}
else if (fieldStatus[x][y]==BLOCK_OPEN)
{
if (fieldValue[x][y]==-1)
g.drawImage(imgMine, screenX, screenY, g.TOP|g.LEFT);
else
g.drawImage(imgOpen[fieldValue[x][y]], screenX, screenY, g.TOP|g.LEFT);
}
if (x==selectedX && y==selectedY)
{
g.setColor(0x000000);
g.drawRect(screenX, screenY, IMAGE_WIDTH-1, IMAGE_HEIGHT-1);
}
}
public void commangAction(Command c, Displayable d)
{
if (c==cmdExit)
{
midlet.exit();
}
else if (c==cmdFlag)
{
if (status!=GAME_PLAY) return;
if (fieldStatus[selectedX][selectedY] == BLOCK_OPEN) return;
if (fieldStatus[selectedX][selectedY] == BLOCK_CLOSE)
{
fieldStatus[selectedX][selectedY] = BLOCK_FLAG;
flagCount++;
}
else if (fieldStatus[selectedX][selectedY] == BLOCK_FLAG)
{
fieldStatus[selectedX][selectedY] = BLOCK_CLOSE;
flagCount++;
}
message = "Remains:" + (mineCount - flagCount);
status = GAME_REDRAW_ONE;
repaint();
}
}
}
저도 영어 짧지만 ^^ 간단하게 해석해 보면
[ MineSweeperCanvas 는 추상적이지 않고 추상메소드 commandAction를 override 되지 않았다. ]
즉, 추상메소드인 commandAction를 MineSweeperCanvas에 다시 선언하여 구체적인 내용을 써 주어야 하는데,
그 메소드가 없어서 발생한 에러입니다.
소스를 보니, 오타가 있었네요. ^^
public void commangAction(Command c, Displayable d)
를
public void commandAction(Command c, Displayable d)
로 하셔야죠^^
뭐가 다른지 잘 보세요. ^^