本次作业要求设计服务器和客户端,由于之前对网络编程是一窍不通,上上节课听宗学长讲述Tcp的时候心里想这个东西还真是高大上啊一点儿都听不懂,但是上个周末看了看C#网络编程的博客和书之后,发现这个东西入门其实很简单.经过几天的需求分析代码维护之后,我们的作业已经初具成果,先展示一下效果.

服务器:

客户端:

是不是很华丽的说。。。

感觉就像做了一个实验室的小项目一样。。。代码量有一千的说。。。当然如果要做的更好还可以加很多优化。。。但是(见最后吐槽)。。

下面根据作业要求来展示一下我们的设计:

多人游戏, 每个选手有一个客户程序在运行, 和一个服务器通过互联网的某种协议交互。

我们采用的是TCP编程,遵循TCP/IP协议。

在有网络接的地方就可以玩 (LAN, WiFi,  3G 都应该可以)。

这个。。。明显可以保证吧,我们获得主机的地址然后连接

客户程序要先向服务器注册, 确保在一个游戏的过程中, 注册信息能保证一个(并且只有一个)客户以某确定的用户名参与游戏。

首先为了方便演示,我们用随机数生成Player+num形式的用户名,单击登录按钮之后,会发送一个Login请求,这时服务器会判断userList中是否存在该用户名,如果存在,那么会返回一个sorry消息,告诉该客户端无法登录;如果不存在,那么就将该用户加入userList中,同时返回一个success消息,告诉客户端登录成功.

服务器可以规定一次锦标赛有多少轮,  每轮的具体提交数据的格式是什么。 在服务器规定的时间范围内, 每个客户程序向服务器提交黄金点数据。 客户程序之间不交流。

我们在服务器的界面上进行了如下设计:

我们人为的将允许同时参加游戏的最多人数设定好,为了放置服务器过载?(这里当然满足这门课60人的需求是绰绰有余了。。),游戏轮数,每轮游戏的时间可以自行设定,游戏规则采用radiobutton来设定.同时服务器的这些设定在单击开始游戏之后就会变为enabled=false,防止中途更改.同时这些设定也会传给客户端,同样客户端也只能显示设定而无法更改设定

在一轮介绍后, 服务器把此轮的结果 (参与用户名,  提交的数据,第一名,G-number) 公布在服务器上。  每个客户程序都能自由获取。

每轮结束后,我们会将本轮游戏结果发送给客户端,同时将本轮排名和黄金点变化曲线实时更新在服务器上,当然想在客户端方面获取只要在添加一个webbrowser控件链接到我们的服务器相应地址就可以.

一轮的优胜程序可以得 10 分, 一轮的最后一名得 (–1)分, 其余选手得 0 分。  在规定时间内不能提交数字的客户程序得 (-5) 分。 如果有并列第一名, 则服务器取提交数字较早的客户程序作为优胜者。  如果有并列最后一名, 则并列者都得 (-1) 分。

这个老师的判定这是奇怪…每个User类设计一个grade属性,同时开一个list来存每轮的最后一名.

每次锦标赛事先规定好是采取下列哪一个模式:

  1. 每个客户程序必须提交一个有理数。

  2. 每个客户程序必须提交两个有理数。  (任何一个数字最接近G-number 则此客户程序就是优胜。)

这个就是简单的判断吧…规则在游戏一开始就能确定了..上述已经提到这一点,另外实现起来就是send,number1,number2的问题而已

客户程序可以用任何语言编写, 只要它能够按要求和服务器交互即可。

我们用了C#,话说这学期就跟C#打交道了,而且C#网络编程很方便,很多东西都已经包装的很好了.

服务器必须实时地通过一个网页显示每个用户的得分 (人可以从这里看进展,客户端程序会从这里拿数据进行分析)。

我们的Webbrowser控件就是通过读取我们的网页来显示得分的…另外我们的曲线图使用bitmap绘制的(C#的chart控件还没有开始学..),然后将bitmap存为图片同时html显示该图片就好.这里遇到了一个很大的问题是图片开始时一直是X,搜了好多资料之后告诉我是图像色彩模式不统一?后来索性把图片格式从Jpg改为Png,问题解决.据说说rpg转cmyk的问题?...

服务器必须能避免接口拥堵, DDOS 等意外情况。

哈哈.我们相信我们的服务器.

接下来从代码方面分析一下我们的设计

服务器:

我们设计了一个User类来存用户信息,

一个Service类来用来实时显示服务器状态(addItem)和向客户端发送消息

至于老师提到的接口设计,我们放到FormServer类里,不过想不太明白的是,我们设计接口不就是为了大家设计客户端程序提交黄金点么…这样的话不就是每个人写一个productNumber()来生成自己的答案就好了么…客户端所能获取到的就是上一轮的黄金点数据…然后就靠各位当作一个数学题+博弈题来考虑了..

我们的FormServer中,开始游戏后会开一个线程来监听tcp连接,当有连接后会分配一个线程进行相应处理.对于每轮游戏的时间问题我们用了Timer,在每一个timerElapsed事件里进行先发送一个pause消息来暂停游戏,进行相应结果处理后,再重新发送start消息开始游戏.同时我们还用了获取当前事件DateTime同时利用while(now.AddSeconds(some  seconds)>DateTime.now){}的方法进行延时处理,不用Thread.sleep的原因是直觉感觉这样会有问题...

消息处理总结如下:

 1 switch (command)
2 {
3 case "login":
4 if (userList.Count > maxUsers)
5 {
6 sendString = "sorry";
7 service.sendToOne(user, sendString);
8 service.addItem("人数已满,拒绝" + splitString[1] + "进入游戏");
9 isExist = false ;
10 }
11 else
12 {
13 bool flag = true;
14 for (int i = 0; i < userList.Count; i++)
15 {
16 if (userList[i].userName == splitString[1])
17 {
18 flag = false;
19 break;
20 }
21 }
22 if (!flag)
23 {
24 sendString = "sorry";
25 service.sendToOne(user, sendString);
26 service.addItem("用户名已存在,拒绝" + splitString[1] + "进入游戏");
27 isExist = false;
28 }
29 else
30 {
31 user.pos = num++;//用户进入先后顺序
32 userList.Add(user);
33 user.userName = splitString[1];
34 sendString = "success";
35 service.sendToOne(user, sendString);
36 service.addItem(string.Format("用户 {0} 加入游戏成功!", user.userName));
37 }
38 }
39 break;
40 case "logout":
41 service.addItem(string.Format("{0}退出游戏", user.userName));
42 normalExit = true;
43 isExist = false;
44 break;
45 case "send":
46 service.addItem(string.Format("{0}提交数据: {1},提交成功", user.userName, splitString[1]));
47 sendString = string.Format("success");
48 service.sendToOne(user, sendString);
49 user.number = double.Parse(splitString[1]);
50 if (splitString.Length == 3)
51 {
52 user.number2 = double.Parse(splitString[2]);
53 }
54 user.hasSend = true;
55 break;
56 default:
57 service.sendToOne(user, "无效指令: " + receiveString);
58 break;

客户端:

客户端也拥有一个Service类,用来显示服务器和客户端状态

客户端的主体是FormClient类,这里对于消息的处理我们总结如下:

 1 switch (command)
2 {
3 case "sorry":
4 MessageBox.Show("连接成功,但游戏人数已满或者用户名已存在,无法进入.");
5 isExist = false;
6 break;
7 case "pause":
8 buttonSend.Enabled = false;
9 break;
10 case "start":
11 service.addItemToListBox("收到: " + receiveString);
12 if (isRandom)
13 {
14 randomSend();
15 }
16 else
17 {
18 buttonSend.Enabled = true;
19 }
20 break;
21 case "success":
22 service.addItemToListBox("本轮向服务器提交答案成功,等待下一轮游戏开始");
23 buttonSend.Enabled = false;
24 break;
25 case "result":
26 service.addItemToListBox(string.Format("上一轮游戏结果: Gnum is {0}, winner is {1}.", splitString[1], splitString[2]));
27 break;
28 case "mode":
29 if (splitString[1] == "0")
30 {
31 mode = 0;
32 radioButtonMode1.Checked = true;
33 radioButtonMode2.Checked = false;
34 radioButtonMode1.Enabled = false;
35 radioButtonMode2.Enabled = false;
36 textBoxNumber2.Enabled = false;
37 service.addItemToListBox(string.Format("本轮游戏模式为: 每个客户程序必须提交一个有理数"));
38 }
39 else
40 {
41 mode = 1;
42 radioButtonMode1.Checked = false;
43 radioButtonMode2.Checked = true;
44 radioButtonMode1.Enabled = false;
45 radioButtonMode2.Enabled = false;
46 textBoxNumber2.Enabled = true;
47 service.addItemToListBox(string.Format("本轮游戏模式为: 每个客户程序必须提交两个有理数(任何一个数字最接近G-number 则此客户程序就是优胜.)"));
48 }
49 break;
50 default: break;

最后,强烈吐槽一句。。。

超喜欢这门课,学到了好多东西,比如我之前从未接触过C#,比如我之前根本不了解网络编程,比如我之前做UI一点都不熟练,比如我之前根本不知道可以将代码打包成类库,比如我之前不会单例模式,比如我之前不知道单元测试代码覆盖率什么的,比如我对VS....用的越来越熟练了....

强烈建议这门课成为必修课。。。而且是学分很重的必修课。。。因为现在我每周花时间最多的课就是这门了。。。。。。

而无论我有多么喜欢这门课。。。接下来的时间里必然会将大部分时间献给五千行甚至八千行的编译大作业。。。献给我们的cocos2d-x游戏项目。。。献给我们的数据库大作业。。。这门课。。。接下来。。。尽量搞一些讲座什么的吧。。。。。。

【现代程序设计】homework-05的更多相关文章

  1. 标准C程序设计七---05

    Linux应用             编程深入            语言编程 标准C程序设计七---经典C11程序设计    以下内容为阅读:    <标准C程序设计>(第7版) 作者 ...

  2. 现代程序设计homework——04

    题目: 详见:http://www.cnblogs.com/xinz/p/3341551.html 题目本身确实很难,“很难想到一个比较优雅的算法”,这是一个老师请来专门讲解这道题的大牛的原话.确实, ...

  3. 软工+C(9): 助教指南,持续更新...

    上一篇:提问与回复 下一篇:从命令行开始逐步培养编程能力(Java) 目录: ** 0x00 Handshake ** 0x01 点评 ** 0x02 评分 ** 0x03 知识储备 ** 0x04 ...

  4. 20172319 2018.03.27-04.05 《Java程序设计》第4周学习总结

    20172319 2018.03.27-04.05 <Java程序设计>第4周学习总结 教材学习内容总结 第四章 编写类 类与对象的回顾:对象是有状态的,状态由对象的属性值确定.属性由类中 ...

  5. 20145219 《Java程序设计》第05周学习总结

    20145219 <Java程序设计>第05周学习总结 教材学习内容总结 try.catch 1.求平均数程序示例 import java.util.Scanner; public cla ...

  6. C语言程序设计|05

    问题 回答 这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-4/homework/9772 我在 ...

  7. 20145218 《Java程序设计》第05次实验报告

    北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1452 指导教师:娄嘉鹏 实验名称:Java网络编程及安全 一.实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使 ...

  8. # 20145210 《Java程序设计》第05周学习总结

    教材学习内容总结 第八章 异常处理 8.1语法与继承架构 •使用 try.catch •Java中所有信息都会被打包为对象,如果愿意,可以尝试(try)捕捉(catch)代表错误的对象后做一些处理 • ...

  9. 2017"百度之星"程序设计大赛 - 复赛 01,03,05

    Arithmetic of Bomb Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  10. 读书笔记(05) - 事件 - JavaScript高级程序设计

    HTML依托于JavaScript来实现用户与WEB网页之间的动态交互,接收用户操作并做出相应的反馈,而事件在此间则充当桥梁的重要角色. 日常开发中,经常会为某个元素绑定一个事件,编写相应的业务逻辑, ...

随机推荐

  1. 批量删除亚马逊kindle云端文档

    首先鄙视亚马逊的不负责任,kindle的云端管理系统犹如一坨狗屎,根本没有考虑的任何用户体验,只能一个一个删除不说,删除后又回到第一页...翻页也没有输入页码的地方,如果在第100页删除文档后,又回到 ...

  2. Linux里如何查找文件内容 (转)

    Linux查找文件内容的常用命令方法. 从文件内容查找匹配指定字符串的行: $ grep "被查找的字符串" 文件名例子:在当前目录里第一级文件夹中寻找包含指定字符串的.in文件g ...

  3. linux 的终端字体色和背景色的修改方法(一)

    更改Linux系统终端的颜色主题 随着Linux系统在服务器端的崛起,Linux也在慢慢进军个人桌面系统领域.如果在使用Linux系统的终端时,对其颜色主题不是很满意,该怎么修改颜色的主题呢?今天笔者 ...

  4. C++编程思想重点笔记(上)

    C和C++指针的最重要的区别在于:C++是一种类型要求更强的语言.就void *而言,这一点表现得更加突出.C虽然不允许随便地把一个类型的指针指派给另一个类型,但允许通过void *来实现.例如: b ...

  5. Sixth scrum meeting - 2015/10/31

    概述 今天是周末,我们小组由于之前拖延的比较久,所以今天仍然在努力的开发…… 目前开发已经到了中期阶段,今天遇到了一个问题就是,由于小组的某些同学对git的使用不太熟悉,导致在git push的时候遇 ...

  6. ruby实时查看日志

    (文章是从我的个人主页上粘贴过来的, 大家也可以访问我的主页 www.iwangzheng.com) 在调试代码的时候,把日志文件打开,边操作边调试能很快帮助我们发现系统中存在的问题. $tail r ...

  7. PHP网页数据正则采集

    $url ="https://********"; $contents = file_get_contents($url); //抓取页面数据 //如果出现中文乱码使用下面代码 / ...

  8. Android程序启动程序与页面的跳转

    package login; import com.example.login.R; import android.app.Activity; import android.content.Inten ...

  9. HDOJ 2955 Robberies (01背包)

    10397780 2014-03-26 00:13:51 Accepted 2955 46MS 480K 676 B C++ 泽泽 http://acm.hdu.edu.cn/showproblem. ...

  10. Mybatis 动态sql标签

    1.动态SQL片段 通过SQL片段达到代码复用         <!-- 动态条件分页查询 -->          <sql id="sql_count"> ...