我编写了一些代码来跟踪buff,作为流行游戏《英雄联盟》的补充。

我的代码非常重复,而且还存在无法跟踪多个buff的问题,尽管那可能不是该问题的主题,所以回答时请不要考虑这一点。

import java.util.Scanner;


public class MainProgram {

    public static void main(String[] args) {

        Scanner keyboard = new Scanner(System.in);    

        System.out.println("Jungle Timers v1.0");

        System.out.println("\nSelect a buff to time:");
        System.out.println("\n1. Blue");
        System.out.println("2. Enemy Blue");
        System.out.println("3. Red");
        System.out.println("4. Enemy Red");
        System.out.println("5. Dragon");
        System.out.println("6. Baron");

        System.out.print("\n>  ");
        int timerChoice = keyboard.nextInt();

        keyboard.close();

        switch (timerChoice) {
        case 1:
            friendlyBlue();
        case 2:
            enemyBlue();
        case 3:
            friendlyRed();
        case 4:
            enemyRed();
        case 5:
            Dragon();
        case 6:
            Baron();
            }

    }

    public static void friendlyBlue() {
        System.out.println("\nTracking your blue...");
        System.out.println("5 Minutes left");
        int friendlyBlue = 300;
        long startTime = System.currentTimeMillis() / 1000;
        long endTime = startTime + friendlyBlue;

        while (System.currentTimeMillis() / 1000 < endTime) {
            while (startTime != System.currentTimeMillis() / 1000) {
                startTime += 1;
                if (endTime - startTime > 1)
                    if (endTime - startTime == 240)
                        System.out.println("4 Minutes left");
                    if (endTime - startTime == 180)
                        System.out.println("3 Minutes left");
                    if (endTime - startTime == 120)
                        System.out.println("2 Minutes left");
                    if (endTime - startTime == 60)
                        System.out.println("1 Minute left");
                    if (endTime - startTime == 30)
                        System.out.println("30 Seconds left");
                    if (endTime - startTime == 15)
                        System.out.println("15 Seconds left");
                    if (endTime - startTime == 5)
                        System.out.println("5 Seconds left");
                else if (endTime - startTime == 1) {
                    System.out.println("Blue Buff is up!");
                }
            }
        }
    }

    public static void enemyBlue() {
        System.out.println("\nTracking enemy blue...");
        System.out.println("5 Minutes left");
        int enemyBlue = 300;
        long startTime = System.currentTimeMillis() / 1000;
        long endTime = startTime + enemyBlue;

        while (System.currentTimeMillis() / 1000 < endTime) {
            while (startTime != System.currentTimeMillis() / 1000) {
                startTime += 1;
                if (endTime - startTime > 1)
                    if (endTime - startTime == 240)
                        System.out.println("4 Minutes left");
                    if (endTime - startTime == 180)
                        System.out.println("3 Minutes left");
                    if (endTime - startTime == 120)
                        System.out.println("2 Minutes left");
                    if (endTime - startTime == 60)
                        System.out.println("1 Minute left");
                    if (endTime - startTime == 30)
                        System.out.println("30 Seconds left");
                    if (endTime - startTime == 15)
                        System.out.println("15 Seconds left");
                    if (endTime - startTime == 5)
                        System.out.println("5 Seconds left");
                else if (endTime - startTime == 1) {
                    System.out.println("Enemy Blue Buff is up!");
                }
            }
        }
    }

    public static void friendlyRed() {
        System.out.println("\nTracking your red...");
        System.out.println("5 Minutes left");
        int friendlyRed = 300;
        long startTime = System.currentTimeMillis() / 1000;
        long endTime = startTime + friendlyRed;

        while (System.currentTimeMillis() / 1000 < endTime) {
            while (startTime != System.currentTimeMillis() / 1000) {
                startTime += 1;
                if (endTime - startTime > 1)
                    if (endTime - startTime == 240)
                        System.out.println("4 Minutes left");
                    if (endTime - startTime == 180)
                        System.out.println("3 Minutes left");
                    if (endTime - startTime == 120)
                        System.out.println("2 Minutes left");
                    if (endTime - startTime == 60)
                        System.out.println("1 Minute left");
                    if (endTime - startTime == 30)
                        System.out.println("30 Seconds left");
                    if (endTime - startTime == 15)
                        System.out.println("15 Seconds left");
                    if (endTime - startTime == 5)
                        System.out.println("5 Seconds left");
                else if (endTime - startTime == 1) {
                    System.out.println("Red Buff is up!");
                }
            }
        }
    }

    public static void enemyRed() {
        System.out.println("\nTracking enemy red...");
        System.out.println("5 Minutes left");
        int enemyRed = 300;
        long startTime = System.currentTimeMillis() / 1000;
        long endTime = startTime + enemyRed;

        while (System.currentTimeMillis() / 1000 < endTime) {
            while (startTime != System.currentTimeMillis() / 1000) {
                startTime += 1;
                if (endTime - startTime > 1)
                    if (endTime - startTime == 240)
                        System.out.println("4 Minutes left");
                    if (endTime - startTime == 180)
                        System.out.println("3 Minutes left");
                    if (endTime - startTime == 120)
                        System.out.println("2 Minutes left");
                    if (endTime - startTime == 60)
                        System.out.println("1 Minute left");
                    if (endTime - startTime == 30)
                        System.out.println("30 Seconds left");
                    if (endTime - startTime == 15)
                        System.out.println("15 Seconds left");
                    if (endTime - startTime == 5)
                        System.out.println("5 Seconds left");
                else if (endTime - startTime == 1) {
                    System.out.println("Enemy Red Buff is up!");
                }
            }
        }
    }

    public static void Dragon() {
        System.out.println("\nTracking dragon...");
        System.out.println("6 Minutes left");
        int dragon = 360;
        long startTime = System.currentTimeMillis() / 1000;
        long endTime = startTime + dragon;

        while (System.currentTimeMillis() / 1000 < endTime) {
            while (startTime != System.currentTimeMillis() / 1000) {
                startTime += 1;
                if (endTime - startTime > 1)
                    if (endTime - startTime == 300)
                        System.out.println("5 Minutes left");
                    if (endTime - startTime == 240)
                        System.out.println("4 Minutes left");
                    if (endTime - startTime == 180)
                        System.out.println("3 Minutes left");
                    if (endTime - startTime == 120)
                        System.out.println("2 Minutes left");
                    if (endTime - startTime == 60)
                        System.out.println("1 Minute left");
                    if (endTime - startTime == 30)
                        System.out.println("30 Seconds left");
                    if (endTime - startTime == 15)
                        System.out.println("15 Seconds left");
                    if (endTime - startTime == 5)
                        System.out.println("5 Seconds left");
                else if (endTime - startTime == 1) {
                    System.out.println("Dragon is up!");
                }
            }
        }
    }

    public static void Baron() {
        System.out.println("\nTracking baron...");
        System.out.println("7 Minutes left");
        int baron = 420;
        long startTime = System.currentTimeMillis() / 1000;
        long endTime = startTime + baron;

        while (System.currentTimeMillis() / 1000 < endTime) {
            while (startTime != System.currentTimeMillis() / 1000) {
                startTime += 1;
                if (endTime - startTime > 1)
                    if (endTime - startTime == 360)
                        System.out.println("6 Minutes left");
                    if (endTime - startTime == 300)
                        System.out.println("5 Minutes left");
                    if (endTime - startTime == 240)
                        System.out.println("4 Minutes left");
                    if (endTime - startTime == 180)
                        System.out.println("3 Minutes left");
                    if (endTime - startTime == 120)
                        System.out.println("2 Minutes left");
                    if (endTime - startTime == 60)
                        System.out.println("1 Minute left");
                    if (endTime - startTime == 30)
                        System.out.println("30 Seconds left");
                    if (endTime - startTime == 15)
                        System.out.println("15 Seconds left");
                    if (endTime - startTime == 5)
                        System.out.println("5 Seconds left");
                else if (endTime - startTime == 1) {
                    System.out.println("Baron is up!");
                }
            }
        }
    }
}


评论

您知道吗,已经存在类似的东西? blog.overwolf.com/releases/overwolf-version-0-33-199-released

@ Vogel612我知道,但是出于学习目的,这对我来说似乎很有趣:-)

@ Vogel612实际上很多东西。包括无数的应用程序。话虽如此,您好世界存在100584902次,并且每天都有新代码对其进行编码。 OP肯定在这里学到了一些有关方法/功能的宝贵知识。

#1 楼

(相对严格的审查...提前道歉)
我认为关于您的代码最不正确的两个问题是有缺陷的switch语句和错误的计时机制选择。使用这些机制的决定导致了糟糕的OOP设计。
但是,首先,切换错误:

switch (timerChoice) {
case 1:
    friendlyBlue();
case 2:
    enemyBlue();
case 3:
    friendlyRed();
case 4:
    enemyRed();
case 5:
    Dragon();
case 6:
    Baron();
    }


如果用户选择1,他们会做的一切!!!您的切换用例应“中断”:
switch (timerChoice) {
case 1:
    friendlyBlue();
    break;
case 2:
    enemyBlue();
    break;
case 3:
    friendlyRed();
    break;
case 4:
    enemyRed();
    break;
case 5:
    Dragon();
    break;
case 6:
    Baron();
    break;
    }

与代码约定有关的其他问题(例如Baron中的大写B以及Dragon中的D不太重要)。 Java中的代码是“失败”的,除非您希望同时执行以下语句,否则还需要中断。
计时器
对于Java中的任何计时问题,正确的解决方案是使用该库计时器功能。在最新的Java版本中,正确的工具是ScheduledExecutorService。这项服务可让您安排将来的任务。
我将其构建为:
private final class TimedEvent {
    private final long preTarget;
    private final String message;
    TimedEvent(long millis, String message) {
        this.preTarget = millis;
        this.message = message;
    }
    private long delayTo(final long target) {
        return target - preTarget;
    }
}

.....

public static final TimedEvent[] EVENTS = {
    new TimedEvent(240000, "4 Minutes left"),
    new TimedEvent(180000, "3 Minutes left"),
    new TimedEvent(120000, "2 Minutes left"),
    new TimedEvent(60000,  "1 Minute left"),
    new TimedEvent(30000,  "30 Seconds left"),
    new TimedEvent(15000,  "15 Seconds left"),
    new TimedEvent(5000,   "5 Seconds left"),
    new TimedEvent(1000,   "1 Second left")
};

....

然后,在设置了TimedEvents的情况下,您可以循环调度它们,倒计时到目标时间.....
final long now = System.currentTimeMillis();
final long target = now + sometime; /// whatever you are counting down to....
for (final TimedEvent te : EVENTS) {
    long delay = te.delayTo(target);
    if (delay >= 0) {
        Callable<Object> torun = new Callable<Void>() {
            public void call() {
                System.out.println(te.getMessage());
                return null;
            }
        }
        scheduler.schedule(torun, delay, TimeUnit.MILLISECONDS);
    }
}


#2 楼

您可以拉出每个函数的while循环并使其成为自己的函数。这样的事情

private static void Countdown(long startTime, long endTime, string finalMsg){
    while (System.currentTimeMillis() / 1000 < endTime) {
        while (startTime != System.currentTimeMillis() / 1000) {
            startTime += 1;
            if (endTime - startTime > 1) {
                if (endTime - startTime == 240)
                    System.out.println("4 Minutes left");
                if (endTime - startTime == 180)
                    System.out.println("3 Minutes left");
                if (endTime - startTime == 120)
                    System.out.println("2 Minutes left");
                if (endTime - startTime == 60)
                    System.out.println("1 Minute left");
                if (endTime - startTime == 30)
                    System.out.println("30 Seconds left");
                if (endTime - startTime == 15)
                    System.out.println("15 Seconds left");
                if (endTime - startTime == 5)
                    System.out.println("5 Seconds left");
            } else if (endTime - startTime == 1) {
                System.out.println(finalMsg);
            }
        }
}


然后从每个函数调用Countdown函数。我认为它看起来会更干净一些,并且不会重复。

评论


\ $ \ begingroup \ $
我还要预先计算endTime-startTime以提高性能。如果操作正确,您甚至可以缩短参数列表,然后...
\ $ \ endgroup \ $
–Vogel612♦
2014年4月24日14:42

\ $ \ begingroup \ $
@ Vogel612一个不错的编译器会为您进行优化。
\ $ \ endgroup \ $
–法老王
2014年4月24日19:38在

\ $ \ begingroup \ $
一个为什么总是写显式花括号的完美例子。同样,重复的if语句应使用else if链接。更好的是,使用开关块。 (我看到@JerryCoffin已经解决了这个问题。)
\ $ \ endgroup \ $
– 200_success
14-4-25在3:32



#3 楼

首先:我认为@DFord提出的观点非常好。

其次,我认为您应该更好地缩进代码。特别是,您的主要if / then / else链的缩进具有误导性:

        if (endTime - startTime > 1)
            if (endTime - startTime == 360)
                System.out.println("6 Minutes left");
            if (endTime - startTime == 300)
                System.out.println("5 Minutes left");
            if (endTime - startTime == 240)
                System.out.println("4 Minutes left");
            if (endTime - startTime == 180)
                System.out.println("3 Minutes left");
            if (endTime - startTime == 120)
                System.out.println("2 Minutes left");
            if (endTime - startTime == 60)
                System.out.println("1 Minute left");
            if (endTime - startTime == 30)
                System.out.println("30 Seconds left");
            if (endTime - startTime == 15)
                System.out.println("15 Seconds left");
            if (endTime - startTime == 5)
                System.out.println("5 Seconds left");
        else if (endTime - startTime == 1) {
            System.out.println("Foo is up!");


else遵循这样的if语句链时,它会附加到最近没有其他的if。一个if语句仅控制一个以下语句(如果要控制多个语法语句,则该语句必须是复合语句)。换句话说,代码的确像:

if (endTime - startTime > 1)
    if (endTime - startTime == 360)
        System.out.println("6 Minutes left");

// The following are evaluated regardless of whether the `> 1` condition was met
if (endTime - startTime == 300)
    System.out.println("5 Minutes left");
if (endTime - startTime == 240)
    System.out.println("4 Minutes left");
if (endTime - startTime == 180)
    System.out.println("3 Minutes left");
if (endTime - startTime == 120)
    System.out.println("2 Minutes left");
if (endTime - startTime == 60)
    System.out.println("1 Minute left");
if (endTime - startTime == 30)
    System.out.println("30 Seconds left");
if (endTime - startTime == 15)
    System.out.println("15 Seconds left");
if (endTime - startTime == 5)
    System.out.println("5 Seconds left");
else if (endTime - startTime == 1) {
    System.out.println("Foo is up!");


基于您的缩进,您显然希望它更像这样:

if (endTime - startTime > 1) {
    if (endTime - startTime == 360)
        System.out.println("6 Minutes left");
    if (endTime - startTime == 300)
        System.out.println("5 Minutes left");
    if (endTime - startTime == 240)
        System.out.println("4 Minutes left");
    if (endTime - startTime == 180)
        System.out.println("3 Minutes left");
    if (endTime - startTime == 120)
        System.out.println("2 Minutes left");
    if (endTime - startTime == 60)
        System.out.println("1 Minute left");
    if (endTime - startTime == 30)
        System.out.println("30 Seconds left");
    if (endTime - startTime == 15)
        System.out.println("15 Seconds left");
    if (endTime - startTime == 5)
        System.out.println("5 Seconds left");
}
else if (endTime - startTime == 1) {
    System.out.println("Foo is up!");


在这种情况下,花括号阻止了else附着在紧接的if上,迫使其附着在您显然打算使用的if上。

尽管最初可能似乎(或什至)有些浪费,我倾向于完全避免该问题:我可能会把要打印的语句放到某种Map中,而不是一堆if语句,然后在其中进行查找映射并打印给定时间的关联值(如果有的话)。

// In real code, you'll need to pick some class that implements the Map interface,
// but for the moment, I'm not really concerned with which one you pick.
Map<Integer, string> names;

names.put(360, "6 minutes left");
names.put(300, "5 minutes left");
//...
names.put(5, "5 seconds left");


然后代码仅查询names中的当前时间并打印出来一个字符串(如果有一个特定值)。另外:虽然我在这里使用了names,但这可能不是一个很好的例子-在命名实变量时,几乎应该确定一个可以更好地反映其预期功能的名称。例如,类似timeToString

还要注意,这使得将值和字符串导出到配置文件中相当容易,而不是将它们嵌入代码中。例如,如果您最终想将程序翻译成俄语或法语(或其他任何一种),则翻译这些字符串不会(本身)强制重新编译关联的代码。同样,如果您决定添加或删除某些消息,则将它们移动到外部数据文件中就变得很简单。程序而无需重新编译(或无需重写至少一些代码)。尽管如此,将这样的字符串保留在代码外部确实有助于使任务更易于管理。

#4 楼

概念:
您的概念不适合多次倒计时使用,相反,您可能想尝试以下方法:
当心,这是原始草案!
public class Buff{
    private int respawnSeconds;
    private String name;
    private int respawnsAtSecond;
    //constructor + getters and setters

    public void kill(int currentGameSeconds){
      this.respawnsAtSecond = currentGameSeconds + respawnSeconds;
    }
}

public class Game{
    private int elapsedSeconds;
    private Set<Buff> buffs;

    public void start(){
        elapsedSeconds = 0;
        buffs.add(new Buff("friendlyBlue", 300));
        //Add the other buffs
    }

    //You need some ticking mechanism, maybe you could use something like a while(true)
}


旁注:
命名:
您的方法名称不一致。.蓝色和红色方法是camelCase,但是您的较大目标是PascalCasedDragonBaron),除此之外,您的用法非常一致带有非常清晰易懂的驼峰式局部变量。
方法职责:
使您的方法做得太多。他们同时进行计数,打印和计算...提取子方法并为不同的物镜名称添加参数。

#5 楼

我从未接触过Java,因此它可能无法编译,但是除了DFords答案(在循环内)之外,还可以使用使您的代码短一些的方法:

long seconds = endTime - startTime;
if (seconds == 1)
    System.out.println(finalMsg);
else if (seconds == 5)
    System.out.println("5 Seconds left");
else if (seconds == 15)
    System.out.println("15 Seconds left");
else if (seconds == 30)
    System.out.println("30 Seconds left");
else if (seconds <= 240 && seconds % 60 == 0)
    System.out.println(seconds/60 + " minutes left");


评论


\ $ \ begingroup \ $
打败我。那应该是360,而不是240。
\ $ \ endgroup \ $
–法老王
2014年4月24日19:48在

\ $ \ begingroup \ $
@Pharap嗯。好像OP从多个点开始计数(240、300和360)。
\ $ \ endgroup \ $
–Lennart_96
2014年4月24日在21:03

#6 楼

@Dford完全正确,可以将时间事件放到单独的方法中。

当您将开关与可读的final结合使用时,我仍然觉得它更具可读性

private static final int MINUTES_4 = 240;
private static final int MINUTES_3 = 180;
private static final int MINUTES_2 = 120;
private static final int MINUTES_1 = 60;
private static final int SECONDS_30 = 30;
private static final int SECONDS_15 = 15;
private static final int SECONDS_5 = 5;
private static final int SECONDS_1 = 1;

private static void Countdown(long startTime, long endTime, string finalMsg){
    while (System.currentTimeMillis() / 1000 < endTime) {
        while (startTime != System.currentTimeMillis() / 1000) {
            String message;
            startTime++;
            switch (endTime - startTime) {
               case MINUTES_4 : message = "4 Minutes left";
               break;
               case MINUTES_3 : message = "3 Minutes left";
               break;
               case MINUTES_2 : message = "2 Minutes left";
               break;
               case MINUTES_1 : message = "1 Minutes left";
               break;
               case SECONDS_30 : message = "30 seconds left";
               break;
               case SECONDS_15 : message = "15 seconds left";
               break;
               case SECONDS_5  : message = "5 seconds left";
               break;
               case SECONDS_1  : message = finalMsg;
               default : break;
            }
            if (null != message) {
                System.out.println(message);
            }
        }
    }
}


#7 楼

我对您的代码进行了一些修改,以现在可以进行多种倒计时:


为您的buff创建一个实体
创建具有buff的地图
使用该地图删除主函数中的switch语句
使用映射使菜单动态化
为每个计时器启动一个新线程以启动多个计时器



package test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;


public class LolTimer 
{       
    /**List with running countdowns*/
    private static List<String> countdowns = new ArrayList<String>();

    /**Main function*/
    public static void main(String[] args) 
    {
        //variable instantiation
        Scanner myScanner = new Scanner(System.in); 
        HashMap<Integer, Buff> BuffMap = creatBuffs();
        int numberBuffs = BuffMap.size();
        int buffID = 0;

        //Print the menue with buffs etc.
        System.out.println("Jungle Timers v1.0");
        System.out.println("\nSelect a buff to time:\n");
        for(int i = 1; i <= numberBuffs; i++)
            System.out.println(i + ". " + BuffMap.get(i).m_sName);
        System.out.println(numberBuffs+1 + ". EXIT");
        System.out.print("\n>  ");

        //loop to track as many buffs as the user want
        while(buffID != numberBuffs+1)
        {
            buffID = myScanner.nextInt();
            if(buffID > 0 && buffID <= numberBuffs)
            {
                Buff buff = BuffMap.get(buffID);
                trackBuff(buff.m_nRespawnTime, buff.m_sName);
            }
        }

        //if exit is choosen -> close scanner and exit the programm
        myScanner.close();
        System.exit(0);
    }

    /**Decide if a Buff is still running or not.*/
    public static void trackBuff(int nRespawnTime, String sName)
    {
        if(countdowns.contains(sName))
            System.out.println("This Countdown is still running.");
        else 
        {
            System.out.println("\nTracking " + sName + "...");
            startThread(nRespawnTime, sName);
        }
    }

    /**Starts new Thread with a new Countdowntimer.*/
    public static void startThread(int nRespawnTime, final String sName)
    {
        countdowns.add(sName);

        final int m_nStartTime = (int) (System.currentTimeMillis() / 1000);
        final int m_nEndTime = m_nStartTime + nRespawnTime;

        Thread updateThread = new Thread() 
        {
            @Override
            public void run() 
            {
                int curTime = m_nStartTime;
                int m_nTimeDiff = 0;

                while (System.currentTimeMillis() / 1000 < m_nEndTime) 
                {
                    while (curTime != System.currentTimeMillis() / 1000) 
                    {
                        m_nTimeDiff = m_nEndTime - curTime;
                        curTime += 1;
                        if (m_nTimeDiff == 420)
                            System.out.println(sName + ": 7 Minutes left");
                        if (m_nTimeDiff == 360)
                            System.out.println(sName + ": 6 Minutes left");
                        if (m_nTimeDiff == 300)
                            System.out.println(sName + ": 5 Minutes left");
                        if (m_nTimeDiff == 240)
                            System.out.println(sName + ": 4 Minutes left");
                        if (m_nTimeDiff == 180)
                            System.out.println(sName + ": 3 Minutes left");
                        if (m_nTimeDiff == 120)
                            System.out.println(sName + ": 2 Minutes left");
                        if (m_nTimeDiff == 60)
                            System.out.println(sName + ": 1 Minute left");
                        if (m_nTimeDiff == 30)
                            System.out.println(sName + ": 30 Seconds left");
                        if (m_nTimeDiff == 15)
                            System.out.println(sName + ": 15 Seconds left");
                        if (m_nTimeDiff == 5)
                            System.out.println(sName + ": 5 Seconds left");
                    }
                }

                System.out.println(sName + " is up!");
                countdowns.remove(sName);
                Thread.currentThread().interrupt();
            }
        };
        updateThread.start(); 
    }

    /**Creat all the Buffs you want. You fastly can add some Buffs(wolves, ghosts) here.*/
    public static HashMap<Integer, Buff> creatBuffs()
    {
        HashMap<Integer, Buff> BuffMap = new HashMap<>();
        BuffMap.put(1, new Buff(300, "your Blue"));
        BuffMap.put(2, new Buff(300, "enemy Blue"));
        BuffMap.put(3, new Buff(300, "your Red"));
        BuffMap.put(4, new Buff(300, "enemy Blue"));
        BuffMap.put(5, new Buff(300, "Dragon"));
        BuffMap.put(6, new Buff(300, "Baron"));
        return BuffMap;
    }
}

/**Entity for your Buffs*/
class Buff
{
    public int m_nRespawnTime;
    public String m_sName;

    public Buff(int time, String name)
    {
        m_nRespawnTime = time;
        m_sName = name;
    }
}


#8 楼

如果我们在谈论正确的类封装或其他方法,那么这就是我可以做的过度设计的版本。

我也是C#程序员,因此某些语法可能有些不足,但是我至少已经做了一些努力,至少使用了正确的Java。


在Main方法中保留控制台提示
创建一个代表您不同类型的计时器的枚举
创建本质上仅是一个存储字符串的数据存储库类(例如“跟踪敌人的蓝色。 ..“)和其他常量值(例如添加到计时器中的300)。

使用有意义的名称。一切都是静态的final。类似于@chillworld的答案。
将其命名为GlobalConstants,或任何对您有意义的名称。


创建一个负责管理计时器的类(将其称为Tracker或东西。)此类将包括:

以上述枚举为参数的构造函数
用于局部存储所述枚举的私有字段
倒数方法(来自@DFord的答案)与来自@ Lennart_96的答案的优化
一个初始化方法,该方法根据本地枚举值设置计时器值等,并调用一个单独的方法来显示您的初始倒计时消息(也基于枚举值)。



最后你会得到类似的东西:

public enum TimerType {
    FriendlyBlue, EnemyBlue...
}

public class MainProgram {
    private TimerType tType;
    public static void main(String[] args) {
        // Do your console prompts

        // Assign the timer type
        switch (timerChoice) {
            case 1: tType = TimerType.FriendlyBlue; break;
            case 2: ...
        }

        // Create the tracker object and kick off the timer
        new Tracker(tType);
    }
}

public class Tracker {
    private TimerType tType;
    private string initialTrackingMessage;
    ...

    public Tracker(TimerType timerType) {
        tType = timerType;
        InitializeTracker();
        CountDown();
    }

    private void InitializeTracker() {
        initialTrackingMessage = GetInitialTrackingMessageForTrackingType();
        // Initialize any other variables

        DisplayMessage(initialTrackingMessage);
    }

    private string GetInitialTrackingMessageForTrackingType() {
        string returnMessage;
        switch (tType) {
            case FriendlyBlue: returnMessage = GlobalConstants.TRACKING_BLUE; break;
            ...
        }
        return returnMessage;
    }

    private void DisplayMessage(string message) {
        System.out.println(message);
        // Any other logic you want to do
    }

    private void CountDown() {
        // Your countdown logic here
    }
}

public static class GlobalConstants() {
    // Messages
    public static final string TRACKING_BLUE = "Tracking your blue..."
    ...

    // Values
    public static final int INITIAL_TIMER_LENGTH = 300;
}


我确定你注意到我喜欢在我的编码中使用整个单词。对于那些在您离开后必须维护您的代码的人来说,这确实很棒。如果您不喜欢从构造函数中全部完成的想法,则还可以轻松添加Start()方法或用于初始化和倒计时的方法。

如果最终为每种类型的计时器添加了更多详细信息,则此方法将使将核心类转换为抽象类甚至适当地转换为接口变得更加容易。也许两者都有。 Countdown方法适用于抽象类,但InitializeTracker方法可能更适用于接口,除非您需要默认实现。同样,方法和类型(类,枚举)每个都仅执行一个功能,这是良好的OO设计的重要支柱。

EDIT

以解决您的次要问题),您可以通过保留Tracker对象的集合,轻松地通过这种方法跟踪多个buff。

#9 楼

让我来解决您的“重复”部分,在其中检查剩余的时间。.一些简单的数学运算可以减小这些块的大小:

int secLeft = endTime - startTime;
int minsLeft = secLeft/60;
if( secLeft % 60 == 0 ) // only happens at multiples of 60, eg 0,60,120,180..
{
    // Message of form "2 minutes left"
    String msg = Integer.toString(minsLeft) + " Minutes left";
}
else if( secLeft == 30 )
{
    // need special cases for the smaller values
}