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

Không có nhận xét nào: