玩家阶段狩猎游戏 - Java
因此,我将所有这些类放在一起,以实现 Predators 和 Prey 以及世界之间的所有连接。我唯一真正困惑的是 Predator 类的 run() 方法(它们如何狩猎)。
理论很简单。捕食者必须聚集在猎物周围的北、南、东、西侧,DataChannel 类会注意到这一点并捕获猎物并将其从地图上删除。但我的工作是让这一切发生,让掠食者相互交流,然后追逐并追捕猎物(我编程让它随机移动)。
这是所有的课程。请记住,Predator 类的 run() 方法是我感到困惑的地方。其他一切都是我想要的。有什么帮助吗?
/**
Predator class, with no "hunting" functionality.
*/
import java.io.*;
import javax.imageio.ImageIO;
import java.util.ArrayList;
import javaclient2.*;
import javaclient2.structures.*;
public class Predator extends Thread
{
private Position2DInterface position_interface = null;
private BlobfinderInterface blob_finder = null;
private PlayerClient playerClient = null;
private DataChannel dc = null;
private String name = "";
public Predator(String name, DataChannel dc, int id, float x, float y){
this.name = name;
this.playerClient = new PlayerClient("localhost", 6665);
blob_finder = playerClient.requestInterfaceBlobfinder(id,
PlayerConstants.PLAYER_OPEN_MODE);
position_interface = playerClient.requestInterfacePosition2D(id,
PlayerConstants.PLAYER_OPEN_MODE);
playerClient.runThreaded (-1, -1);
//wait until the intefaces are ready before doing anything
while(!blob_finder.isDataReady() ||
!position_interface.isDataReady()) {
try{
sleep(100);
}catch(Exception e){
System.err.println("Error sleeping!");
e.printStackTrace();
System.exit(-1);
}
}
PlayerPose pp = new PlayerPose();
pp.setPx(x);
pp.setPy(y);
position_interface.setOdometry(pp);
this.dc = dc;
dc.registerPredator(name, position_interface);
}
/**
* @param recipient The predator to deliver the message to.
* @param msg The message.
*
* Deliver a message to another predator.
*
*/
public void sendMessage(String recipient, Object msg){
dc.sendMessage(recipient, msg);
}
/**
* @param msg The message.
*
* Deliver a message to all other predators.
*
*/
public void broadcastMessage(Object msg){
for(String predator : dc.getPredators()){
sendMessage(predator, msg);
}
}
/**
*
* Get the next message from other predators.
*
* @return The next message, or null if there are no unread messages.
*
*/
public Object getMessage(){
return dc.getMessage(this.name);
}
public void run(){
// hunt the prey!
System.out.println("There are " + dc.numLivingPreys() +
" left to capture!");
}
}
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Vector;
import java.util.Set;
import javaclient2.*;
import javaclient2.structures.*;
/**
Object that records all of the predator locations, and kills prey when
they have been captured.
*/
public class DataChannel extends Thread{
static final float FUDGE_FACTOR = 1;
static final float CAPTURE_RANGE = 5;
private ConcurrentHashMap<String, Position2DInterface> pred_pids =
new ConcurrentHashMap<String, Position2DInterface>();
private ConcurrentHashMap<String, Position2DInterface> prey_pids =
new ConcurrentHashMap<String, Position2DInterface>();
private ConcurrentHashMap<String, Prey> preys =
new ConcurrentHashMap<String, Prey>();
private ConcurrentHashMap<String, ConcurrentLinkedQueue<Object>> msgs =
new ConcurrentHashMap<String, ConcurrentLinkedQueue<Object>>();
public void registerPredator(String name, Position2DInterface pid){
pred_pids.put(name, pid);
msgs.put(name, new ConcurrentLinkedQueue<Object>());
}
public void registerPrey(String name, Position2DInterface pid, Prey prey){
prey_pids.put(name, pid);
preys.put(name, prey);
}
public int numLivingPreys(){
return preys.size();
}
public Set<String> getPredators(){
return msgs.keySet();
}
public void sendMessage(String recipient, Object msg){
(msgs.get(recipient)).add(msg);
}
public Object getMessage(String recipient){
return (msgs.get(recipient)).poll();
}
public float getPredX(String predator){
try{
return (pred_pids.get(predator)).getX();
}catch(Exception ex) {}
return -1.0f;
}
public float getPredY(String predator){
try{
return (pred_pids.get(predator)).getY();
}catch(Exception ex) {}
return -1.0f;
}
public float getPreyX(String prey){
try{
return (prey_pids.get(prey)).getX();
}catch(Exception ex) {}
return -1.0f;
}
public float getPreyY(String prey){
try{
return (prey_pids.get(prey)).getY();
}catch(Exception ex) {}
return -1.0f;
}
public void run(){
while(true){
try{
sleep(100);
}catch(Exception e){
System.err.println("Error sleeping!");
e.printStackTrace();
System.exit(-1);
}
//get the location of each predator
Vector<Float> xpos = new Vector<Float>();
Vector<Float> ypos = new Vector<Float>();
Vector<String> pred_names= new Vector<String>();
for(String predator : pred_pids.keySet()){
if(pred_pids.get(predator) == null){
System.err.println("pred_pids does not have " + predator);
System.exit(-1);
}
xpos.add(getPredX(predator));
ypos.add(getPredY(predator));
pred_names.add(predator);
}
//for each prey, see if all of the four positions are guarded
for(String prey : prey_pids.keySet()){
boolean north = false;
boolean south = false;
boolean east = false;
boolean west = false;
if(prey_pids.get(prey) == null){
System.err.println("prey_pids does not have " + prey);
System.exit(-1);
}
float prey_x = getPreyX(prey);
float prey_y = getPreyY(prey);
for(int i=0; i < xpos.size(); i++){
//NORTH
if(Math.abs(xpos.get(i) - prey_x)<FUDGE_FACTOR &&
(ypos.get(i) - prey_y) > 0 &&
(ypos.get(i) - prey_y) < CAPTURE_RANGE){
north = true;
}
//SOUTH
if(Math.abs(xpos.get(i) - prey_x)<FUDGE_FACTOR &&
(prey_y - ypos.get(i)) > 0 &&
(prey_y - ypos.get(i)) < CAPTURE_RANGE){
south = true;
}
//EAST
if(Math.abs(ypos.get(i) - prey_y)<FUDGE_FACTOR &&
(xpos.get(i) - prey_x) > 0 &&
(xpos.get(i) - prey_x) < CAPTURE_RANGE){
east = true;
}
//WEST
if(Math.abs(ypos.get(i) - prey_y)<FUDGE_FACTOR &&
(prey_x - xpos.get(i)) > 0 &&
(prey_x - xpos.get(i)) < CAPTURE_RANGE){
west = true;
}
}
//prey is boxed in
if(north && south && east && west){
(preys.get(prey)).die();
preys.remove(prey);
prey_pids.remove(prey);
}
}
if(preys.size() == 0){
System.err.println("Congratulations: All prey are captured.");
System.exit(0);
}
}
}
}
import javaclient2.structures.*;
import javaclient2.*;
import java.util.Random;
/**
Prey class.
*/
public class Prey extends Thread{
private final int ROTATE_SECONDS = 500;
private final int MOVE_SECONDS = 3000;
private final int WAIT_SECONDS = 8000;
private final int WAIT_JITTER = 4000;
private Position2DInterface position_interface = null;
private PlayerClient playerClient = null;
private DataChannel dc = null;
private String my_name = null;
private boolean keep_going = true;
Random rand = new Random();
public Prey(String name, DataChannel dc, int id, float x, float y){
this.playerClient = new PlayerClient("localhost", 6665);
position_interface = playerClient.requestInterfacePosition2D(id,
PlayerConstants.PLAYER_OPEN_MODE);
playerClient.runThreaded (-1, -1);
this.dc = dc;
this.my_name = name;
while(!position_interface.isDataReady()) {
try{
sleep(100);
}catch(Exception e){
System.err.println("Error sleeping!");
e.printStackTrace();
System.exit(-1);
}
}
PlayerPose pp = new PlayerPose();
pp.setPx(x);
pp.setPy(y);
position_interface.setOdometry(pp);
dc.registerPrey(name, position_interface, this);
}
public float getX(){
try{
return position_interface.getX();
}catch(Exception ex) {}
return -1.0f;
}
public float getY(){
try{
return position_interface.getY();
}catch(Exception ex) {}
return -1.0f;
}
public void run(){
float old_x = getX();
float old_y = getY();
while(keep_going){
float current_x = getX();
float current_y = getY();
float x, y;
if(current_x <=0){
if(rand.nextFloat() < 0.75)
x = rand.nextFloat()*6;
else
x = rand.nextFloat()*-6;
}else{
if(rand.nextFloat() < 0.75)
x = rand.nextFloat()*-6;
else
x = rand.nextFloat()*6;
}
if(current_y <=0){
if(rand.nextFloat() < 0.75)
y = rand.nextFloat()*12;
else
y = rand.nextFloat()*-12;
}else{
if(rand.nextFloat() < 0.75)
y = rand.nextFloat()*-12;
else
y = rand.nextFloat()*12;
}
PlayerPose pp = new PlayerPose();
pp.setPx(x);
pp.setPy(y);
position_interface.setVelocity(pp, 0);
sleep(MOVE_SECONDS);
position_interface.setSpeed(0.0f, 0.0f);
sleep(WAIT_SECONDS + rand.nextInt() % WAIT_JITTER);
}
position_interface.setSpeed(9999.0f, 0.0f);
}
public void sleep(int ms){
try{
Thread.sleep(ms);
}catch(Exception e){
System.err.println("Error sleeping.");
e.printStackTrace();
System.exit(-1);
}
}
public float angle_diff(float current, float desired)
{
float diff = desired - current;
while(diff > 180.0f) diff -= 360.0f;
while(diff < -180.0f) diff += 360.0f;
return diff;
}
public float fix_angle(float f){
while(f < 0.0f) f += 360.0f;
while(f > 360.0f) f -= 360.0f;
return f;
}
public void die(){
System.err.println("Prey \"" + this.my_name + "\" has been killed!");
this.keep_going = false;
}
}
public class Driver{
public static void main(String args[]){
DataChannel dc = new DataChannel();
//instantiate the predators
Predator pred1 = new Predator("pred1", dc, 0, 0, 13);
Predator pred2 = new Predator("pred2", dc, 1, 0, 0);
Predator pred3 = new Predator("pred3", dc, 2, 0, -13);
Predator pred4 = new Predator("pred4", dc, 3, -13, -8);
Predator pred5 = new Predator("pred5", dc, 4, -13, 8);
//instantiate the prey
Prey prey1 = new Prey("prey1", dc, 5, 18, 18);
Prey prey2 = new Prey("prey2", dc, 6, 18, -18);
Prey prey3 = new Prey("prey3", dc, 7, 18, -9);
Prey prey4 = new Prey("prey4", dc, 8, 18, 9);
//start all the threads
dc.start();
pred1.start();
pred2.start();
pred3.start();
pred4.start();
pred5.start();
prey1.start();
prey2.start();
prey3.start();
prey4.start();
}
}
So I have all these classes put together for all the connectivity between Predators and Prey and the world. The only thing I'm really stumped on is the run() method for the Predator class (how they hunt).
The theory is simple. The predators have to gather around the Prey on it's North, South, East and West side, and the DataChannel class will notice that and capture the prey and take it off the map. But my job is to get this to happen, by having the Predators communicate with one another, and then chase and hunt down the Prey (who I programmed to move randomly).
Here's all the classes. Remember, the run() method for the Predator class is where I'm stumped. Everything else is how I want it to be. Any help?
/**
Predator class, with no "hunting" functionality.
*/
import java.io.*;
import javax.imageio.ImageIO;
import java.util.ArrayList;
import javaclient2.*;
import javaclient2.structures.*;
public class Predator extends Thread
{
private Position2DInterface position_interface = null;
private BlobfinderInterface blob_finder = null;
private PlayerClient playerClient = null;
private DataChannel dc = null;
private String name = "";
public Predator(String name, DataChannel dc, int id, float x, float y){
this.name = name;
this.playerClient = new PlayerClient("localhost", 6665);
blob_finder = playerClient.requestInterfaceBlobfinder(id,
PlayerConstants.PLAYER_OPEN_MODE);
position_interface = playerClient.requestInterfacePosition2D(id,
PlayerConstants.PLAYER_OPEN_MODE);
playerClient.runThreaded (-1, -1);
//wait until the intefaces are ready before doing anything
while(!blob_finder.isDataReady() ||
!position_interface.isDataReady()) {
try{
sleep(100);
}catch(Exception e){
System.err.println("Error sleeping!");
e.printStackTrace();
System.exit(-1);
}
}
PlayerPose pp = new PlayerPose();
pp.setPx(x);
pp.setPy(y);
position_interface.setOdometry(pp);
this.dc = dc;
dc.registerPredator(name, position_interface);
}
/**
* @param recipient The predator to deliver the message to.
* @param msg The message.
*
* Deliver a message to another predator.
*
*/
public void sendMessage(String recipient, Object msg){
dc.sendMessage(recipient, msg);
}
/**
* @param msg The message.
*
* Deliver a message to all other predators.
*
*/
public void broadcastMessage(Object msg){
for(String predator : dc.getPredators()){
sendMessage(predator, msg);
}
}
/**
*
* Get the next message from other predators.
*
* @return The next message, or null if there are no unread messages.
*
*/
public Object getMessage(){
return dc.getMessage(this.name);
}
public void run(){
// hunt the prey!
System.out.println("There are " + dc.numLivingPreys() +
" left to capture!");
}
}
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Vector;
import java.util.Set;
import javaclient2.*;
import javaclient2.structures.*;
/**
Object that records all of the predator locations, and kills prey when
they have been captured.
*/
public class DataChannel extends Thread{
static final float FUDGE_FACTOR = 1;
static final float CAPTURE_RANGE = 5;
private ConcurrentHashMap<String, Position2DInterface> pred_pids =
new ConcurrentHashMap<String, Position2DInterface>();
private ConcurrentHashMap<String, Position2DInterface> prey_pids =
new ConcurrentHashMap<String, Position2DInterface>();
private ConcurrentHashMap<String, Prey> preys =
new ConcurrentHashMap<String, Prey>();
private ConcurrentHashMap<String, ConcurrentLinkedQueue<Object>> msgs =
new ConcurrentHashMap<String, ConcurrentLinkedQueue<Object>>();
public void registerPredator(String name, Position2DInterface pid){
pred_pids.put(name, pid);
msgs.put(name, new ConcurrentLinkedQueue<Object>());
}
public void registerPrey(String name, Position2DInterface pid, Prey prey){
prey_pids.put(name, pid);
preys.put(name, prey);
}
public int numLivingPreys(){
return preys.size();
}
public Set<String> getPredators(){
return msgs.keySet();
}
public void sendMessage(String recipient, Object msg){
(msgs.get(recipient)).add(msg);
}
public Object getMessage(String recipient){
return (msgs.get(recipient)).poll();
}
public float getPredX(String predator){
try{
return (pred_pids.get(predator)).getX();
}catch(Exception ex) {}
return -1.0f;
}
public float getPredY(String predator){
try{
return (pred_pids.get(predator)).getY();
}catch(Exception ex) {}
return -1.0f;
}
public float getPreyX(String prey){
try{
return (prey_pids.get(prey)).getX();
}catch(Exception ex) {}
return -1.0f;
}
public float getPreyY(String prey){
try{
return (prey_pids.get(prey)).getY();
}catch(Exception ex) {}
return -1.0f;
}
public void run(){
while(true){
try{
sleep(100);
}catch(Exception e){
System.err.println("Error sleeping!");
e.printStackTrace();
System.exit(-1);
}
//get the location of each predator
Vector<Float> xpos = new Vector<Float>();
Vector<Float> ypos = new Vector<Float>();
Vector<String> pred_names= new Vector<String>();
for(String predator : pred_pids.keySet()){
if(pred_pids.get(predator) == null){
System.err.println("pred_pids does not have " + predator);
System.exit(-1);
}
xpos.add(getPredX(predator));
ypos.add(getPredY(predator));
pred_names.add(predator);
}
//for each prey, see if all of the four positions are guarded
for(String prey : prey_pids.keySet()){
boolean north = false;
boolean south = false;
boolean east = false;
boolean west = false;
if(prey_pids.get(prey) == null){
System.err.println("prey_pids does not have " + prey);
System.exit(-1);
}
float prey_x = getPreyX(prey);
float prey_y = getPreyY(prey);
for(int i=0; i < xpos.size(); i++){
//NORTH
if(Math.abs(xpos.get(i) - prey_x)<FUDGE_FACTOR &&
(ypos.get(i) - prey_y) > 0 &&
(ypos.get(i) - prey_y) < CAPTURE_RANGE){
north = true;
}
//SOUTH
if(Math.abs(xpos.get(i) - prey_x)<FUDGE_FACTOR &&
(prey_y - ypos.get(i)) > 0 &&
(prey_y - ypos.get(i)) < CAPTURE_RANGE){
south = true;
}
//EAST
if(Math.abs(ypos.get(i) - prey_y)<FUDGE_FACTOR &&
(xpos.get(i) - prey_x) > 0 &&
(xpos.get(i) - prey_x) < CAPTURE_RANGE){
east = true;
}
//WEST
if(Math.abs(ypos.get(i) - prey_y)<FUDGE_FACTOR &&
(prey_x - xpos.get(i)) > 0 &&
(prey_x - xpos.get(i)) < CAPTURE_RANGE){
west = true;
}
}
//prey is boxed in
if(north && south && east && west){
(preys.get(prey)).die();
preys.remove(prey);
prey_pids.remove(prey);
}
}
if(preys.size() == 0){
System.err.println("Congratulations: All prey are captured.");
System.exit(0);
}
}
}
}
import javaclient2.structures.*;
import javaclient2.*;
import java.util.Random;
/**
Prey class.
*/
public class Prey extends Thread{
private final int ROTATE_SECONDS = 500;
private final int MOVE_SECONDS = 3000;
private final int WAIT_SECONDS = 8000;
private final int WAIT_JITTER = 4000;
private Position2DInterface position_interface = null;
private PlayerClient playerClient = null;
private DataChannel dc = null;
private String my_name = null;
private boolean keep_going = true;
Random rand = new Random();
public Prey(String name, DataChannel dc, int id, float x, float y){
this.playerClient = new PlayerClient("localhost", 6665);
position_interface = playerClient.requestInterfacePosition2D(id,
PlayerConstants.PLAYER_OPEN_MODE);
playerClient.runThreaded (-1, -1);
this.dc = dc;
this.my_name = name;
while(!position_interface.isDataReady()) {
try{
sleep(100);
}catch(Exception e){
System.err.println("Error sleeping!");
e.printStackTrace();
System.exit(-1);
}
}
PlayerPose pp = new PlayerPose();
pp.setPx(x);
pp.setPy(y);
position_interface.setOdometry(pp);
dc.registerPrey(name, position_interface, this);
}
public float getX(){
try{
return position_interface.getX();
}catch(Exception ex) {}
return -1.0f;
}
public float getY(){
try{
return position_interface.getY();
}catch(Exception ex) {}
return -1.0f;
}
public void run(){
float old_x = getX();
float old_y = getY();
while(keep_going){
float current_x = getX();
float current_y = getY();
float x, y;
if(current_x <=0){
if(rand.nextFloat() < 0.75)
x = rand.nextFloat()*6;
else
x = rand.nextFloat()*-6;
}else{
if(rand.nextFloat() < 0.75)
x = rand.nextFloat()*-6;
else
x = rand.nextFloat()*6;
}
if(current_y <=0){
if(rand.nextFloat() < 0.75)
y = rand.nextFloat()*12;
else
y = rand.nextFloat()*-12;
}else{
if(rand.nextFloat() < 0.75)
y = rand.nextFloat()*-12;
else
y = rand.nextFloat()*12;
}
PlayerPose pp = new PlayerPose();
pp.setPx(x);
pp.setPy(y);
position_interface.setVelocity(pp, 0);
sleep(MOVE_SECONDS);
position_interface.setSpeed(0.0f, 0.0f);
sleep(WAIT_SECONDS + rand.nextInt() % WAIT_JITTER);
}
position_interface.setSpeed(9999.0f, 0.0f);
}
public void sleep(int ms){
try{
Thread.sleep(ms);
}catch(Exception e){
System.err.println("Error sleeping.");
e.printStackTrace();
System.exit(-1);
}
}
public float angle_diff(float current, float desired)
{
float diff = desired - current;
while(diff > 180.0f) diff -= 360.0f;
while(diff < -180.0f) diff += 360.0f;
return diff;
}
public float fix_angle(float f){
while(f < 0.0f) f += 360.0f;
while(f > 360.0f) f -= 360.0f;
return f;
}
public void die(){
System.err.println("Prey \"" + this.my_name + "\" has been killed!");
this.keep_going = false;
}
}
public class Driver{
public static void main(String args[]){
DataChannel dc = new DataChannel();
//instantiate the predators
Predator pred1 = new Predator("pred1", dc, 0, 0, 13);
Predator pred2 = new Predator("pred2", dc, 1, 0, 0);
Predator pred3 = new Predator("pred3", dc, 2, 0, -13);
Predator pred4 = new Predator("pred4", dc, 3, -13, -8);
Predator pred5 = new Predator("pred5", dc, 4, -13, 8);
//instantiate the prey
Prey prey1 = new Prey("prey1", dc, 5, 18, 18);
Prey prey2 = new Prey("prey2", dc, 6, 18, -18);
Prey prey3 = new Prey("prey3", dc, 7, 18, -9);
Prey prey4 = new Prey("prey4", dc, 8, 18, 9);
//start all the threads
dc.start();
pred1.start();
pred2.start();
pred3.start();
pred4.start();
pred5.start();
prey1.start();
prey2.start();
prey3.start();
prey4.start();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
掠食者实际上并不需要交流。它们只需要找到猎物,并尽可能靠近它。
因此,如果
p1
和p2
代表捕食者,而o1
代表猎物:p1
已尽可能接近o1
,所以它保持原状。然而,
p2
可以通过移动到 B3 来接近。现在,在您的示例代码中,您有 4 个捕食者和 5 个猎物。这可能会导致没有足够的掠食者集中在一个猎物上来消灭它。为了实现这一点,你需要一个启发式的方法,比如:“更喜欢捕食者最多的猎物”。
您可能还需要考虑双方平等的情况。你最终可能会遇到一个猎物一个捕食者。如果一段时间内猎物没有被消灭,捕食者就会放弃,从而解决这个问题。您需要包含一些随机性,以便并非所有掠食者同时放弃。类似
baseGiveUpTime + (int)(2 * numPred * Math.random())
The predators don't actually need to communicate. They just need to locate prey, and move as close as possible to it.
So, if
p1
andp2
represents predators ando1
represents prey:p1
is as close as it can get too1
, so it stays put.p2
, however, can get closer by moving to B3.Now, in your sample code, you have 4 predators and 5 prey. This could lead to a case where there are not enough predators focused on one prey to eliminate it. For that to work, you need a heuristic like: "prefer the prey with the most predators".
You may also need to consider the case where both sides are equal. You could wind up with one predator per prey. That can be handled by having predators give up if a period elapses without their prey being eliminated. You will want to include some randomness so that not all the predators give up at the same time. Something like
baseGiveUpTime + (int)(2 * numPred * Math.random())