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)
로 하셔야죠^^
뭐가 다른지 잘 보세요. ^^