排行榜排序以获取玩家排名

时间:2018-10-18 03:23:55

标签: php

我正在尝试根据得分查找球员的记录。如果两个玩家的得分并列,那么玩过很少游戏的玩家将排名最高。如果两名球员在得分和打牌次数上并列,那么在球员名单上第一名的球员排名更高。

这是到目前为止我尝试过的代码。

http://sandbox.onlinephpfunctions.com/code/ca5f93990e1cb6a69bbbd734afde32f1ffa51522

但是我得到的答案不正确。

   <?php
    class LeagueTable
    {
        public function __construct($players)
        {
            $this->standings = array();
            foreach($players as $index => $p)
            {
                $this->standings[$p] = array
                (
                    'index' => $index,
                    'games_played' => 0, 
                    'score' => 0
                );
            }
        }

    public function recordResult($player, $score)
    {
        $this->standings[$player]['games_played']++;
        $this->standings[$player]['score'] += $score;
    }

    public function playerRank($rank)
    {
        $ranks = $this->standings;
        uasort($ranks, function ($a, $b) {
            if ($a['score'] >= $b['score']) {
                if ($a['score'] == $b['score']) {
                    if ($a['games_played'] >= $b['games_played']) {
                        if ($a['games_played'] == $b['games_played']) {
                            return $a['index'] > $b['index'];
                        } else {
                            return true;
                        }
                    } else {
                        return false;
                    }
                } else {
                    return true;
                }
            } else {
                return false;
            }
        });

        print_r($this->standings);
    }
}

$table = new LeagueTable(array('Mike', 'Chris', 'Arnold'));
$table->recordResult('Mike', 2);
$table->recordResult('Mike', 3);
$table->recordResult('Arnold', 5);
$table->recordResult('Chris', 5);
echo $table->playerRank(1);

结果

  I am getting Array 
    ( 
        [Mike] => Array 
            ( 
                [index] => 0 
                [games_played] => 2 
                [score] => 5 
            ) 

        [Chris] => Array 
            ( 
                [index] => 1 
                [games_played] => 1 
                [score] => 5 
            ) 

        [Arnold] => Array 
            ( 
                [index] => 2 
                [games_played] => 1 
                [score] => 5 
            ) 

    )  BUT my test says Example case: Wrong answer 
      Players have different scores: Wrong answer 
      Players tied by score: Wrong answer 
      Players tied by games played: Wrong answer 

4 个答案:

答案 0 :(得分:3)

此功能将执行您想要的操作。棘手的部分是您希望玩家获得最高得分或最低游戏次数或最低指数。因此,games_playedindex的排序中每个测试的条件与score的条件不同。排序后,我们返回与$rank变量关联的键,请记住排名从1开始,但键数组从0开始,所以我们必须从$rank减去1。

public function playerRank($rank)
{
    $ranks = $this->standings;
    uasort($ranks, function ($a, $b) {
        // sort by score
        if ($a['score'] != $b['score']) 
            return ($a['score'] > $b['score']) ? -1 : 1;
        // equal! sort by games played
        if ($a['games_played'] != $b['games_played'])
            return ($a['games_played'] < $b['games_played']) ? -1 : 1;
        // equal! sort by index
        return ($a['index'] < $b['index']) ? -1 : 1;
    });

    return array_keys($ranks)[$rank-1];
}

我已经在https://www.testdome.com/questions/php/league-table/15401?visibility=1测试了此代码,并通过了所有测试。

答案 1 :(得分:1)

uasort需要返回0,-1或1。我还进行了一些重新排列。您还需要使用发送的$rank返回播放器并结束播放。

public function playerRank($rank) {
    // sort standings
    uasort($this->standings, function ($a, $b) {
        if($a['score'] == $b['score']) {
            if($a['games_played'] == $b['games_played']) {
                if($a['index'] == $b['index']) {
                    return 0;
                }
                return $a['index'] < $b['index'] ? -1 : 1;
            }
            return $a['games_played'] < $b['games_played'] ? -1 : 1;
        }
        return $a['score'] < $b['score'] ? -1 : 1;
    });
    // return player at rank
    return print_r($this->standing[$rank], 1);
}

答案 2 :(得分:1)

使用php函数数组multisort()

http://www.php.net/array_multisort

<?php
    class LeagueTable
    {
        public function __construct($players)
        {
            $this->standings = array();
            foreach($players as $index => $p)
            {
                $this->standings[$p] = array
                (
                    'index' => $index,
                    'games_played' => 0, 
                    'score' => 0
                );
            }
        }

    public function recordResult($player, $score)
    {
        $this->standings[$player]['games_played']++;
        $this->standings[$player]['score'] += $score;
    }


    public function playerRank()
    {
        $data = $this->standings;


        array_multisort(array_column($data, 'score'),  SORT_DESC,
                array_column($data, 'games_played'), SORT_ASC,
                array_column($data, 'index'), SORT_ASC,
                $data);

        print_r($data);
    }
}

$table = new LeagueTable(array('Mike', 'Chris', 'Arnold'));
$table->recordResult('Mike', 2);
$table->recordResult('Mike', 3);
$table->recordResult('Arnold', 5);
$table->recordResult('Chris', 5);
echo $table->playerRank();

答案 3 :(得分:0)

使用array_multisort()函数,我的回答有所改善,并且 我已经在测试了此代码 https://www.testdome.com/questions/php/league-table/15401?visibility=1,它通过了所有测试。

   public function playerRank(int $rank) : string
    {

        $data = $this->standings;
        $sorted_data=[];

        array_multisort(
                array_column($data, 'score'),  SORT_DESC,
                array_column($data, 'games_played'), SORT_ASC,
                array_column($data, 'index'), SORT_ASC,
                $data);

         $current_rank = 1;
         foreach($data as $player_name => $value)
         {
            $sorted_data['rank'] = $current_rank;
            $sorted_data[$current_rank]['name'] = $player_name;
            $current_rank++;
         }

    return $sorted_data[strval($rank)]["name"];
    }