改进足球模拟算法

caw*_*caw 7 php simulation

在另一个问题中,你帮我建立了足球模拟算法.我在那里得到了一些非常好的答案.再次感谢!

现在我编写了这个算法.我想改进它并找到可能存在的小错误.我不想讨论如何解决它 - 正如我们在上一个问题中所做的那样.现在我只想改进它.你能再帮我一次吗?

  1. 有什么错误吗?
  2. 嵌套的if子句的结构是否正确?可以改进吗?
  3. 根据我的描述,战术是否正确整合?

应该对随机性产生影响的战术设置:

  • $ tactics [x] [0]调整(1 =防守,2 =中立,3 =进攻):价值越高,防守越弱,进攻越强
  • $ tactics x游戏速度(1 =慢速,2 =中等,3 =快速):值越大,机会越多但获得快速反击的风险越高
  • $ tactics x传球距离(1 =短,2 =中,3 =长):值越高越少但获得的机会越多,越位越快
  • $ tactics x创造变化(1 =安全,2 =中等,3 =有风险):价值越高,你的机会越多,但获得快速反击的风险越高
  • $ tactics [x] [4]防守压力(1 =低,2 =中等,3 =高):值越大,反击越快你就会有
  • $ tactics [x] [5]攻击性(1 =低,2 =中等,3 =高):值越大,你将被犯规所阻止的攻击越多

注意: Tactic 0和tactic 4部分集成在引擎的其余部分,此功能不需要.

目前的算法:

<?php
function tactics_weight($wert) {
    $neuerWert = $wert*0.1+0.8;
    return $neuerWert;
}
function strengths_weight($wert) {
    $neuerWert = log10($wert+1)+0.35;
    return $neuerWert;
}
function Chance_Percent($chance, $universe = 100) {
    $chance = abs(intval($chance));
    $universe = abs(intval($universe));
    if (mt_rand(1, $universe) <= $chance) {
        return true;
    }
    return false;
}
function simulate_attack($teamname_att, $teamname_def, $strength_att, $strength_def) {
    global $minute, $goals, $_POST, $matchReport, $fouls, $yellowCards, $redCards, $offsides, $shots, $tactics;
    // input values: attacker's name, defender's name, attacker's strength array, defender's strength array
    // players' strength values vary from 0.1 to 9.9
    $matchReport .= '<p>'.$minute.'\': '.comment_action($teamname_att, 'attack');
    $offense_strength = $strength_att['forwards']/$strength_def['defenders'];
    $defense_strength = $strength_def['defenders']/$strength_att['forwards'];
    if (Chance_Percent(50*$offense_strength*tactics_weight($tactics[$teamname_att][1])/tactics_weight($tactics[$teamname_att][2]))) {
        // attacking team passes 1st third of opponent's field side
        $matchReport .= ' '.comment_action($teamname_def, 'advance');
        if (Chance_Percent(25*tactics_weight($tactics[$teamname_def][5]))) {
            // the defending team fouls the attacking team
            $fouls[$teamname_def]++;
            $matchReport .= ' '.comment_action($teamname_def, 'foul');
            if (Chance_Percent(43)) {
                // yellow card for the defending team
                $yellowCards[$teamname_def]++;
                $matchReport .= ' '.comment_action($teamname_def, 'yellow');
            }
            elseif (Chance_Percent(3)) {
                // red card for the defending team
                $redCards[$teamname_def]++;
                $matchReport .= ' '.comment_action($teamname_def, 'red');
            }
            // indirect free kick
            $matchReport .= ' '.comment_action($teamname_att, 'iFreeKick');
            if (Chance_Percent(25*strengths_weight($strength_att['forwards']))) {
                // shot at the goal
                $shots[$teamname_att]++;
                $matchReport .= ' '.comment_action($teamname_att, 'iFreeKick_shot');
                if (Chance_Percent(25/strengths_weight($strength_def['goalkeeper']))) {
                    // attacking team scores
                    $goals[$teamname_att]++;
                    $matchReport .= ' '.comment_action($teamname_att, 'shot_score');
                }
                else {
                    // defending goalkeeper saves
                    $matchReport .= ' '.comment_action($teamname_def, 'iFreeKick_shot_save');
                }
            }
            else {
                // defending team cleares the ball
                $matchReport .= ' '.comment_action($teamname_def, 'iFreeKick_clear');
            }
        }
        elseif (Chance_Percent(17)*tactics_weight($tactics[$teamname_att][2])) {
            // attacking team is caught offside
            $offsides[$teamname_att]++;
            $matchReport .= ' '.comment_action($teamname_def, 'offside');
        }
        else {
            // attack isn't interrupted
            // attack passes the 2nd third of the opponent's field side - good chance
            $matchReport .= ' '.comment_action($teamname_def, 'advance_further');
            if (Chance_Percent(25*tactics_weight($tactics[$teamname_def][5]))) {
                // the defending team fouls the attacking team
                $fouls[$teamname_def]++;
                $matchReport .= ' '.comment_action($teamname_def, 'foul');
                if (Chance_Percent(43)) {
                    // yellow card for the defending team
                    $yellowCards[$teamname_def]++;
                    $matchReport .= ' '.comment_action($teamname_def, 'yellow');
                }
                elseif (Chance_Percent(3)) {
                    // red card for the defending team
                    $redCards[$teamname_def]++;
                    $matchReport .= ' '.comment_action($teamname_def, 'red');
                }
                if (Chance_Percent(19)) {
                    // penalty for the attacking team
                    $shots[$teamname_att]++;
                    $matchReport .= ' '.comment_action($teamname_att, 'penalty');
                    if (Chance_Percent(77)) {
                        // attacking team scores
                        $goals[$teamname_att]++;
                        $matchReport .= ' '.comment_action($teamname_att, 'shot_score');
                    }
                    elseif (Chance_Percent(50)) {
                        // shot misses the goal
                        $matchReport .= ' '.comment_action($teamname_att, 'penalty_miss');
                    }
                    else {
                        // defending goalkeeper saves
                        $matchReport .= ' '.comment_action($teamname_def, 'penalty_save');
                    }
                }
                else {
                    // direct free kick
                    $matchReport .= ' '.comment_action($teamname_att, 'dFreeKick');
                    if (Chance_Percent(33*strengths_weight($strength_att['forwards']))) {
                        // shot at the goal
                        $shots[$teamname_att]++;
                        $matchReport .= ' '.comment_action($teamname_att, 'dFreeKick_shot');
                        if (Chance_Percent(33/strengths_weight($strength_def['goalkeeper']))) {
                            // attacking team scores
                            $goals[$teamname_att]++;
                            $matchReport .= ' '.comment_action($teamname_att, 'shot_score');
                        }
                        else {
                            // defending goalkeeper saves
                            $matchReport .= ' '.comment_action($teamname_def, 'dFreeKick_shot_save');
                        }
                    }
                    else {
                        // defending team cleares the ball
                        $matchReport .= ' '.comment_action($teamname_def, 'dFreeKick_clear');
                    }
                }
            }
            elseif (Chance_Percent(62*strengths_weight($strength_att['forwards'])*tactics_weight($tactics[$teamname_att][2])*tactics_weight($tactics[$teamname_att][3]))) {
                // shot at the goal
                $shots[$teamname_att]++;
                $matchReport .= ' '.comment_action($teamname_att, 'shot');
                if (Chance_Percent(30/strengths_weight($strength_def['goalkeeper']))) {
                    // the attacking team scores
                    $goals[$teamname_att]++;
                    $matchReport .= ' '.comment_action($teamname_att, 'shot_score');
                }
                else {
                    if (Chance_Percent(50)) {
                        // the defending defenders block the shot
                        $matchReport .= ' '.comment_action($teamname_def, 'shot_block');
                    }
                    else {
                        // the defending goalkeeper saves
                        $matchReport .= ' '.comment_action($teamname_def, 'shot_save');
                    }
                }
            }
            else {
                // attack is stopped
                $matchReport .= ' '.comment_action($teamname_def, 'stopped');
                if (Chance_Percent(15*$defense_strength*tactics_weight($tactics[$teamname_att][1])*tactics_weight($tactics[$teamname_att][3])*tactics_weight($tactics[$teamname_def][4]))) {
                    // quick counter attack - playing on the break
                    $strength_att['defenders'] = $strength_att['defenders']*0.8; // weaken the current attacking team's defense
                    $matchReport .= ' '.comment_action($teamname_def, 'quickCounterAttack');
                    $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line
                    return simulate_attack($teamname_def, $teamname_att, $strength_def, $strength_att); // new attack - this one is finished
                }
            }
        }
    }
    // attacking team doesn't pass 1st third of opponent's field side
    elseif (Chance_Percent(15*$defense_strength*tactics_weight($tactics[$teamname_att][1])*tactics_weight($tactics[$teamname_att][3])*tactics_weight($tactics[$teamname_def][4]))) {
        // attack is stopped
        // quick counter attack - playing on the break
        $matchReport .= ' '.comment_action($teamname_def, 'stopped');
        $strength_att['defenders'] = $strength_att['defenders']*0.8; // weaken the current attacking team's defense
        $matchReport .= ' '.comment_action($teamname_def, 'quickCounterAttack');
        $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line
        return simulate_attack($teamname_def, $teamname_att, $strength_def, $strength_att); // new attack - this one is finished
    }
    else {
        // ball goes into touch - out of the field
        $matchReport .= ' '.comment_action($teamname_def, 'throwIn');
        if (Chance_Percent(33)) {
            // if a new chance is created
            if (Chance_Percent(50)) {
                // throw-in for the attacking team
                $matchReport .= ' '.comment_action($teamname_def, 'throwIn_att');
                $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line
                return simulate_attack($teamname_att, $teamname_def, $strength_att, $strength_def); // new attack - this one is finished
            }
            else {
                // throw-in for the defending team
                $matchReport .= ' '.comment_action($teamname_def, 'throwIn_def');
                $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line
                return simulate_attack($teamname_def, $teamname_att, $strength_def, $strength_att); // new attack - this one is finished
            }
        }
    }
    $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line
    return TRUE; // finish the attack
}
Run Code Online (Sandbox Code Playgroud)

更新(2014年):几年后,我现在已经在GitHub上发布了游戏的完整代码库作为开源.如果有兴趣的话,您可以在此文件中找到此模拟的具体实现.

cwa*_*ole 8

一般来说,这看起来是一个相当复杂的问题,我不确定你会得到多少效率.

也就是说,我已经看到了一些可以帮助你的东西.

首先,我将在参数中键入变量.这可能不一定会使您的代码更快,但它会使它更容易阅读和调试.接下来,我将删除$ teamname_att,$ teamname_def参数,并将它们作为关联$ strength_att,$ strength_def数组中的值.由于这些数据总是配对,这将降低意外使用一个团队名称作为对另一个团队的参考的风险.

这将使您不必在数组中不断查找值:

// replace all $tactics[$teamname_att] with $attackers
$attackers = $tactics[$teamname_att]; 
$defenders = $tactics[$teamname_def];
// Now do the same with arrays like $_POST[ "team1" ];
Run Code Online (Sandbox Code Playgroud)

你有三个辅助函数,都有这个模式:

function foo( $arg ){
    $bar = $arg * $value;
    return $bar;
}
Run Code Online (Sandbox Code Playgroud)

因为这意味着每次运行函数时都必须创建一个额外的变量(可能代价很高),请使用以下变量:

function tactics_weight($wert) {
    return $wert*0.1+0.8;
}

function strengths_weight($wert) {
    return log10($wert+1)+0.35;
}

/*
 Perhaps I missed it, but I never saw Chance_Percent( $num1, $num2 )
 consider using this function instead: (one line instead of four, it also
 functions more intuitively, Chance_Percent is your chance out of 100 
 (or per cent)

 function Chance_Percent( $chance ) {
     return (mt_rand(1, 100) <= $chance);
 }    

*/
function Chance_Percent($chance, $universe = 100) {
    $chance = abs(intval($chance)); // Will you always have a number as $chance?
                                    // consider using only abs( $chance ) here.
    $universe = abs(intval($universe));
    return (mt_rand(1, $universe) <= $chance);
}
Run Code Online (Sandbox Code Playgroud)

我忍不住注意到这种模式一直在出现:

$matchReport .= ' ' . comment_action($teamname_att, 'attack');
Run Code Online (Sandbox Code Playgroud)

我的一般经验是,如果你将$ matchReport的连接移动到comment_action,那么它会快一些(通常不到十几毫秒,但是因为你在递归函数中调用了这个函数的六倍,这可能每次跑步减少十分之几秒.

我认为这会更好(从读者的角度来看,也可以从

最后,有几次您将使用相同参数对同一函数使用相同的调用.提前打电话:

$goalieStrength = strengths_weight($strength_def['goalkeeper']);
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.


Jas*_*ers 5

我(很快)通读了它,我发现了一些事情:

  • 发出红色/黄色卡的百分比在该领域的所有三分之一中是相同的,这是故意的吗?我不是一个足球运动员,但是我会说这场比赛的最后三分之一比第一场更容易发生.(因为如果你是第一个,你可能会捍卫)

  • 确定罚分的百分比对于每支球队来说都是相同的,但是一些球队,或者更确切地说是球员,比其他球队更有可能得分.

  • 你没有考虑角球,犯规后可能造成的伤病,或使用头部进球(这可能在报告中值得一提).

除此之外,你只需要运行这个仿真很多次,看看你选择的值是正确的; 调整算法.最好的办法是手动调整它(例如,从文件中读取所有常量并运行几百个具有不同值和不同团队的模拟),最简单的方法是实现遗传算法来尝试查找更好的价值观

基本上你所拥有的是真正的游戏玩法/ ai代码,所以你可能想要阅读游戏工作室用来管理这类代码的技术.(有一点是将变量放在谷歌电子表格中,然后你可以更轻松地共享/调整).

此外,即使你错过了真正的足球比赛所具有的一些东西,也没有必要尽可能地做到真实,因为通常在这些情况下提供漂亮的游戏玩法比提供准确的模拟更重要.


Jam*_*son 5

好像似乎不见了: -

#include oscar.h;
void function dive (int ball_location, int[] opposition, int[] opposition_loc) {
    if (this.location != PenaltyBox || ball_location != PenatlyBox)
       return;
    } else {
       for (x = 0; x < 11; x++) {
           if ( opposition_loc[x] = PenaltyBox ) {
               scream(loudly);
               falldown();
               roll_around();
               cry();
               roll_around();
               scream(patheticaly);
               plead_with_ref();
               return;
            }
     }
     return;
}
Run Code Online (Sandbox Code Playgroud)