JAVA: Interacting ArrayLists? - java

So, this is in a game environment. I have 2 ArrayLists, one is a party of 3 characters you own, and the other is an ArrayList of 3 enemy characters.
I have a method called combat which puts character "a" from your party and "b" from the enemy party in combat. I have this working without any problems, but when one of the characters dies in either ArrayList, the targets have to switch.
For example:
1)Characters a, b, c Vs. Character d, e, f
2)I use my combat method so that a fights d, b fights e, and c fights f. All is well so far.
3)Character a loses and dies, now I have to make character b fight d and e, while c keeps fighting f.
Any ideas on how I could go about doing this?

I would just remove the dead character at the end of combat() method and then run the combat() again recursively until one of the lists is empty.
Pseudocode:
protected void combat(List<Character> heroes, List<Character> enemies) {
if (heroes.isEmpty() || enemies.isEmpty()) {
//one of the parties wins
return;
}
List<Pair<Character, Character>> vs = new LinkedList<>();
int i = 0;
while ( i< heroes.length() && i< enemies.length()) {
vs.add(heroes.get(i), enemies.get(i));
++i;
}
for (Pair<Character, Character> fight : vs) {
//figure out the loser
Character loser = fight(vs.getFirst(), vs.getSecond();
if (loser.isEnemy()) {
enemies.remove(loser);
} else {
heroes.remove(loser);
}
}
combat(heroes, enemies);
}

List friends = new ArrayList();
List enemies = new ArrayList();
// populate the lists.
// map the opponents to each other.
//if elementA in friend dies while fighting elementX
friends.remove("elementA");
//during fighting
if(friends.size()>0){
//new enemy of element X is
friends.get(1);
}
else{
//enemies has won over friends.
}

Related

incrementing an object in a 2d array

Good day, so I intend for my code to loop through my array and increment the row index of object by 1 position. I used timer task because I want the object to move forward after certain amount of time. This is the code I have tried. I have looked but I have struggled to find solution relevant to my problem. Would appreciate the help.
class cat_function extends TimerTask {
public void run() {
synchronized (game.board) {
for (int i = 0; i < game.board.length; i++) {
for (int k = 0; k < game.board[0].length; k++) {
if (game.board[i][k] instanceof cat) {
cat garfield = new cat(0, 0);
game.board[i][k] = garfield;
game.board[i][k + 1] = garfield;
}
}
}
}
}
}
Assuming:
game.board is defined as a Cat[][]
an empty cell's value is null
Then all you have to do is
if (game.board[i][k] instanceof cat) {
game.board[i][k + 1] = game.board[i][k]; // Put cat in new location
game.board[i][k] = null; // Remove cat from previous location
}
However, this code still has two problems
What do you do when you reach the edge of the board. You'll have to add logic to make it do something different so you don't fall of the edge.
There's no need to scan the entire game board every time just to find the Cat. Keep the cat's location (indexes) separately so you always know where it is and don't have to look for it.
If there can be more than one cat on the board you will also need logic to decide what happens if two cats "collide" when moving (i.e. you try to move a cat into a cell that already contains a cat).
Solving those problems is left as an exercise for you.

Listing all the Games

Following a question here OP is interested in listing all unique 2x2 games. Games here are game theory games in which there with two players and two strategies each. Hence, there are four possible outcomes (see diagram). These outcomes comes with 'payoffs' for each players. Payoff 'pairs' are two payoffs for each player from some combinations of strategies. Payoffs are given in integers and cannot exceed 4.
For instance, consider the following example of a 2x2 game (with a payoff pair is written in the brackets, and P1 and P2 denote player 1 and 2 respectively):
P2
Right Left
Up (2,2) (3,4)
P1
Down (1,1) (4,3)
The payoffs here take the values [ (2,2),(3,4) | (1,1),(4,3) ].
Now, clearly many other games (i.e. unique payoff matrices) are possible. If payoffs for each players is given by 1,2,3,4 (which we can permute in 4!=24 ways) then 24*24 games are possible. OP was interested with listing all these games.
Here comes the subtle part: two unique payoff matrices may nevertheless represent games if one can be obtained from the other by
i) exchanging columns (i.e. relabel Player A's strategies)
ii) exchanging rows (i.e. relabel Player B's strategies)
iii) Exchange the players (i.e. exchanging the payoff pairs and
mirroring the matrix along the first diagonal)
OP posted the following code that correctly lists all 78 possible games in which the payoffs for each can be (1,2,3,4).
I am interested in changing the code so that the program lists all unique games where the possible payoffs are different: i.e. (1,2,3,3) for player 1 and (1,2,3,4) for player 2. Here, there would be 4!/2! ways of permuting (1,2,3,3) and therefore fewer games.
#!/usr/bin/groovy
// Payoff Tuple (a,b) found in game matrix position.
// The Tuple is immutable, if we need to change it, we create a new one.
// "equals()" checks for equality against another Tuple instance.
// "hashCode()" is needed for insertion/retrievel of a Tuple instance into/from
// a "Map" (in this case, the hashCode() actually a one-to-one mapping to the integers.)
class Tuple {
final int a,b
Tuple(int a,int b) {
assert 1 <= a && a <= 4
assert 1 <= b && b <= 4
this.a = a
this.b = b
}
#!/usr/bin/groovy
// Payoff Tuple (a,b) found in game matrix position.
// The Tuple is immutable, if we need to change it, we create a new one.
// "equals()" checks for equality against another Tuple instance.
// "hashCode()" is needed for insertion/retrievel of a Tuple instance into/from
// a "Map" (in this case, the hashCode() actually a one-to-one mapping to the integers.)
class Tuple {
final int a,b
Tuple(int a,int b) {
assert 1 <= a && a <= 4
assert 1 <= b && b <= 4
this.a = a
this.b = b
}
boolean equals(def o) {
if (!(o && o instanceof Tuple)) {
return false
}
return a == o.a && b == o.b
}
int hashCode() {
return (a-1) * 4 + (b-1)
}
String toString() {
return "($a,$b)"
}
Tuple flip() {
return new Tuple(b,a)
}
}
// "GameMatrix" is an immutable structure of 2 x 2 Tuples:
// top left, top right, bottom left, bottom right
// "equals()" checks for equality against another GameMatrix instance.
// "hashCode()" is needed for insertion/retrievel of a GameMatrix instance into/from
// a "Map" (in this case, the hashCode() actually a one-to-one mapping to the integers)
class GameMatrix {
final Tuple tl, tr, bl, br
GameMatrix(Tuple tl,tr,bl,br) {
assert tl && tr && bl && br
this.tl = tl; this.tr = tr
this.bl = bl; this.br = br
}
GameMatrix colExchange() {
return new GameMatrix(tr,tl,br,bl)
}
GameMatrix rowExchange() {
return new GameMatrix(bl,br,tl,tr)
}
GameMatrix playerExchange() {
return new GameMatrix(tl.flip(),bl.flip(),tr.flip(),br.flip())
}
GameMatrix mirror() {
// columnEchange followed by rowExchange
return new GameMatrix(br,bl,tr,tl)
}
String toString() {
return "[ ${tl},${tr} | ${bl},${br} ]"
}
boolean equals(def o) {
if (!(o && o instanceof GameMatrix)) {
return false
}
return tl == o.tl && tr == o.tr && bl == o.bl && br == o.br
}
int hashCode() {
return (( tl.hashCode() * 16 + tr.hashCode() ) * 16 + bl.hashCode() ) * 16 + br.hashCode()
}
}
// Check whether a GameMatrix can be mapped to a member of the "canonicals", the set of
// equivalence class representatives, using a reduced set of transformations. Technically,
// "canonicals" is a "Map" because we want to not only ask the membership question, but
// also obtain the canonical member, which is easily done using a Map.
// The method returns the array [ canonical member, string describing the operation chain ]
// if found, [ null, null ] otherwise.
static dupCheck(GameMatrix gm, Map canonicals) {
// Applying only one of rowExchange, colExchange, mirror will
// never generate a member of "canonicals" as all of these have player A payoff 4
// at topleft, and so does gm
def q = gm.playerExchange()
def chain = "player"
if (q.tl.a == 4) {
}
else if (q.tr.a == 4) {
q = q.colExchange(); chain = "column ∘ ${chain}"
}
else if (q.bl.a == 4) {
q = q.rowExchange(); chain = "row ∘ ${chain}"
}
else if (q.br.a == 4) {
q = q.mirror(); chain = "mirror ∘ ${chain}"
}
else {
assert false : "Can't happen"
}
assert q.tl.a == 4
return (canonicals[q]) ? [ canonicals[q], chain ] : [ null, null ]
}
// Main enumerates all the possible Game Matrixes and builds the
// set of equivalence class representatives, "canonicals".
// We only bother to generate Game Matrixes of the form
// [ (4,_) , (_,_) | (_,_) , (_,_) ]
// as any other Game Matrix can be trivially transformed into the
// above form using row, column and player exchange.
static main(String[] argv) {
def canonicals = [:]
def i = 1
[3,2,1].permutations { payoffs_playerA ->
[4,3,2,1].permutations { payoffs_playerB ->
def gm = new GameMatrix(
new Tuple(4, payoffs_playerB[0]),
new Tuple(payoffs_playerA[0], payoffs_playerB[1]),
new Tuple(payoffs_playerA[1], payoffs_playerB[2]),
new Tuple(payoffs_playerA[2], payoffs_playerB[3])
)
def ( c, chain ) = dupCheck(gm,canonicals)
if (c) {
System.out << "${gm} equivalent to ${c} via ${chain}\n"
}
else {
System.out << "${gm} accepted as canonical entry ${i}\n"
canonicals[gm] = gm
i++
}
}
}
}
I have attempted changing the "assert 1 <= a && a <= 4" to "assert 1 <= a && a <= 3" and then changing the 4's to a 3 further down in the code. This does not seem to work.
I am not sure however what the "int hashCode() {return (a-1) * 4 + (b-1)" or if "(q.tl.a == 4) {
}
else if (q.tr.a == 4) {" does and therefore not sure how to change this.
Apart from this, I suspect that the flips and exchanges can remain the way they are, since this should produce a procedure for identifying unique games no matter what the specific payoff set is (i.e. whether it's 1,2,3,4 or 1,2,3,3).
I have calculated the number of unique games for different payoff sets by hand which may be useful for reference.
I had a similar situation making an AI for Othello/Reversi, and wanting the state-space to be as small as possible to remove redundant processing.
The technique I used was to represent the game as a set of meta-states, or in your case, meta-outcomes, where each meta consists of all the permutations which are equivalent. Listing and identifying equivalent permutations involved coming up with a normalization scheme which determines which orientation or reflection is the key for the meta instance. Then all new permutations are transformed to normalize them before comparing to see if they represented a new instance.
In your case, if swapping rows and columns are both considered equivalent, you might consider the case where the orientation of sorted order puts the smallest value in the top-left corner and the next smallest adjacent value in the top-right corner. This normalizes all 4 flip positions (identity, h-flip, v-vlip, hv-flip) into a single representation.

Battleship stuck on battle board implementation

we recently somewhat learned Object Oriented Programming and already have a project on it due soon, so I am not too familiar with OOP. However, we were assigned a project of creating a Battleship game.
I have created a ship, square, and battle board class. I have tested all three, and all tests have also passed except for one method on Battleboard classs. To test each class, I used a toString method. This is in my battle board's toString method:
for (int i = 0; i < squares.length; i++) {
Just a couple of problems that I spotted, there can be more as the code is still incomplete:
A. In the very beginning of
public boolean addShip(int length, boolean isHorizontal, int startRow, int startCol) {
there is
square = new Square();
It seems logical to check whether a ship exists at the square to which you add it, but instead you check whether it exists in a brand new square. We don't have Square code, but I assume that it does not have a ship initially.
B. In the same method there is the following code:
if (isHorizontal == true) {
ship = new Ship(length, isHorizontal, startRow, startCol);
for (int i = 0; i < ship.getLength(); i++) {
if (startCol > numberOfColumns) {
return false;
} else {
square.addShip(ship);
startCol++;
}
}
}
So the ship is being repeatedly added to the same brand new square which is not related to the board. Later, that square is not added anywhere and now used anyhow.
I'm not sure how to fix this, but probably all the squares should have been inialized before this method is called, no squares should been created in this method; instead, you need to find a square corresponding to the current iteration`.
C. The following code
} else if (!square.hasBeenHit() && square.hasShip()) {
//Returns length of ship if there is a ship that hasn't been hit
if (ship.getLength() == 1) {
toString += "1 ";
} else if (ship.getLength() == 2) {
toString += "2 ";
} else if (ship.getLength() == 3) {
toString += "3 ";
} else if (ship.getLength() == 4) {
toString += "4 ";
}
}
uses the same ship on all iterations, so it behaves in the same way on all the iterations (appends 1). The correct thing would be to find a ship belonging to the current square (i, j), if it exists, and use it.
D. A brand new square is created on each loop, again, although you are iterating over squares! It would be more logical to write square = squares[i][j] instead of square = new Square().
I'd recommend you to use a debugger to see what happens in your code.

How can I random an ArrayList with dispersion?

I'm trying to do an application which set a game plan for a tournament.
I have a method:
public List<Match> creerMatchsTousContreTous(List<Equipe> lEquipe) {
List<Match> lMatch = new ArrayList<>();
for (int i = 0; i < lEquipe.size(); i++) {
for (int j = i + 1; j < lEquipe.size(); j++) {
Match match = new Match();
match.setEquA(lEquipe.get(i));
match.setEquB(lEquipe.get(j));
lMatch.add(match);
}
}
return lMatch;
}
This method receid a list of Teams. Each one must to play which each others. This return a list of plays (Match).
I want now to random the plays. I need that a Team A who plays the first Play not play the next one. And so more.
I use:
Collections.shuffle(lMatch);
But that ramdom the list of plays and it is possible that a tema play two successive plays.
How can I achieve that?
Thanks
Best Regards
EDIT:
EXAMPLE:
The method return a list of games:
TEAM 1 : TEAM 2
TEAM 2 : TEAM 3
TEAM 1 : TEAM 3
TEAM 4 : TEAM 3
TEAM 2 : TEAM 4
TEAM 4 : TEAM 3
creerMatchsTousContreTous() return in this example a list with 6 values. But here for example, in the first game, TEAM 2 is playing, in the second game he is also playing, and this mustn't be.
I would suggest adding a boolean variable, such as justPlayed or hasPlayed, to the Team class. This variable would track if a particular team has just played in a game.
Collections.shuffle(lMatch); // get two random teams using shuffle
while(Match.Team1.getHasPlayed() == True or Match.Team2.getHasPlayed() == True){
Collections.shuffle(lMatch); // try to find different teams
}
lMatch.play(); // you've found two teams, so now you can call your play method
for(Team t:lEquipe){ // go through the list of teams and
t.setHasPlayed(false); // reset the rest each team's boolean
}
Match.Team1.setHasPlayed(true);
Match.Team2.setHasPlayed(true); // set the boolean to true at the end of the turn
//
This is obviously pseudocode, since I don't know your implementation of Match and Team. Still, consider using the boolean instance field and checking if it has been modified in the previous turn.
The one below is a recursive approach. I think it can provide solution in a faster way than one suggested by #Sonedring, as constraint is applied after every randomization.
It is also safer for a corner case where you have less than 4 teams. In the corner case you will not find a solution and you don't to run an endless loop.
Hope this helps.
public static void randomize(List<Match> matches) {
List<Match> randomizedList = new ArrayList<>();
int numberOfAttempts = 256;
// tmpSubList is a temporary list that contains all matches
// (excluding unwanted) after n-th iteration (randomization).
List<Match> tmpSubList = new ArrayList<Match>(matches);
while (matches.size() > 0) {
// if tmpSubList contains - it means there is no match that can be added.
// Need to restart randomization algorithm.
if (tmpSubList.size() == 0) {
System.out.println("Restarting algorithm.");
if (--numberOfAttempts == 0) {
throw new ArithmeticException("Could not find solution.");
}
// Need to restart:
matches.addAll(randomizedList);
tmpSubList.addAll(randomizedList);
randomizedList.clear();
}
int randomIndex = (int) (tmpSubList.size() * Math.random());
Match match = tmpSubList.remove(randomIndex);
matches.remove(match); // remove also from the main list;
randomizedList.add(match);
Equipe lastTeam1 = match.getEquA();
Equipe lastTeam2 = match.getEquB();
tmpSubList.clear();
matches.stream()
.filter( x -> !x.getEquA().equals(lastTeam1) && !x.getEquB().equals(lastTeam1) )
.filter( x -> !x.getEquA().equals(lastTeam2) && !x.getEquB().equals(lastTeam2) )
.forEach( x -> tmpSubList.add(x));
}
matches.addAll(randomizedList);
}

JAVA: trouble finding which element of array to use in a function?

In my Undead class I have a method written which allows an undead character to sacrifice itself and split its remaining health between the two remaining team mates (the total number of players in the array of chars is always 3).
My function for this is
public void sacrifice(Character other1, Character other2){
int healthgiven = health/2;
health -= health;
other1.health += healthgiven;
other2.health += healthgiven;
System.out.println(name + " has sacrified himself for the team.
His health has been distributed among the two remaining allies. ");
}
This works as far as I know, but it becomes a problem when I have to use it in the main. I somehow have to figure out which elements of the list are the two other characters (who can be Undead as well). Basically when I end up calling undeadchar.sacrifice(other1, other2), I need to find the two characters that are not undeadchar. Sorry if it's confusing I will rewrite this if necessary.
I think you should place a check before calling the method sacrifice.
Assuming that you have getHealth() function in your Player and once the player sacrifices health the health of player is 0 then,
List<Player> PlayersList = new ArrayList<Player>();
Player sacrificingPlayer = ... //Your logic to find sacrificing player
List<Player> healthyPlayers = GetHealthyPlayer(PlayersList );
sacrificingPlayer.sacrifice(healthyPlayers.get(0), healthyPlayers.get(1));
and function GetHealthyPlayer();
public List<Player> GetHealthyPlayer(List<Player> PlayersList )
{
List<Player> Players = new ArrayList<Player>();
int PlayerCount = 0;
for (Player pl: PlayersList )
{
if(pl.getHealth() > 0)
{
Players.add(pl);
PlayerCount++;
if(PlayerCount == 2) //Since we need only two healthy player
break;
}
}
if(PlayerCount != 2)
throw Exception("Two healthy players not found "); //Or you Can return null and check
return Players;
}
Assuming you have something like:
ArrayList<Character> chars = ...; // all of them
Character sacrificingChar = ...; // the one that will sacrifice himself
Then you can do:
List<Character> others = new ArrayList<>(chars);
others.remove(sacrificingChar);
sacrificingChar.sacrifice(others.get(0), others.get(1));
Using Java 8:
List<Character> charList = ...
Character sacrificeChar = ...
List<Character> notSacrificeList = charList.stream()
.filter(x -> !x.equals(sacrificeChar))
.map(Character::new)
.collect(Collectors.toList());

Categories

Resources