public class Game extends java.awt.Frame {public Game () {setTitle ( "Tetris game - Ghost Valley"); addWindowListener (new java.awt.event.WindowAdapter () {public void windowClosing (java.awt.event. WindowEvent E) {Dispose (); System.exit (0);}}); Gamecanvas Gamecanvas = New Gamecanvas (); setLayout (new java.awt.borderLayout ()); add (gamecanvas, "center"); setResizable false); setLocation (... (java.awt.Toolkit.getDefaultToolkit () getScreenSize () width-gameCanvas.getPreferredSize () width) / 2, (java.awt.Toolkit.getDefaultToolkit () getScreenSize () height-.. Gamecanvas.getPreferredSize (). HEIGHT / 2); Pack (); show ();} public static void main (String args []) {new game ();} java.awt.canvas urgents runnable { Public static final int bksize = 5; public static final int bdWidth = 20; public static final int bdheight = 30; // Inner Class Block Pr Ivate class block {public boolean bkdata [] [] = new boolean [bksize] [bksize]; public int RPOS, CPOS; Public Block (Final Boolean Bkdata1 [] [], Int rpos, int CPOS) {//this.bkdata = (Boolean [] []) bkdata1.clone (); for (int i = 0; i
For (int J = 0; J
THISBKDATA [I] [j] = bkdata1 [i] [j]; this.rpos = rpos; this.cpos = cpos;} public block (final block bk) {//this.bkdata = (Boolean [] [ ]) BK.BKDATA.CLONE (); for (int i = 0; i
For (int J = 0; J
THIS.BKDATA [I] [J] = BK.BKDATA [I] [J]; this.rpos = bk.rpos; this.cpos = bk.cpos;} PUBLIC VOID DoAction (int action) {switch (action) { case Message.MOVE_UP: this.rpos--; break; case Message.MOVE_DOWN: this.rpos ; break; case Message.MOVE_LEFT: this.cpos--; break; case Message.MOVE_RIGHT: this.cpos ; break; case Message .ROTATE_CLOCK: {Final INT X0 = Bksize / 2; Final Int Y0 = Bksize / 2; // Boolean Bkdata1 [] [] = (Boolean [] []) this.bkdata.clone (); boolean bkdata1 [] [] = New boolean [bksize] [bksize]; for (int i = 0; ifor (int J = 0; J
BKDATA1 [I] [J] = this.bkdata [i] [j]; for (int x = 0; x
For (int y = 0; y
THIS.BKDATA [Y] = BKDATA1 [X] [Y]; Break;} case message.Rotate_anticlock: {Final Int x0 = bksize / 2; Final Int Y0 = Bksize / 2; // Boolean bkdata1 [] [] = (boolean [] []) this.bkdata.clone (); boolean bkdata1 [] [] = new bolean [bksize] [bksize]; for (int i = 0; i
For (int J = 0; J
BKDATA1 [I] [J] = this.bkdata [i] [j]; for (int x = 0; x
For (int y = 0; y
THISBKDATA [-Y 2 * x0] [x] = bkdata1 [x] [y]; break;}}}} // inner class board / private class board}}} // inner class board / private class board {public boolean bddata [] [] = new boolean [ BDHEIGHT] [BDWIDTH]; public board () {clear ();} public board (final board) {//this.bddata = (boolean [] []) Board.bddata.clone (); for (int i = 0; IFOR (int J = 0; J
this.bddata [i] [j] = Board.bddata [i] [j];} public void clear () {for (int i = 0; i
For (int J = 0; J
BDDATA [I] [J] = false;}}
// Inner class Message / private class Message {public static final int MOVE_UP = 1; public static final int MOVE_DOWN = 2; public static final int MOVE_LEFT = 3; public static final int MOVE_RIGHT = 4; public static final int ROTATE_CLOCK = 5; // Rotate Clock-Wise Public Static Final Int Rotate_anticlock = 6; // Rotate AnticLock-Wise Public Message (Int Action) {this.Action = action;} public int getAction; } // Inner class Queue /// fields of class Game private Board m_board = new Board (); // only access by the message processor thread private block m_block = null; // block currently existing private MessageQueue m_msgQueue = new MessageQueue ( ); // awt thread by a message processor and access private BlockDataPoolQueue m_blockDataPoolQueue = new BlockDataPoolQueue (); private int m_S = 0; / method run main message processing thread public void run () {boolean bkdataPool [] [] [] =
{{{False, false, true, false, false}, {false, false, true, false, false}, {false, false, true, false, false}, {false, false, true, false, false}, {False, False, true, false, false}}, {false, false, false, false, false}, {false, true, true, true, false}, {false, false, true, false, false}, {False, False, True, false, false}, {false, false, true, false, false}, false, false, false, false, false}}, {{false, false, false, false, false}, {False, False, True, False, true, true, true, false}, {false, false, true, false, false}, {false, false, false, false, false}}} {False, False, false, false, false}, {false, false, false, false, false}, {false, true, true, true, false}, {false, true, false, true, false}, {FALSE , False, False, false, false}}, {{false, false, false, false, false}, {false, false, false, false, false} , {False, true, true, {false, false, true, false, false}, false, false, false, false, false}}}; repainTrequest (); while (true) {switch ( m_S) {case 0: try {Thread.currentThread (.) sleep (50);} catch (InterruptedException ex) {} break; case 1: Block bk1 = new Block (m_blockDataPoolQueue.getNextBlockData (), 0, (BDWIDTH-BKSIZE )/2);
IF (iScollided (M_Board, BK1)) {m_block = BK1; M_S = 2;} else m_s = 3; repaintRequest (); break; case 2: message msg; synchronized (m_msgqueue) // Wait a new message {while (WHILE) m_msgqueue.empty ()) {Try {m_msgqueue.wait ();} catch (interruptedException e) {}} msg = (message) m_msgqueue.dl ();} block bk2 = new block (m_block); bk2.doAction (MSG) .getAction ()); if (! iScollided (M_Board, BK2)) {// Action can perform m_block.doAction (msg.getAction ()); m_s = 2; repaintRequest ();} else if () == Message.Move_down) {// Down movement The action cannot perform Merge (M_Board, m_block); m_block = null; packupboard (m_board); m_s = 1; repaintRequest ();} Break; Case 3: try {thread.currentthread (). Sleep (50);
} CatCH (Exception EX) {} Break;}}} / method iSclLided / Private Boolean ISCOLLIDED (Final Block BK1, Final Block BK2) // Determine whether the two blocks overlap {for (int R1 = 0; R1 {INT R2 = R1 BK1.RPOS-BK2.RPOS; IF (R2> = 0 && r2
{
For (int C1 = 0; C1
{
INT C2 = C1 BK1.CPOS-BK2.CPOS;
IF (C2> = 0 && C2
IF (BK1.BKDATA [R1] [C1] && Bk2.bkdata [R2] [C2])
Return True;
}
}
}
Return False;
}
Private Boolean IsCollid (Final Board Board, Final Block Block) / / Determine whether a block is overlapping
{
For (int i = 0; i
For (int J = 0; J
IF (Block.rpos i> = 0 && Block.rpos i
= 0 && Block.cpos J
IF (block.bkdata [i] [j] && board.bddata [i block.rpos] [j block.cpos])
Return True;
Else IF (block.bkdata [i] [j])
Return True;
}
}
Return False;
}
Private Void Merge (Board Board, Final Block Block) // Merged Board <=== Block
{
For (int i = 0; i
For (int J = 0; J
IF (block.rpos i> = 0 && block.rpos i <= bdheight-1 && block.cpos j> = 0 && block.cpos j <= bdwidth-1)
Board.bddata [block.rpos i] [block.cpos j] | = block.bkdata [i] [j];
}
Private int packupboard (Board board) // eliminate
{
INT LINESDELETED = 0;
For (INT i = bdheight-1; i> = 0;) {// Detect the i-th line
Boolean full = true;
For (int J = 0; J
IF (! board.bddata [i] [j]) {
Full = false;
Break;
}
}
IF (full) {// 第 第 行 行
For (int K = I-1; k> = 0; k -) {
For (int C = 0; C
Board.bddata [K 1] [C] = Board.bddata [K] [C];
}
For (int C = 0; C
Board.bddata [0] [C] = false; LINESDELETED ;
Else
I-;
}
Return LinesDeled;
}
// conncture
Final INT X0 = 10, Y0 = 15;
Final Int Cellsize = 12;
Public Java.awt.dimension getPreferredSize ()
{
Return new java.awt.dimension (2 * x0 cellsize * bdwidth, 2 * Y0 cellsize * bdheight);
}
Public Gamecanvas ()
{
SetBackground (java.awt.color.black);
AddKeylistener (New Java.awt.Event.KeyAdapter () {
Public void keypressed (java.awt.event.keyevent e)
{
Switch (E.GetKeycode ()) {
Case java.awt.event.keyevent.vk_left:
Postmessage (New Message (MersSage.Move_left);
Break;
Case java.awt.event.keyevent.vk_right:
Postmessage (New Message (Message.Move_Right);
Break;
Case java.awt.event.keyevent.vk_down:
Postmessage (new message.move_down);
Break;
Case java.awt.event.keyevent.vk_up:
Postmessage (New Message (Message.Rotate_Clock);
Break;
Case java.awt.event.keyevent.vk_enter:
Postmessage (New Message (MersSage.Rotate_anticlock);
Break;
Case java.awt.event.keyevent.vk_page_up:
Postmessage (New Message (MersSage.Move_UP);
Break;
Case java.awt.event.keyevent.vk_space:
IF (m_s == 0)
m_s = 1;
Break;
Case java.awt.event.keyevent.vk_f1:
IF (m_s == 3) {
M_Board.clear ();
m_s = 0;
RepaintRequest ();
}
}
}
});
New thread () {
Public void Run ()
{
While (true) {
Try {
SLEEP (500);
} catch (interruptedexception e) {
}
Postmessage (new message.move_down);
}
}
} .start ();
New thread (this) .start (); // message processing thread
}
Public void PostMessage (Message MSG)
{
IF (m_s == 1 || m_s == 2) {
Synchronized (m_msgqueue) {
M_Msgqueue.en (MSG);
m_msgqueue.notify ();
}
}
}
Public void repaintRequest ()
{
Repaint ();
}
Public void Paint (java.awt.graphics g)
{
// Draw M_Boardg.SetColor (java.awt.color.blue);
g.drawRect (X0, Y0, Cellsize * bdwidth-1, cellsize * bdheight-1);
Switch (m_s) {
Case 1:
Case 2:
G.SetColor (java.awt.color.yellow);
Break;
Case 3:
G.SetColor (java.awt.color.lightgray);
Break;
}
For (int i = 0, y = y0; i
For (int J = 0, x = X0; J
IF (M_Board.bddata [i] [j])
G.FillRect (x, y, cellsize-1, cellsize-1);
}
}
// Draw Next Block show
G.SetColor (java.awt.color.lightgray);
Boolean nextblockdata [] [] = m_blockdatapoolqueue.peeknextblockdata ();
For (int i = 0, y = y0; i
For (int J = 0, x = x0 (bdwidth-bksize) * cellsize; J
IF (NextBlockData [i] [j])
g.drawRect (x 1, y 1, cellsize-1, cellsize-1);
}
}
// DRAW M_BLOCK
IF (m_s == 2) {
G.SetColor (java.awt.color.red);
For (int i = 0, y = y0 m_block.rpos * cellsize; i
For (int J = 0, x = x0 m_block.cpos * cellsize; J
IF (m_block.bkdata [i] [j])
G.FillRect (x, y, cellsize-1, cellsize-1);
}
}
}
G.SetColor (java.awt.color.red);
G.setfont (new java.awt.font (g.getfont (). getFontName (), g.getfont (). getStyle (), 16));
Switch (m_s) {
Case 0:
g.drawstring ("Start the game by empty"! ", 50, 100);
Break;
Case 3:
g.drawstring ("The game ends, press the F1 key to start!", 20, 100);
Break;
}
}
Private Class BlockDataPoolQueue Extends Queue
{
Public blockDataPoolQueue () {this.currentblockdata = bkdatapool [ran.nextint (bkdatapool.length)];
Public Boolean [] [] peeknextblockdata ()
{
Return this.currentblockdata;
}
Public boolean [] [] getNextBlockData ()
{
Boolean [] [] bkd = this.currentblockdata;
THIS.CURRENTBLOCKDATA = BKDATAPOOL [RAN.NEXTINT (BKDataPool.Length)];
Return BKD;
}
Private boolean [] [] currentblockdata = null;
Private java.util.random ran = new java.util.random ();
Private Boolean BkdataPool [] [] [] = {{false, false, true, true, false},
{False, False, True, False, False},
{False, False, True, False, False},
{False, True, True, False, False},
{False, False, False, False, False}},
{{False, False, False, False, False},
{False, True, True, False, False},
{False, False, True, False, False},
{False, False, True, True, False},
{False, False, False, False, False}},
{{False, False, False, False, False},
{False, False, True, False, False},
{False, True, True, True, False},
{False, False, True, False, False},
{False, False, False, False, False}},
{{False, False, False, False, False},
{False, False, False, False, False},
{False, True, True, True, False},
{False, False, False, True, False},
{False, False, False, False, False}},
{{False, False, False, False, False},
{False, True, False, False, False},
{False, False, True, False, False},
{False, False, False, False, False},
{False, False, False, False, False}},
{{False, False, False, False, False},
{False, False, False, False, False},
{False, False, True, False, False},
{False, False, False, False, False},
{False, False, False, False, False}},
{{False, False, False, False, False},
{False, True, True, False, False},
{False, True, True, False, False},
{False, False, False, False, False},
{False, False, False, False, False}},
{{False, False, False, False, False},
{False, False, False, False, False},
{False, True, True, True, False},
{False, False, True, False, False},
{False, False, False, False, False}}}
}
Private class queue
{
PRIVATE NODE Head;
PRIVATE NODE TAIL;
Public queue ()
{
HEAD = new node ();
Tail = new node ();
Head.prev = tail.next = null;
Head.Next = TAIL;
Tail.prev = head;
}
Public void en (Object Item)
{
Node Q = new node ();
Q.DATA = Item;
Q.NEXT = TAIL;
q.prev = tail.prev;
Tail.prev.next = q; tail.prev = q;
}
Public Object DL ()
{
IF (! EMPTY ()) {
Node P = head.next;
Head.next.next.prev = head;
Head.Next = head.next.next;
Return P.DATA;
Else
Return NULL;
}
Public Object PEEK ()
{
IF (! EMPTY ())
Return head.next.data;
Else
Return NULL;
}
Public Boolean Empty ()
{
Return (Head.Next == Tail) || (tail.prev == head);
}
Public void clear ()
{
Head.Next = TAIL;
Tail.prev = head;
}
Public int eleMnum ()
{
INT NUM = 0;
For (node = head.next; q! = tail; q= q.next)
Num ;
Return Num;
}
Private class node
{
Object data;
Node prev;
Node next;
}
}
// Inner Class MessageQueue
Private Class MessageQueue
{
PRIVATE NODE Head;
PRIVATE NODE TAIL;
Public messagequeue ()
{
HEAD = new node ();
Tail = new node ();
Head.prev = tail.next = null;
Head.Next = TAIL;
Tail.prev = head;
}
Public void en (Message MSG)
{
Node P = new node ();
p.Message = msg;
p.NEXT = TAIL;
p.PREV = tail.prev;
Tail.prev.next = p;
Tail.PREV = P;
}
Public Message DL ()
{
IF (! EMPTY ()) {
Node P = head.next;
Head.next.next.prev = head;
Head.Next = head.next.next;
Return P.Message;
Else
Return NULL;
}
Public Message peek () // should be used in the first use of EMPTY
{
IF (! EMPTY ())
Return head.next.Message;
Else
Return NULL;
}
Public Boolean Empty ()
{
Return (Head.Next == Tail) || (tail.prev == head);
}
Public void clear ()
{
Head.Next = TAIL;
Tail.prev = head;
}
Private class node
{
Message message;
Node prev;
Node next;
}
}
}