四则运算完结篇

一开始我们所用代码选用了我们之中较好的我的搭档的代码,就是代码量稍微大了些 但是实现的功能更全。

这次php版的四则运算出炉了

由于c++代码转php代码有个BUG调不出来,首先,环境:

WampServer 3.0 64bit

netbeans 8.1

然后,数据库设计,

三个表:用户表user,管理员表admin,答题记录表ansrecord

表结构在这里

/*
Navicat MySQL Data Transfer

Source Server         : tp
Source Server Version : 50709
Source Host           : localhost:3306
Source Database       : 2zhuzi

Target Server Type    : MYSQL
Target Server Version : 50709
File Encoding         : 65001

Date: 2016-03-31 16:22:23
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `admin`
-- ----------------------------
DROP TABLE IF EXISTS `admin`;
CREATE TABLE `admin` (
  `adminid` int(11) NOT NULL AUTO_INCREMENT,
  `adminname` varchar(255) NOT NULL,
  `pwd` varchar(255) NOT NULL,
  PRIMARY KEY (`adminid`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of admin
-- ----------------------------
INSERT INTO `admin` VALUES (‘1‘, ‘admin‘, ‘123456‘);
INSERT INTO `admin` VALUES (‘2‘, ‘root‘, ‘123456‘);

-- ----------------------------
-- Table structure for `ansrecord`
-- ----------------------------
DROP TABLE IF EXISTS `ansrecord`;
CREATE TABLE `ansrecord` (
  `ansrecordid` int(11) NOT NULL AUTO_INCREMENT,
  `userid` int(11) NOT NULL,
  `question` varchar(255) NOT NULL,
  `rightans` double NOT NULL,
  `lastans` varchar(255) NOT NULL,
  PRIMARY KEY (`ansrecordid`),
  KEY `userid` (`userid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of ansrecord
-- ----------------------------

-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `userid` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `pwd` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  PRIMARY KEY (`userid`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

再然后,用户部分:

包括用户登录,用户注册,用户首页三个页面,可实现用户注册,登陆,注销,跳转到在线答题,访问隔离(好像叫这么个名字)等功能,

接下来是管理员部分:

包括 管理员登录,管理员首页,用户列表,答题记录列表四个页面,可实现管理员的登录,注销,查看用户列表,删除特定用户,查看答题记录,删除指定答题记录等功能。

最后,在线答题部分:

这部分就是核心包括OJ首页,设置题目各种属性,题目列表页面,旧题浏览页面,可实现题目属性设定,服务器端生成题目,旧题浏览,保存答题结果等功能。

题目生成是questionGenerator这个类完成的。

由于xdebug+netbeans/phpstrom/sublime/zendstudio 什么什么的环境弄不起来,所以在线判断这部分功能就阉了。。  其实写好了调了好久调不对。。

下面是我们的核心代码

1 <?php
  2 class questionGenerator
  3 {
  4     private $itemNum = 5;
  5     private $isMulandDiv = true;
  6     private $isParentheses = true;
  7     private $isNeg = true;
  8     private $isRem = true;
  9     private $start = 0;
 10     private $end = 100;
 11     public $items = array();
 12     function __construct($itemNum, $isMulandDiv, $isParentheses, $isNeg, $isRem, $start, $end) {
 13         $this->itemNum = $itemNum;
 14         $this->isMulandDiv = $isMulandDiv;
 15         $this->isParentheses = $isParentheses;
 16         $this->isNeg = $isNeg;
 17         $this->isRem = $isRem;
 18         $this->start = $start;
 19         $this->end = $end;
 20     }
 21
 22     function isTrueFraction($numerator,$denominator){   //判断产生的分数是否是真分数
 23         if($numerator >= $denominator){
 24             return false;
 25         }
 26         for($i = 2; $i <= $numerator;$i++){               //判断分数是否能够约分
 27             if(($numerator % $i == 0)&&($denominator % $i == 0)){
 28                 return false;
 29             }
 30         }
 31         return true;
 32     }
 33
 34     function getNum($start = 0, $end = 100,$isParentheses = false,$depth = 0){    // 若带括号 则为 a op ( b op c ) 的形式 op为运算符
 35         if($isParentheses){
 36             $num1 = mt_rand($start,$end);
 37             if($depth < 2){         //控制递归层数,带括号的式子少于10个
 38                 $num2 = "( " . $this->getNum($start,$end,mt_rand() % 2 == 0,$depth + 1) . " )";
 39                 return strval($num1) . " , " . $num2;
 40             }else{
 41                 $num2 = "( " . $this->getNum($start,$end,false,$depth + 1) . " )";
 42                 return strval($num1) . " , " . $num2;
 43             }
 44         }else{
 45             if(mt_rand() % 7 == 0){      //若随机数n是7的倍数,产生一个真分数和一个整数,否则为两个整数
 46                 $num1 = mt_rand($start,$end);
 47                 $num2 = mt_rand($start,$end);
 48                 $num3 = mt_rand($start,$end);
 49                 if($this->isTrueFraction($num1,$num2)){
 50                     return strval($num1) . "/" . strval($num2) . " , " . strval($num3);
 51                 }else{
 52                     return $this->getNum($start,$end);
 53                 }
 54             }else{
 55                 $num1 = mt_rand($start,$end);
 56                 $num2 = mt_rand($start,$end);
 57                 return strval($num1) . " , " . strval($num2);
 58             }
 59         }
 60     }
 61
 62     function getOperator($num2 = ‘1‘,$isMulandDiv = true){     // 默认第二个参数不为0,默认包括乘除法
 63         $op = array(‘+‘,‘-‘,‘*‘,‘/‘);
 64         if($isMulandDiv){
 65             if($num2 == ‘0‘){    //避免除数为0
 66                 return $op[mt_rand() % 3];
 67             }else{
 68                 return $op[mt_rand() % 4];
 69             }
 70         }else{
 71             return $op[mt_rand() % 2];
 72         }
 73     }
 74
 75     function isNegative($num1, $num2, $op){
 76         if($op == ‘-‘){
 77             if(intval($num1) < intval($num2)){
 78                 return true;
 79             }else{
 80                 return false;
 81             }
 82         }else{
 83             if(intval($num1) + intval($num2) < 0){
 84                 return true;
 85             }else{
 86                 return false;
 87             }
 88         }
 89     }
 90
 91     function isRemainder($num1, $num2){
 92         if(intval($num1) % intval($num2) == 0){
 93             return false;
 94         }else{
 95             return true;
 96         }
 97     }
 98
 99     function generateQuest(){
100         $addFlag = false;
101         $one = 1;
102         while (count($this->items) < $this->itemNum){
103             $num = $this->getNum($this->start,$this->end,$this->isParentheses);
104             while (strpos($num,",")){
105                 $addFlag = true;
106                 if(substr($num,intval(strpos($num,",")) + 2,1) == ‘(‘){   //运算符后紧跟括号,运算符选取只和isMulandDiv有关
107                     $op = $this->getOperator(‘1‘,$this->isMulandDiv);
108                    $num = str_replace(",",$op,$num,$one);
109                 }else{           //运算符后是数字,运算符选取和num2和isMulandDiv有关,此时是不带括号或最右边的算式
110                     $num2 = substr($num, intval(strrpos($num,",")) + 2, intval(strpos($num,")")) - intval(strrpos($num,",")) - 3);
111                     $op = $this->getOperator($num2,$this->isMulandDiv);
112                     $num = str_replace(",", $op, $num, $one);
113                     $begin = 0;        //找到形如 a op b 的式子
114                     if(strpos($num, "(")){     //如果式子里有()的话
115                         $begin = intval(strrpos($num, "(")) + 2;
116                     }
117                     $num1 = substr($num, $begin, intval(strrpos($num, $op)) - $begin - 1);
118                     if( $op == ‘-‘ || $op == ‘+‘)
119                     {
120                         if(!$this->isNeg && $this->isNegative($num1, $num2, $op))
121                         {
122                             $addFlag = FALSE;
123                             break;
124                         }
125                     }elseif ($op == ‘/‘) {
126                         if(!$this->isRem && $this->isRemainder($num1, $num2)){
127                             $addFlag = FALSE;
128                             break;
129                         }
130                     }
131                 }
132             }
133             if(!$addFlag){    //满足要求,可以添加
134                 continue;
135             }
136             if(!in_array($num, $this->items)){   //判断是否重复,不重复则添加
137                 array_push($this->items, $num);
138             }
139         }
140     }
141
142     function calculate($num1,$num2,$op){
143         switch ($op){
144             case "+":
145                 return $num1 + $num2;
146                 break;
147             case "-":
148                 return $num1 - $num2;
149                 break;
150             case  "*":
151                 return $num1 * $num2;
152                 break;
153             case "/":
154                 return $num1 / $num2;
155                 break;
156             default :
157                 echo "<script>alert(‘Calculate Error !!!‘);location=‘setattr.php‘;</script>";
158         }
159     }
160
161     function getResult(){
162         $pri = array(
163             ‘+‘ => array(‘+‘ => ‘>‘, ‘-‘ => ‘>‘, ‘*‘ => ‘<‘, ‘/‘ => ‘<‘, ‘(‘ => ‘<‘, ‘)‘ => ‘>‘, ‘#‘ => ‘>‘),
164             ‘-‘ => array(‘+‘ => ‘>‘, ‘-‘ => ‘>‘, ‘*‘ => ‘<‘, ‘/‘ => ‘<‘, ‘(‘ => ‘<‘, ‘)‘ => ‘>‘, ‘#‘ => ‘>‘),
165             ‘*‘ => array(‘+‘ => ‘>‘, ‘-‘ => ‘>‘, ‘*‘ => ‘>‘, ‘/‘ => ‘>‘, ‘(‘ => ‘<‘, ‘)‘ => ‘>‘, ‘#‘ => ‘>‘),
166             ‘/‘ => array(‘+‘ => ‘>‘, ‘-‘ => ‘>‘, ‘*‘ => ‘>‘, ‘/‘ => ‘>‘, ‘(‘ => ‘<‘, ‘)‘ => ‘>‘, ‘#‘ => ‘>‘),
167             ‘(‘ => array(‘+‘ => ‘<‘, ‘-‘ => ‘<‘, ‘*‘ => ‘<‘, ‘/‘ => ‘<‘, ‘(‘ => ‘<‘, ‘)‘ => ‘=‘, ‘#‘ => ‘‘),
168             ‘)‘ => array(‘+‘ => ‘>‘, ‘-‘ => ‘>‘, ‘*‘ => ‘>‘, ‘/‘ => ‘>‘, ‘(‘ => ‘‘, ‘)‘ => ‘>‘, ‘#‘ => ‘>‘),
169             ‘#‘ => array(‘+‘ => ‘<‘, ‘-‘ => ‘<‘, ‘*‘ => ‘<‘, ‘/‘ => ‘<‘, ‘(‘ => ‘<‘, ‘)‘ => ‘‘, ‘#‘ => ‘=‘)
170         );
171         $ansL = array();
172         foreach ($this->items as $exp){
173             $stackOps = array();
174             $stackNums = array();
175             array_push($stackOps,"#");
176             $exp = $exp . " #";
177             $flag = -1;
178             while (!(substr($exp,$flag + 1,1) == "#" && end($stackOps) == "#")){
179                 $str = substr($exp, $flag + 1, strpos($exp, " ", $flag + 1) - $flag -1);
180                 if(!in_array($str,array("+","-","*","/","(",")","#"))){
181                     if(strpos($str,"/")){
182                         $numerator = substr($str,0,strpos($str,"/"));
183                         $denominator = substr($str,strpos($str,"/") + 1);
184                         array_push($stackNums,floatval($numerator)/floatval($denominator));
185                         $flag = strpos($exp," ",$flag + 1);
186                     }  else {
187                         array_push($stackNums,floatval($str));
188                         $flag = strpos($exp," ",$flag + 1);
189                     }
190                 }  else {
191                     if($pri[end($stackOps)][$str] == "<"){
192                         array_push($stackOps,$str);
193                         $flag = strpos($exp," ",$flag + 1);
194                     }elseif ($pri[end($stackOps)][$str] == ">") {
195                         $op = end($stackOps);
196                         array_pop($stackOps);
197                         $num2 = end($stackNums);
198                         array_pop($stackNums);
199                         $num1 = end($stackNums);
200                         array_pop($stackNums);
201                         array_push($stackNums, $this->calculate($num1, $num2, $op));
202                     }elseif ($pri[end($stackOps)][$str] == "=") {
203                         array_pop($stackOps);
204                         $flag = strpos($exp," ",$flag + 1);
205                     }  else {
206                         echo "<script>alert(‘Push&Pop Error !!!‘);location=‘setattr.php‘;</script>";
207                     }
208                 }
209             }
210             array_push($ansL, end($stackNums));
211         }
212         return $ansL;
213     }
214
215     function getQuestionList(){
216         return $this->items;
217     }
218
219
220 }

复制代码

基本思路和c++版的相同,不过php 数组的特性,还有字符串处理的优势,还是更方便一些,代码少了一半。

数据库连接用的是PDO,虽然比直接用mysql_* 的函数麻烦一点,但是安全性更高,

访问隔离(貌似是这么叫的)在每一部分都有,通过

session_start();
if(!isset($_SESSION[‘adminid‘]) && !isset($_SESSION[‘adminname‘]) ){
    echo "<script>alert(‘请登录!‘);location=‘adminlogin.html‘;</script>";
}

或者

session_start();
if (!isset($_SESSION[‘adminid‘]) && !isset($_SESSION[‘adminname‘])) {
    echo "<script>alert(‘请登录!‘);location=‘adminlogin.html‘;</script>";
}

实现,简单。

管理员部分对特定数据操作是在遍历中加入GET请求实现的

例如:

复制代码
<?php
$stmt = $pdo->prepare("select * from ansrecord");
$stmt->execute();
$res = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<table border="1" align="center" width="40%" >
            <tr><th>序号</th><th>用户ID</th><th>题目</th><th>最后答案</th><th>操作</th></tr>
            <tr><td></td><td></td></tr>
            <?php
            foreach ($res as $key => $value) {
                echo "<tr><td>" . $key . "</td><td>" . $value[‘userid‘] . "</td><td>" . $value[‘question‘] . "</td><td>".$value[‘lastans‘]."</td><td><a href=\"ansrecordmangagement.php?action=DELETE&ansrecordid=".$value[‘ansrecordid‘]."\" >删除记录</a></td></tr>";
            }
            $stmt = null;
            $pdo = null;
            ?>
        </table>

从用户界面->OJ首页->OJ->题目属性设置->题目列表->提交题目和答案到数据库

题目属性设置页面提交一个POST表单,通过PHP输入过滤器对表单内容过滤,然后将属性做参数传入questionGenerator构造函数

$qG = new questionGenerator($itemNum, $isMulandDiv, $isParentheses, $isNeg, $isRem, $start, $end);
$qG->generateQuest();
$qL = $qG->getQuestionList();
$numofqL = count($qL);

将题目通过只读的input框 显示,答案也用表单收集,题目数量通过一个隐藏域传入表单

<form method="post" action="submitquestandans.php">
        <table>
            <tr><th>题目</th><th>答案</th></tr>

            <?php
            echo "<tr><td colspan=\"2\"><input type=\"hidden\" value=\"".$numofqL."\" name=\"numofqL\" > </td></tr>";
            foreach ($qL as $key => $value) {
                echo "<tr><td><input type=\"text\" name=\"question".$key."\" value=\"".$value."\" readonly=\"true\" ></td><td><input type=\"text\" name=\"answer".$key."\" required size=\"10\" ></td></tr>";
            }
            ?>
            <tr><td colspan="2"><input type="submit" name="qL_submit" value="提交" ></td></tr>
        </table>
       </form>

我的队友信1301-2班 肖兴堂

时间: 2024-11-05 13:34:01

四则运算完结篇的相关文章

从无到有写一个运维APP(三)完结篇

前言:自己的挖的坑还得填,此篇为完结篇,环境的搭建参考第一篇从无到有写一个运维APP(一),至于第二篇就跳过吧,写个APP没那么复杂.由于自己现在无业游民,所以没有什么现成的环境,环境就随便找个公网的..再者当下的完成度应该算不上一个完整的APP,但是作为参考,依瓢画葫芦绝对足够了,如果等完整产品,可能得等一段时间了,下面的是该项目的地址. 项目地址: https://github.com/youerning/MyApp(star一下呗) 效果图如下 文章目录: 准备工作 代理 页面框架 获取数

DTRACE简介之完结篇3

https://blogs.oracle.com/swan/entry/dtrace%E7%AE%80%E4%BB%8B_3 DTRACE简介之完结篇 By samwan on 四月 13, 2007 已经有好长一段时间没有更新blog了,不是我懒,确实是这段时间太忙.工作加上生活,算了,不找借口了,还是来把DTRACE简介作个完结吧.本来开始写的时候只准备用一篇文章来描述,等真正写出来就发现,不行了,Dtrace实在是太强大了,即便是加上今天的,也没有完全讲到,遗漏的地方就只有请各位看官自己去

SpringMVC学习系列(12) 完结篇 之 基于Hibernate+Spring+Spring MVC+Bootstrap的管理系统实现

到这里已经写到第12篇了,前11篇基本上把Spring MVC主要的内容都讲了,现在就直接上一个项目吧,希望能对有需要的朋友有一些帮助. 一.首先看一下项目结构: InfrastructureProjects:是抽取出的基础项目,主要封装了一些通用的操作. SpringMVC3Demo:就是管理系统所在的项目. WeiXinAPI:是之前做微信管理平台测试时封装一些操作,如果不需要把该项目移除即可. 注:项目的前端UI框架用的是国外的一个基于Bootstrap框架的开发的Demo,如不需要替换为

第18完结篇-JAVA XML

第18完结篇-JAVA XML 每篇一句 :我们不缺方法,缺的是一往无前的决心和魄力 初学心得: 我们应该从中吸取教训,而不是累积伤痛 (笔者:JEEP/711)[JAVA笔记 | 时间:2017-05-21| JAVA XML ] 1.什么是XML Extensible Markup Language:翻译过来为可扩展标记语言 Xml技术是w3c组织发布的,目前推荐遵循的是W3C组织于2000发布的XML1.0规范 在XML语言中,它允许用户自定义标签 一个标签用于描述一段数据:一个标签可分为

hostapd wpa_supplicant madwifi详细分析(十四)——完结篇

注:这篇文章不谈技术 查看了一下<hostapd wpa_supplicant madwifi详细分析>系列文章,断断续续更新到现在,发现中间的持续时间都快要两年了.记得那时候刚毕业到公司,组长叫我看项目的无线部分代码,自己稀里糊涂的看了一个月,组长问我: vap是怎么创建的?sta和AP是怎么建立连接的?wds是怎么工作的?WPS中PIN和PUSHBUTTON的区别是什么?我们DUT中几种加密方式是怎么实现的?hostapd是用来干什么的? 这些问题把我问的瞠目结舌,十分羞愧,感觉自己花了一

不就是抽个血吗,至于么-jQuery,Linux完结篇

hi 趁着周一去抽血化验,真开心...下午报告才出来,不过早上来了就开始各种晕菜,叫错名字,说错话.....至于么.. 还有在教研室的30天就可以肥家了,凯森凯森.今天不想干活(哪天想干过我就问问),学学jquery吧. 1.jQuery 十.UI型插件 10.1 拖曳插件——draggable 拖曳插件draggable的功能是拖动被绑定的元素,当这个jQuery UI插件与元素绑定后,可以通过调用draggable()方法,实现各种拖曳元素的效果,调用格式如下: $(selector). d

怒学Python——完结篇——I/O

好吧,没想到居然这么快,才两天我就把入门看完了,当然只是入门,以后如果用到,会把那些各个类型的细化都总结一下例如数学函数,或者总结一下一些框架的应用如Scarpy(爬虫框架,听着就很兴奋呢,很多人都是了解有,但是没用过......),笔者写完这段暂时先开心的看电影去,回学校再说. Python的屏幕I/O:如果是交互式编程,直接输入就好,这里的是在脚本式编程才用到,用到的方法是input和raw_input,下面给出例子 #!/usr/bin/python print raw_input() #

《程序员的呐喊》读后感,完结篇

前50页也写过: http://blog.csdn.net/wide288/article/details/30112009 有人讲五号字是在网上用的最舒服的字号,但对我像我一样的近视生来说,大点再大点(包扩屏幕)才是最好的. 花了些时间读完了,本书的前面几十页差点让我失望,不过好在后面越读越精彩. 面试,吐槽,对各个公司的点评,代码方面,管理方面.都很有趣. 本书,字少,页数少,版面小. 我想这就是它没有<黑客与画家>有名的原因吧. 从书中,也从我所在公司工作中,我体会到了,需要什么.怎样会

Apache Flink fault tolerance源码剖析完结篇

这篇文章是对Flinkfault tolerance的一个总结.虽然还有些细节没有涉及到,但是基本的实现要点在这个系列中都已提及. 回顾这个系列,每篇文章都至少涉及一个知识点.我们来挨个总结一下. 恢复机制实现 Flink中通常需要进行状态恢复的对象是operator以及function.它们通过不同的方式来达到状态快照以及状态恢复的能力.其中function通过实现Checkpointed的接口,而operator通过实现StreamOpeator接口.这两个接口的行为是类似的. 当然对于数据