现代程序设计 homework-05
本次作业要求设计服务器和客户端,由于之前对网络编程是一窍不通,上上节课听宗学长讲述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来存每轮的最后一名.
每次锦标赛事先规定好是采取下列哪一个模式:
每个客户程序必须提交一个有理数。
每个客户程序必须提交两个有理数。 (任何一个数字最接近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的更多相关文章
- 标准C程序设计七---05
Linux应用 编程深入 语言编程 标准C程序设计七---经典C11程序设计 以下内容为阅读: <标准C程序设计>(第7版) 作者 ...
- 现代程序设计homework——04
题目: 详见:http://www.cnblogs.com/xinz/p/3341551.html 题目本身确实很难,“很难想到一个比较优雅的算法”,这是一个老师请来专门讲解这道题的大牛的原话.确实, ...
- 软工+C(9): 助教指南,持续更新...
上一篇:提问与回复 下一篇:从命令行开始逐步培养编程能力(Java) 目录: ** 0x00 Handshake ** 0x01 点评 ** 0x02 评分 ** 0x03 知识储备 ** 0x04 ...
- 20172319 2018.03.27-04.05 《Java程序设计》第4周学习总结
20172319 2018.03.27-04.05 <Java程序设计>第4周学习总结 教材学习内容总结 第四章 编写类 类与对象的回顾:对象是有状态的,状态由对象的属性值确定.属性由类中 ...
- 20145219 《Java程序设计》第05周学习总结
20145219 <Java程序设计>第05周学习总结 教材学习内容总结 try.catch 1.求平均数程序示例 import java.util.Scanner; public cla ...
- C语言程序设计|05
问题 回答 这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-4/homework/9772 我在 ...
- 20145218 《Java程序设计》第05次实验报告
北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1452 指导教师:娄嘉鹏 实验名称:Java网络编程及安全 一.实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使 ...
- # 20145210 《Java程序设计》第05周学习总结
教材学习内容总结 第八章 异常处理 8.1语法与继承架构 •使用 try.catch •Java中所有信息都会被打包为对象,如果愿意,可以尝试(try)捕捉(catch)代表错误的对象后做一些处理 • ...
- 2017"百度之星"程序设计大赛 - 复赛 01,03,05
Arithmetic of Bomb Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- 读书笔记(05) - 事件 - JavaScript高级程序设计
HTML依托于JavaScript来实现用户与WEB网页之间的动态交互,接收用户操作并做出相应的反馈,而事件在此间则充当桥梁的重要角色. 日常开发中,经常会为某个元素绑定一个事件,编写相应的业务逻辑, ...
随机推荐
- MinGW GCC下sleep()函数问题
在MinGW GCC下编译带sleep()函数的测试程序,不管是包含了unistd.h头文件,还是stdio.h.stdlib.h头文件,就是找不到该函数的定义!在linux下,sleep()函数的头 ...
- sdut 2840 Best string Orz~ (dp)
题目 题意:有n1个o, n2个r, n3个z, n4个~, 求有多少种组合使 组合出来的字符串的任意前缀都满足 o的个数>=r的个数, r的个数>=z的个数 …………………… 思路:递推 ...
- codeforces 235 div2 C Team
题目:http://codeforces.com/contest/401/problem/C 题意:n个0,m个1,求没有00或111的情况. 这么简单的题..... 做题的时候脑残了...,今天,贴 ...
- 關於NPOI的一點補充和示例
最近看到很多人分享NPOI的用法. 但是很多都不是完整示例或者並沒有實戰效果. 剛好最近有個VB.NET的項目有升級原有的oledb select sheet$的做法. 很明顯,NPOI有更好的穩定性 ...
- LA 2797 (平面直线图PLSG) Monster Trap
题意: 平面上有n条线段,一次给出这n条线段的两个端点的坐标.问怪兽能否从坐标原点逃到无穷远处.(两直线最多有一个交点,且没有三线共交点的情况) 分析: 首先说明一下线段的规范相交:就是交点唯一而且在 ...
- (转)c语言_链表实例讲解(两个经典例子)
建立一个学生成绩的线性链表,对其实现插入,删除,输出,最后销毁. #include <stdio.h>#include <stdlib.h> struct grade { ...
- ssl选购
上机实践,参考了: http://www.lovelucy.info/nginx-ssl-certificate-https-website.html http://nginx.org/cn/docs ...
- 【C#学习笔记】类型转换
using System; namespace ConsoleApplication { class Program { static void Main(string[] args) { " ...
- RTSP协议学习笔记
一. RTSP协议概述 RTSP(Real-Time Stream Protocol )是一种基于文本的应用层协议,在语法及一些消息参数等方面,RTSP协议与HTTP协议类似. RTSP ...
- VS2013密匙
在网上找到的,亲测有用: BWG7X-J98B3-W34RT-33B3R-JVYW9