You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java开发赛车模拟器:不修改原数组如何实现车手成绩排名

问题描述

我目前正尝试开发一款赛车模拟器来学习Java编程,已为每位车手及其驾驶的赛车创建了对应的对象数组:

public static Driver drivers[] = new Driver[18];

每位车手关联多项属性值,这些属性会决定车手的比赛表现:

int overall;
int rating;

int corners;
int straightaways;
int rain;
int skill;
int experience;
int pace;
int awareness;

进入比赛流程模拟首场赛事时,我会获取车手的overall属性值(取值范围为50-100),在该值基础上叠加“赛事日幸运值”因素得到未排序的完赛成绩。当前实现的比赛模拟类代码如下:

package races;

import racers.CreateDrivers;
import racers.Driver;

public class RaceSimulator {
    
    // 复制车手数组,暂不确定是否需要
    public Driver currentRace[] = CreateDrivers.drivers.clone(); 
    
    public static void SimulateNextRace() {
        
        System.out.println("\nFirst Race is Beginning!!\n");
        
        int racedayLuck;
        int raceFinishUnsorted;
        
        for(int i = 0; i < CreateDrivers.drivers.length; i++) {
            racedayLuck = (int) (Math.random() * 20 + 1);
            
            raceFinishUnsorted = racedayLuck + CreateDrivers.drivers[i].getOverall();
                        
            CreateDrivers.drivers[i].setRacedayFinish(raceFinishUnsorted);
            System.out.println(CreateDrivers.drivers[i].getName() + ": " + CreateDrivers.drivers[i].getRacedayFinish());
        }
        
        // TODO 完成车手排名逻辑,为对应车手设置积分
    }
    
    public static void getRank() {
        //
    }
    
}

控制台输出示例如下:

First Race is Beginning!!

Joseph Morgan: 90
Malachi Nguyen: 90
Greg Hart: 76
Ian Banks: 78
Gabriel Mcdonald: 84
Spencer Meyer: 94
Jordan Soto: 95
Abraham Wells: 94
Charles Frederiks: 82
Trevor Fleming: 92
Nathaniel Nguyen: 67
Johnathan Herrera: 79
Derek Miller: 88
Grant Reynolds: 86
Kyle Bailey: 82
Conner Sullivan: 98
Paul Perry: 96
Antonio Larson: 87

目前遇到的问题:无法在不对原数组排序的前提下,对所有CreateDrivers.drivers[x]对象的完赛成绩进行排名比对。需要在不修改任何原有属性值的前提下完成车手排名,同时支持为对应车手累加“赛季积分”。之前尝试过为Driver类添加id属性,对id数组排序后再反向匹配对应车手,但认为应当存在更简便的方式来完成18个整型成绩的比对排名。

解决方案

不需要给Driver类额外加id做反向匹配,只需要复制一份原数组的引用做排序,完全不会改动原数组的顺序和原有属性值,实现逻辑非常简单:

  • 首先克隆一份车手数组的副本,注意这里是浅克隆,数组里存的是Driver对象的引用,克隆不会新建Driver对象,也不会修改原数组里的引用顺序,只是生成了一个新的数组容器
  • 对这个副本数组,按照车手的完赛成绩做降序排序(成绩越高排名越靠前)
  • 遍历排序后的副本数组,按照排名给对应车手累加积分即可,整个过程原drivers数组的顺序、车手除了积分之外的属性都不会被改动

直接补全代码里的排名和积分计算逻辑就行,参考实现:

import java.util.Arrays;

public static void calculateRaceResult() {
    // 克隆原数组得到排序用副本,完全不影响原数组顺序
    Driver[] sortedDrivers = CreateDrivers.drivers.clone();

    // 对副本按完赛成绩降序排序,成绩高的排前面
    Arrays.sort(sortedDrivers, (a, b) -> Integer.compare(b.getRacedayFinish(), a.getRacedayFinish()));

    // 积分规则可自行调整,示例采用F1标准积分,索引0对应第一名
    int[] pointsTable = {25, 18, 15, 12, 10, 8, 6, 4, 2, 1};
    for (int rank = 0; rank < sortedDrivers.length; rank++) {
        Driver driver = sortedDrivers[rank];
        System.out.printf("第%d名:%s 成绩:%d%n", rank+1, driver.getName(), driver.getRacedayFinish());
        // 前10名累计积分,剩余名次积0分
        if (rank < pointsTable.length) {
            driver.setPoints(driver.getPoints() + pointsTable[rank]);
        }
    }
}

如果出现成绩相同的情况,上面的写法会按照数组原有的先后顺序排定同名次先后,需要追加平局判定规则(比如过弯属性高的排前面),只需要在比较逻辑里追加判断即可,示例:

Arrays.sort(sortedDrivers, (a, b) -> {
    int scoreCompare = Integer.compare(b.getRacedayFinish(), a.getRacedayFinish());
    if (scoreCompare != 0) {
        return scoreCompare;
    }
    // 成绩相同时比较过弯属性,属性值高的排前面
    return Integer.compare(b.getCorners(), a.getCorners());
});

你之前定义的currentRace数组就是用来承载这个排序副本的,完全不需要额外加id字段做反向匹配,整个实现只需要十余行代码,排序操作仅作用在克隆出的新数组上,原数组的顺序从头到尾都不会发生改变。

内容的提问来源于stack exchange,提问作者Colin Koenig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 08:12:13