I am working on a little tiny game, where there is a Attacker and a Defender.
Player Attacker = new Player();
Player Defender = new Player();
class Player {
int armees = 0;
int tarningar = 0;
Dice Dices[];
Player() {
armees = 10;
// if object name is Attacker, tarninger = 3, if defender = 2
Dices= new Dice[tarningar];
for(int i = 0; i < Dices.length; i++) {
Dices[i]=new Dice();
}
}
}
I have commented inside the code above, where i wish to have a if statement to determine how many dices it should have.
If this is not possible to do, another way of doing this maybe?
I also tried to
Attacker.tarningar = 3;
Defender.tarningar = 2;
right under where the object gets defined in main, but it doesn't work, because it has already ran Player() inside class.
(I'm still new to java) Thanks
Maybe you could do:
Player(boolean isAttacker){
armees = 10;
// if object name is Attacker, tarninger = 3, if defender = 2
int diceNum;
if (isAttacker) diceNum = 2;
else diceNum = 3;
Dices= new Dice[diceNum];
for(int i=0;i<Dices.length;i++){
Dices[i]=new Dice();
}
}
Then you will need to tell the player if it is attacking or defending when it is constructed.
Player p = new Player(true); // creates an attacker
You should add a variable determining whether this is an attacker or a defender. Or even better, if they do different things, create subclasses for attacker and defender.
Change your code to this:
Player Attacker = new Player(true);
Player Defender = new Player(false);
class Player {
boolean attacker;
int armees = 0;
int tarningar = 0;
Dice Dices[];
Player(boolean attacker) {
this.attacker = attacker;
armees = 10;
tarninger = attacker ? 3 : 2;
Dices= new Dice[tarningar];
for(int i = 0; i < Dices.length; i++) {
Dices[i] = new Dice();
}
}
}
If you are trying to differentiate based on variable names, it's not possible because that information is removed during compiler optimizations. If the instances are accessible, you could do
if (this == attacker)
{
...
}
or you could introduce a new field to store name
Player attacker = new Player("Attacker");
or perhaps an enum.
Player attacker = new Player(PlayerType.Attacker);
Related
I am trying to do a warm start using the Java API and having some issues when passing the initial solution to the model.
In my model file(.mod) I have a 2D decision variable defined as,
range nodes = 1..5;
range vehicles = 1..2;
dvar int service_time[nodes][vehicles];
In my java file I am building the model as below and trying to pass an initial solution to the above decision variable using the addMipStart() function (as described here),
static public void main(String[] args) throws Exception {
int status = 127;
try {
IloOplFactory.setDebugMode(true);
IloOplFactory oplF = new IloOplFactory();
IloOplErrorHandler errHandler = oplF.createOplErrorHandler(System.out);
IloOplModelSource modelSource = oplF.createOplModelSource(DATADIR + "/myModFile.mod");
IloOplSettings settings = oplF.createOplSettings(errHandler);
IloOplModelDefinition def = oplF.createOplModelDefinition(modelSource, settings);
IloCplex cplex = oplF.createCplex();
IloOplModel opl = oplF.createOplModel(def, cplex);
//adding the custom data source
IloOplDataSource dataSource = new VRPDataSource(oplF);
opl.addDataSource(dataSource);
//generating the model
opl.generate();
//creating the initial solution
int i = 5;
int j = 2;
IloIntVar[][] var2D = new IloIntVar[i][];
double[][] var2D_startingVals = new double[i][];
for(int index1=0; index1 < i; index1++){
var2D[index1] = new IloIntVar[j];
var2D_startingVals[index1] = new double[j];
for(int index2 = 0; index2 < j; index2++){
String varName = "service_time("+ (index1+1) +")("+ (index2+1) +")";
var2D[index1][index2] = cplex.intVar(0, 50, varName);
//lets assume a unit matrix as the starting solution
var2D_startingVals[index1][index2] = 1;
}
}
//flatten the multi-dimensional IloNumVar and double arrays
IloNumVar[] flat_var2D = new IloNumVar[i*j];
double[] flat_var2D_startingVals = new double[i*j];
for(int index1=0; index1 < i; index1++){
for(int index2=0; index2 < j; index2++){
flat_var2D[index1*j + index2] = var2D[index1][index2];
flat_var2D_startingVals[index1*j + index2] = var2D_startingVals[index1][index2];
}
}
// adding the MIPStart
cplex.addMIPStart(flat_var2D, flat_var2D_startingVals, IloCplex.MIPStartEffort.Auto, "addMIPStart start");
if(cplex.solve()){
// more code
}else{
// more code
}
// more code
}catch(Exception ex){
// more code
}
}
Unfortunately I am having an exception in the line which calls the cplex.addMIPStart() function as,
[java] ### CONCERT exception: The referenced IloExtractable has not been extracted by the IloAlgorithm
[java] ilog.concert.IloException: The referenced IloExtractable has not been extracted by the IloAlgorithm
[java] at ilog.cplex.cppimpl.cplex_wrapJNI.IloCplex_addMIPStart__SWIG_0(Native Method)
[java] at ilog.cplex.cppimpl.IloCplex.addMIPStart(IloCplex.java:866)
[java] at ilog.cplex.IloCplex.addMIPStart(IloCplex.java:13219)
[java] at ilog.cplex.IloCplex.addMIPStart(IloCplex.java:13228)
[java] at myJavaClass.myJavaClass.main(myJavaClass.java:412)
I am thinking the error is due to the way I prepare the initial solution, can somebody please help me to sort this out.
Thank you very much.
The problem is that you're creating new variables, not referencing the existing variables in the model. These new variables do not exist in the objective, constraints, etc., so you get the IloException (see this technote).
You should be able to access the existing variables doing something like the following (note that this code has not been tested):
IloIntRange nodes = opl.getElement("nodes").asIntRange();
IloIntRange vehicles = opl.getElement("vehicles").asIntRange();
IloIntVarMap serviceTime = opl.getElement("service_time").asIntVarMap();
final int nbNodes = nodes.getSize();
final int nbVehicles = vehicles.getSize();
IloNumVar[] startX = new IloNumVar[nbNodes * nbVehicles];
double[] startVals = new double[nbNodes * nbVehicles];
for (int i = 0; i < nbNodes; i++) {
IloIntVarMap inner = serviceTime.getSub(nodes.getValue(i));
for (int j = 0; j < nbVehicles; j++) {
int idx = i * nbVehicles + j;
startX[idx] = inner.get(vehicles.getValue(j));
startVals[idx] = 1.0;
}
}
cplex.addMIPStart(startX, startVals);
Take a look at the Iterators.java example and the documentation for getElement.
So, here is my functions:
private void sendLeft() {
leftSendersIndexes = newLeftSendersIndexes;
Agent rightRecepient;
int rightRecepientIdx = 0;
Agent leftSender;
for (int i = 0; i < leftSendersIndexes.size(); i++) {
rightRecepientIdx = leftSendersIndexes.get(i) + 1;
rightRecepient = list.get(rightRecepientIdx);
leftSender = list.get(rightRecepientIdx - 1);
rightRecepient.setNewLeftMsg(leftSender.getLeftMsg());
rightRecepient.setLeftMsg(0); // reset left messages
}
}
private void sendRight() {
rightSendersIndexes = newRightSendersIndexes;
Agent leftRecepient;
int leftRecepientIdx = 0;
Agent rightSender;
for (int i = 0; i < rightSendersIndexes.size(); i++) {
leftRecepientIdx = rightSendersIndexes.get(i) - 1;
leftRecepient = list.get(leftRecepientIdx);
rightSender = list.get(leftRecepientIdx + 1);
leftRecepient.setNewRightMsg(rightSender.getRightMsg());
}
}
They are very similar. The problem is that in first function I have leftRecepientIdx+1 and after that leftRecepientIdx-1 and I have leftRecepientIdx-1 and leftRecepientIdx+1 in second function. I may to combine two functions in one and add a boolean parameter. But is there a better way to get rid of duplication?
One way to do that is with this refactoring:
private void sendLeft() {
leftSendersIndexes = newLeftSendersIndexes;
send(leftSendersIndexes, -1);
}
private void sendRight() {
rightSendersIndexes = newRightSendersIndexes;
send(rightSendersIndexes, +1);
}
private void send(List<Integer> indexes, int direction) {
for (int i = 0; i < indexes.size(); i++) {
int recipientIdx = indexes.get(i) - direction;
Agent recipient = list.get(recipientIdx);
Agent sender = list.get(recipientIdx + direction);
if (direction == -1) {
recipient.setNewLeftMsg(sender.getLeftMsg());
recipient.setLeftMsg(0); // reset left messages
}
else {
recipient.setNewRightMsg(sender.getRightMsg());
}
}
}
The send method encapsulates the logic based on the direction parameter: +1 for right, -1 for left.
The order in which those appears is important, I would suggest merging, but, I have no idea what that would do. Keep them separate, if this was borrowed, this was made on purpose.
Both functions are some send functions where sender and receiver are different and reset may happen. So I would try to make one function with arguments sender, receiver and boolean reset.
I have an agent class that does things:
public class Agent {
private Context<Object> context;
private Geography<Object> geography;
public int id;
boolean female;
public Agent(Context<Object> context, Geography<Object> geography, int id, boolean female) {
this.id = id;
this.context = context;
this.geography = geography;
this.female = female;
}
... setters getters
... do things methods
}
In the context builder class, where my agents are added into the context (geographic space composed of latitude and longitude coordinates), I want to make a random percentage of my Agents female (female = true).
for (int i = 0; i < 100; i++) {
Agent agent = new Agent(context, geography, i, false);
int id = i++;
if(id > 50) {
boolean female = true;
}
context.add(agent);
//specifies where to add the agent
Coordinate coord = new Coordinate(-79.6976, 43.4763);
Point geom = fac.createPoint(coord);
geography.move(agent, geom);
}
I believe the code above constructs the last 50 agents as female. How can I make it so they are randomly created as female? I change the number of agents created quite a bit.
with your code, you ALWAYS create an agent that is MALE.
try to evaluate if it's female before creating an instance of Agent:
Agent agent = null;
boolean isFemale = false;
for (int i = 0; i < 100; i++) {
int id = i++;
if(id > 50) {
isFemale = true;
}
agent = new Agent(context, geography, i, isFemale);
context.add(agent);
//specifies where to add the agent
Coordinate coord = new Coordinate(-79.6976, 43.4763);
Point geom = fac.createPoint(coord);
geography.move(agent, geom);
}
if you want it random, try using Random utility:
Random random = new Random();
agent = new Agent(context, geography, i, random.nextBoolean());
hope this helps
You can create a single instance of Random outside your for loop and use random.nextBoolean() as a parameter for your boolean female attribute of agent().
Random random = new Random();
for (int i=0; i < 100; i++)
{
boolean isFemale = (random.Next(2) % 2 == 1);
...
}
I can't figure out why eclipse wants me to delete the ";" and replace it with with a ",".
numberOfTimes1 = numberOfTimes + numberOfDelayTimes;
I'm guessing it's some simple syntax thing that I forgot about. Could you please explain why it's doing that and also how to fix it.
Entire Program
public class Spam {
public static void main(String[] args) {
//1- Taking an instance of Timer class.
Timer timer = new Timer("Printer");
//2- Taking an instance of class contains your repeated method.
timeso t = new timeso();
timer.schedule(t, 0, 10);
}
}
class timeso extends TimerTask {
//times member represent calling times.
private int times = 0;
int time = 6; //How long do you wish for the spamming to run?
int numberOfTimes = time * 100;
int delayTime = 5; //How long do you wish for the program to wait before spamming?
int numberOfDelayTimes = delayTime * 100;
numberOfTimes = numberOfTimes + numberOfDelayTimes;
String spam;
Random randomGenerator = new Random();
public void run() {
times++;
if (times >= numberOfDelayTimes && times <= numberOfTimes+numberOfDelayTimes) {
try {
Robot typer = new Robot();
//for(int x = 1;x <=randomGenerator.nextInt(5); x++){
// spam = spam + randomGenerator.nextInt(10);
//}
byte[] bytes = "spam".getBytes();
//byte[] bytes = spam.getBytes();
for (byte b : bytes){
int code = b;
// key code only handles [A-Z] (which is ASCII decimal [65-90])
if (code > 96 && code < 123) code = code - 32;
typer.delay(10/bytes.length+1);
typer.keyPress(code);
typer.keyRelease(code);
}
if(times % (randomGenerator.nextInt(25)+1) == 0){
typer.delay(10/bytes.length+1);
typer.keyPress(KeyEvent.VK_ENTER);
typer.keyRelease(KeyEvent.VK_ENTER);
}
}
catch (AWTException e){
}
} else {
if (times >= numberOfTimes){
try{
Robot typer = new Robot();
typer.delay(10);
typer.keyPress(KeyEvent.VK_ENTER);
typer.keyRelease(KeyEvent.VK_ENTER);
} catch(Exception e){
}
//Stop Timer.
this.cancel();
}
}
}
}
You're trying to call a line of code outside of a method or constructor, and this is why the Java compiler (not Eclipse) is complaining. Do that sort of code in the constructor or method, not naked in the class. In fact all that code in your timeso class is incorrect and needs to be in a method or constructor.
Note: you'll want to learn Java naming convention and stick with it, including starting class names with an upper-case letter and method and variable names with a lower-case letter. Doing this will help others (us!) understand your code better.
I have to make a simple text based game using multi threading. I have chosen to do a guess my animal game. A server will pick a random animal and give out clues and the client has to guess what the animal is within three clues.
However, if the animal is guessed correct, the program just goes to the next clue. I dont understand where i have gone wrong?
The other problem is when the client says y to a new game, it just repeats the same animal. It won't change.
I know it is just the protocol class i need to fix. Please help! I have cried with frustration over this program.
Here is a copy of my protocol class:
public class KKProtocol {
private static final int WAITING = 0;
private static final int ASKNAME = 1;
private static final int SENTCLUE = 2;
private static final int SENTCLUE2 = 3;
private static final int SENTCLUE3 = 4;
private static final int ANOTHER = 5;
private static final int NUMANIMALS = 4;
private int state = WAITING;
private int currentAnimal = (int) (Math.random() * 6); // number of first joke
private String[] clues = {"I like to play", "I like to scratch", "I eat salad", "I annoy you in the morning"};
private String[] clues2 = {"Love walks", "House pet", "garden pet", "I fly everywhere"};
private String[] clues3 = {"Woof", "Meow", "I live in a hutch", "Tweet Tweet"};
private String[] answers = {"Dog",
"Cat",
"Rabbit",
"Bird",};
private String[] name = {};
public String processInput(String theInput) {
String theOutput = null;
// System.out.println("Welcome to my animal guessing game");
if (state == WAITING) {
theOutput = clues[currentAnimal];
state = SENTCLUE;
} else if (state == SENTCLUE) {
if (theInput.equals(answers[currentAnimal])) {
theOutput = "Correct...Your Score is 1....Want to play again? (y/n)";
state = ANOTHER;
} else {
theOutput = clues2[currentAnimal];
state = SENTCLUE2;
}
} else if (state == SENTCLUE2) {
if (theInput.equals(answers[currentAnimal])) {
theOutput = "Correct...Your Score is 2....Want to play again? (y/n)";
state = ANOTHER;
} else {
theOutput = clues3[currentAnimal];
state = SENTCLUE3;
}
} else if (state == SENTCLUE3) {
if (theInput.equals(answers[currentAnimal])) {
theOutput = "Correct...Your Score is 3....Want to play again? (y/n)";
state = ANOTHER;
} else {
theOutput = ("it's" + answers[currentAnimal] + " you fool! Want to play again? (y/n)");
state = ANOTHER;
}
} else if (state == ANOTHER) {
if (theInput.equalsIgnoreCase("y")) {
if (currentAnimal == (NUMANIMALS - 1)) {
currentAnimal = 0;
}
theOutput = clues[currentAnimal];
// else
currentAnimal++;
state = SENTCLUE;
} else {
theOutput = "Bye.";
state = WAITING;
}
}
return theOutput;
}
}
If you need to see the other classes please just ask.
Debug the program and set a break point before your first if clause. How do the variables look like? I suppose you've made a trivial error somewhere in your code which will reveal itself while observing what your program actually does.
You could also paste some of your client code here so that someone could understand what is happening. From the comments I understood that nobody quite got how you use the Protocol class.