⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch19.htm

📁 对于程序员来说可以利用JAVA来开发网络游戏!
💻 HTM
📖 第 1 页 / 共 5 页
字号:
= new String(&quot;You won!&quot;);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gameOver
= true;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection.sendIWON();
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection.sendMove(pos.x);
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;repaint();<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;else<BR>
&nbsp;&nbsp;&nbsp;&nbsp;badMoveSnd.play();<BR>
&nbsp;&nbsp;return true;<BR>
}</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The <TT><FONT FACE="Courier">mouseDown</FONT></TT> method is actually
where each player's physical move is sent to the server. Notice
that this information is sent using the <TT><FONT FACE="Courier">client</FONT></TT>
member variable, which is a <TT><FONT FACE="Courier">Connect4ClientConnection</FONT></TT>
object. This brings up a neat aspect of the design of the Connect4
client: The client communication details in the <TT><FONT FACE="Courier">Connect4</FONT></TT>
class are hidden in the <TT><FONT FACE="Courier">Connect4ClientConnection</FONT></TT>
class.
<P>
The <TT><FONT FACE="Courier">Connect4ClientConnection</FONT></TT>
class is in charge of managing the client socket and ensuring
that information is sent back and forth to the server correctly.
<TT><FONT FACE="Courier">Connect4ClientConnection</FONT></TT>
is derived from <TT><FONT FACE="Courier">SocketAction</FONT></TT>,
which is another good example of code reuse. The constructor for
<TT><FONT FACE="Courier">Connect4ClientConnection</FONT></TT>
takes an <TT><FONT FACE="Courier">Applet</FONT></TT> object as
its only parameter:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">Connect4ClientConnection(Applet a) throws
IOException {<BR>
&nbsp;&nbsp;super(new Socket(a.getCodeBase().getHost(), PORTNUM));
<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
The <TT><FONT FACE="Courier">Connect4ClientConnection</FONT></TT>
constructor creates a socket connection based on the applet parameter
and a port number. Note that this port number must match the port
number used by the server.
<P>

<CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Warning</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
If the port numbers for the client and server don't match, none of the socket communication will be able to take place. In other words, the game won't run if the port numbers don't match.</BLOCKQUOTE>
</TD></TR>
</TABLE></CENTER>
<P>
<P>
The <TT><FONT FACE="Courier">getTheirMove</FONT></TT> method in
<TT><FONT FACE="Courier">Connect4ClientConnection</FONT></TT>
is used to get the other player's move so that the client game
can be updated. Listing 19.7 contains the source code for the
<TT><FONT FACE="Courier">getTheirMove</FONT></TT> method.
<HR>
<BLOCKQUOTE>
<B>Listing 19.7. The Connect4ClientConnection class's getTheirMove
method.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public int getTheirMove() {<BR>
&nbsp;&nbsp;// Make sure we're still connected<BR>
&nbsp;&nbsp;if (!isConnected()) <BR>
&nbsp;&nbsp;&nbsp;&nbsp;throw new NullPointerException(&quot;Attempted
to read closed socket!&quot;);<BR>
<BR>
&nbsp;&nbsp;try {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;String s = receive();<BR>
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(&quot;Received: &quot;
+ s);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (s == null)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return GAMEOVER;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;s = s.trim();<BR>
&nbsp;&nbsp;&nbsp;&nbsp;try {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (new Integer(s)).intValue();
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;catch (NumberFormatException e) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// It was probably a status
report error<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return getStatus(s);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;catch (IOException e) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(&quot;I/O Error: &quot;
+ e);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;System.exit(1);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;return 0;<BR>
&nbsp;&nbsp;}<BR>
}</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The <TT><FONT FACE="Courier">getTheirMove</FONT></TT> method basically
just receives a string from the server and resolves it down to
an integer, which is then returned. The integer it receives is
a game state constant as defined in <TT><FONT FACE="Courier">Connect4ClientConnection</FONT></TT>.
The following are the game state constants defined in <TT><FONT FACE="Courier">Connect4ClientConnection</FONT></TT>:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">static final int ERROR = -1;<BR>
static final int PLSWAIT = -2;<BR>
static final int YOURTURN = -3;<BR>
static final int THEIRTURN = -4;<BR>
static final int THEYWON = -5;<BR>
static final int THEYQUIT = -6;<BR>
static final int THEYTIED = -7;<BR>
static final int GAMEOVER = -8;</FONT></TT>
</BLOCKQUOTE>
<P>
Although these game state constants are similar in function to
the ones defined on the server side in the <TT><FONT FACE="Courier">Game</FONT></TT>
class, keep in mind that they are client-specific and make sense
only in the context of a client. The constants are all negative,
which is based on the fact that the integer state constant is
also used to convey the location of a player's move; all moves
are in the range 0 through 6, which corresponds to the column
into which a piece is being dropped.
<P>
The <TT><FONT FACE="Courier">getStatus</FONT></TT> method resolves
a string status message into an integer game state constant. Listing
19.8 contains the source code for <TT><FONT FACE="Courier">getStatus</FONT></TT>.
<HR>
<BLOCKQUOTE>
<B>Listing 19.8. The </B><TT><B><FONT FACE="Courier">Connect4ClientConnection</FONT></B></TT><B>
class's </B><TT><B><FONT FACE="Courier">getStatus</FONT></B></TT><B>
method.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">private int getStatus(String s) {<BR>
&nbsp;&nbsp;s = s.trim();<BR>
&nbsp;&nbsp;if (s.startsWith(&quot;PLSWAIT&quot;))<BR>
&nbsp;&nbsp;&nbsp;&nbsp;return PLSWAIT;<BR>
&nbsp;&nbsp;if (s.startsWith(&quot;THEIRTURN&quot;))<BR>
&nbsp;&nbsp;&nbsp;&nbsp;return THEIRTURN;<BR>
&nbsp;&nbsp;if (s.startsWith(&quot;YOURTURN&quot;))<BR>
&nbsp;&nbsp;&nbsp;&nbsp;return YOURTURN;<BR>
&nbsp;&nbsp;if (s.startsWith(&quot;THEYWON&quot;))<BR>
&nbsp;&nbsp;&nbsp;&nbsp;return THEYWON;<BR>
&nbsp;&nbsp;if (s.startsWith(&quot;THEYQUIT&quot;))<BR>
&nbsp;&nbsp;&nbsp;&nbsp;return THEYQUIT;<BR>
&nbsp;&nbsp;if (s.startsWith(&quot;THEYTIED&quot;))<BR>
&nbsp;&nbsp;&nbsp;&nbsp;return THEYTIED;<BR>
&nbsp;&nbsp;if (s.startsWith(&quot;GAMEOVER&quot;))<BR>
&nbsp;&nbsp;&nbsp;&nbsp;return GAMEOVER;<BR>
<BR>
&nbsp;&nbsp;// Something has gone horribly wrong!<BR>
&nbsp;&nbsp;System.out.println(&quot;received invalid status from
server: &quot; + s);<BR>
&nbsp;&nbsp;return ERROR;<BR>
}</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The <TT><FONT FACE="Courier">getStatus</FONT></TT> method is used
by <TT><FONT FACE="Courier">getTheirMove</FONT></TT> to convert
incoming text messages to their integer equivalent.
<P>
The <TT><FONT FACE="Courier">sendMove</FONT></TT> method is pretty
straightforward; it simply sends the player's move to the server:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public void sendMove(int col) {<BR>
&nbsp;&nbsp;String s = (new Integer(col)).toString();<BR>
&nbsp;&nbsp;send(s);<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
Likewise, the <TT><FONT FACE="Courier">sendIQUIT</FONT></TT>,
<TT><FONT FACE="Courier">sendIWON</FONT></TT>, and <TT><FONT FACE="Courier">sendITIED</FONT></TT>
methods are used to send the corresponding messages <TT><FONT FACE="Courier">IQUIT</FONT></TT>,
<TT><FONT FACE="Courier">IWON</FONT></TT>, and <TT><FONT FACE="Courier">ITIED</FONT></TT>
to the server:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public void sendIQUIT() {<BR>
&nbsp;&nbsp;send(&quot;IQUIT&quot;);<BR>
}<BR>
<BR>
public void sendIWON() {<BR>
&nbsp;&nbsp;send(&quot;IWON&quot;);<BR>
}<BR>
<BR>
public void sendITIED() {<BR>
&nbsp;&nbsp;send(&quot;ITIED&quot;);<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
That wraps up the client side of NetConnect4. If you're still
a little dizzy from all the code, feel free to go through it again
and study the details until you feel comfortable with everything.
Trust me, it's perfectly normal to get confused during your first
dealings with network game programming-I sure did!
<H2><A NAME="Summary"><B><FONT SIZE=5 COLOR=#FF0000>Summary</FONT></B></A>
</H2>
<P>
Today you wrote your fourth complete Java game. Well, you actually
modified one of the games you had already written. However, turning
a single-player game into a two-player game that can be played
over the Web might as well constitute a whole new game. In learning
how the game was implemented, you saw how the client/server architecture
and Java socket services are used in a practical scenario. You
also reused the generic socket class you developed yesterday,
thereby reinforcing the values of applying OOP techniques to Java
game programming.
<P>
With four complete Java games under your belt, you're probably
ready to chart some new territory in regard to Java game development.
That's a good thing, because tomorrow's lesson focuses on a subject
that has long been crucial to successful game programming: optimization.
Tomorrow's lesson guides you through some tricks and techniques
for speeding up your Java game code.
<H2><A NAME="QA"><B><FONT SIZE=5 COLOR=#FF0000>Q&amp;A</FONT></B></A>
<BR>
</H2>

<TABLE>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>I still don't follow the whole client/server strategy as it applies to NetConnect4. Can you briefly explain it again?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD>Of course. The game server sits around in a never-ending loop waiting for client players to show up. When a player connects to the server, the server spawns a daemon thread to manage the communications necessary 
to support a single game. This daemon serves as a communication channel between the two clients (players) involved in the game, which is necessary because there is no facility to enable clients to communicate directly with each other.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>Would this same client/server strategy work for a game with more than two players?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD WIDTH=559>Absolutely. The code would get a little messier because the daemon would have to manage a group of clients rather than just two, but conceptually there is no problem with adding more client players to 
the mix.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>How do I incorporate NetConnect4 into a Web site?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD>Beyond simply including the client applet in an HTML document that is served up by your Web server, you must also make sure that the NetConnect4 server (<TT><FONT FACE="Courier">NetConnect4Server</FONT></TT>) is 
running on the Web server machine. Without the game server, the clients are worthless.
</TD></TR>
</TABLE>
<P>
<H2><A NAME="Workshop"><B><FONT SIZE=5 COLOR=#FF0000>Workshop</FONT></B></A>
</H2>
<P>
The Workshop section provides questions and exercises to help
you get a better feel for the material you learned today. Try
to answer the questions and at least ponder the exercises before
moving on to tomorrow's lesson. You'll find the answers to the
questions in appendix A, &quot;Quiz Answers.&quot;
<H3><A NAME="Quiz"><B>Quiz</B></A></H3>
<OL>
<LI>What is a daemon thread?
<LI>What is the significance of the <TT><FONT FACE="Courier">Game</FONT></TT>
class?
<LI>What is the purpose of the <TT><FONT FACE="Courier">Connect4ClientConnection</FONT></TT>
class?
</OL>
<H3><A NAME="Exercises"><B>Exercises</B></A></H3>
<OL>
<LI>Enhance the NetConnect4 game to display the name of each player
as he is making his move. Hint: To get the name of a player, use
the <TT><FONT FACE="Courier">getHostName</FONT></TT> method after
getting an <TT><FONT FACE="Courier">InetAddress</FONT></TT> object
for a socket using <TT><FONT FACE="Courier">getInetAddress</FONT></TT>.
<LI>Modify the NetConnect4 game to enable players to choose who
they want to play with. Admittedly, this is a pretty big modification,
but I think you can handle it. Hint: This task involves modifying
the client/server design so that clients connect and are added
to a list of potential players. A player can then choose an opponent
from the list, in which case they are paired together normally.
</OL>
<P>
<HR WIDTH="100%"></P>

<CENTER><P><A HREF="ch18.htm"><IMG SRC="pc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="index.htm"><IMG SRC="hb.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="#CONTENTS"><IMG SRC="cc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="ch20.htm"><IMG 
SRC="nc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A></P></CENTER>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -