| import java.util.Random; | 
          
            |  | 
          
            | import javax.microedition.lcdui.Canvas; | 
          
            | import javax.microedition.lcdui.Display; | 
          
            | import javax.microedition.lcdui.Graphics; | 
          
            | import javax.microedition.lcdui.Image; | 
          
            | import javax.microedition.midlet.MIDlet; | 
          
            |  | 
          
            | public class TemplateMIDlet extends MIDlet implements Runnable { | 
          
            |  | 
          
            | int FIELD_WIDTH = 12; | 
          
            | int FIELD_HEIGHT = 22; | 
          
            |  | 
          
            | int[][][] pattern = { | 
          
            | { | 
          
            | {0, 1, 0}, | 
          
            | {0, 1, 0}, | 
          
            | {0, 1, 0} | 
          
            | }, { | 
          
            | {0, 1, 0}, | 
          
            | {0, 1, 1}, | 
          
            | {0, 0, 0} | 
          
            | } | 
          
            | }; | 
          
            |  | 
          
            | int mode = 0; // ゲーム内の状態を表すモード(0:落下開始、1:落下中、2:着地) | 
          
            | int score = 0; | 
          
            | int totalLines = 0; | 
          
            | Thread thread; | 
          
            | Random random = new Random(); | 
          
            | StringBuffer keyBuffer = new StringBuffer(); | 
          
            | int[][] field = new int[FIELD_HEIGHT][FIELD_WIDTH]; | 
          
            | int[][] next = new int[pattern[0].length][pattern[0].length]; | 
          
            |  | 
          
            | Image offi; | 
          
            | Canvas canvas; | 
          
            |  | 
          
            | int COLOR_GRAY = 0xC0C0C0; | 
          
            | int COLOR_BLUE = 0x0000FF; | 
          
            | int COLOR_RED = 0xFF0000; | 
          
            | int COLOR_BLACK = 0x000000; | 
          
            | int COLOR_WHITE = 0xFFFFFF; | 
          
            |  | 
          
            | public TemplateMIDlet() { | 
          
            | canvas = new Canvas() { | 
          
            | public void paint(Graphics g) { | 
          
            | g.drawImage(offi, 0, 0, Graphics.TOP | Graphics.LEFT); | 
          
            | } | 
          
            |  | 
          
            | protected void keyPressed(int keyCode) { | 
          
            | // 落下中でかつ先行入力が2つ未満の場合のみキー入力を受け付ける | 
          
            | if (mode == 1 && keyBuffer.length() < 2) { | 
          
            | int ga = getGameAction(keyCode); | 
          
            | if (ga == Canvas.DOWN) { | 
          
            | keyBuffer.append('D'); | 
          
            | } else if (ga == Canvas.UP) { | 
          
            | keyBuffer.append('U'); | 
          
            | } else if (ga == Canvas.LEFT) { | 
          
            | keyBuffer.append('L'); | 
          
            | } else if (ga == Canvas.RIGHT) { | 
          
            | keyBuffer.append('R'); | 
          
            | } else { | 
          
            | keyBuffer.append('A'); | 
          
            | } | 
          
            | } | 
          
            | } | 
          
            |  | 
          
            | protected void keyRepeated(int keyCode) { | 
          
            | // キーを押しっぱなしの場合の動作はキーが押された場合と同じ | 
          
            | keyPressed(keyCode); | 
          
            | } | 
          
            | }; | 
          
            | offi = Image.createImage(canvas.getWidth(), canvas.getHeight()); | 
          
            | Display.getDisplay(this).setCurrent(canvas); | 
          
            | } | 
          
            |  | 
          
            | protected void startApp() { | 
          
            | if (thread == null) { | 
          
            | thread = new Thread(this); | 
          
            | thread.start(); | 
          
            | } | 
          
            | } | 
          
            |  | 
          
            | protected void pauseApp() { | 
          
            | // このイベントは利用しないので実装する必要はない | 
          
            | } | 
          
            |  | 
          
            | protected void destroyApp(boolean unconditional) { | 
          
            | // このイベントは利用しないので実装する必要はない | 
          
            | } | 
          
            |  | 
          
            | public void run() { | 
          
            | int x = 0; | 
          
            | int y = 0; | 
          
            | int count = 0; | 
          
            | int prevKey = '0'; | 
          
            | Graphics g = offi.getGraphics(); | 
          
            | initField(); | 
          
            | int[][] current = new int[pattern[0].length][pattern[0].length]; | 
          
            | copy(pattern[Math.abs(random.nextInt() % pattern.length)], next); | 
          
            | while (true) { | 
          
            | if (mode == 0) { | 
          
            | if (keyBuffer.length() > 0) { | 
          
            | keyBuffer.delete(0, keyBuffer.length() - 1); | 
          
            | } | 
          
            | copy(next, current); | 
          
            | copy(pattern[Math.abs(random.nextInt() % pattern.length)], next); | 
          
            | int rotateCount = Math.abs(random.nextInt() % 4); | 
          
            | for (int i = 0; i < rotateCount; i++) { | 
          
            | rotate(next); | 
          
            | } | 
          
            | x = FIELD_WIDTH / 2 - (int)Math.sqrt(pattern[0].length); | 
          
            | y = 0; | 
          
            | // ゲーム終了判定 | 
          
            | if (isHit(x, y, current)) { | 
          
            | initField(); | 
          
            | score = 0; | 
          
            | totalLines = 0; | 
          
            | } | 
          
            | mode = 1; | 
          
            | count = 0; | 
          
            | } else if (mode == 1) { | 
          
            | boolean fix = false; | 
          
            | if (count != 0) { | 
          
            | char key = 'N'; // 'N' は何も押していないことを表す | 
          
            | if (count % 20 == 0) { | 
          
            | if (!(keyBuffer.length() > 0 && keyBuffer.charAt(0) == 'D')) { | 
          
            | keyBuffer.insert(0, 'D'); | 
          
            | } | 
          
            | } | 
          
            | if (keyBuffer.length() > 0) { | 
          
            | key = keyBuffer.charAt(0); | 
          
            | keyBuffer.deleteCharAt(0); | 
          
            | if (key == 'L') { | 
          
            | x--; | 
          
            | } else if (key == 'R') { | 
          
            | x++; | 
          
            | } else if (key == 'D') { | 
          
            | y++; | 
          
            | } else if (key == 'A') { | 
          
            | rotate(current); | 
          
            | } else if (key == 'U') { | 
          
            | while (!isHit(x, y, current)) { | 
          
            | y++; | 
          
            | } | 
          
            | } | 
          
            | if (isHit(x, y, current)) { | 
          
            | if (key == 'L') { | 
          
            | x++; | 
          
            | } else if (key == 'R') { | 
          
            | x--; | 
          
            | } else if (key == 'A') { | 
          
            | if (prevKey == 'L') { | 
          
            | if (!isHit(x + 1, y, current)) { | 
          
            | x++; | 
          
            | } else { | 
          
            | rotate(current); | 
          
            | rotate(current); | 
          
            | rotate(current); | 
          
            | } | 
          
            | } else if (prevKey == 'R') { | 
          
            | if (!isHit(x - 1, y, current)) { | 
          
            | x--; | 
          
            | } else { | 
          
            | rotate(current); | 
          
            | rotate(current); | 
          
            | rotate(current); | 
          
            | } | 
          
            | } | 
          
            | } else if (key == 'D' || key == 'U') { | 
          
            | y--; | 
          
            | fix = true; | 
          
            | } | 
          
            | } | 
          
            | if (key == 'L' || key == 'R') { | 
          
            | prevKey = key; | 
          
            | } | 
          
            | } | 
          
            | } | 
          
            |  | 
          
            | for (int i = 0; i < FIELD_HEIGHT; i++) { | 
          
            | for (int j = 0; j < FIELD_WIDTH; j++) { | 
          
            | if (field[i][j] == 1) { | 
          
            | field[i][j] = 0; | 
          
            | } | 
          
            | } | 
          
            | } | 
          
            |  | 
          
            | for (int i = 0; i < current.length; i++) { | 
          
            | for (int j = 0; j < current[i].length; j++) { | 
          
            | if (current[i][j] == 1) { | 
          
            | field[y + i][x + j] = 1; | 
          
            | if (fix) { | 
          
            | field[y + i][x + j] = 2; | 
          
            | } | 
          
            | } | 
          
            | } | 
          
            | } | 
          
            |  | 
          
            | // メインフィールドを描画 | 
          
            | drawBlocks(g); | 
          
            |  | 
          
            | // 次に出現するブロックを描画 | 
          
            | drawNext(g); | 
          
            |  | 
          
            | // 得点と消去したライン数を描画 | 
          
            | drawScore(g); | 
          
            |  | 
          
            | if (fix) { | 
          
            | mode = 2; | 
          
            | } | 
          
            | if (count == 0) { | 
          
            | sleep(150); | 
          
            | } else { | 
          
            | sleep(50); | 
          
            | } | 
          
            | count++; | 
          
            | } else if (mode == 2) { | 
          
            | // 一列揃ったかどうかを判定する | 
          
            | int[] eraseLines = new int[pattern[0].length]; | 
          
            | int index = 0; | 
          
            | for (int i = 0; i < FIELD_HEIGHT; i++) { | 
          
            | boolean complete = true; | 
          
            | for (int j = 1; j < FIELD_WIDTH - 1; j++) { | 
          
            | if (field[i][j] != 2) { | 
          
            | complete = false; | 
          
            | break; | 
          
            | } | 
          
            | } | 
          
            | if (complete) { | 
          
            | eraseLines[index++] = i; | 
          
            | } | 
          
            | } | 
          
            | if (index != 0) { | 
          
            | for (int i = 0; i < 5; i++) { | 
          
            | for (int j = 0; j < index; j++) { | 
          
            | for (int k = 1; k < FIELD_WIDTH - 1; k++) { | 
          
            | field[eraseLines[j]][k] = i % 2 == 0 ? 0 : 2; | 
          
            | } | 
          
            | } | 
          
            | drawBlocks(g); | 
          
            | canvas.repaint(); | 
          
            | canvas.serviceRepaints(); | 
          
            | sleep(150); | 
          
            | } | 
          
            | for (int i = 0; i < index; i++) { | 
          
            | for (int j = eraseLines[i] - 1; j > 0; j--) { | 
          
            | field[j + 1] = field[j]; | 
          
            | field[j] = new int[FIELD_WIDTH]; | 
          
            | field[j][0] = field[j][FIELD_WIDTH - 1] = -1; | 
          
            | } | 
          
            | } | 
          
            | score += index * index * 10; | 
          
            | totalLines += index; | 
          
            | } | 
          
            | mode = 0; | 
          
            | } | 
          
            | canvas.repaint(); | 
          
            | canvas.serviceRepaints(); | 
          
            | } | 
          
            | } | 
          
            |  | 
          
            | void copy(int[][] src, int[][] dest) { | 
          
            | for (int i = 0; i < src.length; i++) { | 
          
            | System.arraycopy(src[i], 0, dest[i], 0, src[i].length); | 
          
            | } | 
          
            | } | 
          
            |  | 
          
            | void rotate(int[][] omino) { | 
          
            | int[][] temp = new int[omino[0].length][omino[0].length]; | 
          
            | temp[0][2] = omino[0][0]; | 
          
            | temp[1][2] = omino[0][1]; | 
          
            | temp[2][2] = omino[0][2]; | 
          
            | temp[0][1] = omino[1][0]; | 
          
            | temp[1][1] = omino[1][1]; | 
          
            | temp[2][1] = omino[1][2]; | 
          
            | temp[0][0] = omino[2][0]; | 
          
            | temp[1][0] = omino[2][1]; | 
          
            | temp[2][0] = omino[2][2]; | 
          
            | for (int i = 0; i < omino.length; i++) { | 
          
            | System.arraycopy(temp[i], 0, omino[i], 0, temp[i].length); | 
          
            | } | 
          
            | } | 
          
            |  | 
          
            | boolean isHit(int x, int y, int[][] omino) { | 
          
            | for (int i = 0; i < omino.length; i++) { | 
          
            | for (int j = 0; j < omino[i].length; j++) { | 
          
            | if (omino[i][j] == 1) { | 
          
            | if (field[y + i][x + j] == -1 || field[y + i][x + j] == 2) { | 
          
            | return true; | 
          
            | } | 
          
            | } | 
          
            | } | 
          
            | } | 
          
            | return false; | 
          
            | } | 
          
            |  | 
          
            | void initField() { | 
          
            | for (int i = 0; i < FIELD_HEIGHT; i++) { | 
          
            | for (int j = 0; j < FIELD_WIDTH; j++) { | 
          
            | if (j == 0 || j == FIELD_WIDTH - 1) { | 
          
            | field[i][j] = -1; | 
          
            | } else if (i == FIELD_HEIGHT - 1) { | 
          
            | field[i][j] = -1; | 
          
            | } else { | 
          
            | field[i][j] = 0; | 
          
            | } | 
          
            | } | 
          
            | } | 
          
            | for (int i = 1; i < FIELD_WIDTH - 1; i++) { | 
          
            | field[FIELD_HEIGHT - 1][i] = -1; | 
          
            | } | 
          
            | for (int i = 0; i < FIELD_HEIGHT; i++) { | 
          
            | field[i][0] = -1; | 
          
            | field[i][FIELD_WIDTH - 1] = -1; | 
          
            | } | 
          
            | } | 
          
            |  | 
          
            | void drawBlocks(Graphics g) { | 
          
            | int blockSize = canvas.getHeight() / (FIELD_HEIGHT + 2); | 
          
            | for (int i = 0; i < FIELD_HEIGHT; i++) { | 
          
            | for (int j = 0; j < FIELD_WIDTH; j++) { | 
          
            | if (field[i][j] == -1) { | 
          
            | g.setColor(COLOR_GRAY); | 
          
            | g.fillRect(j * blockSize, i * blockSize, blockSize, blockSize); | 
          
            | } else if (field[i][j] == 1) { | 
          
            | g.setColor(COLOR_RED); | 
          
            | g.fillRect(j * blockSize, i * blockSize, blockSize, blockSize); | 
          
            | } else if (field[i][j] == 2) { | 
          
            | g.setColor(COLOR_BLUE); | 
          
            | g.fillRect(j * blockSize, i * blockSize, blockSize, blockSize); | 
          
            | } else { | 
          
            | g.setColor(COLOR_BLACK); | 
          
            | g.fillRect(j * blockSize, i * blockSize, blockSize, blockSize); | 
          
            | } | 
          
            | } | 
          
            | } | 
          
            | } | 
          
            |  | 
          
            | void drawNext(Graphics g) { | 
          
            | int ominoSize = pattern[0].length; | 
          
            | int blockSize = canvas.getHeight() / (FIELD_HEIGHT + 2); | 
          
            | for (int i = 0; i < ominoSize; i++) { | 
          
            | for (int j = 0; j < ominoSize; j++) { | 
          
            | if (next[i][j] == 1) { | 
          
            | g.setColor(COLOR_RED); | 
          
            | g.fillRect((FIELD_WIDTH + j + 1) * blockSize, (i + 1) * blockSize, blockSize, blockSize); | 
          
            | } else { | 
          
            | g.setColor(COLOR_WHITE); | 
          
            | g.fillRect((FIELD_WIDTH + j + 1) * blockSize, (i + 1) * blockSize, blockSize, blockSize); | 
          
            | } | 
          
            | } | 
          
            | } | 
          
            | } | 
          
            |  | 
          
            | void drawScore(Graphics g) { | 
          
            | int blockSize = canvas.getHeight() / (FIELD_HEIGHT + 2); | 
          
            | int fontHeight = g.getFont().getHeight(); | 
          
            | int offx = (FIELD_WIDTH + 1) * blockSize; | 
          
            | int offy = (FIELD_HEIGHT) * blockSize - fontHeight * 2; | 
          
            | g.setColor(COLOR_WHITE); | 
          
            | g.fillRect(offx, offy, canvas.getWidth() - offx, fontHeight * 2); | 
          
            | g.setColor(COLOR_BLACK); | 
          
            | g.drawString("Line:" + totalLines, offx, offy + fontHeight, Graphics.BOTTOM | Graphics.LEFT); | 
          
            | g.drawString("Score:" + score, offx, offy + fontHeight * 2, Graphics.BOTTOM | Graphics.LEFT); | 
          
            | } | 
          
            |  | 
          
            | void sleep(long millis) { | 
          
            | try { | 
          
            | Thread.sleep(millis); | 
          
            | } catch (InterruptedException e) { | 
          
            | // 例外は発生しない | 
          
            | } | 
          
            | } | 
          
            |  | 
          
            | } |