Метод не работает корректно по истечении необходимого времени
Всем здравствуйте! Пытаюсь реализовать что-то на подобии простой фермы. Например растения можно посадить и собрать урожай, а у каждого растения есть время созревания. На текущий момент сложность заключается в том, что изменено не первое указанное для посадки поле, по прошествии нужного количества времени, а последнее указанное на момент этого времени. Приведу фрагмент кода, чтобы не засорять. Буду рад любой помощи и советам. Возможно я в целом мыслю неправильно и нужно реализовывать иначе.
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
public class Player {
final char SIGN_PLANT = 'X';
final char SIGN_EMPTY = '_';
final char SIGN_HARVEST = '0';
private int cash;
private char[] field;
transient Scanner scanner;
private Plant plant;
Player(){
scanner = new Scanner(System.in);
field = new char[8];
cash = 100;
plant = new Plant("Cucumber", 10, 15, 5);
}
void game(){
initField(); //инициализация поля
printField(); //печать поля
while(true){
toPlant(); //посадка
if(isFieldFull()){
System.out.println("JUST WAIT");
break;
}
printField(); //печать поля
execute(() -> getHarvest(), plant.getTime());
// getHarvest();
}
printField();
}
void initField(){
for (int i = 0; i < 8; i++) {
field[i] = SIGN_EMPTY;
}
}
void printField(){
for (int i = 0; i < 8; i++) {
System.out.print(field[i] + " ");
}
}
int x;
void toPlant(){
do{
System.out.println("Enter cell for your plant (1-8)");
x = scanner.nextInt() - 1;
if(field[x] != SIGN_HARVEST && field[x] != SIGN_PLANT){
if(cash >= plant.getSeedPrice()){
cash = cash - plant.getSeedPrice();
System.out.println("YOUR CASH IS " + cash);
}
else{
System.out.println("YOU HAVEN'T ENOUGH MONEY");
}
}
} while (!isCellValid(x));
field[x] = SIGN_PLANT;
}
public static void execute(Runnable task, long delaySec) {
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
task.run();
timer.cancel();
}
};
timer.schedule(timerTask, delaySec*1000);
}
public void getHarvest() {
// Runnable task = () -> {
// try {
// Thread.sleep(plant.getTime());
// field[x] = SIGN_HARVEST;
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// };
// Thread thread = new Thread(task);
// thread.start();
field[x] = SIGN_HARVEST;
// field[x] = SIGN_HARVEST;
}
int y;
void takeHarvest(){
do{
y = scanner.nextInt() - 1;
for (int i = 0; i < 8; i++) {
if(field[y] == SIGN_HARVEST){
cash = cash + plant.getHarvestPrice();
}
}
System.out.println("YOUR CASH IS " + cash);
} while (!isCellValid(y));
field[y] = SIGN_EMPTY;
}
boolean isCellValid(int x){
if(x < 0 || x >= 8){
System.out.println("OLOLO! YOU WERE ABROAD");
return false;
}
return field[x] == SIGN_EMPTY;
}
boolean isFieldFull(){
for (int i = 0; i < 8; i++) {
if (field[i] == SIGN_EMPTY){
return false;
}
}
return true;
}
}
Ответы (1 шт):
Попробуйте использовать более высокоуровневые решения. Благо в джаве их достаточно. А низкоуровневые оставьте для тех, кто специализируются на многопоточности. Таким образом, мы можете избежать большого количества багов, которые к тому же будет очень сложно воспроизвести и исправить. Например, если вам необходимо отсроченное исполнение какой-либо задачи, можно использовать таймер. Если обернуть его в метод с удобным интерфейсом, то все очень сильно упростится. В данном случае есть само отсроченное действие и время , через которое необходимо его выполнить. Поэтому в методе будет 2 параметра.Первый принимает интерфейс Runnable. Это удобно, поскольку это функциональный интерфейс, следовательно, мы сможем передать лямбду. Второй аргумент - время в секундах, спустя которое и будет выполнено действие, переданное в лямбде.
import com.google.gson.Gson;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.List;
import java.util.Optional;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.Arrays;
import static java.lang.System.out;
public class Game {
private final static String JSON_FILE_NAME = "json.txt";
private final Scanner scanner;
private final List<Plant> plants;
private final List<Field> fields;
private int cash;
public static void main(String[] args) throws FileNotFoundException {
new Game(jsonToPlants(JSON_FILE_NAME), 100, 8).start();
}
private static List<Plant> jsonToPlants(String fileName) throws FileNotFoundException {
return Arrays.asList(new Gson().fromJson(new FileReader(fileName), Plant[].class));
}
public Game(List<Plant> plants, int cash, int fieldSize) {
this.cash = cash;
this.plants = plants;
this.scanner = new Scanner(System.in);
this.fields = new CopyOnWriteArrayList<>();
for (int i = 0; i < fieldSize; i++) fields.add(new Field());
}
public void start() {
while (true) {
out.println(fields);
out.println("YOUR CASH : " + cash);
out.println("Enter cell for your plant (1-8)");
validField(scanner.nextLine()).ifPresent(fieldNumber -> {
Field field = fields.get(fieldNumber);
out.println("Enter plants number (1-" + plants.size() + ")");
if (field.isEmpty()) {
validPlant(scanner.nextLine()).ifPresent(plantNumber -> {
Plant plant = plants.get(plantNumber);
execute(() -> getHarvest(fieldNumber), plant.getTime());
cash -= plant.getSeedPrice();
fields.set(fieldNumber, field.update(plant));
});
} else {
cash += field.getHarvestPrice();
fields.set(fieldNumber, field.update());
}
});
}
}
private Optional<Integer> validPlant(String userInput) {
try{
Integer number = Integer.valueOf(userInput)-1;
if (number < 0 || number >= plants.size()) return printAndReturnOptional("OLOLO! YOU WERE ABROAD");
if (cash < plants.get(number).getSeedPrice()) return printAndReturnOptional("YOU HAVEN'T ENOUGH MONEY");
return Optional.of(number);
}catch(NumberFormatException e){
return printAndReturnOptional("OLOLO! INCORRECT INPUT");
}
}
private Optional<Integer> validField(String userInput) {
try{
Integer number = Integer.valueOf(userInput)-1;
if (isFieldFull()) return printAndReturnOptional("JUST WAIT");
if (number < 0 || number >= fields.size()) return printAndReturnOptional("OLOLO! YOU WERE ABROAD");
if (fields.get(number).isFull()) return printAndReturnOptional("OLOLO! FIELD NOT EMPTY");
return Optional.of(number);
}catch(NumberFormatException e){
return printAndReturnOptional("OLOLO! INCORRECT INPUT");
}
}
private Optional printAndReturnOptional(String arg) {
out.println(arg);
return Optional.empty();
}
public void getHarvest(int fieldNumber) {
fields.set(fieldNumber, fields.get(fieldNumber).update());
out.println(fields);
}
private void execute(Runnable task, long delaySec) {
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
task.run();
timer.cancel();
}
};
timer.schedule(timerTask, delaySec * 1000);
}
private boolean isFieldFull() {
return !fields.stream().anyMatch(cell->cell.isEmpty());
}
}
public class Field {
private Sign sign;
private Plant plant;
public Field() {
this.sign = Sign.EMPTY;
}
public boolean isEmpty(){
return this.sign == Sign.EMPTY;
}
public boolean isFull(){
return this.sign == Sign.PLANT;
}
public Field update(Plant plant) {
this.sign = this.sign.update();
this.plant = plant;
return this;
}
public Field update() {
return update(sign==Sign.EMPTY ? null : plant);
}
public int getHarvestPrice() {
return plant.getHarvestPrice();
}
@Override
public String toString() {
return sign.toString();
}
}
public class Plant {
private String name;
private int seedPrice;
private int harvestPrice;
private long time;
public Plant() {
}
public Plant(String name, int seedPrice, int harvestPrice, long time) {
this.name = name;
this.seedPrice = seedPrice;
this.harvestPrice = harvestPrice;
this.time = time;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSeedPrice() {
return seedPrice;
}
public void setSeedPrice(int seedPrice) {
this.seedPrice = seedPrice;
}
public int getHarvestPrice() {
return harvestPrice;
}
public void setHarvestPrice(int harvestPrice) {
this.harvestPrice = harvestPrice;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
@Override
public String toString() {
return "Plant{"
+ "name='" + name + '\''
+ ", seedPrice=" + seedPrice
+ ", harvestPrice=" + harvestPrice
+ ", time=" + time
+ '}';
}
}
public enum Sign {
EMPTY("_"),
PLANT("X"),//семена
HARVEST("0");//урожай
private final String symbol;
private Sign(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
public Sign update(){
final Sign[] signs = Sign.values();
return signs.length<=this.ordinal()+1 ? signs[0] : signs[this.ordinal()+1];
}
}