本节作业:

熟练使用类和模块,写一个交互性强、有冲突的程序。

故本次写了一个文字回合制的PK游戏,系统主程序为根目录下的:game_menu.py

1. 系统功能模块:

第六天的作业:文字游戏程序是在python3.4环境下开发,在python2.7环境下大同小异,主要功能模块如下图:

2. 系统目录结构:

程序采用分层的方式编写,包括系统配置conf、数据库访问层database、业务逻辑层modules,业务处理主程序game_menu.py,主要分类如下图:

3.应用知识点:

a) 类的使用

b) 文件的读写操作

c) 系统模块、自定义模块的操作

d) 日志模块的使用

4.程序流程图如下:

5.程序代码如下

5.1 主程序game_menu.py:

#_*_ coding=utf-8 _*_

'''
Created on 2016年3月15日
@author: 王凯
游戏主程序文件
''' import os,sys,random,time
from datetime import date,datetime
from conf import setting,menu
from modules import common,role,skill,report
from database import dbapi ###角色属性和技能显示函数###
def role_skill_show():
'''
当主菜单选择1时,进行角色的属性和技能查看
:return: 没有返回值
'''
show_flag = False
while not show_flag: ###输出角色默认的菜单,有战士,弓箭手,法师###
print(menu.role_default_menu.format(today, common.numtochr(weekoftoday))) ###选择角色的编号、分别调用战士,弓箭手,法师三个角色类###
role_choose = common.input_msg_choose("请选择查看角色[1-3]: ", ["", "", "","b"]).strip()
if role_choose == '':
roleadj = role.zhanshi(role_choose)
elif role_choose == '':
roleadj = role.gongjianshou(role_choose)
elif role_choose == '':
roleadj = role.fashi(role_choose)
else:
show_flag = True
continue ###输出角色的说明介绍及初始技能###
common.show_message('角色说明如下:', "NOTICE")
roleadj.role_instruction() ###输出角色的三个攻击技能###
common.show_message('【%s】技能如下:' % (roleadj.role), "NOTICE")
skill.skill(role_choose).print_skill_list() ###角色选择###
def choose_role(vs_type,role_choose,role_list):
"""
角色选择函数
:param vs_type 指定是挑战方,还是应战方
:param role_choose: 角色选择输入的字符
:return:role_list 角色名字,角色,角色的血量,角色名字列表
""" role_info = {}
###判断输入值是否为b,如果是则退出###
if role_choose == "b":
sys.exit()
else:
###角色名字列表赋值###
name_list = role_list[role_choose]
###角色类的实例化###
roleadj = role.role(role_choose) ###选择角色各自的名字
vs_name = common.input_msg_choose("请选择%s名字%s : " % (vs_type,name_list), name_list).strip() ###角色初始技能是否开启###
init_skill_info = (roleadj.init_skill,roleadj.init_chance_rate,roleadj.init_harm_rate)
init_skill_flag = common.input_msg_choose("初始技能【%s : %s%% 机率减少伤害 %s%%】,是否开启(y/n)" % init_skill_info, ['y','n']).strip()
###调用role类中的初始技能开关函数###
init_skill_result = roleadj.init_skill_choose(init_skill_flag)
if init_skill_result:
common.show_message('已正常开启初始技能【%s : %s%% 机率减少伤害 %s%%】' % init_skill_info, "INFORMATION")
else:
common.show_message('禁止启用初始技能【%s】' % roleadj.init_skill, "NOTICE") ###挑战和守擂双方在选择同一种角色时,强制选择不同的二个名字###
name_list.remove(vs_name) ###输出角色的技能###
common.show_message('%s【%s】技能如下:' % (vs_type,roleadj.role), "NOTICE")
skill.skill(role_choose).print_skill_list() ###定义角色的信息字典,方便return###
role_info = {
"name" : vs_name,
"role" : roleadj.role,
"life" : roleadj.life,
"init_skill_flag" : roleadj.init_skill_flag,
"init_skill" : roleadj.init_skill,
"init_chance_rate" : roleadj.init_chance_rate,
"init_harm_rate" : roleadj.init_harm_rate
} return(role_info,name_list) ###挑战和守擂双方PK函数###
def role_vs(offensive_info,defensive_info):
'''
挑战和守擂双方PK函数
:param offensive_info: 挑战方的信息字典
:param defensive_info: 防守方的信息字典
:return: 没有返回值
''' ###获取challage的信息###
offensive_choose = offensive_info['choose']
offensive_name = offensive_info['name']
offensive_role = offensive_info['role']
offensive_life = offensive_info['life']
offensive_init_skill_flag = offensive_info['init_skill_flag']
offensive_init_skill = offensive_info['init_skill']
offensive_init_chance_rate = offensive_info['init_chance_rate']
offensive_init_harm_rate = offensive_info['init_harm_rate'] ###获取response的信息###
defensive_choose = defensive_info['choose']
defensive_name = defensive_info['name']
defensive_role = defensive_info['role']
defensive_life = defensive_info['life']
defensive_init_skill_flag = defensive_info['init_skill_flag']
defensive_init_skill = defensive_info['init_skill']
defensive_init_chance_rate = defensive_info['init_chance_rate']
defensive_init_harm_rate = defensive_info['init_harm_rate'] ###PK双方的技能实例化和获取技能编号列表###
offensive_skill_obj = skill.skill(offensive_choose)
offensive_skill_list = offensive_skill_obj.skill_id_list()
defensive_skill_obj = skill.skill(defensive_choose)
defensive_skill_list = defensive_skill_obj.skill_id_list() i = 1
flag = False
common.show_message('双方准备,对战开始',"INFO") ###自动对战的开关###
auto_flag = common.input_msg_choose("是否自动对战(y/n):",['y','n']).strip()
while not flag:
###VS对方菜单,显示对战双方的角色,名字和血量###
print(menu.vs_menu.format(offensive_name,offensive_role,offensive_life,defensive_name,defensive_role,defensive_life))
common.show_message('第{0}回合'.format(i),"NOTICE") ###如果挑战方血量大于0,挑战方开始选择技能###
if offensive_life > 0:
if auto_flag == "y":
###自动对战开启,在技能列表中随机生成一个数字###
offensive_skill_id = str(random.randint(int(offensive_skill_list[0]),int(offensive_skill_list[-1])))
else:
###手工对战时,输入技能编号###
offensive_skill_id = common.input_msg_choose("请挑战方选择技能编号【%s]: " % offensive_skill_list, offensive_skill_list).strip() ###调用技能伤害函数,并计算双方的剩余血量###
(offensive_life,defensive_life) = offensive_skill_obj.skill_harm(offensive_skill_id,offensive_info,defensive_info)
offensive_info['life'] = offensive_life
defensive_info['life'] = defensive_life
else:
common.show_message('挑战方【%s】已经挂了,应战方【%s】守擂成功' % (offensive_name,defensive_name),"ERROR")
###挑战方挂了,进行PK记录回写报表文件###
report.record_input_file(offensive_role,offensive_name,defensive_role,defensive_name,True)
###挑战方挂了,进行PK记录回写日志文件###
common.log_input_file(offensive_name,defensive_name,True) ###PK结束,退出本次循环###
flag = True
continue ###守擂方血量大于0,开始选择技能###
if defensive_life > 0:
if auto_flag == "y":
###自动对战开启,在技能列表中随机生成一个数字###
defensive_skill_id = str(random.randint(int(defensive_skill_list[0]),int(defensive_skill_list[-1])))
else:
###手工对战时,输入技能编号###
defensive_skill_id = common.input_msg_choose("请应战方选择技能编号【%s]: " % defensive_skill_list, defensive_skill_list).strip() ###调用技能伤害函数,并计算双方的剩余血量###
(defensive_life,offensive_life) = defensive_skill_obj.skill_harm(defensive_skill_id,defensive_info,offensive_info)
defensive_info['life'] = defensive_life
offensive_info['life'] = offensive_life
else:
common.show_message('挑战方【%s】成功获胜,应战方【%s】已经升天了' % (offensive_name,defensive_name),"ERROR")
###守擂方挂了,进行PK记录回写报表文件###
report.record_input_file(offensive_role,offensive_name,defensive_role,defensive_name,False)
###挑战方挂了,进行PK记录回写日志文件###
common.log_input_file(offensive_name,defensive_name,False) ###PK结束,退出本次循环###
flag = True
continue time.sleep(2)
i += 1 ###PK场菜单函数###
def battlefield(role_name_list):
'''
在进入PK场后,选择双方的角色###
:param role_name_list: 角色名字列表
:return: 没有返回值
''' ###进入PK场,输出角色选择菜单###
print(menu.role_default_menu.format(today, common.numtochr(weekoftoday))) ###初始化PK双方的角色信息字典###
challenge_role_info = {}
response_role_info = {} ###选择挑战方角色、名称及初始技能###
challenge_choose = common.input_msg_choose("请选择挑战方角色[1-3]: ", ["", "", "","b"]).strip()
(challenge_role_info,role_name_list[challenge_choose]) = choose_role('挑战方',challenge_choose,role_name_list)
challenge_role_info['choose'] = challenge_choose ###选择应战方角色、名称及初始技能###
response_choose = common.input_msg_choose("请选择应战方角色[1-3]: ", ["", "", "","b"]).strip()
(response_role_info,role_name_list[response_choose]) = choose_role('应战方',response_choose,role_name_list)
response_role_info['choose'] = response_choose
response_role_info['life'] += 100 ###调用role_vs,进行对战环节###
role_vs(challenge_role_info,response_role_info) ###PK战绩排序函数###
def pk_result_sorted(sort_list,dates,value=0):
'''
对PK战绩进行不同的排序
:param sort_list 角色名字列表
:param dates 起始和结束日期
:param value 指定排序的值
:return 无返回值
''' ###调用PK记录报表,获取所有角色名字的信息###
all_user_pk_result = {}
user_pk_list = report.print_vs_all_report(sort_list,dates,value)
all_user_pk_result = {'startdate':dates['start'],
'enddate':dates['end'],
'vs_record':"\n".join(user_pk_list)
}
###输出所有角色名字的PK记录并进行排序###
common.show_message(menu.all_vs_history.format(**all_user_pk_result),"NOTICE") ###主程序开始,显示主菜单###
if __name__ == "__main__": ###定义并赋值当前的日期和星期几的显示###
today = datetime.now().strftime("%Y-%m-%d")
weekoftoday = date.weekday(datetime.now()) ### -------- 开始主程序 ---------###
flag = False
while not flag: ###定义三类角色的名字列表,战士,弓箭手,法师各有二个用户###
_role_list = { "" : ['za','zb'],
"" : ['ga','gb'],
"" : ['fa','fb']
} ###显示游戏的主菜单界面,分别有角色,PK场,战绩榜###
print(menu.main_menu.format(today, common.numtochr(weekoftoday)))
choose = common.input_msg_choose("选择功能编号[0-3]: ", ["", "", "", ""]).strip() ###0、退出游戏###
if choose == "":
flag = True
continue ###1、角色及技能介绍###
if choose == "":
role_skill_show() ###调用角色信息显示函数### ###2、PK场###
if choose == "":
battlefield(_role_list) ###调用PK场函数### ###3、战绩榜###
if choose == "": ###定义初始的用户列表和用户选择菜单###
_name_list = ['za','zb','ga','gb','fa','fb']
_name_add_list = ['za','zb','ga','gb','fa','fb','b'] ###调用report函数的起始和结束日期输入函数###
date_dict = report.get_date()
###调用PK记录的排序函数,默认是按用户排序的###
pk_result_sorted(_name_list,date_dict) pk_flag = False
while not pk_flag: ###输入指定排序的方式编号###
sort_input = common.input_msg_choose("输入战绩排序编号[0-3]:", ["","","",""]).strip()
###选择0时,结束排序,进行用户查询环节###
if sort_input != "":
###根据输入的排序编号进行具体排序###
pk_result_sorted(_name_list,date_dict,int(sort_input))
continue query_flag = False
while not query_flag:
###输入具体的角色名字,来查询具体的PK记录###
user_name = common.input_msg_choose("输入用户【%s】,返回(b): " % _name_list,_name_add_list).strip()
###当输入b时,返回到主菜单###
if user_name == 'b':
pk_flag = True
query_flag = True
continue
else:
###当选择具体角色名字时,生成并输出自己的PKu结果和具体记录###
user_pk_result = dict()
user_pk_result = report.print_vs_report(user_name,date_dict)
common.show_message(menu.role_vs_history.format(**user_pk_result),"NOTICE")

game_menu

5.2 配置文件包conf:

5.2.1 参数配置文件setting.py

#_*_ coding=utf-8 _*_

'''
Created on 2016年3月15日
@author: 王凯
定义基本的变量
''' import os,sys ###程序文件主目录###
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
###添加主目录到环境变量###
sys.path.append(BASE_DIR) ###定义角色和技能数据库信息###
DATABASE = dict(engineer="file", dbpath=os.path.join(BASE_DIR, "database"), tables={"role" : "role","skill" : "skill"}) ###日志文件存放路径###
LOG_PATH = os.path.join(BASE_DIR, "log") ###角色初始生命值###
init_hp = 1000

setting

5.2.2 界面显示模板文件menu.py

#_*_ coding=utf-8 _*_

'''
Created on 2016年3月15日
@author: 王凯 该模块用来定义系统的菜单模板
''' # 主程序中的菜单输出信息### main_menu = '''
-------------------------------------------------------------------------
kevin在线游戏
今天 {0} 星期{1}
-------------------------------------------------------------------------
【1】角色介绍 【2】PK场 【3】战绩榜 【0】退出
-------------------------------------------------------------------------
''' ###角色菜单输出信息### role_default_menu = '''
-------------------------------------------------------------------------
角色
今天 {0} 星期{1}
-------------------------------------------------------------------------
【1】战士 【2】弓箭手 【3】法师
返回(b)
-------------------------------------------------------------------------
''' ###对战菜单### vs_menu = '''
-------------------------------------------------------------------------
挑战方:{0}({1}) 应战方:{3}({4})
VS
血量:{2} 血量:{5}
-------------------------------------------------------------------------
''' ###所有用户战榜菜单###
all_vs_history = '''
------------------------------------------------------------------------------
战绩榜 VS时间:{startdate} 至 {enddate}
------------------------------------------------------------------------------
战绩:
用户 挑战次数 挑战成功次数 守擂次数 守擂成功次数 PK次数 PK成功次数
{vs_record}
------------------------------------------------------------------------------
【1】挑战成功次数 【2】守擂成功次数 【3】PK成功次数 【0】用户查询
------------------------------------------------------------------------------
''' ###具体用户的战榜和PK记录信息###
role_vs_history = '''
------------------------------------------------------------------------------
战绩榜 用户:{user} VS时间:{startdate} 至 {enddate}
------------------------------------------------------------------------------
战绩:
挑战【{attack_sum}】次,成功【{attack_ok}】次 | 守擂【{defence_sum}】次,成功【{defence_ok}】次 | PK【{all_sum}】次,成功【{ok_sum}】次 PK战况:
------------------------------------------------------------------------------
对战时间 结果
{vs_record}
'''

menu

5.3 数据库包database:

5.3.1 初始化数据模块db_init.py

#_*_ coding=utf-8 _*_

'''
Created on 2016年3月15日
@author: 王凯
定义角色和技能的信息,并初始化输出到数据库db文件
''' import json,os,sys ###程序文件主目录######程序文件主目录###
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
###添加主目录到环境变量###
sys.path.append(BASE_DIR) ###导入如下三个模块###
from conf import setting
from modules import common
from database import dbapi ###角色列表###
role_list = {
"": {"role": "战士", "init_skill":"守护","init_skill_flag":1,"chance_rate" : 50 , "harm_rate" : 20},
"": {"role": "弓箭手", "init_skill":"闪避","init_skill_flag":1,"chance_rate" : 40 , "harm_rate" : 25},
"": {"role": "法师", "init_skill":"法盾","init_skill_flag":1,"chance_rate" : 30 , "harm_rate" : 40},
} ###角色的技能列表###
role_skill_list = {
"": {"role": "战士", "skill": (
{"id": "", "level": "初级技能", "name": "野蛮冲锋","init_harm": 100, "chance_rate" : 40 , "harm_rate" : 20},
{"id": "", "level": "中级技能", "name": "旋风斩", "init_harm": 150, "chance_rate" : 30 , "harm_rate" : 20},
{"id": "", "level": "高级技能", "name": "百刃斩" ,"init_harm": 200, "chance_rate" : 20 , "harm_rate" : 20},
)},
"": {"role": "弓箭手", "skill": (
{"id": "", "level": "初级技能", "name": "点射","init_harm": 100, "chance_rate" : 40 , "harm_rate" : 20},
{"id": "", "level": "中级技能", "name": "连射", "init_harm": 150, "chance_rate" : 30 , "harm_rate" : 20},
{"id": "", "level": "高级技能", "name": "爆裂箭" ,"init_harm": 200, "chance_rate" : 20 , "harm_rate" : 10},
)},
"": {"role": "法师", "skill": (
{"id": "", "level": "初级技能", "name": "火球术","init_harm": 100, "chance_rate" : 40 , "harm_rate" : 20},
{"id": "", "level": "中级技能", "name": "冰咆哮", "init_harm": 150, "chance_rate" : 30 , "harm_rate" : 20},
{"id": "", "level": "高级技能", "name": "地狱雷光" ,"init_harm": 200, "chance_rate" : 20 , "harm_rate" : 20},
)}
} '''
###初始化角色数据库文件 role.db###
def init_db_role():
_db_file = os.path.join(setting.DATABASE['dbpath'], "role.db")
with open(_db_file, "w+") as f:
f.write(json.dumps(role_list)) ###初始化角色技能数据库文件 skill.db###
def init_db_skill():
_db_file = os.path.join(setting.DATABASE['dbpath'], "skill.db")
with open(_db_file, "w+") as f:
f.write(json.dumps(role_skill_list)) '''
###初始化角色数据库文件 role.db###
def init_db_role():
_db_file = os.path.join(setting.DATABASE['dbpath'], "role.db")
###调用函数,将角色列表以json的格式写入文件###
dbapi.write_db_json(role_list,_db_file) ###初始化角色技能数据库文件 skill.db###
def init_db_skill():
_db_file = os.path.join(setting.DATABASE['dbpath'], "skill.db")
###调用函数,将角色技能列表以json的格式写入文件###
dbapi.write_db_json(role_skill_list,_db_file) ###初始化技能数据表###
def init_database():
tables = list(setting.DATABASE['tables'].values()) ###数据表名称列表###
database = setting.DATABASE['dbpath'] ###数据表存放路径### for _table in tables:
###数据库文件存在判断###
if not os.path.exists(os.path.join(database, "{0}.db".format(_table))):
print("Table {0}.db create successfull".format(_table))
###通过反射初始化数据表###
if hasattr(sys.modules[__name__], "init_db_{0}".format(_table)):
init_func = getattr(sys.modules[__name__], "init_db_{0}".format(_table))
init_func()
else:
###如果不存在,则输出错误日志###
common.write_log("init table {0} failed,no function init_db_{0} found".format(_table),"error") ###主程序开始,调用初始化函数,生成数据库文件###
if __name__ == "__main__":
init_database()

db_init

5.3.2 数据访问层模块dbapi.py

#_*_ coding=utf-8 _*_

'''
Created on 2016年3月15日
@author: 王凯 数据库访问层:
1 提供从数据文件、报表文件中读取数据的接口
2 将数据写入到数据文件的接口
''' import os,sys,json
from conf import setting
from modules.common import write_log ###追加信息到指定文件###
def append_db_json(contant, filename):
"""
将信息以 json 格式写入数据表文件(追加)
:param contant: 要写入的 json 格式内容
:param filename: 要写入的数据表文件名
:return: 无返回
"""
try:
with open(filename, 'a+') as fa:
fa.write(json.dumps(contant))
fa.write("\n")
except Exception as e:
write_log(e,'critical') ###覆盖重写信息到指定文件###
def write_db_json(contant, filename):
"""
将信息以 json 格式写入数据表文件(覆盖)
:param contant: 写入的json数据内容
:param filename: 要写入的文件名
:return: 无返回结果
"""
try:
with open(filename, 'w+') as fw:
fw.write(json.dumps(contant))
except Exception as e:
write_log(e,'critical') ###从指定数据库文件中读取数据###
def load_data_from_db(tabename):
"""
从指定的数据表中获取所有数据,通过 json 方式将数据返回
:param tabename: 数据文件名
:return: 返回数据库文件信息
"""
try:
with open(tabename, 'r+') as f:
return json.load(f)
except Exception as e:
write_log(e,'critical') ###从VS报表中读取指定用户的PK记录###
def load_vs_report(startdate, enddate,user=''):
"""
查找报表记录中的指定用户的PK记录,将结果存入到列表中
:param user: 角色用户名
:param startdate: 开始日期
:param enddate: 结束日期
:return: 返回用户的PK记录
""" ###指定报表的文件名###
_file = os.path.join(setting.LOG_PATH, "vs_report")
result = list() try:
with open(_file, "r") as f:
for line in f:
_record = json.loads(line) ###指定输入用户信息是否为空###
if user:
###判断用户是否存在###
if _record['attack_name'] == user or _record['defence_name'] == user:
###通过输入的起始和结束日期对报表记录进行匹配,是则追加到返回列表中###
if _record["time"] >= startdate and _record["time"] <= enddate:
result.append(_record)
###输入用户为空,则追加所有用户记录到返回列表中###
else:
if _record["time"] >= startdate and _record["time"] <= enddate:
result.append(_record) return result
###执行异常,则输出到错误日志文件###
except Exception as e:
write_log("dbapi > load_vs_report > {0}".format(e),"critical")

dbapi

5.3.3 数据文件role.db

{"": {"init_skill": "\u6cd5\u76fe", "harm_rate": 40, "chance_rate": 30, "init_skill_flag": 1, "role": "\u6cd5\u5e08"}, "": {"init_skill": "\u5b88\u62a4", "harm_rate": 20, "chance_rate": 50, "init_skill_flag": 1, "role": "\u6218\u58eb"}, "": {"init_skill": "\u95ea\u907f", "harm_rate": 25, "chance_rate": 40, "init_skill_flag": 1, "role": "\u5f13\u7bad\u624b"}}

role.db

5.3.4 数据文件skill.db

{"": {"skill": [{"level": "\u521d\u7ea7\u6280\u80fd", "chance_rate": 40, "id": "", "name": "\u706b\u7403\u672f", "init_harm": 100, "harm_rate": 20}, {"level": "\u4e2d\u7ea7\u6280\u80fd", "chance_rate": 30, "id": "", "name": "\u51b0\u5486\u54ee", "init_harm": 150, "harm_rate": 20}, {"level": "\u9ad8\u7ea7\u6280\u80fd", "chance_rate": 20, "id": "", "name": "\u5730\u72f1\u96f7\u5149", "init_harm": 200, "harm_rate": 20}], "role": "\u6cd5\u5e08"}, "": {"skill": [{"level": "\u521d\u7ea7\u6280\u80fd", "chance_rate": 40, "id": "", "name": "\u91ce\u86ee\u51b2\u950b", "init_harm": 100, "harm_rate": 20}, {"level": "\u4e2d\u7ea7\u6280\u80fd", "chance_rate": 30, "id": "", "name": "\u65cb\u98ce\u65a9", "init_harm": 150, "harm_rate": 20}, {"level": "\u9ad8\u7ea7\u6280\u80fd", "chance_rate": 20, "id": "", "name": "\u767e\u5203\u65a9", "init_harm": 200, "harm_rate": 20}], "role": "\u6218\u58eb"}, "": {"skill": [{"level": "\u521d\u7ea7\u6280\u80fd", "chance_rate": 40, "id": "", "name": "\u70b9\u5c04", "init_harm": 100, "harm_rate": 20}, {"level": "\u4e2d\u7ea7\u6280\u80fd", "chance_rate": 30, "id": "", "name": "\u8fde\u5c04", "init_harm": 150, "harm_rate": 20}, {"level": "\u9ad8\u7ea7\u6280\u80fd", "chance_rate": 20, "id": "", "name": "\u7206\u88c2\u7bad", "init_harm": 200, "harm_rate": 10}], "role": "\u5f13\u7bad\u624b"}}

skill.db

5.4 业务处理包modules:

5.4.1 公共函数模块common.py

#_*_ coding=utf-8 _*_

'''
Created on 2016年3月15日
@author: 王凯
''' import os,sys,logging,random,re
from datetime import datetime,date
from conf import setting ###生成随机数,用于机率判断来是否触发技能###
def random_decide(random_num,cmp_value,cmp_mode='eq'):
"""
生成一个指定范围值之内随机数,并对随机数进行判断
:param random_num:用来定义随机数的范围值
:param cmp_value:定义需要比对的值
:param cmp_flag:如果是gt或lt,则进行大于或小于判断,如果是eq,则为等于判断,默认为eq
:return: 返回True或False
""" ###生成指定范围的随机数
ra = random.randrange(1,random_num) ###根据比较符,输出判断的字符串###
if cmp_mode == 'eq':
express = "{0} == {1}"
elif cmp_mode == 'gt':
express = "{0} > {1}"
elif cmp_mode == 'lt':
express = "{0} < {1}"
else:
show_message('比较模式错误','ERROR')
return False flag = eval(express.format(ra,cmp_value)) ###根据结果,返回正确与否###
if flag:
return True
return False ###根据等级分颜色显示###
def show_message(msg, msgtype):
"""
对print函数进行封装,根据不同类型显示不同颜色
:param msg: 显示的消息体
:param msgtype: 消息类型
:return: 返回格式化过的内容
""" if msgtype == "INFO":
show_msg = "\033[1;34m{0}\033[0m\n".format(msg)
elif msgtype == "INFORMATION":
show_msg = "\033[1;32m{0}\033[0m\n".format(msg)
elif msgtype == "NOTICE":
show_msg = "\033[1;33m{0}\033[0m\n".format(msg)
elif msgtype == "ERROR":
show_msg = "\033[1;31m{0}\033[0m\n".format(msg)
else:
show_msg = "{0}\n".format(msg)
print(show_msg) ###根据等级将异常信息输出到日志文件###
def write_log(content,levelname):
"""
将程序执行过程上中的异常信息记录到日志文件
:param content: 日志信息
:param levelname:日志级别
:return: 无返回,写入文件 game.log
""" ###指定日志文件的路径###
_filename = os.path.join(setting.LOG_PATH, "game.log") ###自定义日志的格式和等级###
logging.basicConfig(level=logging.INFO,
encoding = "UTF-8",
format='%(asctime)s %(levelname)s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
filename=_filename,
filemode='a+')
if levelname == 'debug':
logging.debug(content)
elif levelname == 'info':
logging.info(content)
elif levelname == 'warning':
logging.warning(content)
elif levelname == 'error':
logging.error(content)
elif levelname == 'critical':
logging.critical(content)
else:
show_message('输入错误',"ERROR") ###根据等级将异常信息输出到日志文件###
def write_file(content,levelname,file_name):
"""
将程序执行过程上中的异常信息记录到指定日志文件
:param content: 日志信息
:param levelname:日志级别
:return: 无返回,写入文件 game.log
""" ###自定义日志的格式和等级###
logging.basicConfig(level=logging.INFO,
encoding = "UTF-8",
format='%(asctime)s %(levelname)s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
filename = file_name,
filemode='a+')
if levelname == 'debug':
logging.debug(content)
elif levelname == 'info':
logging.info(content)
elif levelname == 'warning':
logging.warning(content)
elif levelname == 'error':
logging.error(content)
elif levelname == 'critical':
logging.critical(content)
else:
show_message('输入错误',"ERROR") ###将PK记录单独的记录到一个VS日志中,并非report###
def log_input_file(attack_name,defence_name,flag=True):
'''
将PK记录单独的记录到一个VS日志
:param attack_name: 日志中的挑战用户
:param defence_name: 日志中的守擂用户
:param flag: 对应挑战是否成功,输出的标志位
:return: 无返回,直接写日志到相应文件
'''
if flag:
info_str = '[{0}] is fail,[{1}] is success'
else:
info_str = '[{0}] is success,[{1}] is fail'
log_info = info_str.format(attack_name,defence_name)
vs_log = os.path.join(setting.LOG_PATH, "vs.log")
write_file(log_info,'info',vs_log) ###将数字星期转换为中文数字###
def numtochr(num_of_weekday):
"""
将数字星期转换为中文数字
:param num_of_weekday: 星期几的数字字符( 0,1,2,3,4,5,6)
:return: 中文 星期几
"""
chrtuple = ('一', '二', '三', '四', '五', '六','日')
num = int(num_of_weekday)
return chrtuple[num] ###获取汉字个数###
def get_chinese_num(uchar):
i = 0
for utext in uchar:
if u'\u4e00' <= utext <= u'\u9fa5':
i += 1
return i ###中英文混合左对齐###
def myljust(str1, width, fillchar = None):
'''
中英文混合左对齐
:param str1: 欲对齐字符串
:param width: 宽度
:param fillchar: 填充字符串
:return: 新的经过左对齐处理的字符串对象
'''
if fillchar == None:
fillchar = ' ' ###将中文转化为gb2312进行计算字符长度,一般一个汉字占2个字节###
length = len(str1.encode('gb2312'))
fill_char_size = width - length if width >= length else 0
return "%s%s" %(str1, fillchar * fill_char_size) ###中英文混合右对齐###
def myrjust(str1, width, fillchar = None):
'''
中英文混合右对齐
:param str1: 欲对齐字符串
:param width: 宽度
:param fillchar: 填充字符串
:return: 新的经过右对齐处理的字符串对象
'''
if fillchar == None:
fillchar = ' ' ###将中文转化为gb2312进行计算字符长度,一般一个汉字占2个字节###
length = len(str1.encode('gb2312'))
fill_char_size = width - length if width >= length else 0
return "%s%s" %(fillchar * fill_char_size, str1) ###中英文混合居中###
def mycenter(str1, width, fillchar = None):
'''
中英文混合居中对齐
:param str1: 欲对齐字符串
:param width: 宽度
:param fillchar: 填充字符串
:return: 新的经过居中对齐处理的字符串对象
'''
if fillchar == None:
fillchar = ' ' ###将中文转化为gb2312进行计算字符长度,一般一个汉字占2个字节###
length = len(str1.encode('gb2312')) fill_char_size = width - length if width >= length else 0
if length%2 == 0:
return "%s%s%s" %(fillchar * (fill_char_size //2), str1, fillchar* (fill_char_size // 2))
else:
return "%s%s%s" %(fillchar * (fill_char_size //2 + 1), str1, fillchar* (fill_char_size // 2)) ###判断input输入的信息是否在指定列表中的公共检测函数###
def input_msg_choose(message, limit_value=list()):
"""
判断input输入的信息是否为空的公共检测函数,为空继续输入,不为空返回输入的信息
:param limit_value: 对输入的值有限制,必须为limit_value的值;ex:["admin","user"]
:param message: input()函数的提示信息
:return: 返回输入的信息
"""
is_null_flag = True
while is_null_flag:
input_value = input(message).strip().lower()
if not input_value:
show_message("输入不能为空!", "ERROR")
continue ###输出q,则退出判断循环###
elif limit_value == 'q':
is_null_flag = False
continue
elif len(limit_value) > 0:
###输入信息不在指定列表中###
if input_value not in limit_value:
show_message("输入的值不正确,请重新输入!", "ERROR")
continue
else:
is_null_flag = False
else:
pass
return input_value ###判断input输入的信息是否为空的公共检测函数###
def input_msg(message):
"""
判断input输入的信息是否为空的公共检测函数,为空继续输入,不为空返回输入的信息
:param message: input()函数的提示信息
:return: 返回输入的信息
"""
is_null_flag = True
while is_null_flag:
input_value = input(message).strip().lower()
if not input_value:
show_message("输入不能为空!", "ERROR")
continue
else:
is_null_flag = False
return input_value ###对输入的日期进行判断是否正确###
def input_date(msg, default_date):
"""
对输入的日期进行判断是否正确 yyyy-mm-dd or yyyy-m-d
:param msg:输入提示信息
:param default_date: 默认日期
:return:返回日期 str类型
"""
check_flag = False
while not check_flag:
strdate = input(msg).strip()
if not strdate:
strdate = default_date try:
date_list = strdate.split("-")
###对输入的日期以-进行分隔,并判断是否是日期数字###
result = date(int(date_list[0]), int(date_list[1]), int(date_list[2]))
check_flag = True
except ValueError:
show_message("输入日期不合法,请重新输入!", "ERROR")
continue
return result.strftime("%Y-%m-%d") ###对列表进行冒泡排序###
def list_sort_by(sort_list,num1,num2):
'''
根据name对列表进行排序
:param sort_list:要排序的列表
:param num1要排序的主列编号
:param num1要排序的次列编号
:return: 排序后的列表
''' ###因输出的列表内容是以多个空格分隔的字符串,故要进行字符串匹配和分隔###
r = re.compile('\s+')
for i in range(len(sort_list)-1):
for j in range(i+1,len(sort_list)): ###对字符串进行正则表达式分隔处理,并对相应的列进行大小比对,对列表进行冒泡操作###
if r.split(sort_list[i])[num1] < r.split(sort_list[j])[num1]:
tmp = sort_list[i]
sort_list[i] = sort_list[j]
sort_list[j] = tmp
###如果排序的主列值相同,则对次列进行大小判断,并对列表进行冒泡操作###
elif r.split(sort_list[i])[num1] == r.split(sort_list[j])[num1]:
if r.split(sort_list[i])[num2] < r.split(sort_list[j])[num2]:
tmp = sort_list[i]
sort_list[i] = sort_list[j]
sort_list[j] = tmp
else:
pass return(sort_list)

common

5.4.2 报表模块report.py

#_*_ coding=utf-8 _*_

'''
Created on 2016年3月15日
@author: 王凯
主要对报表的读取、写入、修改等操作
''' import calendar
import os
from datetime import datetime, timedelta
from datetime import date
from database import dbapi
from conf import menu,setting
from modules import common ###将角色PK的记录写回到指定的报表文件###
def record_input_file(attack_role,attack_name,defence_role,defence_name,flag=True):
'''
将角色PK的记录写回到指定的报表文件
:param attack_role: 挑战方的角色
:param attack_name: 挑战方的名字
:param defence_role: 守擂方的角色
:param defence_name: 守擂方的名字
:param flag: 挑战是否成功的标志位
:return: 没有返回值,直接回写报表文件
''' result = False if flag:
report_str = '【{0}:{1}】挑战失败,【{2}:{3}】守擂成功' else:
report_str = '【{0}:{1}】挑战成功,【{2}:{3}】守擂失败'
result = True report_info = report_str.format(attack_role,attack_name,defence_role,defence_name) ###报表要记录的内容格式###
report_record = {"time": datetime.now().strftime("%Y-%m-%d %H:%M"),
"attack_role": attack_role,
"attack_name": attack_name,
"defence_role": defence_role,
"defence_name": defence_name,
"attack_result": result,
"detail": report_info
} vs_file = os.path.join(setting.LOG_PATH, "vs_report")
dbapi.append_db_json(report_record,vs_file) ###日期输入及判断###
def get_date():
"""
用户输入一个时间段,如果显示报表是要提供开始、结束日期,返回开始,结束时间
:return: 字典格式,{"start":startdate, "end": enddate}
"""
startdate = common.input_date("输入查询开始时间(yyyy-mm-dd)[default:2016-01-01]: ", "2016-01-01")
enddate = common.input_date("输入查询结束时间(yyyy-mm-dd)[default: today]: ", datetime.now().strftime("%Y-%m-%d")) return {"start": startdate, "end": enddate} ###根据具体用户来获取PK的记录###
def print_vs_report(user,date_dict):
"""
根据具体用户来获取PK的记录
:param user: 角色用户的名字
:param date_dict:起始和结束日期的字典
:return: 返回用户的PK结果和记录
""" ###获取到起始和结束日期###
startdate = date_dict["start"]
enddate = date_dict["end"] ###定义PK的信息输出的列表和字典###
msglist = list()
msgdict = dict() ###调用报表加载函数来获取报表记录###
_recordlist = dbapi.load_vs_report(startdate, enddate,user) ###初始化PK记录的初始变量###
attack_sum = 0
attack_ok = 0
defence_sum = 0
defence_ok = 0
ok_sum = 0
all_sum = 0 ###对具体用户的PK记录,来统计挑战、守擂和PK的成功次数和总次数###
for record in _recordlist:
tmpmsg = "{time} {detail}".format(time=record["time"],detail=record['detail'])
msglist.append(tmpmsg) if user == record['attack_name']:
if record['attack_result']:
attack_ok += 1
attack_sum += 1 if user == record['defence_name']:
if not record['attack_result']:
defence_ok += 1
defence_sum += 1 all_sum += 1 ###总的PK成功次数###
ok_sum = attack_ok + defence_ok ###定义返回字典的具体信息###
msgdict = { 'user':user,
'startdate':startdate,
'enddate':enddate,
'attack_sum':attack_sum,
'attack_ok':attack_ok,
'defence_sum':defence_sum,
'defence_ok':defence_ok,
'all_sum':all_sum,
'ok_sum':ok_sum,
'vs_record':"\n".join(msglist)
}
return msgdict ###输出所有用户的PK报表信息###
def print_vs_all_report(user_list,dates,num=0):
"""
输出所有用户的PK报表信息
:param user_list: 角色用户名字列表
:param dates 起始和结束的日期字典
:param num 指定信息的排序编号
:return:
""" ###定义PK的信息输出的列表和字典###
msgdict = dict()
msglist = list() ###对所有角色名字列表进行遍历并格式化输出信息###
for user in user_list:
record_dict = print_vs_report(user,dates)
_user = common.mycenter(str(record_dict['user']),10)
_attack_sum = common.mycenter(str(record_dict['attack_sum']),10)
_attack_ok = common.mycenter(str(record_dict['attack_ok']),10)
_defence_sum = common.mycenter(str(record_dict['defence_sum']),10)
_defence_ok = common.mycenter(str(record_dict['defence_ok']),10)
_all_sum = common.mycenter(str(record_dict['all_sum']),10)
_ok_sum = common.mycenter(str(record_dict['ok_sum']),10) record_list = [_user,_attack_sum,_attack_ok,_defence_sum,_defence_ok,_all_sum,_ok_sum]
record_msg = "{0}{1}{2}{3}{4}{5}{6}".format(*record_list)
msglist.append(record_msg) ###根据输入的排序编号进行相应处理###
if num == 0:
sorted_msglist = msglist
elif num == 1:
sorted_msglist = common.list_sort_by(msglist,3,2)
elif num == 2:
sorted_msglist = common.list_sort_by(msglist,5,4)
elif num == 3:
sorted_msglist = common.list_sort_by(msglist,7,6)
else:
pass return(sorted_msglist)

report

5.4.3 角色类模块role.py

#_*_ coding=utf-8 _*_

'''
Created on 2016年3月15日
@author: 王凯
定义角色的类和三种角色的子类
''' import os
from conf import setting,menu
from modules import common
from database import dbapi class role(object):
'''
定义角色的根类
:param role_num 角色对应的数字编号
:return 没有返回值
''' ###指定角色的数据库文件####
__database = "{0}.db".format(os.path.join(setting.DATABASE['dbpath'], setting.DATABASE["tables"]["role"])) def __init__(self,role_num):
self.life = setting.init_hp ###角色的初始血量### ###定义角色初始化技能参数###
self.role = ''
self.init_skill = ''
self.init_skill_flag = 0
self.init_chance_rate = ''
self.init_harm_rate = '' self.dict_role_list = {} self.role_num = role_num
self.db_load() ###调用执行角色数据库文件的读取和赋值###
self.skill_init() ###角色初始技能的赋值### ###调用执行角色数据库文件的读取,并赋值给dict_role_list###
def db_load(self):
self.dict_role_list = dbapi.load_data_from_db(self.__database) ###角色初始技能的赋值###
def skill_init(self):
self.dict_role = self.dict_role_list[self.role_num]
self.role = self.dict_role["role"]
self.init_skill = self.dict_role["init_skill"]
self.init_chance_rate = self.dict_role["chance_rate"]
self.init_harm_rate = self.dict_role["harm_rate"] ###根据输入的初始技能开关进行赋值###
def init_skill_choose(self,flag):
if flag == "y":
self.init_skill_flag = self.dict_role["init_skill_flag"]
return True
else:
return False ###定义战士角色的子类###
class zhanshi(role):
'''
定义战士角色的类,继承role类
''' def __init__(self,role_num):
super(zhanshi,self).__init__(role_num) ###战士子类的角色介绍函数###
def role_instruction(self):
self.mess = '''
战士介绍:
出身于乡村,依靠出色的才能,光靠一把武器从事佣兵生活的少年。
性格直率,充满正义感,像孩子一样,从来不会掩饰自己的感受。
容易相信别人,虽然偶尔会因此受伤,但很快就会克服伤痛,重新站起来。
是坚韧不拔的热血英雄。
战士具有强大的近战攻击力,一直活跃在战斗的最前方。
强大的力量和充沛的体力让他可以摧毁敌人的一切防御。 初始技能:
【%s】:%s%% 机率减少伤害 %s%%
''' % (self.init_skill,self.init_chance_rate,self.init_harm_rate)
common.show_message(self.mess, "INFORMATION") ###定义弓箭手角色的子类###
class gongjianshou(role):
'''
定义弓箭手角色的类,继承role类
'''
def __init__(self,role_num):
super(gongjianshou,self).__init__(role_num) ###弓箭手子类的角色介绍函数###
def role_instruction(self):
self.mess = '''
弓箭手介绍:
虽然身在外地,但一直固守着自己特有的文化,是天生的弓箭手。
原来是谨慎、善良的和平主义者,为了对抗破坏自然的龙而站出来战斗,是出色的战士。
弓箭手擅长使用弓箭,在后方进行远距离攻击。
凭借快速的移动和多样的远程攻击,使敌人根本无法靠近自己。 初始技能:
【%s】:%s%% 机率减少伤害 %s%%
''' % (self.init_skill,self.init_chance_rate,self.init_harm_rate)
common.show_message(self.mess, "INFORMATION") ###定义法师角色的子类###
class fashi(role):
'''
定义法师角色的类,继承role类
'''
def __init__(self,role_num):
super(fashi,self).__init__(role_num) ###法师子类的角色介绍函数###
def role_instruction(self):
self.mess = '''
法师介绍:
拥有卓越的魔法才能,从小就离开了父母,加入魔法师团的天才少女。
对自己的才能充满自信,并对未来充满希望,因此眼光很高。
自尊心很强,甚至有点过于自信。对认可自己能力的人,表现出很强的依赖心。
泼辣的语言,会让人对她的性格产生误解。其实她也有善良、温柔、可爱的一面。
魔法师拥有可以同时攻击多个敌人的强力魔法,但防御力较低。
一旦被敌人包围,很容易陷入危险之中。 初始技能:
【%s】:%s%% 机率减少伤害 %s%%
''' % (self.init_skill,self.init_chance_rate,self.init_harm_rate)
common.show_message(self.mess, "INFORMATION")

role类

5.4.4 技能类模块skill.py

#_*_ coding=utf-8 _*_

'''
Created on 2016年3月15日
@author: 王凯
定义角色的技能类
''' import os
from conf import setting,menu
from modules import common
from database import dbapi ###技能的根类###
class skill(object):
'''
定义技能的类
''' ###指定角色技能的数据库文件####
__database = "{0}.db".format(os.path.join(setting.DATABASE['dbpath'],setting.DATABASE["tables"]["skill"])) def __init__(self,role_num):
self.life = setting.init_hp ###角色的初始血量### ###定义技能值初始化参数###
self.id = ''
self.level = ''
self.skill = ''
self.init_harm = ''
self.chance_rate = ''
self.harm_rate = '' self.dict_skill_list = {} self.role_num = role_num
self.db_load() ###调用执行技能数据库文件的读取和赋值###
self.dict_skill = self.dict_skill_list[self.role_num]
self.role = self.dict_skill["role"]
self.skill_list = self.dict_skill["skill"] ###调用执行技能数据库文件的读取和赋值###
def db_load(self):
self.dict_skill_list = dbapi.load_data_from_db(self.__database) ###输出角色技能列表###
def print_skill_list(self):
"""
将角色技能列表中的输出到屏幕
:return: 输出到屏幕
""" print("|{0}|{1}|{2}|".format('技能编号'.center(8), '技能名称'.center(18),'技能描述'.center(40)))
print('%s' % '-' * 85) for skill_info in self.skill_list:
sk_name = '{0}:{1}'.format(skill_info['level'],skill_info['name'])
sk_name_chinese_num = common.get_chinese_num(sk_name)
sk_name_len_num = len(sk_name)
sk_name_space_str = (20 - sk_name_len_num - sk_name_chinese_num) * " " sk_desc = '基础攻击:{0} {1}%机率产生暴击伤害,为基础伤害的{2}%'.format(skill_info['init_harm'],skill_info['chance_rate'],skill_info['harm_rate'])
sk_desc_chinese_num = common.get_chinese_num(sk_name)
sk_desc_len_num = len(sk_name)
sk_desc_space_str = (70 - sk_name_len_num - sk_name_chinese_num) * " " print('| %-10s | %s |%s|' % (skill_info['id'], sk_name + sk_name_space_str,sk_desc + sk_desc_space_str))
print('%s' % '-' * 85,"\n") ###获取技能的编号列表###
def skill_id_list(self):
"""
获取技能编号,并追加到技能列表,在对战中进行攻击,最后返回技能编号列表
:return: 技能列表
"""
_skill_list = []
_skill_tuple = self.dict_skill["skill"]
# 开始遍历,并生成技能编号列表
for _skill in _skill_tuple:
_skill_list.append(_skill['id'])
return _skill_list ###角色PK中,技能的伤害计算###
def skill_harm(self,skill_id,attack,defence):
"""
根据输入的技能编号,在对战中进行攻击,输入相应信息,并进行伤害和血量的计算
:param skill_id 技能的编号
:param attack 挑战方的参数字典
:param defence 守擂方的参数字典
:return 返回对战双方的血量
""" ###技能元组的赋值###
_skill_tuple = self.dict_skill["skill"]
attack_harm = 0
###开始遍历,并判断赋值###
for _skill in _skill_tuple:
###技能匹配成功,并进行参数赋值###
if _skill['id'] == skill_id:
skill_name = _skill['name']
skill_init_harm = _skill['init_harm']
skill_chance_rate = _skill['chance_rate']
skill_harm_rate = _skill['harm_rate'] ###调用随机数的生成和对比函数,来判断技能暴击属性是否触发###
attack_skill_trigger = common.random_decide(100,skill_chance_rate,'lt') ###PK信息输出的变量初始化###
mess_attack_init = '进攻方【{0}({1})】发动技能【{2}】,'.format(attack['name'],attack['role'],skill_name)
mess_attack_trigger = '【{0}({1})】发动技能【{2}】并触发属性【暴击】,'.format(attack['name'],attack['role'],skill_name)
mess_attack_harm = '造成伤害【{0}】,'
mess_defence_init = '防守方【{0}({1})】'.format(defence['name'],defence['role'])
mess_defence_trigger = '防守方【{0}({1})】触发初始技能【{2}】,'.format(defence['name'],defence['role'],defence['init_skill'])
mess_defence_life = '剩余血量【{0}】' mess_attack_info = mess_attack_init
mess_defence_info = mess_defence_init ###守擂方的初始技能是否开启###
if defence['init_skill_flag'] == 1:
###调用随机数的生成和对比函数,来判断防守方的初始属性是否触发###
defence_skill_trigger = common.random_decide(100,defence['init_chance_rate'],'lt') ###挑战和防守双方的技能均触发成功,计算伤害值###
if defence_skill_trigger and attack_skill_trigger:
attack_harm = (skill_init_harm * (100 + skill_harm_rate) /100) * (100 - defence['init_harm_rate']) / 100 mess_attack_info = mess_attack_trigger
mess_defence_info = mess_defence_trigger
###挑战方攻击技能暴击属性触发成功,计算伤害值###
elif attack_skill_trigger:
attack_harm = skill_init_harm * (100 + skill_harm_rate) /100 mess_attack_info = mess_attack_trigger
###防守方的技能触发成功,计算伤害值###
elif defence_skill_trigger:
attack_harm = skill_init_harm * (100 - defence['init_harm_rate']) / 100 mess_defence_info = mess_defence_trigger
###双方均未触发成功,计算伤害值###
else:
attack_harm = skill_init_harm else:
###挑战方攻击技能暴击属性触发成功,计算伤害值###
if attack_skill_trigger:
attack_harm = skill_init_harm * (100 + skill_harm_rate) /100 mess_attack_info = mess_attack_trigger
###双方均未触发成功,计算伤害值###
else:
attack_harm = skill_init_harm ###计算守擂方的剩余血量###
defence['life'] -= attack_harm
defence['life'] = int(defence['life'])
message = mess_attack_info + mess_attack_harm.format(attack_harm) + mess_defence_info + mess_defence_life.format(defence['life'])
common.show_message(message,"INFORMATION") ###返回双方的剩余血量###
return(attack['life'],defence['life'])

skill类

5.5 日志报表目录log:

5.5.1 错误日志game.log

2016-03-18 23:28:44 PM ERROR init table role failed,no function init_db_role found
2016-03-18 23:29:23 PM ERROR init table role failed,no function init_db_role found
2016-03-18 23:29:32 PM ERROR init table role failed,no function init_db_role found
2016-03-18 23:29:44 PM ERROR init table role failed,no function init_db_role found
2016-03-18 23:31:19 PM ERROR init table role failed,no function init_db_role found
2016-03-20 20:33:36 PM ERROR init table skill failed,no function init_db_skill found
2016-03-20 23:47:45 PM CRITICAL dbapi > load_vs_report > 'defence_name_name'
2016-03-20 23:52:19 PM CRITICAL dbapi > load_vs_report > 'defence_name_name'
2016-03-20 23:52:33 PM CRITICAL dbapi > load_vs_report > 'defence_name_name'

game.log

5.5.2 对战日志vs.log

2016-03-20 22:40:48 PM INFO [za] is fail,[ga] is success
2016-03-20 22:42:07 PM INFO [fb] is fail,[fa] is success
2016-03-20 22:43:14 PM INFO [za] is success,[fb] is fail
2016-03-20 23:33:52 PM INFO [za] is fail,[zb] is success
2016-03-21 00:02:09 AM INFO [gb] is success,[za] is fail
2016-03-21 00:05:33 AM INFO [fb] is success,[fa] is fail
2016-03-22 22:47:32 PM INFO [zb] is success,[ga] is fail
2016-03-22 22:48:20 PM INFO [fa] is success,[fb] is fail
2016-03-26 12:22:40 PM INFO [za] is fail,[fb] is success
2016-03-26 20:47:11 PM INFO [gb] is success,[fa] is fail
2016-03-26 20:47:50 PM INFO [gb] is fail,[za] is success
2016-03-26 21:02:20 PM INFO [zb] is success,[fa] is fail
2016-03-26 21:02:59 PM INFO [zb] is success,[ga] is fail
2016-03-26 21:04:01 PM INFO [fb] is success,[ga] is fail
2016-03-26 22:35:46 PM INFO [gb] is fail,[fa] is success
2016-03-27 01:50:00 AM INFO [zb] is fail,[fa] is success
2016-03-27 01:51:07 AM INFO [ga] is success,[fa] is fail
2016-03-27 16:17:58 PM INFO [za] is success,[fa] is fail

vs.log

5.5.3 对战报表vs_report

{"defence_name": "ga", "attack_result": false, "attack_name": "za", "time": "2016-03-20 22:40", "attack_role": "\u6218\u58eb", "defence_role": "\u5f13\u7bad\u624b", "detail": "\u3010\u6218\u58eb\uff1aza\u3011\u6311\u6218\u5931\u8d25,\u3010\u5f13\u7bad\u624b\uff1aga\u3011\u5b88\u64c2\u6210\u529f"}
{"defence_name": "fa", "attack_result": false, "attack_name": "fb", "time": "2016-03-20 22:42", "attack_role": "\u6cd5\u5e08", "defence_role": "\u6cd5\u5e08", "detail": "\u3010\u6cd5\u5e08\uff1afb\u3011\u6311\u6218\u5931\u8d25,\u3010\u6cd5\u5e08\uff1afa\u3011\u5b88\u64c2\u6210\u529f"}
{"defence_name": "fb", "attack_result": true, "attack_name": "za", "time": "2016-03-20 22:43", "attack_role": "\u6218\u58eb", "defence_role": "\u6cd5\u5e08", "detail": "\u3010\u6218\u58eb\uff1aza\u3011\u6311\u6218\u6210\u529f,\u3010\u6cd5\u5e08\uff1afb\u3011\u5b88\u64c2\u5931\u8d25"}
{"defence_role": "\u6218\u58eb", "time": "2016-03-20 23:33", "attack_result": false, "attack_role": "\u6218\u58eb", "defence_name": "zb", "attack_name": "za", "detail": "\u3010\u6218\u58eb\uff1aza\u3011\u6311\u6218\u5931\u8d25,\u3010\u6218\u58eb\uff1azb\u3011\u5b88\u64c2\u6210\u529f"}
{"attack_result": true, "detail": "\u3010\u5f13\u7bad\u624b\uff1agb\u3011\u6311\u6218\u6210\u529f,\u3010\u6218\u58eb\uff1aza\u3011\u5b88\u64c2\u5931\u8d25", "attack_role": "\u5f13\u7bad\u624b", "attack_name": "gb", "defence_name": "za", "defence_role": "\u6218\u58eb", "time": "2016-03-21 00:02"}
{"defence_role": "\u6cd5\u5e08", "time": "2016-03-21 00:05", "attack_result": true, "attack_name": "fb", "attack_role": "\u6cd5\u5e08", "detail": "\u3010\u6cd5\u5e08\uff1afb\u3011\u6311\u6218\u6210\u529f,\u3010\u6cd5\u5e08\uff1afa\u3011\u5b88\u64c2\u5931\u8d25", "defence_name": "fa"}
{"time": "2016-03-22 22:47", "detail": "\u3010\u6218\u58eb\uff1azb\u3011\u6311\u6218\u6210\u529f,\u3010\u5f13\u7bad\u624b\uff1aga\u3011\u5b88\u64c2\u5931\u8d25", "defence_name": "ga", "attack_result": true, "defence_role": "\u5f13\u7bad\u624b", "attack_role": "\u6218\u58eb", "attack_name": "zb"}
{"time": "2016-03-22 22:48", "detail": "\u3010\u6cd5\u5e08\uff1afa\u3011\u6311\u6218\u6210\u529f,\u3010\u6cd5\u5e08\uff1afb\u3011\u5b88\u64c2\u5931\u8d25", "defence_name": "fb", "attack_result": true, "defence_role": "\u6cd5\u5e08", "attack_role": "\u6cd5\u5e08", "attack_name": "fa"}
{"time": "2016-03-26 12:22", "defence_role": "\u6cd5\u5e08", "detail": "\u3010\u6218\u58eb\uff1aza\u3011\u6311\u6218\u5931\u8d25,\u3010\u6cd5\u5e08\uff1afb\u3011\u5b88\u64c2\u6210\u529f", "attack_name": "za", "attack_role": "\u6218\u58eb", "defence_name": "fb", "attack_result": false}
{"attack_role": "\u5f13\u7bad\u624b", "attack_name": "gb", "defence_name": "fa", "attack_result": true, "time": "2016-03-26 20:47", "defence_role": "\u6cd5\u5e08", "detail": "\u3010\u5f13\u7bad\u624b\uff1agb\u3011\u6311\u6218\u6210\u529f,\u3010\u6cd5\u5e08\uff1afa\u3011\u5b88\u64c2\u5931\u8d25"}
{"attack_role": "\u5f13\u7bad\u624b", "attack_name": "gb", "defence_name": "za", "attack_result": false, "time": "2016-03-26 20:47", "defence_role": "\u6218\u58eb", "detail": "\u3010\u5f13\u7bad\u624b\uff1agb\u3011\u6311\u6218\u5931\u8d25,\u3010\u6218\u58eb\uff1aza\u3011\u5b88\u64c2\u6210\u529f"}
{"attack_name": "zb", "defence_name": "fa", "detail": "\u3010\u6218\u58eb\uff1azb\u3011\u6311\u6218\u6210\u529f,\u3010\u6cd5\u5e08\uff1afa\u3011\u5b88\u64c2\u5931\u8d25", "attack_result": true, "attack_role": "\u6218\u58eb", "defence_role": "\u6cd5\u5e08", "time": "2016-03-26 21:02"}
{"attack_name": "zb", "defence_name": "ga", "detail": "\u3010\u6218\u58eb\uff1azb\u3011\u6311\u6218\u6210\u529f,\u3010\u5f13\u7bad\u624b\uff1aga\u3011\u5b88\u64c2\u5931\u8d25", "attack_result": true, "attack_role": "\u6218\u58eb", "defence_role": "\u5f13\u7bad\u624b", "time": "2016-03-26 21:02"}
{"attack_name": "fb", "defence_name": "ga", "detail": "\u3010\u6cd5\u5e08\uff1afb\u3011\u6311\u6218\u6210\u529f,\u3010\u5f13\u7bad\u624b\uff1aga\u3011\u5b88\u64c2\u5931\u8d25", "attack_result": true, "attack_role": "\u6cd5\u5e08", "defence_role": "\u5f13\u7bad\u624b", "time": "2016-03-26 21:04"}
{"attack_role": "\u5f13\u7bad\u624b", "defence_name": "fa", "attack_result": false, "detail": "\u3010\u5f13\u7bad\u624b\uff1agb\u3011\u6311\u6218\u5931\u8d25,\u3010\u6cd5\u5e08\uff1afa\u3011\u5b88\u64c2\u6210\u529f", "defence_role": "\u6cd5\u5e08", "time": "2016-03-26 22:35", "attack_name": "gb"}
{"defence_role": "\u6cd5\u5e08", "attack_name": "zb", "attack_result": false, "detail": "\u3010\u6218\u58eb\uff1azb\u3011\u6311\u6218\u5931\u8d25,\u3010\u6cd5\u5e08\uff1afa\u3011\u5b88\u64c2\u6210\u529f", "time": "2016-03-27 01:50", "defence_name": "fa", "attack_role": "\u6218\u58eb"}
{"defence_role": "\u6cd5\u5e08", "attack_name": "ga", "attack_result": true, "detail": "\u3010\u5f13\u7bad\u624b\uff1aga\u3011\u6311\u6218\u6210\u529f,\u3010\u6cd5\u5e08\uff1afa\u3011\u5b88\u64c2\u5931\u8d25", "time": "2016-03-27 01:51", "defence_name": "fa", "attack_role": "\u5f13\u7bad\u624b"}
{"defence_role": "\u6cd5\u5e08", "attack_role": "\u6218\u58eb", "defence_name": "fa", "detail": "\u3010\u6218\u58eb\uff1aza\u3011\u6311\u6218\u6210\u529f,\u3010\u6cd5\u5e08\uff1afa\u3011\u5b88\u64c2\u5931\u8d25", "time": "2016-03-27 16:17", "attack_result": true, "attack_name": "za"}

vs_report

6.程序部分功能模块截图展示:

6.1 主菜单:

6.2 输入1,进入角色介绍菜单,并查看战士的介绍:

6.3 返回主菜单,输入2,进入PK场:

说明:

每个角色有二个用户,挑战和应战方不能同时选择同一种角色下的同一用户,例当挑战方选择了战士的za时,应战方如果选择战士角色,则只有zb可以选择。

首先输入挑战方的角色、名字以及是否开启初始技能

其次输入应战方的角色、名字以及是否开启初始技能

6.4对战开始,可以选择自动战斗,也可以手动战斗

说明:

自动战斗即在技能范围内随机生成一个数;而手动战斗是手工输入技能的编号

初始技能和暴击属性的触发,也是根据随机生成数和机率进行比较,从而对伤害进行增加或减少。

因挑战方先发起攻击,必然在PK有多出一招的优势,故为了平衡,在防守方的初始血量多加了100

挑战方1000血量,应战方1100血量

每一回合来计算对战双方的血量,如果血量小于0,则结束对战

6.5 返回主菜单,输入3,查看战绩榜:

首先输入查询的开始和结束时间

说明:正常输出PK战绩结果,默认是以角色用户来排序,可以根据其他三种方式进行排序,正常有主排序和次排序字段

输入1,则以挑战成功数为主排序字段,以挑战次数为次排序字段

输入2,则以守擂成功数为主排序字段,以守擂次数为次排序字段

输入3,则以PK成功数为主排序字段,以PK总次数为次排序字段

6.6 输入0,进行具体用户查询环节,并可以查看具体的PK记录信息:

6.7 最后,返回主菜单,输入0,退出程序,结束:

python之在线PK游戏(第六天)的更多相关文章

  1. Python制作的射击游戏

    如果其他朋友也有不错的原创或译文,可以尝试推荐给伯乐在线.] 你有没有想过电脑游戏是怎样制作出来的?其实它没有你想象的那样复杂! 在这个教程里,你要学做一个叫<兔子和獾>的塔防游戏,兔子作 ...

  2. 用Python设计第一个游戏 - 零基础入门学习Python002

    用Python设计第一个游戏 让编程改变世界 Change the world by program 有些鱼油可能会说,哇,小甲鱼你开玩笑呐!这这这这就上游戏啦?你不打算给我们讲讲变量,分支,循环,条 ...

  3. 利用Python完成一个小游戏:随机挑选一个单词,并对其进行乱序,玩家要猜出原始单词

    一 Python的概述以及游戏的内容 Python是一种功能强大且易于使用的编程语言,更接近人类语言,以至于人们都说它是“以思考的速度编程”:Python具备现代编程语言所应具备的一切功能:Pytho ...

  4. 第四百零三节,python网站在线支付,支付宝接口集成与远程调试,

    第四百零三节,python网站在线支付,支付宝接口集成与远程调试, windows系统安装Python虚拟环境 首先保证你的系统已经安装好了Python 安装virtualenv C:\WINDOWS ...

  5. Python开发转盘小游戏

    Python开发转盘小游戏 Python  一 原理分析 Python开发一个图形界面 有12个选项和2个功能键 确定每个按钮的位置 每个按钮的间隔相同 点击开始时转动,当前选项的背景颜色为红色,其他 ...

  6. Python的在线编辑环境

    另外,再提供几个Python的在线编辑环境,可以直接写代码并且运行的环境. 在线Python实验室:http://www.pythoner.cn/labs/ 在线Python编辑器:http://ww ...

  7. 零基础入门学习python--第二章 用Python设计第一个游戏

    知识点汇总1. 什么是BIF? BIF(Built-in Functions)内置函数,共68个,可直接调用,方便程序员快速编写脚本程序.输入dir(__builtins__)即可查看所有内置函数,h ...

  8. 用Python实现童年小游戏贪吃蛇

    贪吃蛇作为一款经典小游戏,早在 1976 年就面世了,我最早接触它还是在家长的诺基亚手机中.

  9. 教你用Python自制拼图小游戏,一起来制作吧

    摘要: 本文主要为大家详细介绍了python实现拼图小游戏,文中还有示例代码介绍,感兴趣的小伙伴们可以参考一下. 开发工具 Python版本:3.6.4 相关模块: pygame模块: 以及一些Pyt ...

随机推荐

  1. java并发编程(三)线程挂起,恢复和终止的正确方法

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17095733    下面我们给出不用上述两个方法来实现线程挂起和恢复的策略--设置标志位. ...

  2. mpstat命令学习

    mpstat是一个linux系统实时监控工具,它与vmstat命令类似 mpstat命令监控了cup的一些统计信息且这些信息存放在/proc/stat文件中 mpstat命令多用在多cpu系统中,查看 ...

  3. PHP连接数据库的方法

    mysql可通过两种方式通过PHP和web相连,一种通过php的mysql相关函数,另一种通过php的ODBC相关函数. 相关函数如下: MYSQL函数 mysql_affected_rows: 得到 ...

  4. 批处理命令 BAT备份MySQL数据库

    批处理命令 BAT备份MySQL数据库 作者: 字体:[增加 减小] 类型:转载 时间:2009-07-23我要评论 MySQL数据的备份工具也许有很多,在这我要给大家分享一下通过DOS批处理命令和M ...

  5. Approaches to Vector Computation

    COMPUTER OR GANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION

  6. NONUNIFORM MEMORY ACCESS

    COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION In terms of commercia ...

  7. WINDOWS下PhoneGap(Cordova)安装笔记

    1.首先下载Node.js  安装nodejs很简单直接点击安装文件下一步直至成功即可,安装notejs的同时npm也会同时安装 成功后打开notejs的命令行工具 输入“node -v”," ...

  8. html5 canvas画流程图

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  9. ios10 safari 的坑!

    | 导语 ios10 的safari,又给前端开发者挖坑了..测试验证此问题只出现在ios10 safari中.想早点知道结论的,可以直接看最后一个结论~因为,解决过程不重要! 个人原创,未经允许,禁 ...

  10. imx6 Image Vector Table (IVT)

    imx6开启启动之后,运行板子上的ROM程序.ROM确定启动的设备,进行一些初始化,然后读取IVT,进行寄存器初始化,最后运行uboot/cpu/arm_cortexa8/start.S中的_star ...