📄 749-752.html
字号:
<HTML>
<HEAD>
<META name=vsisbn content="1571690433"><META name=vstitle content="Black Art of Java Game Programming"><META name=vsauthor content="Joel Fan"><META name=vsimprint content="Sams"><META name=vspublisher content="Macmillan Computer Publishing"><META name=vspubdate content="11/01/96"><META name=vscategory content="Web and Software Development: Programming, Scripting, and Markup Languages: Java"><TITLE>Black Art of Java Game Programming:The Internet MahJong Server</TITLE>
<!-- HEADER --><STYLE type="text/css"> <!-- A:hover { color : Red; } --></STYLE><META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW"><script><!--function displayWindow(url, width, height) { var Win = window.open(url,"displayWindow",'width=' + width +',height=' + height + ',resizable=1,scrollbars=yes'); if (Win) { Win.focus(); }}//--></script><SCRIPT><!--function popUp(url) { var Win = window.open(url,"displayWindow",'width=400,height=300,resizable=1,scrollbars=yes'); if (Win) { Win.focus(); }}//--></SCRIPT><script language="JavaScript1.2"><!--function checkForQuery(fm) { /* get the query value */ var i = escape(fm.query.value); if (i == "") { alert('Please enter a search word or phrase'); return false; } /* query is blank, dont run the .jsp file */ else return true; /* execute the .jsp file */}//--></script></HEAD><BODY>
<TABLE border=0 cellspacing=0 cellpadding=0>
<tr>
<td width=75 valign=top>
<img src="../1571690433.gif" width=60 height=73 alt="Black Art of Java Game Programming" border="1">
</td>
<td align="left">
<font face="arial, helvetica" size="-1" color="#336633"><b>Black Art of Java Game Programming</b></font>
<br>
<font face="arial, helvetica" size="-1"><i>by Joel Fan</i>
<br>
Sams, Macmillan Computer Publishing
<br>
<b>ISBN:</b> 1571690433<b> Pub Date:</b> 11/01/96</font>
</td>
</tr>
</table>
<P>
<!--ISBN=1571690433//-->
<!--TITLE=Black Art of Java Game Programming//-->
<!--AUTHOR=Joel Fan//-->
<!--AUTHOR=Eric Ries//-->
<!--AUTHOR=Calin Tenitchi//-->
<!--PUBLISHER=Macmillan Computer Publishing//-->
<!--IMPRINT=Sams//-->
<!--CHAPTER=18//-->
<!--PAGES=749-752//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="746-749.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="752-756.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<H4 ALIGN="LEFT"><A NAME="Heading29"></A><FONT COLOR="#000077">A Generic Shuffling Algorithm</FONT></H4>
<P>I present here an algorithm for shuffling an array <I>list[]</I> of N objects. Assuming a good random number generator, it gives each possible permutation equal probability, and has complexity O(N). It works, thanks to some elementary facts from combinatorics.</P>
<!-- CODE //-->
<PRE>
import java.util.Random;
Random rand = new Random();
for (int i = 1; i < list.length; i++) {
int j = Math.abs(rand.nextInt()) % (i + 1); // 0 <= j <= i
if (i != j) { // swap list[i]
Object temp = list[i]; // with list[j]
list[i] = list[j];
list[j] = temp;
}
}
</PRE>
<!-- END CODE //-->
<H4 ALIGN="LEFT"><A NAME="Heading30"></A><FONT COLOR="#000077">MahJong Tile Images</FONT></H4>
<P>Clay Breshears (<A HREF="http://www.cs.utk.edu/∼clay/">http://www.cs.utk.edu/∼clay/</A>) has made an excellent collection of color GIF images for MahJong tiles. The tile images I use for my MahJong client are based on his, with some minor modifications and the addition of eight flower tiles (see Figure 18-2).</P>
<P>To use these images, first put them in a subdirectory “tiles” on the server machine, and name the files T0.gif through T42.gif. On the client side, arrange them into an array:</P>
<!-- CODE SNIP //-->
<PRE>
// in class Greeting
public static Image tiles[] = new Image[43];
</PRE>
<!-- END CODE SNIP //-->
<P>I spawn a thread in Greeting.init() to load all the images. It uses the MediaTracker class:
</P>
<!-- CODE //-->
<PRE>
// run() method of Greeting which now extends Runnable
public void run () {
MediaTracker tracker = new MediaTracker(this);
Object errors[] = null;
for (int i = 0; i < 43; i++) {
tiles[i] = getImage(getDocumentBase(), "tiles/T" + i + ".gif");
tracker.addImage(tiles[i], 0);
}
while (true) {
try {
tracker.waitForAll();
} catch (InterruptedException e) {}
if ((errors = tracker.getErrorsAny()) == null)
break; // all images loaded
for (int i = 0; i < 43; i++) {
if (tiles[i] == errors[j]) {
tiles[i] = getImage(getDocumentBase(), "tiles/T" + i + ".gif");
tracker.addImage(tiles[i], 0);
}
}
}
}
</PRE>
<!-- END CODE //-->
<H4 ALIGN="LEFT"><A NAME="Heading31"></A><FONT COLOR="#000077">Displaying and Manipulating a Hand</FONT></H4>
<P>Now we are ready to define a new AWT component, TileWindow, that can display a hand with these tile images. In the actual MahJong client, this component can display several rows and columns, and handles several drawing directions. To illustrate the point, I present here a simplified version that only draws horizontally from left to right, in one row. To mimic real MahJong games, all tiles in a group are displayed right next to each other; there is a padding space between different groups or single tiles.
</P>
<!-- CODE //-->
<PRE>
package client;
import java.awt.*;
import common.*;
class TileWindow extends Canvas {
private static final int XSIZE = 30, YSIZE = 40, PAD = 8;
private Hand hand = null;
private int size;
public TileWindow (int n_tiles) {
size = n_tiles;
setBackground(Color.gray);
}
public synchronized void setHand (Hand h) {
hand = h;
repaint();
}
public Dimension minimumSize () {
return preferredSize();
}
public Dimension preferredSize () {
return new Dimension(size * (XSIZE + PAD) + PAD, 2 * PAD + YSIZE);
}
public synchronized void paint (Graphics g) {
if (hand == null) return;
int i_tile = 0, n_grp = 0, p_col = PAD;
while (i_tile < hand.length()) {
if (hand.groupAt(i_tile) == Hand.SINGLE) {
n_grp = 1;
} else {
int i = i_tile + 1;
n_grp = 2;
while (hand.groupAt(i) != Hand.TAIL) {
i++;
n_grp++;
}
}
if (hand.isSelected(i_tile)) // highlight bounding rectangle?
g.setColor(Color.yellow);
else
g.setColor(getBackground());
g.drawRect(p_col - 2, PAD - 2, XSIZE * n_grp + 3, YSIZE + 3);
for (int n = 0; n < n_grp; n++) {
g.drawImage(Greeting.tiles[(int)hand.tileAt(i_tile++)],
p_col, PAD);
p_col += XSIZE;
}
p_col += PAD;
}
}
}
</PRE>
<!-- END CODE //-->
<P>A player can arrange his concealed tiles by clicking and dragging tiles around. Note that it does not make much sense to let the player group his tiles, because all the groups should correspond to MahJong sets and pairs, and I would rather let the server decide whether they can be formed. So I add an option for a TileWindow to be “editable,” and handle certain mouse events:
</P>
<!-- CODE //-->
<PRE>
private boolean editable = true;
private boolean draggable = false, dragged = false;
private int drag_dx = 0, down_x = 0, down_pos = 0, drag_x0 = 0;
public synchronized void setEditable (boolean e) {
editable = e;
}
public synchronized boolean mouseDown (Event evt, int x, int y) {
if (!editable) return true;
int pos = x / (XSIZE + PAD);
if ((x % (XSIZE + PAD)) < PAD || pos < 0 ||
pos >= hand.length()) { // cancel selection
dragable = false;
hand.unselectAll();
paint(getGraphics());
return true;
}
hand.unselectAll();
hand.select(pos); // select this tile
dragable = true; // prepare for dragging
drag_dx = (XSIZE + PAD) * pos + PAD - 2 - x;
down_x = x;
down_pos = pos;
paint(getGraphics());
return true;
}
public synchronized boolean mouseDrag (Event evt, int x, int y) {
if (!editable || !dragable) return true;
Graphics g = getGraphics();
if (!dragged) { // first drag event
dragged = true;
drag_x0 = x;
g.setColor(Color.black);
g.setXORMode(Color.white);
g.drawRect(x + drag_dx, PAD - 2, XSIZE + 3, YSIZE + 3);
g.setPaintMode();
} else { // more dragging
g.setColor(Color.black);
g.setXORMode(Color.white);
g.drawRect(x + drag_dx, PAD - 2, XSIZE + 3, YSIZE + 3);
g.setPaintMode();
}
return true;
}
public synchronized boolean mouseUp (Event evt, int x, int y) {
if (!editable || !dragged) return true;
dragged = false;
dragable = false;
Graphics g = getGraphics();
g.setColor(Color.black);
g.setXORMode(Color.white);
g.drawRect(drag_x0 + drag_dx, PAD - 2, XSIZE + 3, YSIZE + 3);
g.setPaintMode();
int pos;
if (x < down_x - 3) // move left
pos = (x + drag_dx + XSIZE) / (XSIZE + PAD);
else if (x > down_x + 3) // move right
pos = (x + drag_dx - PAD) / (XSIZE + PAD);
else return true;
byte tile = hand.tileAt(down_pos);
boolean sel = hand.isSelected(down_pos);
hand.killTile(down_pos).insertTile(pos, tile, Hand.SINGLE, sel);
repaint();
return true;
}
</PRE>
<!-- END CODE //-->
<P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="746-749.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="752-756.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
</BODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -