首页 > 解决方案 > 如何对数组中不断更新的(动态)对象进行排序

问题描述

我正在构建一个经典的 Nim 游戏。到目前为止,我已经完成了玩家部分和游戏部分。现在,我正在尝试对数组中的对象进行排序(排名)。我为排序构建了以下内容:

  1. playerList
  2. winRatio,在NimPlayer类中设置它的吸气剂。

目的 :

  1. 降序排序winRatio,即从最高分到最低分。该比率由 计算score/gamePlayed
  2. 如果有平局,请userName按字母顺序排序。

我提到过这个问题:如何在 Java 中对对象数组进行排序?

我知道我应该做的是使用ComparableorComparator进行排序,但是从文章中,他们使用对象中的属性进行排序(到目前为止我找到的所有信息)。我正在处理的是构造函数之外不断更新的数据。

我尝试的是直接打印出数据而不进行排序。

这是我的相关代码(NimPlayer):

public class NimPlayer {
private String userName;
private String familyName;
private String givenName;

static int counter;
private int score;
private int gamePlayed;
static NimPlayer[] playerList = new NimPlayer[2]; // set an array here

//define NimPlayer data type
public NimPlayer(String userName, String surName, String givenName) {
    this.userName = userName;
    this.familyName = surName;
    this.givenName = givenName;

}
// create new data using NimPlayer data type
public static void createPlayer(String userName, String familyName, String givenName) {
    if (counter<10) {
        playerList[counter++] = new NimPlayer(userName, familyName, givenName);
    } else {
        System.out.println("Cannot add more players.");
    }

// all the getter and setter related to the constructor; the getter of the player list.

}
public void setScore(int score) {
    this.score=score;
}
public int getScore() {
    return score;
}
public void setGamePlayed (int gamePlayed) {
    this.gamePlayed = gamePlayed;
}
public int getGamePlayed() {
    return gamePlayed;
}
public int getWinRatio () {
    return Math.round(Float.valueOf(getScore())/ (getGamePlayed()+1)*100) ;
}
}

这是我的主要课程(Nimsys

public static void searchAndPrintRankingData() {
    for (int i = 0; i < NimPlayer.getCounter(); i++) {

        String familyName = NimPlayer.getPlayer()[i].getFamilyName();
        String givenName = NimPlayer.getPlayer()[i].getGivenName();
        int score = NimPlayer.getPlayer()[i].getScore();
        int gamePlayed = NimPlayer.getPlayer()[i].getGamePlayed();
        double winRatio = score/(gamePlayed+1);//wrong calculation for testing

        System.out.println(winRatio+"% | "+gamePlayed+" games | "+givenName+" "+familyName);
    }
}

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    while (true) {
        System.out.print('$');
        String commandin = in.next();
if (commandin.equals("rankings")) {
            String commandOrder = in.nextLine().trim();

            if (commandOrder.equals("asc")) {
                //sort the data
                searchAndPrintRankingData();
            }

            if (commandOrder.equals("") || commandOrder.equals("desc")) {
                //sort the data

                searchAndPrintRankingData(); 
            }            
        }
        }

非常感谢任何帮助。

标签: javaarrayssorting

解决方案


使用接口比较器

执行以下操作:

import java.util.Arrays;
import java.util.Comparator;

class NimPlayer {
    private String userName;
    private String familyName;
    private String givenName;

    private static int counter;
    private static final int SIZE = 4;
    private int score;
    private int gamePlayed;

    static NimPlayer[] playerList = new NimPlayer[SIZE];

    public NimPlayer(String userName, String surName, String givenName) {
        this.userName = userName;
        this.familyName = surName;
        this.givenName = givenName;
    }

    public static void createPlayer(String userName, String familyName, String givenName) {
        if (counter < SIZE) {
            playerList[counter++] = new NimPlayer(userName, familyName, givenName);
        } else {
            System.out.println("Cannot add more players.");
        }
    }

    public static int getCounter() {
        return counter;
    }

    public static NimPlayer[] getPlayerList() {
        return playerList;
    }

    public String getUserName() {
        return userName;
    }

    public String getFamilyName() {
        return familyName;
    }

    public String getGivenName() {
        return givenName;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public int getScore() {
        return score;
    }

    public void setGamePlayed(int gamePlayed) {
        this.gamePlayed = gamePlayed;
    }

    public int getGamePlayed() {
        return gamePlayed;
    }

    public int getWinRatio() {
        return Math.round((Float.valueOf(score) / gamePlayed) * 100);
    }

    @Override
    public String toString() {
        return "User Name: " + userName + ", Name: " + givenName + " " + familyName + ", Score: " + score
                + ", Games Played: " + gamePlayed + ", Win ratio: " + getWinRatio();
    }

}

public class Main {
    static void searchAndPrintRankingData() {
        NimPlayer[] players = NimPlayer.getPlayerList();
        Arrays.sort(players,
                Comparator.comparing((NimPlayer::getWinRatio)).reversed().thenComparing(NimPlayer::getUserName));

        Arrays.stream(players).forEach(System.out::println);
    }

    public static void main(String[] args) {
        NimPlayer.createPlayer("Avi", "Avinash", "Arvind");
        NimPlayer.createPlayer("Harry", "Potter", "Harry");
        NimPlayer.createPlayer("Vishy", "Anand", "Vishwanathan");
        NimPlayer.createPlayer("Bond", "Bond", "James");

        NimPlayer[] players = NimPlayer.getPlayerList();

        players[0].setGamePlayed(2);
        players[0].setScore(40);

        players[1].setGamePlayed(3);
        players[1].setScore(75);

        players[2].setGamePlayed(2);
        players[2].setScore(120);

        players[3].setGamePlayed(4);
        players[3].setScore(100);

        System.out.println("Unsorted: ");
        Arrays.stream(NimPlayer.getPlayerList()).forEach(System.out::println);

        System.out.println();

        System.out.println("Sorted on win ratio (then name, in case of tie): ");
        searchAndPrintRankingData();
    }
}

输出:

Unsorted: 
User Name: Avi, Name: Arvind Avinash, Score: 40, Games Played: 2, Win ratio: 2000
User Name: Harry, Name: Harry Potter, Score: 75, Games Played: 3, Win ratio: 2500
User Name: Vishy, Name: Vishwanathan Anand, Score: 120, Games Played: 2, Win ratio: 6000
User Name: Bond, Name: James Bond, Score: 100, Games Played: 4, Win ratio: 2500

Sorted on win ratio (then name, in case of tie): 
User Name: Vishy, Name: Vishwanathan Anand, Score: 120, Games Played: 2, Win ratio: 6000
User Name: Bond, Name: James Bond, Score: 100, Games Played: 4, Win ratio: 2500
User Name: Harry, Name: Harry Potter, Score: 75, Games Played: 3, Win ratio: 2500
User Name: Avi, Name: Arvind Avinash, Score: 40, Games Played: 2, Win ratio: 2000

注意:如果您希望使用ArrayList<NimPlayer>in searchAndPrintRankingData,下面给出的是相同的代码:

static void searchAndPrintRankingData() {
    List<NimPlayer> players = new ArrayList<NimPlayer>(Arrays.asList(NimPlayer.getPlayerList()));
    Collections.sort(players,
            Comparator.comparing((NimPlayer::getWinRatio)).reversed().thenComparing(NimPlayer::getUserName));

    players.stream().forEach(System.out::println);
}

推荐阅读