zoukankan      html  css  js  c++  java
  • 四则运算4(完结)

    终于熬出头了

    php版的四则运算出炉了

    由于c++代码转php代码有个BUG调不出来,在经历了10+个小时的努力,换了n+个环境了,终于也没把php断点调试环境搭起来,

    所以,就当这是个阉割版的四则运算吧。。。。

    首先,环境:

    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>

    第一次用php做,边做边学,如有错误,感谢指出。

    我的队友 信1301-1 刘伟

    1.系统首页

    2.用户登录

     3.用户首页

    4.答题设置页面

    5.开始答题

    6.浏览答题记录

    7.管理员登陆界面

    8.管理员首页

    9.用户管理列表

    10.用户答题记录:

  • 相关阅读:
    ckplayer的Error #2033:Can not call javascript:ckstyle()解决
    C#中的参数关键字params
    c#中的可选参数和命名参数的使用
    c#中的dynamic类型
    c#中关于变量声明那么点事
    C# 自定义控件的一些文章和博客
    datatable,查询,排序,复制等操作
    HTML5 实现图像模糊算法
    FASTCGI程序,做个备份,以后用
    PHP的一些函数
  • 原文地址:https://www.cnblogs.com/xiaoxt/p/5347377.html
Copyright © 2011-2022 走看看