Chủ Nhật, 24 tháng 2, 2013

Trò chơi trúc xanh

hôm nay tôi sẽ giới thiệu với các bạn một trò chơi khác nữa, đó là trò chơi lật các ô hình để tìm ra những cặp hình giống nhau. Trò chơi này chắc cũng quen thuộc với các bạn qua chương trình trúc xanh phát trên htv7 nhỉ. Chúng ta có file trucxanh.java ban đầu như sau: trucxanh.java
C:\Users\thanhliem\Documents\NetBeansProjects\trucxanh\src\trucxanh.java


import javax.microedition.lcdui.*;
import java.util.*;

public class trucxanh extends Canvas{
    //mảng chứa các mảnh hình
byte[][] board;
//các biến bao gồm: tọa độ khung chọn(x,y), vị trí đã chọn(sx,sy), giá trị chọn(ff)
int x,y,sx,sy,w,h,ff=-1;
Midlet m;
    public trucxanh(Midlet m) {
        try {
setFullScreenMode(true);
w=getWidth();
h=getHeight();
this.m=m;
//hàm general, tạo ra một mảng mới với các cặp giá trị.
general(4,3);
        } catch (Exception e) {
        }
    }


    public void paint(Graphics g) {
g.setColor(0);
g.fillRect(0, 0, w, h);
g.setColor(0x00ff00);
//nếu như mảng không rỗng thì vẽ bảng
if(board!=null)
    //lần lượt cho hàng i
for(int i=0;i<board.length;i++){
    //lần lượt cho cột j
for(int j=0;j<board[0].length;j++){
    //nếu giá trị tìm được trong bảng khác -1 thì vẽ ra
    if(board[i][j]!=-1)
g.drawString(""+board[i][j],10+j*16,10+i*16,0);}}
//nếu giá trị đã chọn khác -1 thì vẽ khung đã chọn vị trí sx,sy
if(ff!=-1){
g.setColor(0xff0000);
g.drawRect(10+sx*16, 10+sy*16, 16, 16);
}
//vẽ khung lựa chọn tại vị trí x,y
g.setColor(0x0000ff);
g.drawRect(10+x*16, 10+y*16, 16, 16);
repaint();
    }
//hàm nhấn phím
    protected void keyPressed(int k) {
    switch(k){
        case -1:
            y--;
    break;
    case -2:
        y++;
    break;
    case -3:
        x--;
    break;
    case -4:
        x++;
    break;
    case -5:
        //nếu chưa chọn (ff==-1) thì cho giá trị vào ff, sx, sy
        if(ff==-1)
        {if(board[y][x]!=-1){sx=x; sy=y; ff=board[y][x];}}
        //ngược lại thì cho so sánh giá trị đã chọn và giá trị vừa chọn
        else
        {if(board[y][x]==ff){board[y][x]=board[sy][sx]=-1; ff=-1;}else{ff=-1;}}
    break;}
    //các công thức này đảm bảo khung lựa chọn không đi ra ngoài bảng
    if(x==board[0].length)x=0;
    if(x<0)x=board[0].length-1;
    if(y==board.length)y=0;
    if(y<0)y=board.length-1;
    
    }


//hàm general sử dụng 2 tham số cột c và hàng r
    void general(int c,int r){
        Random rd=new Random();
        //nếu như một trong 2 số chia hết cho 2 tức là bảng có thể chia cặp
    if(c%2==0||r%2==0){
        board=new byte[r][c];
        //tạo vector chứa các vị trí còn trống
    Vector v=new Vector();
    //cho các giá trị vị trí còn trống vào vector
    for(int i=0;i<c*r;i++){
    v.addElement(""+i);}
    //do bảng là một bảng cặp số nên ta chỉ cần tính nửa số bảng. mỗi lần ta tìm ra giá trị của cặp số, đồng thời cũng tìm giá trị vị trí cho cặp số.
    for(int i=0;i<c*r/2;i++){
        //tìm số ngẫu nhiên.
        int rand=Math.abs(rd.nextInt());
        //giá trị mà cặp số sẽ mang.
        int tile=rand%4;
        //vị trí số thứ nhất.
        int fp=rand%v.size();
        //hàm insertboard tự động điền vào bảng giá trị tại vị trí nhất định.
        insertboard(Integer.parseInt((String)v.elementAt(fp)),tile);
        //sau đó vị trí đó không tồn tại nữa, ta bỏ nó ra khỏi vector chỗ trống.
        v.removeElementAt(fp);
        //tương tự ta có vị trí của số thứ 2.
        int sp=rand%v.size();
        insertboard(Integer.parseInt((String)v.elementAt(sp)),tile);
        v.removeElementAt(sp);
    }
    }}
    //hàm insert board, đây sẽ chèn vào bảng một giá trị tại một vị trí nhất định.
    void insertboard(int xy,int v){
    //bảng có bao nhiêu đối tượng ta sẽ có thể tính ra hàng và cột mà một vị trí số đang ở.
    int c=xy%board[0].length;
    int r=(xy-c)/board[0].length;
    board[r][c]=(byte)v;}
}

Và chúng ta cũng có một file Midlet.java để hiện thị nó ra màn hình như sau: Midlet.java
C:\Users\thanhliem\Documents\NetBeansProjects\trucxanh\src\Midlet.java


import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class Midlet extends MIDlet {

    public void startApp() {
    Display.getDisplay(this).setCurrent(new trucxanh(this));}
    
    public void pauseApp() {
    }
    
    public void destroyApp(boolean unconditional) {
    }
}

Và kết quả ta được như thế này:
file jar
file source nhưng như thế thì chỉ dành cho trẻ con chơi thôi và cũng chưa giống gì với trúc xanh nhỉ, vì nó rõ như ban ngày vậy. thế nên ta cần có hình ảnh vào cho nó đẹp đẽ một chút và cũng làm sao để người chơi phải đoán xem đâu mới là cặp hình đúng. Ta cần thêm một file hình ảnh tile.png

và trucxanh.java trở thành thế này, rất đơn giản thôi. trucxanh.java
C:\Users\thanhliem\Documents\NetBeansProjects\trucxanh\src\trucxanh.java


import javax.microedition.lcdui.*;
import java.util.*;

public class trucxanh extends Canvas{
    //mảng chứa các mảnh hình
byte[][] board;
//các biến bao gồm: tọa độ khung chọn(x,y), vị trí đã chọn(sx,sy), giá trị chọn(ff)
//cũng thêm biến số lượt sai có thể lost và số lần chọn đúng right.
int x,y,sx,sy,w,h,ff=-1,lost=2,right=0;
Midlet m;
//hình ảnh dùng để vẽ các mảnh ảnh khác nhau
Image im;
    public trucxanh(Midlet m) {
        try {
setFullScreenMode(true);
w=getWidth();
h=getHeight();
this.m=m;
//hàm general, tạo ra một mảng mới với các cặp giá trị.
general(4,3);
//tạo hình ảnh từ file nguồn
im=Image.createImage("/tile.png");
        } catch (Exception e) {
        }
    }


    public void paint(Graphics g) {
g.setColor(0);
g.fillRect(0, 0, w, h);
g.setColor(0x00ff00);
//nếu như mảng không rỗng thì vẽ bảng
if(board!=null)
    //lần lượt cho hàng i
for(int i=0;i<board.length;i++){
    //lần lượt cho cột j
for(int j=0;j<board[0].length;j++){
    //nếu giá trị tìm được trong bảng khác -1 thì vẽ ra
    if(board[i][j]!=-1){
        //thay vì vẽ số của ảnh ta tô màu cho nó thành màu đỏ
g.fillRect(10+j*32, 10+i*32, 31, 31);}}}
//nếu giá trị đã chọn khác -1 thì vẽ khung đã chọn vị trí sx,sy
if(ff!=-1){
g.setColor(0xff0000);
g.drawRect(10+sx*32, 10+sy*32, 32, 32);
//tìm ra vị trí mảnh ảnh trong ảnh gốc, mỗi mảnh là 32x32
int c=ff%(im.getWidth()/32);
int r=(ff-c)/(im.getWidth()/32);
//sau đó dùng cách vẽ 1 phần ảnh gốc theo vị trí tìm được
g.drawRegion(im, c*32, r*32, 32, 32, 0, 10+sx*32, 10+sy*32, 0);
}
//vẽ khung lựa chọn tại vị trí x,y
g.setColor(0x0000ff);
g.drawRect(10+x*32, 10+y*32, 32, 32);
//vẽ số lượt sai có thể chọn
g.drawString("rest:"+lost,0,h,Graphics.BOTTOM|Graphics.LEFT);
repaint();
//tính toán và hiển thị kết quả
if(lost<=0){g.drawString("you lost!",w/2,h/2,0);}
if(right==board[0].length*board.length/2){g.drawString("you win!",w/2,h/2,0);}
    }
//hàm nhấn phím
    protected void keyPressed(int k) {
    switch(k){
        case -1:
            y--;
    break;
    case -2:
        y++;
    break;
    case -3:
        x--;
    break;
    case -4:
        x++;
    break;
    case -5:
        //nếu chưa chọn (ff==-1) thì cho giá trị vào ff, sx, sy
        if(ff==-1)
        {if(board[y][x]!=-1){sx=x; sy=y; ff=board[y][x];}}
        //ngược lại thì cho so sánh giá trị đã chọn và giá trị vừa chọn
        else
        {if(board[y][x]==ff){board[y][x]=board[sy][sx]=-1; ff=-1; right++;}else{ff=-1; lost--;}}
    break;}
    //các công thức này đảm bảo khung lựa chọn không đi ra ngoài bảng
    if(x==board[0].length)x=0;
    if(x<0)x=board[0].length-1;
    if(y==board.length)y=0;
    if(y<0)y=board.length-1;
    
    }


//hàm general sử dụng 2 tham số cột c và hàng r
    void general(int c,int r){
        Random rd=new Random();
        //nếu như một trong 2 số chia hết cho 2 tức là bảng có thể chia cặp
    if(c%2==0||r%2==0){
        board=new byte[r][c];
        //tạo vector chứa các vị trí còn trống
    Vector v=new Vector();
    //cho các giá trị vị trí còn trống vào vector
    for(int i=0;i<c*r;i++){
    v.addElement(""+i);}
    //do bảng là một bảng cặp số nên ta chỉ cần tính nửa số bảng. mỗi lần ta tìm ra giá trị của cặp số, đồng thời cũng tìm giá trị vị trí cho cặp số.
    for(int i=0;i<c*r/2;i++){
        //tìm số ngẫu nhiên.
        int rand=Math.abs(rd.nextInt());
        //giá trị mà cặp số sẽ mang.
        int tile=rand%4;
        //vị trí số thứ nhất.
        int fp=rand%v.size();
        //hàm insertboard tự động điền vào bảng giá trị tại vị trí nhất định.
        insertboard(Integer.parseInt((String)v.elementAt(fp)),tile);
        //sau đó vị trí đó không tồn tại nữa, ta bỏ nó ra khỏi vector chỗ trống.
        v.removeElementAt(fp);
        //tương tự ta có vị trí của số thứ 2.
        int sp=rand%v.size();
        insertboard(Integer.parseInt((String)v.elementAt(sp)),tile);
        v.removeElementAt(sp);
    }
    }}
    //hàm insert board, đây sẽ chèn vào bảng một giá trị tại một vị trí nhất định.
    void insertboard(int xy,int v){
    //bảng có bao nhiêu đối tượng ta sẽ có thể tính ra hàng và cột mà một vị trí số đang ở.
    int c=xy%board[0].length;
    int r=(xy-c)/board[0].length;
    board[r][c]=(byte)v;}
}



file jar file source

Thứ Năm, 14 tháng 2, 2013

the Sky Fall

Không phải là phim đâu, mà là một trò chơi đơn giản: nhân vật của chúng ta sẽ rơi xuống vào một rừng mũi tên đang bắn lên, chúng ta sẽ điều khiển để nhân vật đừng chạm vào mũi tên nào hết. các bạn cần có 3 file sau, tôi đã chú thích trong từng file hết rồi, chắc các bạn cũng hiểu thôi. Đầu tiên là file muiten.java muiten.java
C:\Users\thanhliem\Documents\NetBeansProjects\SkyFall\src\muiten.java

import javax.microedition.lcdui.*;
import java.util.*;

public class muiten {
//các biến: độ rộng màn hình, cao màn hình, vị trí x, vị trí y, chiều dài mũi tên, tốc độ mũi tên
    int w, h, x, y, len, speed;
    //biến chỉ mốc thời gian di chuyển lần cuối
    long lm = 0;
//    biến số ngẫu nhiên
    Random rd = new Random();
    //biến đầu mũi tên, và biến đuôi mũi tên dùng vẽ hình mũi tên
    byte[][] mim = {
        {0, 1, 0},
        {1, 1, 1}},
            dim = {{1, 0, 1}};
//hàm khởi tạo nhận các giá trị rộng,cao màn hình và một số nguyên ngẩu nhiên
    public muiten(int w, int h, int rd) {
        this.w = w;
        this.h = h;
        this.rd = new Random(rd);
        //dùng hàm general để khởi tạo
        general();
    }
//hàm general xác định tọa độ x, y chiều dài và tốc độ ngẫu nhiên cho mũi tên
    public void general() {
        //hàm Math.abs(số nguyên) chỉ sang trị tuyệt đối, nextInt là lấy số nguyên ngẫu nhiên, dấu % là phép chia lấy dư.
        x = Math.abs(rd.nextInt()) % w;
        y = h + 3;
        len = Math.abs(rd.nextInt()) % (h / 10);
        speed = Math.abs(rd.nextInt()) % 3 + 2;
    }

    public void draw(Graphics g) {
        //lấy màu hiện tại lưu lại vào ocl
        int ocl = g.getColor();
        //dặt màu mới
        g.setColor(ocl & 0xff);
        //cho vẽ mũi tên qua hàm drawmuiten
        drawmuiten(g);
        //đặt lại màu cũ
        g.setColor(ocl);
        //kiểm tra nếu như cách khoảng 20 mili giây từ lần cuối di chuyển lm thì cho mũi tên di chuyển tiếp
        if (lm < System.currentTimeMillis() - 20) {
            y -= speed;
            lm = System.currentTimeMillis();
        }
        //nếu như tọa độ y bé hơn -h/10 thì cho tạo lại mũi tên.
        if (y < -h / 10) {
            general();
        }
    }
//hàm check dùng để kiểm tra xem nhân vật và mũi tên có chạm nhâu không, gồm tọa độ x,y của nhân vật và độ cao rộng của nhân vật
    boolean check(int x, int y, int w, int h) {
        int sx = (this.x - x);
        int sy = (this.y - y);
        if (sx > 0 && sy > 0 && sx <= w && sy <= h) {
            return true;
        }
        return false;
    }
//hàm vẽ mũi tên sẽ vẽ mũi tên theo tọa độ của nó
    public void drawmuiten(Graphics g) {
        //vẽ đầu mũi tên
        for (int i = 0; i < mim.length; i++) {
            for (int j = 0; j < mim[0].length; j++) {
                if (mim[i][j] != 0) {
                    g.fillRect(x + j, y + i, 1, 1);
                }
            }
        }
        //vẽ thân mũi tên
        g.drawLine(x + 1, y, x + 1, y + len);
        //vẽ đuôi mũi tên
        for (int i = 0; i < dim.length; i++) {
            for (int j = 0; j < dim[0].length; j++) {
                if (dim[i][j] != 0) {
                    g.fillRect(x + j, y + len + i, 1, 1);
                }
            }
        }
    }
}

Tiếp theo đó là file skyfall.java: skyfall.java
C:\Users\thanhliem\Documents\NetBeansProjects\SkyFall\src\skyfall.java

import javax.microedition.lcdui.*;
import java.util.*;

public class skyfall extends Canvas {
//biến mt chứa các mũi tên sẽ bay lên từ dưới màn hình
    muiten[] mt = new muiten[10];
    Midlet m;
    //biến ngẩu nhiên rd
    Random rd = new Random();
    //các biến: rộng cao màn hình, tọa độ x, y của nhân vật, biến t số ngẩu nhiên, phím bấm k
    int w, h, x, y, t = 0, k;
    //hình ảnh nhân vật dùng để vẽ
    Image man;
    //các biến đúng sai: di chuyển, chẳn lẻ, kết thúc
    boolean move = false, chan = true, over = false;
    //biến mốc di chuyển lần cuối để tính khoảng thời gian di chuyển
    long lm;

    public skyfall(Midlet m) {
        try {
            this.m = m;
            setFullScreenMode(true);
            //tạo ra các phân tử mũi tên cho mảng mt
            for (int i = 0; i < mt.length; i++) {
                //gồm chiều rộng cao màn hình và một số nguyên ngẫu nhiên
                mt[i] = new muiten(getWidth(), getHeight(), t);
                t = rd.nextInt();
            }
            //ban đầu cho tọa độ nhân vật ở giữa màn hình
            y = getHeight() / 2;
            x = getWidth() / 2;
            //tạo ra hình ảnh nhân vật là ảnh 32x32
            man = Image.createImage("/man.png");
        } catch (Exception e) {
        }
    }

    public void paint(Graphics g) {
        //kiểm tra xem đã bị trúng tên chưa
        over = over();
        //xét xem lần di chuyển cuối cùng và có di chuyển tiếp không, hàm System.currentTimeMillis() dùng lấy thời gian hiện tại ở dạng mili giây.
        if (move && lm < System.currentTimeMillis() - 10) {
            if (k == -3 || k == KEY_NUM4) {
                x--;
            }
            if (k == -4 || k == KEY_NUM6) {
                x++;
            }
            //sau đó gán giá trị thời gian hiện tại cho biến lm
            lm = System.currentTimeMillis();
        }
        //đặt màu mới và tô màn hình
        g.setColor(0x90b5ff);
        g.fillRect(0, 0, getWidth(), getHeight());
        //hàm vẽ này vẽ ra một phần của hình ảnh, bao gồm: hình ảnh, tọa độ x trên ảnh, tọa độ y trên ảnh, chiều rộng cần vẽ, chiểu cao cần vẽ, quay góc, tọa độ vẽ x, tọa độ vẽ y, điểm neo.
        g.drawRegion(man, chan ? 0 : 16, 0, 16, 32, 0, x, y, Graphics.TOP | Graphics.LEFT);
        //sau đó cho biến chẳn lẻ thay đổi, nếu chẳn thì thành lẻ và ngược lại
        chan = !chan;
        //đặt màu mới, vẽ các phần tử muiten trong mảng mt
        g.setColor(0xff);
        for (int i = 0; i < mt.length; i++) {
            mt[i].draw(g);
        }
        //nếu kết thúc over=true thì cho dừng lại, không thì vẽ tiếp.
        if (over) {
        } else {
            repaint();
        }
    }
//hàm over kiểm tra xem có chạm nhân vật và muiten không
    boolean over() {
        for (int i = 0; i < mt.length; i++) {
            if (mt[i].check(x, y, 16, 32)) {
                return true;
            }
        }
        return false;
    }
//hàm xử lí phím, bấm phím nào thì cho k= mã phím đó
    public void keyPressed(int k) {
        move = true;
        this.k = k;
        if (k == -7) {
            //hàm notifyDestroyed của MIDlet dùng để đóng ứng dụng.
            m.notifyDestroyed();
        }
    }
//nếu buông nút bấm thì không cho di chuyển nữa.
    public void keyReleased(int k) {
        move = false;
    }
}

Và cuối cùng là cho hiển thị thông qua một Midlet.java như ta vẫn thường hay dùng: Midlet.java
C:\Users\thanhliem\Documents\NetBeansProjects\SkyFall\src\Midlet.java
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

/**
 * @author thanhliem
 */
public class Midlet extends MIDlet {

    public void startApp() {
        Display.getDisplay(this).setCurrent(new skyfall(this));
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }
}

Các bạn thấy đó, rất là đơn giản phải không nào, để trò chơi thêm phần hấp dẫn bạn có thể thêm biến điểm tính theo lượt những mũi tên được tạo lại sau mỗi lần general mới, trong muiten.java hay là thêm thắt những thứ khác nữa như mạng, vật phẩm chẳng hạn. và đây là file source jar.

ngày sinh của mình

khi tôi còn học lớp 11 tôi đã từng nghĩ về một ngày sinh nhật của mình như vậy. nhưng thật chất đó là sinh nhật lạ nhất của tôi, không có một người bạn, không có một lời chúc mừng. tôi không nghĩ về nó như vậy vì đó không phải là sinh nhật đầu tiên tôi như vậy, suốt trong những năm trước chưa bao giờ tôi được tổ chức sinh nhật hoặc chính mình tổ chức cho mình. năm đó thay vì nghĩ về chuyện mình là một người thất bại thì tôi cũng nghĩ như vậy nhưng là đem so sánh với những thần tượng của tôi ngày đó. tôi còn nhớ năm đó là năm mà người ta nói đến những thiên tài âm nhạc, những người nổi tiếng khi chỉ là một thiếu niên và tôi cảm thấy mình thật là nhỏ bé bất tài biết nhường nào. tôi không biết và thật sự không cần biết đến những thứ khác nữa và sau này tôi cũng không bao giờ muốn nhắc lại khoảng thời gian học cấp 3 của mình nữa. nhưng bạn biết không sinh nhật năm đó tôi có một món quà nhỏ mà không biết là nó được đưa cho tôi khi nào, đó thật sự là một điều gì đó thật sự kì lạ, nó làm trái tim tôi nhưng nóng bừng trở lại, nhưng lí trí của tôi lại nói rằng đó là một điều thật sự ngu ngốc và nó chỉ là một cái bẫy làm tan nát con tìm mà thôi. tôi đã nghĩ về nó, đã vẽ lại hình ảnh của món quà trong nhật kí và nói những chuyện điên rồ, nhưng rồi tôi cũng nghe theo lí trí mình. tôi không biết đó là món quà của ai tặng nhưng tôi xa lánh những người mà tôi nghĩ là có khả năng nhất, tôi luôn làm tốt chuyện như vậy. chạy trốn khỏi những cái bẫy trái tim. tôi thật sự không còn nghĩ đến nó nữa, nhưng trong suốt cuộc đời này tôi luôn cảm thấy thiếu nợ những người quanh tôi, tôi không thể nào tìm kiếm tình yêu cho chính mình được nữa. tôi nghĩ là nếu như tôi đợi mãi như thế này thì sẽ không có tội lỗi gì với ai cả, và cho đến khi tôi biết tất cả họ đều có một cuộc sống hạnh phúc, hoặc có ai đó có thể ở bên cạnh tôi bất chấp không có một sự ràng buột gì hôn nhân. thật sự điều đó là không thể xảy ra, ai cũng muốn có một cái gì đó ràng buột, dù họ có tin tôi đến đâu đi nữa thì bảo hiểm vẩn không phải là thứ bỏ đi. vừa qua sinh nhật tôi một lần nữa và tôi không có một người bạn nào ở bên mình cả, tôi nhận được duy nhất một tin nhắn chúc mừng sinh nhật từ một người mà tôi không biết mặt, nhưng dù sao nó cũng làm tôi vui lắm, và sau đó là buồn. có lẽ số phận của tôi ngày hôm nay chính là kết quả của tôi, sau khi tổn thương những trái tim muốn quan tâm san sẻ với tôi. cho dù thế nào đi nữa tôi cũng không thấy hối tiếc về những gì mà mình đã làm, tôi biết là chắc chắn mình đã làm đúng, vì tôi không bao giờ muốn ràng buộc bởi một cái gì cả, kể cả hôn nhân.

Chủ Nhật, 10 tháng 2, 2013

trò chơi chó cắn

Cờ chó cắn chắc là cờ đơn giản nhất mà tôi từng chơi khi còn nhỏ và ở bất cứ đâu cũng có thể chơi được. nó còn đơn giản hơn là tic tac toe nữa đấy, và hôm nay tôi sẽ hướng dẫn viết một bàn cờ chó cắn đơn giản. đầu tiên là quân cờ chó cắn, gồm có các thông tin sau: tree.java
C:\Users\thanhliem\Documents\NetBeansProjects\Tree\src\tree.java

10 
11 public class tree {
12     //vị trí hiện tại của quân cờ và màu của quân cờ
13     int position,color;
14     //hàm khởi tạo nhận giá trị vị trí và màu quân cờ
15     public tree(int pos,int color){
16     this.position=pos;
17     this.color=color;}
18 }
19 
Còn đây là file banco.java dùng để tiến hành các lệnh vẽ theo game, điều kiện trò chơi, cách chơi…. banco.java
C:\Users\thanhliem\Documents\NetBeansProjects\Tree\src\banco.java

import javax.microedition.lcdui.*;
import java.util.*;

public class banco extends Canvas {
    Midlet m;
    //biến các điểm tọa độ của bàn cờ
    int[][] moc;
    //biến các điểm có thể di chuyển trên bàn cờ
    boolean[] free=new boolean[5];
    int w,h,dx,dy,k;
    boolean mot=true,finish=false,win=false;
    //biến các quân cờ, vị trí của ta là 0, 2 của máy là 1, 3
    tree[] quan;
    //biến rd này dùng để chọn ngẫu nhiên nhân vật tự động
    Random rd=new Random();
    public banco(Midlet m){
    setFullScreenMode(true);
    w=getWidth(); h=getHeight();
    //điểm vẽ bàn cờ
    dx=(w-128)/2;
    dy=(h-128)/2;
    //tạo các tọa độ vẽ bàn cờ, 128x128
    moc=new int[5][2];
    for(int i=0;i<2;i++){
    for(int j=0;j<2;j++){
    moc[i*2+j][0]=i*128;
    moc[i*2+j][1]=j*128;}}
    moc[4][0]=64;
    moc[4][1]=64;
    //tạo các quân cờ ban đầu, của ta là số chẵn 0, 2
    quan=new tree[4];
    for(int i=0;i<quan.length;i++){
        //các điểm đặt quân không còn trống, không thể di chuyển vào
        free[i]=false;
        //đặt màu cho các quân cờ, quân ta màu xanh lá 0, 2 chia hết cho 2
        quan[i]=new tree(i,i%2==0?0x00f000:0x0000f0);}
    //điểm còn lại chưa đặt quân cờ trống là ở giữa bàn cờ vị trí 4
    free[4]=true;
    this.m=m;}
    public void paint(Graphics g){
    g.setColor(0);
    g.fillRect(0,0,w,h);
    //vẽ bàn cờ
    vebanco(g);
    //vẽ quân cờ
    vequanco(g);
    g.setColor(0xf000f0);
    //nếu kết thúc thì vẽ kết quả
    if(finish)
    g.drawString(win?"you win!":"you lose!",w/2,h,Graphics.BOTTOM|Graphics.HCENTER);
    //vẽ hướng dẫn chơi game
    g.drawString("nhấn 5 để di chuyển.",w/2,0,Graphics.TOP|Graphics.HCENTER); 
    g.drawString("nhấn * để thay đổi đối tượng",w/2,0+g.getFont().getHeight(),Graphics.TOP|Graphics.HCENTER);
    repaint();
    }
    protected void keyPressed(int k){
        //nếu mot==true thì ta điều khiển quân 0, sai ta điều khiển quân 2
        //tìm ra vị trí trống có thể đi tiếp
        int focus=mot?0:2,move=free();
        //nếu chưa xong game thì cho di chuyển
        if(!finish)
            //nếu như bấm phím 5 thì cho di chuyển
    if(k==KEY_NUM5||k==-5)
        //nếu di chuyển được thì cho auto di chuyển
    if(move(focus,move)){
    auto();}
    //nếu không thì chuyển qua quân còn lại di chuyển, nếu được thì auto di chuyển
    else if(move(focus==0?2:0,move)){
    auto();
    }
    //ngược lại thì thua và kết thúc trò chơi
    else{finish=true; win=false;}
        //nhấn phím * để thay đổi đối tượng điều khiển
   if(k==KEY_STAR)mot=!mot;}
    
    //di chuyển nhân vật tự động
    void auto(){
        //tìm ra vị trí còn trống
    int move=free();
    //chọn ngẫu nhiên nhân vật tự động giữa 1 và 3
    int focus=rd.nextInt()%2==0?1:3;
    //cho di chuyển, nếu 1 không di chuyển thì chuyển qua 3 và ngược lại
    if(move(focus,move)){}else{
        //nếu cả 1 và 3 đều không còn di chuyển được nữa thì kết thúc trò chơi, người chơi thắng
        if(!move(focus==1?3:1,move)){
        finish=true;
        win=true;}}}
    
    //vẽ bàn cờ
   void vebanco(Graphics g){
   g.setColor(0xf0f000);
   //vẽ 2 gạch chéo bàn cờ
   g.drawLine(dx+moc[0][0],dy+moc[0][1],dx+moc[3][0],dy+moc[3][1]);
   g.drawLine(dx+moc[1][0], dy+moc[1][1],dx+moc[2][0], dy+moc[2][1]);
   //vẽ khung vuông bàn cờ
   g.drawRect(dx, dy, 128, 128);
   //vẽ nơi dành cho con chó, chữ "chó"
   g.drawString("chó",dx+64,dy,Graphics.BASELINE|Graphics.HCENTER);
    }
   
   //vẽ các quân cờ
   void vequanco(Graphics g){
       //xác định đối tượng đang chọn, 0 hay là 2
       int focus=mot?0:2;
   for(int i=0;i<4;i++){
       //tìm ra vị trí hiện tại của quân được chọn
       int pos=quan[i].position;
       //vẽ con trỏ chọn đối tượng
       if(i==focus){
       g.setColor(0xf00000);
       g.fillArc(dx+moc[pos][0]-9, dy+moc[pos][1]-9, 18, 18, 0, 360);}
       g.setColor(quan[i].color);
   g.fillArc(dx+moc[pos][0]-8, dy+moc[pos][1]-8, 16, 16, 0, 360);
   }
   }
   
   //kiểm tra xem có thể chuyển từ vị trí này tới vị trí trống được ko
   boolean cango(int pos,int npos){
   if(pos==1&&npos==2)return false;
   if(pos==2&&npos==1)return false;
   if(pos==0&&npos==3)return false;
   if(pos==3&&npos==0)return false;
   if(pos==0&&npos==2)return false;
   if(pos==2&&npos==0)return false;
   return true;}
   
   //tìm ra vị trí còn trống
   int free(){
       //kiểm tra trong mảng free xem có vị trí nào trống thì trả lại
       for(int i=0;i<5;i++){
   if(free[i])return i;}
   return 0;}
   
   //cho di chuyển và nếu di chuyển được thì trả lại giá trị đúng sai
   boolean move(int pos,int npos){
       if(cango(quan[pos].position,npos)){
           //đặt vị trí đang đứng thành trống
       free[quan[pos].position]=true;
       //cho chuyển sang vị trí mới
       quan[pos].position=npos;
       //đặt vị trí mới không còn trống nữa
       free[quan[pos].position]=false;
       return true;}
   return false;}
}

Và cũng cần có file Midlet.java để ứng dụng có thể hiện thị được. Cái này thì cũng đơn giản và quen quá rồi. Midlet.java
C:\Users\thanhliem\Documents\NetBeansProjects\Tree\src\Midlet.java

public class Midlet extends MIDlet {

    public void startApp() {
        Display.getDisplay(this).setCurrent(new banco(this));
    }
    
    public void pauseApp() {
    }
    
    public void destroyApp(boolean unconditional) {
    }
}

source file jar