记录:随机数抽奖
要求:每次生成3个 1 - 10 之间可重复(或不可重复)的随机数,10次为一轮,每轮要求数字5出现6次、数字4出现3次、…。
提炼需求:
1,可设置最小数、最大数、每次抽奖生成随机数的个数、是否允许重复
2,可设置每轮指定数字的出现次数
3,可设置每轮的抽奖次数
注意:设置项发生变化,则重置游戏
效果图示例:
Choujianglog 模型
<?phpnamespace app\admin\model\choujiang;use think\Model;class Choujianglog extends Model
{// 表名protected $name = 'choujiang_log';// 自动写入时间戳字段protected $autoWriteTimestamp = 'integer';// 定义时间戳字段名protected $createTime = 'createtime';protected $updateTime = false;protected $deleteTime = false;// 追加属性protected $append = [];// 获取抽奖当前轮次public function getLunci($choujiang_id, $yilunchoujiagcishu) {$lunci = $this->where(['choujiang_id'=>$choujiang_id])->max('lunci');if(!$lunci){$lunci = 1;}return $lunci;}// 获取抽奖接下来的轮次public function getnextLunci($choujiang_id, $yilunchoujiagcishu) {$lunci = $this->where(['choujiang_id'=>$choujiang_id])->max('lunci');if(!$lunci){$lunci = 1;}$choujiangcishu = $this->where(['choujiang_id'=>$choujiang_id, 'lunci'=>$lunci])->group('sign')->count();if($choujiangcishu >= $yilunchoujiagcishu){$lunci += 1;}return $lunci;}// 生成signpublic function createSign() {$str = '123567890123567890123567890';//34个字符$str = str_shuffle($str); //随机地打乱字符串中的所有字符$sign = date('YmdHis').substr($str,0,4); //截取字符串if($this->where(['sign'=>$sign])->value('sign')){$this->createSign();}else{return $sign;}}}
Choujiang模型
<?phpnamespace app\admin\model\choujiang;use think\Model;class Choujiang extends Model
{// 表名protected $name = 'choujiang';// 自动写入时间戳字段protected $autoWriteTimestamp = 'integer';// 定义时间戳字段名protected $createTime = 'createtime';protected $updateTime = 'updatetime';protected $deleteTime = false;// 追加属性protected $append = ['state_text'];public function getStateList(){return ['1' => __('State 1'), '2' => __('State 2')];}public function getStateTextAttr($value, $data){$value = $value ? $value : (isset($data['state']) ? $data['state'] : '');$list = $this->getStateList();return isset($list[$value]) ? $list[$value] : '';}}
Choujiangset模型
<?phpnamespace app\admin\model\choujiang;use think\Model;class Choujiangset extends Model
{// 表名protected $name = 'choujiang_set';// 自动写入时间戳字段protected $autoWriteTimestamp = false;// 定义时间戳字段名protected $createTime = false;protected $updateTime = false;protected $deleteTime = false;// 追加属性protected $append = ['state_text'];public function getStateList(){return ['1' => __('State 1'), '2' => __('State 2')];}public function getStateTextAttr($value, $data){$value = $value ? $value : (isset($data['state']) ? $data['state'] : '');$list = $this->getStateList();return isset($list[$value]) ? $list[$value] : '';}}
代码:
<?phpnamespace app\api\controller;use app\common\controller\Api;
use think\Exception;
use think\Validate;
use app\admin\model\choujiang\Choujiang as ChoujiangModel;
use app\admin\model\choujiang\Choujianglog as ChoujianglogModel;
use app\admin\model\choujiang\Choujiangset as ChoujiangsetModel;/*** 随机数接口*/
class Choujiang extends Api
{protected $noNeedLogin = ['*'];protected $noNeedRight = ['*'];protected $yilunchoujiagcishu = 10; //一轮抽奖次数protected $default_min_val = 1; //(默认)最小数protected $default_max_val = 10; //(默认)最大数protected $default_geshu = 3; //(默认)个数protected $default_state = 1; //(默认)允许重复:1=是,2=否public function _initialize(){parent::_initialize();if(!((new ChoujiangsetModel())->where(['id'=>['>', 0]])->value('id'))){(new ChoujiangsetModel())->save(['min_val'=>$this->default_min_val,'max_val'=>$this->default_max_val,'geshu'=>$this->default_geshu,'state'=>$this->default_state,]);}if(!((new ChoujiangModel())->where(['id'=>['>', 0]])->value('id'))){$info = (new ChoujiangsetModel())->where(['id'=>['>', 0]])->field('min_val,max_val,geshu,state')->find();(new ChoujiangModel())->save(['min_val'=>$info['min_val'],'max_val'=>$info['max_val'],'geshu'=>$info['geshu'],'state'=>$info['state'],]);}}/*** 生成随机数页面,获取设置** @ApiMethod (GET)* @ApiHeaders (name=token, type=string, required=false, description="请求的Token")*/public function getSet(){try { $info = (new ChoujiangsetModel())->where(['id'=>['>', 0]])->field('min_val,max_val,geshu,state')->find();$this->success("OK", ['info' => $info,]);} catch (Exception $e) {$this->error($e->getMessage());}}/*** 生成随机数页面,修改设置** @ApiMethod (POST)* @ApiHeaders (name=token, type=string, required=false, description="请求的Token")// * @param string $min_val 最小数// * @param string $max_val 最大数* @param string $geshu 个数// * @param string $state 允许重复:1=是,2=否*/public function editSet(){try { $min_val = $this->request->post('min_val/d',1);$max_val = $this->request->post('max_val/d',10);$geshu = $this->request->post('geshu/d',3);$state = $this->request->post('state',1);if(!in_array($geshu, [1,2,3])){$this->error('个数只能设置为1,2,3');}if($min_val >= $max_val){$this->error('最小数应小于最大数');}if($min_val <= 0 || $max_val <= 0){$this->error('最小数和最大数应>0');}if(!in_array($state, [1,2])){$this->error('允许重复只能设置为1,2');}$info = (new ChoujiangsetModel())->where(['id'=>['>', 0]])->field('min_val,max_val,geshu,state')->find();$data = ['min_val' => $min_val,'max_val' => $max_val,'geshu' => $geshu,'state' => $state,];$info->save($data);$choujianginfo = (new ChoujiangModel())->where(['id'=>['>', 0]])->field('min_val,max_val,geshu,state')->order('id desc')->find();// 若配置修改则重置游戏if($choujianginfo['min_val'] != $data['min_val'] || $choujianginfo['max_val'] != $data['max_val'] || $choujianginfo['geshu'] != $data['geshu'] || $choujianginfo['state'] != $data['state']){(new ChoujiangModel())->save(['min_val'=>$data['min_val'],'max_val'=>$data['max_val'],'geshu'=>$data['geshu'],'state'=>$data['state'],]);}$this->success("保存成功", ['info' => $data,]);} catch (Exception $e) {$this->error($e->getMessage());}}/*** 生成随机数页面,生成随机数** @ApiMethod (POST)* @ApiHeaders (name=token, type=string, required=false, description="请求的Token")*/public function choujiang(){try { $newchoujianginfo = (new ChoujiangModel())->where(['id'=>['>', 0]])->field('id,min_val,max_val,geshu,state,neidingcishu,content')->order('id desc')->find();$nextlunci = (new ChoujianglogModel)->getnextLunci($newchoujianginfo['id'], $this->yilunchoujiagcishu); //获取抽奖接下来的轮次$min = $newchoujianginfo['min_val'];$max = $newchoujianginfo['max_val'];$geshu = $newchoujianginfo['geshu'];$state = $newchoujianginfo['state']; $neidingcishu = $newchoujianginfo['neidingcishu']; // 当前轮次抽奖次数$choujiangcishu = (new ChoujianglogModel)->where(['choujiang_id'=>$newchoujianginfo['id'], 'lunci'=>$nextlunci])->group('sign')->count();if($choujiangcishu == 0){ //开始新一轮$numbers = []; // 生成的数字$keyArr = []; //内定数字// 优先将内定数字放入数组if($neidingcishu){foreach(json_decode($neidingcishu, true) as $key=>$value){// 生成数字$key,并确保满足条件($value次)for ($i = 0; $i < $value; $i++) {$numbers[] = $key;}$keyArr[] = $key;}}// 除去内定数字之外的数字集$shuziArr = array_values(array_diff(range($min, $max), $keyArr));// 填补,确保没有超出条件限制shuffle($shuziArr); // 打乱数组顺序$shuziArrwhile = $shuziArr;while (count($numbers) < $geshu*$this->yilunchoujiagcishu) {if(count($shuziArrwhile) <= 0){$shuziArrwhile = $shuziArr;}$shuzi = array_shift($shuziArrwhile);$numbers[] = $shuzi;}// 打乱数组顺序,确保随机性shuffle($numbers);// 允许重复:1=是,2=否if($state == 1){// 分割数组$newNumbers = array_chunk($numbers, $geshu);}else{$newNumbers = [];for ($i = 0; $i < count($numbers); $i += $geshu) {$randomarr = array_values(array_unique(array_slice($numbers, $i, $geshu)));if(count($randomarr) != $geshu){$this->error('抱歉,参数配置错误');}$newNumbers[] = $randomarr;}}$firstArr = array_shift($newNumbers);}else{$newNumbers = json_decode($newchoujianginfo['content'], true);$firstArr = array_shift($newNumbers);}// 保存抽奖记录$choujianglogModel = new ChoujianglogModel();$sign = $choujianglogModel->createSign();$logData = [];foreach($firstArr as $k=>$v){$logData[] = ['choujiang_id'=>$newchoujianginfo['id'], 'lunci'=>$nextlunci,'number'=>$v,'sign'=>$sign,];}$choujianglogModel->allowField(true)->saveAll($logData);// 保存剩余待抽奖项$newchoujianginfo->save(['content'=>json_encode($newNumbers)]);$this->success("OK", ['data' => $firstArr,]);} catch (Exception $e) {$this->error($e->getMessage());}}/*** 内定数字页面,获取数据** @ApiMethod (GET)* @ApiHeaders (name=token, type=string, required=false, description="请求的Token")*/public function getChoujiangSet(){try { $newchoujianginfo = $this->choujiangset();$this->success("OK", ['info' => $newchoujianginfo,]);} catch (Exception $e) {$this->error($e->getMessage());}}private function choujiangset() {$newchoujianginfo = (new ChoujiangModel())->where(['id'=>['>', 0]])->field('id,min_val,max_val,geshu,state,neidingcishu')->order('id desc')->find();$lunci = (new ChoujianglogModel)->getLunci($newchoujianginfo['id'], $this->yilunchoujiagcishu); //获取抽奖当前轮次$neidingcishu_arr = [];if($newchoujianginfo['neidingcishu']){foreach(json_decode($newchoujianginfo['neidingcishu'], true) as $k=>$v){$neidingcishu_arr[] = ['shuzi'=>$k,'cishu'=>$v,'chouzhongcishu'=>(new ChoujianglogModel)->where(['choujiang_id'=>$newchoujianginfo['id'], 'lunci'=>$lunci, 'number'=>$k])->count(),];}}$newchoujianginfo['neidingcishu_arr'] = $neidingcishu_arr;unset($newchoujianginfo['neidingcishu']);$newchoujianginfo['choujiangcishu'] = (new ChoujianglogModel)->where(['choujiang_id'=>$newchoujianginfo['id'], 'lunci'=>$lunci])->group('sign')->count();return $newchoujianginfo;}/*** 内定数字页面,设置出现次数** @ApiMethod (POST)* @ApiHeaders (name=token, type=string, required=false, description="请求的Token")* @param json $neidingcishu json字符串,例如{"1":"5","2":"3"}*/public function editChoujiangSet(){try { $neidingcishu = htmlspecialchars_decode($this->request->post('neidingcishu/s', ''));$neidingcishu = json_decode($neidingcishu, true);// $neidingcishu = $this->request->post()['neidingcishu'];$choujianginfo = (new ChoujiangModel())->where(['id'=>['>', 0]])->order('id desc')->find();if($neidingcishu){$arr = [];$max_cishu = $this->yilunchoujiagcishu * $choujianginfo['geshu'];$cishu = 0;foreach($neidingcishu as $key=>$value){if($key < $choujianginfo['min_val'] || $key > $choujianginfo['max_val']){$this->error('数字应在最小数与最大数之间');}if($choujianginfo['state']==1 && $value > $max_cishu){$this->error('单个数字出现总次数应<='.$max_cishu);}if($choujianginfo['state']==2 && $value > $this->yilunchoujiagcishu){$this->error('单个数字出现总次数应<='.$this->yilunchoujiagcishu);}$cishu += $value;if($cishu > $max_cishu){$this->error('数字出现总次数应<='.$max_cishu);}$arr[$key] = $value;}if($choujianginfo['min_val']+1 == $choujianginfo['max_val'] && count($arr)==2 && $cishu != $max_cishu){$this->error('数字出现总次数应=='.$max_cishu);}$neidingcishu_str = json_encode($arr);}else{$neidingcishu_str = '';}if($choujianginfo['neidingcishu'] != $neidingcishu_str){$info = (new ChoujiangsetModel())->where(['id'=>['>', 0]])->field('min_val,max_val,geshu,state')->find();(new ChoujiangModel())->save(['min_val'=>$info['min_val'],'max_val'=>$info['max_val'],'geshu'=>$info['geshu'],'state'=>$info['state'],'neidingcishu'=>$neidingcishu_str,]);}$newchoujianginfo = $this->choujiangset();$this->success("保存成功", ['info' => $newchoujianginfo,]);} catch (Exception $e) {$this->error($e->getMessage());}}}
sql
CREATE TABLE `fa_choujiang_set` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',`min_val` int(10) DEFAULT '0' COMMENT '最小数',`max_val` int(10) DEFAULT '0' COMMENT '最大数',`geshu` int(10) DEFAULT '0' COMMENT '个数',`state` enum('1','2') DEFAULT '1' COMMENT '允许重复:1=是,2=否',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='抽奖设置表';CREATE TABLE `fa_choujiang` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',`min_val` int(10) DEFAULT '0' COMMENT '最小数',`max_val` int(10) DEFAULT '0' COMMENT '最大数',`geshu` int(10) DEFAULT '0' COMMENT '个数',`state` enum('1','2') DEFAULT '1' COMMENT '允许重复:1=是,2=否',`neidingcishu` text COMMENT '内定次数',`content` text COMMENT '内容',`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',`updatetime` bigint(16) DEFAULT NULL COMMENT '更新时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COMMENT='抽奖表';CREATE TABLE `fa_choujiang_log` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',`choujiang_id` int(10) DEFAULT '0' COMMENT '抽奖ID',`number` int(10) DEFAULT '0' COMMENT '数字',`sign` varchar(100) DEFAULT NULL COMMENT '标识',`lunci` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '轮次(第几轮)',`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',PRIMARY KEY (`id`),KEY `choujiang_id` (`choujiang_id`)
) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8mb4 COMMENT='抽奖记录表';