具有智能功能的单词构建网络游戏(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/word-building-network-game-with-intelligence-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 9 分钟阅读 - 4193 个词 阅读量 0具有智能功能的单词构建网络游戏(译文)
原文地址:https://www.codeproject.com/Articles/9514/Word-Building-Network-Game-With-Intelligence
原文作者:Mohammed Aijaz Mohiuddin
译文由本站 robot-v1.0 翻译
前言
Word building game using C#.
使用C#建立单词的游戏.
介绍(Introduction)
构词游戏是全世界知名的游戏.也称为(The word building game is a well known game all over the world. It is also called as)拼字游戏(scrabble).在此网络支持的游戏中,四个玩家可以共享同一矩阵板一起玩游戏.玩家可以通过搜索直接加入相应的对手.我使用UDP套接字搜索托管游戏,并使用TCP套接字进行游戏处理.可以在子网内玩此游戏.(. In this network-supported game, four players can play the game together sharing the same matrix board. Players can join their corresponding opponents directly by searching. I have used UDP sockets for searching the hosted game and TCP sockets for game processing. This game can be played within the subnet.)
该网络支持的游戏非常智能.玩家不能通过提交非英语单词来欺骗游戏.该游戏使用约55903个单词的英语单词列表.(This network-supported game is intelligent. A player cannot fool the game by submitting non-English words. This game uses an English word list of around 55903 words.) HashTable
C#的代码用于此实现.该数据结构用于存储单词.当玩家提交单词时,游戏将执行查找操作.可以添加新词(of C# is used for this implementation. This data structure is used to store the words. The game performs lookup operation when a player submits the word. New words can be added in)*wordlist.txt(wordlist.txt)*文件存在于(file present in the)*箱子(bin)*夹.此游戏中开发的网络基础结构是通用的.任何游戏都可以使用此基础网络基础结构.我已经添加了(folder. The network infrastructure developed in this game is general purpose. Any game can use this underlying network infrastructure. I have added)*Howtoplay.pdf(Howtoplay.pdf)*文件以说明玩游戏.(file for the instructions to play the game.)
游戏(Game)
通常,该游戏是两人游戏.像所有其他游戏一样,这两个玩家将轮流将单个英文字母放入给定的盒子矩阵中,以便他们可以在垂直方向或水平方向上形成英文单词.每个玩家将获得等于他们形成的英语单词长度的分数.最终,得分更高的玩家将赢得比赛.(In general, this game is a two-player game. Like all other games, these two players will have turns to put a single English alphabet in the given matrix of boxes so that they can form an English word in vertical direction or horizontal direction. Each player will get points equal to the length of the English word they form. Finally, the player with more points will win the game.)
游戏角色(Game roles)
托管或加入游戏后,游戏实例可以运行以下角色之一:(After hosting or joining the game, the game instance can run one of the following roles:)
- 服务器角色(Server Role)
- 客户角色(Client Role)
- 客户无效角色(Client Inactive Role)
服务器角色(Server Role)
托管游戏后,该游戏将进入此角色.在此角色中,客户端将充当服务器,它将在其中执行三个任务.首先,它将侦听正在搜索活动主机的客户端,并通过确认消息答复它们,以告知其存在.其次,它将等待客户请求加入游戏.一旦接收到加入请求,它将处理该请求,并使用包含一些所需信息的接受消息来答复发送者.第三,它将通过向每个客户端发送一条特殊消息来通知他们有关游戏开始事件的初始化消息以及一些其他信息来初始化和启动游戏,以初始化游戏状态.一旦开始游戏,游戏将退出此角色.(The game will enter this role once it hosts the game. In this role, the client will act as a server where it will perform three tasks. First, it will listen for clients searching for an active host and reply to them with an acknowledgement message informing them of its presence. Second, it will wait for clients to request for joining the game. Once it receives the join request, it will process this request and it will reply to the sender with an acceptance message that has some needed information. Third, it will initialize and start the game by sending every client a special message notifying them about the game start event along with some other information to initialize the game state. The game will exit this role once it starts the game.)
以下代码段是一个将处理此角色的线程.(The following code snippet is a thread that will handle this role.)
private static void TcpServerRole()
{
// start a TCP listener
ServerListener = new TcpListener(GamePort);
ServerListener.Start();
//declare some variables
Socket ss ; //server socket
NetworkStream ns ;
StreamReader sr;
StreamWriter sw;
string IncomingMessage ;
while (true)
{
// wait for incoming messages
ss = ServerListener.AcceptSocket();
// create network, reader and writer streams
ns = new NetworkStream(ss);
sr = new StreamReader(ns);
sw = new StreamWriter (ns);
IPAddress ip;
// read the incoming message
IncomingMessage = sr.ReadLine();
// ((Type 1))
// request for total number of connected players
if (IncomingMessage=="NumberOfPlayers?")
{
// reply with the number of players
sw.WriteLine(Game.ConnectedPlayers.Count.ToString());
sw.Flush();
}
// ((Type 2))
// request for all connected players
if (IncomingMessage=="Players?")
{
// loop over all connectd players
for ( int i=0 ; i < Game.ConnectedPlayers.Count ; i++)
{
// send the player object
sw.WriteLine(Game.ConnectedPlayers[i].ToString());
sw.Flush();
// send the player IP Address
sw.WriteLine(ClientsAddresses[i].ToString());
sw.Flush();
}
}
// ((Type 3))
// request to join the game
if (IncomingMessage.StartsWith("Join"))
{
// get the player string by removing un-needed part
string PlayerStr = IncomingMessage.Remove(0,4);
// get the client (new player) IP Address
ip = ((IPEndPoint)ss.RemoteEndPoint).Address;
// send back the client, the Turn Index
sw.WriteLine(Game.ConnectedPlayers.Count);
sw.Flush();
// add the new player IP Address
ClientsAddresses.Add(ip);
// Add the new player to connected players
Game.ConnectedPlayers.Add(Game.ConvertStringToPlayer(PlayerStr));
// update all other clients of the new player
NewClientUpdateOthers(PlayerStr,ip);
}
// close the socket, end of request
ss.Close();
} //end while
}
客户角色(Client Role)
游戏将通过两种方式进入此角色:通过在要从服务器角色切换到的位置开始游戏,或者通过接收转弯消息(转弯消息通知客户该轮到他/她了).在此角色下,客户端可以执行两项任务.第一个任务是从游戏中接收已播放的动作,然后将其发送给所有其他客户端以更新其内部游戏状态.第二项任务是在当前玩家完成转牌后将转牌传递给下一位玩家.(The game will enter this role by two ways: either by starting the game where it will switch from server role, or by receiving the turn message (the turn message notifies the client that it is his/her turn to play). In this role, the client can do two tasks. The first task is to receive the played action from the game and then send it to all other clients to update their internal game state. The second task is to pass the turn to the next player once the current player finishes his/her turn.)
无效的客户角色(Inactive Client Role)
此角色是加入游戏的客户的进入角色.一旦游戏结束并已将回合转到下一位玩家,游戏还将进入该角色.在此角色下,客户端将等待更新消息,该消息可能是以下之一:(This role is the entry role for clients joining the game. The game will also enter this role once it is finished playing and has passed the turn to the next player. In this role, the client will wait for update messages that can be one of the following:)
- 新玩家加入了游戏(New player joined the game)
- 游戏已经开始,请初始化您的状态(Game has started, initialize your state)
- 新动作(New action)
- 轮到你了(It is your turn)
客户加入游戏后,他们将等待接收新的玩家更新消息.该消息将同时包含新的播放器对象和IP地址,从而使客户端能够更新其播放器列表.同样,客户将需要根据"开始游戏"更新消息初始化其游戏状态.一旦玩家列表完成并且游戏状态被初始化,客户端就准备好接收当前玩家所玩的新动作,以便根据需要更新他们的游戏状态.一旦收到"您的回合"消息,客户端将切换到客户端角色,该消息指示当前玩家已经结束比赛,现在该轮到您了.(Once clients join the game, they will wait to receive a new player update message. This message will contain both the new player object along with the IP address, thus enabling the clients to update their player list. Also, clients will need to initialize their game state according to the “Start Game” update message. Once the player list is complete and the game state is initialized, the clients are ready to receive new actions played by the current player in order to update their game states as needed. The client will switch to Client role once it receives “Your Turn” message which indicates the current player has finished playing and it is now your turn to play.)
以下代码段将处理此角色:(Following code snippet will handle this role:)
private static void UnactiveClient()
{
// set the port that I will listen to
int port = GamePort + Game.MyTurnIndex ;
// create a TCP Listener
TcpListener Client = new TcpListener(port);
Client.Start(); // start listening
// define variables
TcpClient cs ;
NetworkStream ns ;
StreamReader sr;
string update;
bool MyTurnFlag = true;
// loop until you receive your turn
while (MyTurnFlag)
{
// wait for updates
cs = Client.AcceptTcpClient();
// create network & reader streams
ns = cs.GetStream();
sr = new StreamReader(ns);
// read the update
update = sr.ReadLine();
// string array to deal with the update
string[] updateMsg;
// is it a NEW PLAYER Update Message
if (update.StartsWith("New Player -->"))
{
// remove first part (Length of NewPlayer --> is 14)
update = update.Remove(0,14);
// add the new player object
Game.ConnectedPlayers.Add(Game.ConvertStringToPlayer(update));
// reads the new player IP Address
update = sr.ReadLine();
// add the new player IP Address to Address List
ClientsAddresses.Add(update);
// close the socket
cs.Close();
}
// is it a Game Start Update Message
else if(update.StartsWith("Start Game-->"))
{
// A received message can be "Start Game-->5#2
// Upto 5#2 everything is removed
// 5 is the number of columns
// 2 is the number of rows
//remove unneeded info.
update = update.Remove(0,13);
string[] rowcol = update.Split(new char[] {'#'});
int row = Convert.ToInt32(rowcol[0]);
int col = Convert.ToInt32(rowcol[1]);
// These values will be used by MatrixDisplay function
form.row = row;
form.col = col;
Game.IsGameStarted = true; // game state is started
// close the client
cs.Close();
// display matrix on the user form
form.Invoke(new displayMethod(form.MatrixDisplay),null);
}
else if ( update.StartsWith("alphabet"))
{
// Example alphabet-10-10-a#colour#
string x1s;
string y1s;
int index;
index = update.IndexOf("-");
update = update.Remove(0,index+1);
index = update.IndexOf("-");
x1s = update.Substring(0,index);
update = update.Remove(0,index+1);
index = update.IndexOf("-");
y1s = update.Substring(0,index);
string update1 = update.Remove(0,index+1);
update1 = update1.Substring(0,1);
index = update.IndexOf("#");
string colour = update.Remove(0,index+1);
colour = colour.TrimEnd('#');
// pass the parameters to DisplayAlphaBet method
// This function displays the alphabet
form.DisplayAlphaBet(Convert.ToInt32(x1s),
Convert.ToInt32(y1s), update1,colour);
cs.Close();
}
else if(update.StartsWith("Game Over"))
{
string[] ln = update.Split(new char[] {'#'});
ln[0] = ln[0].Remove(0,9);
MessageBox.Show(ln[0] + " Won the game " + "Score:" + ln[1]);
cs.Close();
}
else if (update.StartsWith("word"))
{
int index;
string Stringtemp1;
string Stringtemp2;
Stringtemp1 = update;
Stringtemp2 = update;
// index extraction
index = Stringtemp1.IndexOf("#");
Stringtemp1 = Stringtemp1.Remove(0,index+1);
index = Stringtemp1.IndexOf("@");
Stringtemp1 = Stringtemp1.Substring(0,index);
int LabelIndex = Convert.ToInt32(Stringtemp1);
index = Stringtemp2.IndexOf("@");
Stringtemp2 = Stringtemp2.Remove(0,index+1);
int LabelScore = Convert.ToInt32(Stringtemp2);
index = 0;
index = update.IndexOf("#");
update = update.Substring(0,index);
index = 0;
ArrayList xs = new ArrayList();
ArrayList ys = new ArrayList();
index = update.IndexOf("-");
update = update.Remove(0,index+1);
index = update.IndexOf("W");
string coordinates = update.Substring(0,index);
update = update.Remove(0,index+1);
index = update.IndexOf("-");
update = update.Remove(0,index+1);
string[] ln = coordinates.Split(new char[] {'-'});
for (int i=0;i < ln.Length;i+=2)
xs.Add(ln[i]);
for (int i=1;i < ln.Length;i+=2)
ys.Add(ln[i]);
form.DisplayColour(xs,ys,update,LabelIndex,LabelScore);
cs.Close();
}
// is it a Your Turn Message
else if (update.StartsWith("TURN"))
{
Game.MyTurn = true; // Set my turn
MyTurnFlag = false; // exit from this state
cs.Close(); // close the socket
Client.Stop(); // stop client mode; do not listen for updates
// Current player is the local Player
Game.CurrentPlayerObj = Game.LocalPlayer;
}
else //ignore other messages
cs.Close();
} // End of while(true) statement
}
图解视图(Diagrammatic view)
当用户单击"主机"按钮时,将启动三个线程.下(When a user clicks the Host button, three threads will be started. Under)Form1.cs(Form1.cs)类,称为(class, a thread called as) UpdateThread
开始.该线程从中获取信息(is started. This thread takes the information from) ICommon
界面并将信息更新到用户界面表单.(interface and updates the information to the user interface form.) UdpServerRole
线程侦听UDP广播消息,并使用托管游戏的计算机的IP地址进行确认.(thread listens for UDP broadcast messages and acknowledges with the IP address of the machine where the game is hosted.)
TcpServerRole
处理网络消息传递.它从网络接收消息并做出响应,并更新接口(deals with network messaging. It receives the messages from the network and responds to them and also updates to the interface) ICommon
.当用户单击"开始游戏"按钮时,(. When a user clicks the Start Game button,) TcpServerRole
和(and) UdpServerRole
线程将停止,并且主要用户将执行一些操作.下图显示了一个不错的多线程环境.(threads will be stopped and the main user will do some action. The following figures show a nice multi-threading environment.)
当用户单击"加入"按钮时,(When a user clicks the Join button,) UpdateThread
和(and) ClientThread
开始执行.(start executing.) ClientThread
是通用线程.当用户加入游戏或掉头时,该线程将运行.它接受来自网络的新玩家,开始游戏,字母,游戏结束,单词和回合消息,并更新界面(is a general purpose thread. When a user joins the game or loses his turn, this thread will run. It accepts New player, Start Game, Alphabet, Game Over, Word, and Turn messages from the network and updates to the interface) ICommon
.(.)
局限性(Limitations)
- 只能玩四个玩家.(Only four players can play.)
- 如果在防火墙或NAT之后,则无法播放.(Cannot play if behind a firewall or a NAT.)
- 玩家必须在游戏前达成一致,才能知道自己的IP.(Players must agree before playing in order for them to know their IPs.)
- 由于它是用C#实现的,因此如果没有.NET运行时环境,它将无法在计算机上运行.(Since it is implemented in C#, it will not run on machines without .NET runtime environment.)
结论(Conclusion)
本文介绍了一种通用网络基础结构.任何与已实现的单词构建游戏相似的游戏都可以插入此基础架构.本文充当其他开发中的可重用组件.(In this article, a general-purpose network infrastructure is presented. Any game that is similar to the implemented word building game can be plugged into this infrastructure. The article serves as a re-usable component in other developments.)
致谢(Acknowledgment)
此游戏实现是ICS-571(信息和计算机科学)课程的课程项目,即客户端/服务器编程,由助理教授教授(This game implementation is a course project for course ICS-571 (Information and Computer Science) namely Client/Server programming, taught by Assistant Professor)**纳西尔`达维什(Nasir Al-Darwish)(Nasir Al-Darwish)**在(at)法赫德国王石油和矿产大学,沙特阿拉伯王国,达兰(King Fahad University of Petroleum and Minerals, Kingdom of Saudi Arabia, Dhahran).他的电子邮件地址是darwish@kfupm.edu.sa.通过本课程,已经学习并实现了许多新概念.(. His email address is darwish@kfupm.edu.sa. From this course, many new concepts have been learned and implemented.)
参考文献(References)
- 信箱游戏(Letter box game) .(.)
- 玩文字游戏(Play Word games) .(.)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# WinXP Windows .NET .NET1.1 Visual-Studio VS.NET2003 Dev 新闻 翻译