这一次写的内容是黄金豆小游戏,由于现在偏重写服务器端。对于算法层面其实涉及不多,更多偏于工程上的架构。

总而言之本次作业的服务器核心是用web.py所写,而且为了方便其他用户写客户端,架构非常简单。

具体而言,首先从接口上来说,服务器只涉及到两个表单操作,注册表单和提交表单,注册也同样可以在网页上进行。

由于是测试服务器通讯的,为了方便客户端调试很多细节与题设有所不同,但修改起来非常简单。

注册模块:

   注册需要提交用户名和密码{[username],[password]}

   1.只有在游戏开始前可以进行注册。

   2.注册失败,会返回-1.

     3.注册成功,会返回0.

     4.注册信息会录入注册表中。

提交模块:

     提交模式需要提交用户名和密码以及给的数字{[username],[password],[nut]}

     1.如果下一轮还未开始用户已经提交,便会等待。

     2.如果用户提交后,本轮还未结束,依然等待直到,结束,返回G值

     3.若登录失败,则返回-1(测试完毕后,若为按时提交也返回-1)

游戏模块:

     1.会等待本轮用户提交完毕才会给出G值(测试完毕后改为,若1秒之后仍未提交,直接失败)。

     2.分数策略如提所述。

即服务器与客户端同步,以免发生一开始客户端设计的缺陷引发客户端一次都无法返回有意义的结果。

正式发布时,服务器将不等待客户端的同步。

画图由一个monitor实时返回此时AVG的值。值得一提的是,由于web.py对于线程数有限制(10),我们修改了web.py source里的代码,把THREAD数目放宽才使得该项目成为可能。

测试程序:

开了30个线程测了50组数据,图像反应正常。

#coding=utf-8
import wx
from matplotlib.figure import Figure
import matplotlib.font_manager as font_manager
import numpy as np
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import web
import datetime
import time
from web import form
import matplotlib.pyplot as plt
import thread
web.config.debug = False
import sys
succ = '0'
fail = '1'
PLAYERNUM = 30
reload(sys)
sys.setdefaultencoding("utf-8")
class Game():
nowtime = 0
paticipate_num = 0
active_num = 0
total =0.0
avg = 0.0
score = {}
times = {}
number = {}
def __init__(self):
pass
G = Game()
x = []
y = []
urls=('/','Index',
'/reg','Reg',
'/login','Login',
'/logout','Logout',
'/showusers','Showusers',
)
app=web.application(urls,globals())
render = web.template.render('templates',base='base')
session = web.session.Session(app, web.session.DiskStore('sessions'),initializer={'login':0,'id':'0'})

db1=web.database(dbn='mysql',
db='golden',
user='root',
pw='199089455',
port=3306,)

###首页
class Index:
def GET(self):
#return web.ctx.ip
return datetime.datetime.now().strftime('%Y%m%d%H%M%S%S')

###注册页
class Reg:
vusername= form.regexp(r".{3,20}$", '用户名长度为3-20位')
vpass = form.regexp(r".{6,20}$", '密码长度为6-20位')
vemail = form.regexp(r".*@.*", "must be a valid email address")
regForm=web.form.Form(
form.Textbox('username',vusername,description=u'用户名'),
form.Password("password",vpass,description=u"密码"),
form.Password("password2", description=u"确认密码"),
form.Button(u"马上注册", type="submit", description="submit"),
validators = [
form.Validator("两次输入的密码不一致", lambda i: i.password == i.password2)]
)

def GET(self):
return render.reg(self.regForm,u'注册成功后自动跳往登陆界面')
def POST(self):
formdata=web.input();
username=web.net.websafe(formdata.username)
password=web.net.websafe(formdata.password)
regdate=datetime.datetime.now().strftime('%Y%m%d%H%M%S')
if not self.regForm.validates() and G.paticipate_num>=PLAYERNUM:
return fail
#判断用户名是否存在:
else:
if len(getUserByUserName(username))>0:
#return render.reg(self.regForm,u'用户名已存在')
return fail
else:
ret=addUser(username,password,regdate)
if ret==0:
#return u'注册成功'
G.paticipate_num+=1
G.score [username]= 0
G.times [username]= 0
G.number[username]= 0
return succ
else:
return fail

###登陆页面
class Login:
loginForm=form.Form(form.Textbox('username',description=u'用户名'),
form.Password("password",description=u"密码"),
form.Button(u"马上登陆", type="submit", description="submit"),)
def GET(self):
if logged():
return 'you are logged '+session.id
else:
return render.login(self.loginForm)
def POST(self):
postdata=web.input()
username=web.net.websafe(postdata.username)
password=web.net.websafe(postdata.password)
nut=float(web.net.websafe(postdata.nut))
rslist=getUserByUserName(username)

if len(rslist)==0:
#return render.login(self.loginForm,'用户名不存在')
return
else:
if password==rslist[0].password:
while G.times[username]>=G.nowtime:
time.sleep(0.001)
G.times[username]+=1
G.number[username]=nut
G.active_num+=1
G.total+=nut
while G.times[username]==G.nowtime:
time.sleep(0.001)
return G.avg*0.618
else:
#return render.login(self.loginForm,'用户名及密码不匹配')
return fail

###注销登陆页面
class Logout:
def GET(self):
session.login=0
session.kill()
return 'you have logged out!'

###显示用户列表
class Showusers:
def GET(self):
if logged():
usersList=getUsers()
return render.users(usersList)
else:
return 'please log in first!'

###判断用户是否登陆
def logged():
if session.login==1:
return True
else:
return False

################################################ 数据库操作部分 begin ############################################################

#增加用户
def addUser(username,password,regdate):
ret=db1.insert('t_user',username=username ,password=password,regdate=regdate)
return ret

#获取用户列表
def getUsers(orderby='regdate'):
rs=db1.select('t_user',order=orderby)
rslist=[]
for r in rs:
rslist.append(r)
return rslist

#根据用户名查询用户信息
def getUserByUserName(username):
rs=db1.select('t_user',where='username="'+username+'"')
rslist=[]
for r in rs:
rslist.append(r)
return rslist

################################################ 数据库操作部分 end ############################################################

################################################ 游戏线程 begin ############################################################

def Gamestart():
while (G.paticipate_num!= PLAYERNUM):
time.sleep(0.1)
if G.paticipate_num== PLAYERNUM:
for G.nowtime in range(1,51):
G.total = 0.0
G.active_num = 0
while G.active_num<G.paticipate_num:
time.sleep(0.1)
print G.nowtime
G.avg = G.total/PLAYERNUM
winner = ""
minsqr = 10000.0
loser = ""
maxsqr = -10000.0
for each in G.number:
if (G.number[each]-G.avg*0.618)*(G.number[each]-G.avg*0.618)<minsqr:
minsqr = (G.number[each]-G.avg*0.618)*(G.number[each]-G.avg*0.618)
winner = each
if (G.number[each]-G.avg*0.618)*(G.number[each]-G.avg*0.618)>maxsqr:
maxsqr = (G.number[each]-G.avg*0.618)*(G.number[each]-G.avg*0.618)
loser = each
G.score[winner] += PLAYERNUM
G.score[loser] -= 2
x.append(G.nowtime)
y.append(G.avg)
G.nowtime=51

################################################ 游戏线程 end ############################################################
POINTS = 300
################################################ 绘图部分 begin ############################################################
class PlotFigure(wx.Frame):
"""Matplotlib wxFrame with animation effect"""
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, title="Monitor", size=(600, 400))
# Matplotlib Figure
self.fig = Figure((6, 4), 100)
# bind the Figure to the backend specific canvas
self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
# add a subplot
self.ax = self.fig.add_subplot(111)
# limit the X and Y axes dimensions
self.ax.set_ylim([0, 100])
self.ax.set_xlim([0, POINTS])

self.ax.set_autoscale_on(False)
self.ax.set_xticks([])
# we want a tick every 10 point on Y (101 is to have 10
self.ax.set_yticks(range(0, 101, 10))
# disable autoscale, since we don't want the Axes to ad
# draw a grid (it will be only for Y)
self.ax.grid(True)
# generates first "empty" plots
self.user = [None] * POINTS
self.l_user,=self.ax.plot(range(POINTS),self.user,label='AVG')

# add the legend
self.ax.legend(loc='upper center',
ncol=4,
prop=font_manager.FontProperties(size=10))
# force a draw on the canvas()
# trick to show the grid and the legend
self.canvas.draw()
# save the clean background - everything but the line
# is drawn and saved in the pixel buffer background
self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
# bind events coming from timer with id = TIMER_ID
# to the onTimer callback function
wx.EVT_TIMER(self, TIMER_ID, self.onTimer)

def onTimer(self, evt):
"""callback function for timer events"""
# restore the clean background, saved at the beginning
self.canvas.restore_region(self.bg)
# update the data
temp = G.avg
self.user = self.user[1:] + [temp]
# update the plot
self.l_user.set_ydata(self.user)
# just draw the "animated" objects
self.ax.draw_artist(self.l_user)# It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)
self.canvas.blit(self.ax.bbox)
def __del__( self ):
t.Stop()
########################################################################################################################
TIMER_ID = wx.NewId()
if __name__=="__main__":
thread.start_new_thread(Gamestart,())
thread.start_new_thread(app.run,())
app1 = wx.PySimpleApp()
frame = PlotFigure()
t = wx.Timer(frame, TIMER_ID)
t.Start(50)
frame.Show()
app1.MainLoop()

work5的更多相关文章

  1. python - work5 - 类与对象 - 拓展题

    ''' 5:购物车类,包含的功能如下,请自行设计这个类以及类里面的方法:1)用户输入工资后,打印商品列表(商品列表自行设计展示模式)2)允许用户根据商品编号去选择商品3)用户选择商品后,检查余额是否足 ...

  2. python - work5 - 类与对象

    # -*- coding:utf-8 -*- '''@project: jiaxy@author: Jimmy@file: work_20181119.py@ide: PyCharm Communit ...

  3. Node.js显示页面

    首先我们先要下载并安装Nodejs,然后进入Node.js中安装supervisor, npm -g install supervisor -g表示全局模式 (无论windows哪一个用户登陆都可以使 ...

  4. 4月10日java上机任务

    1. 一维数组的创建和遍历. 声明并创建存放4个人考试成绩的一维数组,并使用for循环遍历数组并打印分数.要求: (1)    首先按“顺序”遍历,即打印顺序为:从第一个人到第四个人: (2)    ...

  5. BM算法学习笔记

    一种nb算法,可以求出数列的递推式. 具体过程是这样的. 我们先假设它有一个递推式,然后按位去算他的值. ;j<now.size();++j)(delta[i]+=1ll*now[j]*f[i- ...

  6. 团体程序设计天梯赛(CCCC) L3019 代码排版 方法与编译原理密切相关,只有一个测试点段错误

    团体程序设计天梯赛代码.体现代码技巧,比赛技巧.  https://github.com/congmingyige/cccc_code

  7. Java第一次实训

    package com.wsy.work; public class JudgeNumber { public static void main(String[] args) { int a = 5; ...

  8. c++ 条件变量

    .条件变量创建 静态创建:pthread_cond_t cond=PTHREAD_COND_INITIALIZER; 动态创建:pthread_cond _t cond; pthread_cond_i ...

  9. 2018 ACM 网络选拔赛 北京赛区

    A Saving Tang Monk II #include <bits/stdc++.h> using namespace std; ; struct node { int x,y,z, ...

随机推荐

  1. 安卓开发44:解决 INSTALL_FAILED_UID_CHANGED 等问题

    apk无法卸载,一般可以下面的方法试一下: 1. 删除/data/app/(filename) 文件夹下的apk包 2. 删除/system/app/(filename) 文件夹下的apk包 3. 将 ...

  2. 车牌识别LPR(七)-- 字符特征

    第七篇:字符特征 选择的字符特征应该满足以下条件: (1)选取的字符特征具有较强的鲁棒性,不受字符变形.弯曲等影响. (2)两个字符的字符特征不能完全相同,但部分相同是允许的,即选择的字符特征是唯一的 ...

  3. sql 存储过程 循环使用

    USE [clab] GO /****** Object: StoredProcedure [dbo].[sp_bd_getResultByEcd] Script Date: 08/06/2014 1 ...

  4. 用git difff 生成补丁

    http://stackoverflow.com/questions/1191282/how-to-see-the-changes-between-two-commits-without-commit ...

  5. Android Touch事件分发机制

    参考:http://blog.csdn.net/xiaanming/article/details/21696315 参考:http://blog.csdn.net/wangjinyu501/arti ...

  6. 代码实现获取log日志和logcat使用方法

    代码实现获取log日志new Thread(new Runnable() {                        @Override                        publi ...

  7. android中给TextView或者Button的文字添加阴影效果

    1在代码中添加文字阴影 TextView 有一个方法 /**      * Gives the text a shadow of the specified radius and color, the ...

  8. Qt之自定义界面(窗体缩放)

    简述 通过前两节内容,我们实现了自定义窗体的移动,以及自定义标题栏-用来显示窗体的图标.标题,以及控制窗体最小化.最大化.关闭. 在这之后,我们还缺少窗体的缩放-当鼠标移动到窗体的边框-左.上.右.下 ...

  9. UVa 12716 (GCD == XOR) GCD XOR

    题意: 问整数n以内,有多少对整数a.b满足(1≤b≤a)且gcd(a, b) = xor(a, b) 分析: gcd和xor看起来风马牛不相及的运算,居然有一个比较"神奇"的结论 ...

  10. GridView表头排序方法设置

    1.效果图 2.前台代码 说明:红色代码为核心代码 <asp:GridView ID="gvData" runat="server" AutoGenera ...