Objects' variables changed by method in another class [duplicate] - java

This question already has answers here:
How to make a method in a class, manipulate variables in another class?
(2 answers)
Closed 5 years ago.
I created a simple method in my CardGames class that replicates a card game to play around with conditional statements. I call the method from a separate Player class because the player earns/loses points based on the card. I want the method to be able to change the player objects points variable.
What I want to have happen is when the playSimpleCardGame gets called by the Player object, the method changes the Player object's points.
But when I run it the points do not change. I've tried extending/implementing both classes (i.e. shooting in the dark). I also created an instance variable points in the CardGames class but then the Player object does not have points as a variable. What am I missing?
public class Player
{
private int points;
public static void main(String[] args)
{
CardGames steve = new CardGames();
System.out.println(steve.playSimpleCardGame("red"));
System.out.println(steve.playSimpleCardGame("red"));
System.out.println(steve.playSimpleCardGame("black"));
System.out.println(steve.playSimpleCardGame("black"));
System.out.println(steve.points);
}
}
public class CardGames
{
/*
* Rules of this game:
* If you draw a red card, you get a point.
* If you draw a black card, you lose two points.
*/
public int playSimpleCardGame(String color)
{
if (color.equalsIgnoreCase("red"))
return points = points + 1;
else
return points = points - 2;
}
}
public class Player
{
private int points;
public Player(){
points=0;
}
public static void main(String[] args)
{
CardGames game = new CardGames();
Player steve = new Player();
System.out.println(game.playSimpleCardGame("red", steve));
System.out.println(game.playSimpleCardGame("red", steve));
System.out.println(game.playSimpleCardGame("black", steve));
System.out.println(game.playSimpleCardGame("black", steve));
System.out.println(steve.points);
}
public int getPoints() {
return points;
}
public void addPoints(int p) {
this.points = points + p;
}
}
public class CardGames
{
/*
* Rules of this game:
* If you draw a red card, you get a point.
* If you draw a black card, you lose two points.
*/
public int playSimpleCardGame(String color, Player player)
{
if (color.equalsIgnoreCase("red"))
{
player.addPoints(1);
return player.getPoints();
}
else
{
player.addPoints(-2);
return player.getPoints();
}
}
}

Firstly, there is no need to extend CardGames class by the Player class. Secondly, even if you wish to do it, it will be a bad design. I won't go into the design part. The following code should answer your problem :
public class Player
{
public Integer points;
public Player(){
points=0;
}
public static void main(String[] args)
{
CardGames game = new CardGames();
Player steve = new Player();
System.out.println(game.playSimpleCardGame("red", steve));
System.out.println(game.playSimpleCardGame("red", steve));
System.out.println(game.playSimpleCardGame("black", steve));
System.out.println(game.playSimpleCardGame("black", steve));
System.out.println(steve.points);
}
}
public class CardGames
{
/*
* Rules of this game:
* If you draw a red card, you get a point.
* If you draw a black card, you lose two points.
*/
public int playSimpleCardGame(String color, Player player)
{
if (color.equalsIgnoreCase("red"))
return player.points = player.points + 1;
else
return player.points = player.points - 2;
}
}

Related

using constructor from another class in java to create objects in separate classs

how can I use the constructor from another class in java to make an object through a method in separate class. For example below is a constructor in a player class
public class Player extends Entity {
public Player(int maxEnergy, int x, int y) {
this.maxEnergy = maxEnergy;
this.energy = maxEnergy;
carryingGhost = false;
xPos = x;
yPos = y;
}
Which I want to use and create objects (player) through a method called
private Player createPlayer() {
and the above method is in separate class as
public class GameEngine {
**The method must return a Player object that represents the player in the
game. it must set the maxEnergy for the player, and the
X and Y positions corresponding to a tile position in the current level.
I have tried to initialize player within method with parameters and
without parameters as**
Player player = new Player(int maxEnergy, int x, int y);
this.player.getEnergy();
this.player.getMaxEnergy();
this.player.setPosition(x, y);
return player;
}
But it give errors.Any help will be appreciated.I am quite close to assume its not possible to have created objects like this.
below I share the complete game engine which is working with other classes as well .
import java.awt.Point;
import java.util.ArrayList;
import java.util.Random;
public enum TileType {
WALL, FLOOR1, FLOOR2, BANK, BREACH, DOOR;
}
public static final int LEVEL_WIDTH = 35;
public static final int LEVEL_HEIGHT = 18;
private Random rng = new Random();
private int levelNumber = 1; //current level
private int turnNumber = 1;
private GameGUI gui;
private TileType[][] level;
private ArrayList<Point> spawnLocations;
private Player player;
private Ghost[] ghosts;
public GameEngine(GameGUI gui) {
this.gui = gui;
}
private TileType[][] generateLevel() {
//YOUR CODE HERE
return null; //change this to return the 2D arrayof TileType
//values that you create above
}
private ArrayList<Point> getSpawns() {
ArrayList<Point> s = new ArrayList<Point>();
// YOUR CODE HERE
return s;
}
private Ghost[] addGhosts() {
//YOUR CODE HERE
return null; //change this to return an array of ghost objects
}
**/**
* Creates a Player object in the game. The method instantiates
* the Player class and assigns values for the energy and position.
* The first version of this method should use fixed a fixed position
for the player to start, by setting fixed X and Y values when calling
the constructor in the Player class. The second version of this method
should use the spawns ArrayLis to select a suitable location to spawn
the player and removes the Point from the spawns ArrayList. This will
prevent the Player from being added to the game inside a wall, bank or
breach for example.
#return A Player object representing the player in the game
*/**
private Player createPlayer() {
//YOUR CODE HERE
return null; //change this to return a Player object
}
public void movePlayerLeft() {
}
public void movePlayerRight() {
}
public void movePlayerUp() {
}
public void movePlayerDown() {
}
private void hitGhost(Ghost g) {
}
private void moveGhosts() {
}
private void moveGhost(Ghost g) {
}
private void cleanDefeatedGhosts() {
}
private void nextLevel() {
}
private void placePlayer() {
}
public void doTurn() {
cleanDefeatedGhosts();
moveGhosts();
gui.updateDisplay(level, player, ghosts);
}
public void startGame() {
level = generateLevel();
spawnLocations = getSpawns();
ghosts = addGhosts();
player = createPlayer();
gui.updateDisplay(level, player, ghosts);
}
}
I have used below method and its not showing error so far.
private Player createPlayer() {
int energy=player.getEnergy();
int maxEnergy=player.getMaxEnergy();
int xPos=player.xPos;
int yPos=player.yPos;
return new Player(maxEnergy,xPos,yPos);
}
The following should do it:
private Player createPlayer() {
int defaultMaxEnergy = 10; // Whatever value it should have
int initialX = 1; // Whatever value it should have
int initialY = 1; // Whatever value it should have
return new Player(defaultMaxEnergy, initialX, initialY);
}
Since the values are not in your descriptions I just selected a random number but you can pick whatever integers you want and that makes sense.
Does something like this work for your case?
public class GameEngine {
private Player createPlayer() {
return new Player(1,2,3);
}
}
Add a default no-args constructor in the player class. Once you create a constructor with Arg, java will not auto provide default one.
You have already declared Player
private Player player;
So you must not try to reinitialize using same variable name, rather
private Player createPlayer() {
Player newPlayer = new Player();
// set the different props of the Player obj
return newPlayer ;
}
What is the error which you are facing ? Can you share that ?

How should I implement a wait-notify approach for a game? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I have to implement a game with three players. I have the classes: player, game, board and edge. The board is a complete graph and each player must extract an edge. When the graph becomes a spanning tree a player wins. I implement the game with threads but I can't figure it out how I should implement a wait-notify approach.The examples found on the internet show only two threads. The wait should be in run method or I should create a new method for wait() and notify() ?I should have a run method in game class? Or just in player class?
Game Class:
public class Game {
private Board board;
private Player winner;
private Edge edges;
private final List<Player> players = new ArrayList<>();
public void addPlayer(Player player) {
players.add(player);
player.setGame(this);
}
public void setWinner(Player winningPlayer) {
int maxPoints = 0;
this.winner = winningPlayer;
for (Player p : players) {
maxPoints += p.getPoints();
p.setPoints(0);
}
winningPlayer.setPoints(maxPoints);
}
public Board getBoard() {
return board;
}
public void setBoard(Board board) {
this.board = board;
}
public List<Player> getPlayers() {
return players;
}
public void start () {
int i;
for (i = 0; i < getPlayers().size(); i++) {
new Thread(getPlayers().get(i)).start();
}
}
}
Board Class:
public class Board {
private final Graph complete;
public Board() {
complete = new Graph();
}
public Board(int size) {
// create the complete graph
this.complete = new Graph(size);
// shuffle its edges
Collections.shuffle(complete.getEdges());
}
public synchronized Edge extract() {
Edge edge = complete.getEdges().getFirst();
complete.getEdges().removeFirst();
return edge;
}
public boolean isEmpty(){
return complete.getEdges().isEmpty();
}
}
Player Class:
public class Player implements Runnable{
private String name;
private Game game;
private Graph graph = new Graph();
private int points;
private static final int THINKING_TIME = 20;
public Player(String name) {
this.name = name;
}
private boolean play() throws InterruptedException {
Board board = game.getBoard();
if (board.isEmpty()) {
return false;
}
graph.add( board.extract() );
System.out.println(name + ": " + graph);
Thread.sleep(THINKING_TIME);
if (graph.isSpanningTree()) {
game.setWinner(this);
}
return true;
}
public void setPoints(int points) {
this.points = points;
}
public int getPoints() {
return points;
}
public Game getGame() {
return game;
}
public void setGame(Game game) {
this.game = game;
}
public void run(){
try {
play();
} catch (InterruptedException e){
System.out.println("error: " + this.name + "'s turn was interrupted");
}
}
}
I only included the relevant classes for this question
Simplifying the task,
we have a board and a queue of players, and
we just must let a player on this board one by one in some given order:
one enters, makes a move, leaves and only then the following can embark.
Board looks pretty much like a shared resource, so we definitely must synchronize the process on it.
Board does nothing, but players do. So the players will wait and notify.
A player
can define if it is one's turn or not
wait if not (literally) - some another not-waiting player can try
then make a move on the board and leaves (id est notify all interested parties to resume trying)
Here is a short example, where board manages the queue oneself. It's runnable but does not solve your precise task. Just illustrates the idea.
public class Game {
private static class PlayBoard {
private int movesLeft;
private List<Player> players;
private int playerToMove;
PlayBoard(int movesLeft) {
this.movesLeft = movesLeft;
}
void setParties(Player... players) {
this.players = Arrays.asList(players);
this.players.forEach((Player player) -> player.prepareForGame(this));
playerToMove = 0;
}
boolean isActive() {
return movesLeft > 0;
}
boolean canIMove(Player player) {
return players.get(playerToMove) == player;
}
void takeMove(Player player) {
playerToMove = players.indexOf(player);
movesLeft--;
System.out.printf("%s's making move. %d moves left\n", player.name, movesLeft);
playerToMove = (playerToMove + 1) % players.size();
}
}
private static class Player {
private final String name;
private PlayBoard playBoard;
Player(String name) {
this.name = name;
}
void prepareForGame(PlayBoard playBoard) {
this.playBoard = playBoard;
}
void play() {
synchronized (playBoard) {
while (playBoard.isActive()) {
if (playBoard.canIMove(this)) {
playBoard.takeMove(this);
playBoard.notifyAll();
} else {
try {
playBoard.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
PlayBoard playBoard = new PlayBoard(12);
playBoard.setParties(new Player("Lea"),
new Player("Susan"),
new Player("Daria"));
List<Thread> threads = playBoard.players.stream()
.map(player -> new Thread(player::play))
.collect(Collectors.toList());
threads.forEach(Thread::start);
for (Thread thread : threads) {
thread.join();
}
}
}

Linking an array to another class in Java

I am working on a game of tic-tac-toe for class and in one class I create a Board object which contains a String array and then pass it to a player class. However I cannot figure out how to allow me to use this information in the new class. Can anybody here give me some pointers?
public static void main(String[] args)
{
//new tic-tac-toe board
Board board = new Board();
//two new players (computer and human)
Player computer = new Player(board, "X"); //Give computer player access to board and assign as X.
Player human = new Player(board, "O"); //Give human player access to board and assign as O.
and the class I'm trying to use it in
package outlab5;
import java.util.Scanner;
public class Player {
private String[][] currentBoard;
private String move;
Scanner input = new Scanner(System.in);
public Player(Board inBoard, String inMove){
move = inMove;
}
public void computerMove(){
boolean valid = false;
while(!valid){
int moveCols = (int)(Math.random()*4);
int moveRows = (int)(Math.random()*4);
System.out.print(currentBoard[0][0]);
}
}
I think your Board class has a field representing the String[][] array, which you are looking for.
In your player class, store the borad object properly.
public class Player {
private String[][] currentBoard;
private String move;
private Board board; //define a variable
Scanner input = new Scanner(System.in);
public Player(Board inBoard, String inMove){
board = inBoard;
move = inMove;
}
You dont show the code of Board class, so i have to guess how you may access the string[][],probably the Board class provides some get-Methods, to get access to the string array.
String[][] currentBoard = board.get....(); //this call must be placed in a method
Here is an example, of how you can do your application.
Board Class
public class Board {
// TODO : Stuff and Stuff ( Where your 3x3 Matrix may be )
}
Player Abstract Class
abstract class Player {
private final Board board;
private final String move;
public Player(Board _board, String _move) {
this.board = _board;
this.move = _move;
}
public void playerMove() {
// TODO : Default Movement Actions
}
public void playerWin() {
// TODO : Default Event on Player Win
}
}
Computer Class
public class Computer extends Player {
public Computer(Board _board, String _move) {
super(_board, _move);
}
#Override
public void playerMove() {
// TODO : Computer Related Movements ( Like AI )
super.playerMove();
}
#Override
public void playerWin() {
// TODO : Computer Related Events for Computer ( Like Increase Dif )
super.playerWin();
}
}
Human Class
public class Human extends Player {
public Human(Board _board, String _move) {
super(_board, _move);
}
#Override
public void playerMove() {
// TODO : Human Related Movements ( Like I/O )
super.playerMove();
}
#Override
public void playerWin() {
// TODO : Human Related Events on Win ( Like Score )
super.playerWin();
}
}

Dealing with object's scope

I'm trying to write a game in Java with a Player class that has 2 subclasses: HumanPlayer and ComputerPlayer. I want to allow the user to choose which player to play against, and once chosen - to create the relevant object and play.
Since the object is created within an if statement, the compiler doesn't let me perform any operations outside the if scope. In other cases I would create the object within the class' scope but in this case I cant know in advance which object to create (human/computer)
Here is some code for illustration:
public class Player {
private String name;
public String getName(){
return name;
}
}
public class HumanPlayer extends Player {
public void play(){
System.out.println("Human playing");
}
}
public class ComputerPlayer extends Player {
public void play(){
System.out.println("Computer playing");
}
}
import java.util.Scanner;
public class PlayerDriver {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Please type 1 for human, 2 for computer");
int selection = in.nextInt();
if (selection==1){
HumanPlayer player = new HumanPlayer();
} else if (selection==2){
ComputerPlayer player = new ComputerPlayer();
} else {
throw new IllegalArgumentException("invalid answer");
}
Player.play(); //can't do that
}
}
Harness the power of polymorphism
Player player = null; // player should never be null as you would have thrown an exception, but for the sake of completeness
if (selection == 1){
player = new HumanPlayer();
} else if (selection == 2){
player = new ComputerPlayer();
} else {
throw new IllegalArgumentException("invalid answer");
}
player.play();
assuming the Player class has a play() method. I see it doesn't. Change your class Player to have an override-able play() method which you override in the sub types.

External Method call help

So what im trying to do is to call an external method upon an object, its a bit trickier than I expected and am having problems properly implementing it.
The method is:
attack(Player victim)
The method needs to call a hit() method on an object; then if the hit() method was successful (test this through a boolean?):
use an if statement to call a damage() method upon the object to determine the damage
call takeDamage() upon (PlayerVictim) to inflict the damage.
Here's the player class that ive coded so far; the attack() method is at the bottom.
My main question is how to use an external method(s) damage() on the currentWeapon and takeDamage() on Player Victim
public class Player
{
private String myPlayerName;
private Weapon myWeapon;
private int myCurrentHealth;
private int myMaxHealth;
private int myNumPotions;
/**
* Constructor initializing class Player
* Parameters of the player should be:
* player name, players initial health, the players weapon.
*/
public Player(String myPlayer, int initialHealth, Weapon currentWeapon) {
myPlayerName = myPlayer;
this.myWeapon = currentWeapon;
myMaxHealth = 30;
myCurrentHealth = initialHealth;
myNumPotions = 0;
}
/**
* Attack method which attacks opposing player
* with current equipped weapon.
*/
public void attack(Player victim) {
currentWeapon.hit();
if (boolean currentWeapon.hit() = true) {
currentWeapon.damage(int dam);
return dam;
}
Player victim.takeDamage(int damage);
}
}
and the weapon class:
import java.util.Random;
public class Weapon
{
private int myHitProb;
private int myMaxDamage;
private Random myRNG;
/**
* Create a new weapon with a hit probability and damage
*/
public Weapon(int hitProb, int damage) {
myHitProb = hitProb;
myMaxDamage = damage;
myRNG = new Random();
}
public boolean hit() {
int r = myRNG.nextInt(100);
if (r < myHitProb) {
return true;
}
else {
return false;
}
}
public int damage() {
int dam = myRNG.nextInt(myMaxDamage) + 1;
return dam;
}
}
Your attack() method may be many things, but compilable java it is not.
Perhaps this is what you meant:
public void attack(Player victim) {
if (currentWeapon.hit()) {
victim.takeDamage(currentWeapon.damage());
}
}
Try to remember this guideline: If it seems hard, you're probably doing it the wrong way (unless you're working on the Mars Lander program :) )

Categories

Resources