Working with more than one class [closed] - java

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am new to java learning java from home using udacity.com and they fave given a question which i am stuck and cant get it working.
project is just to check if player move is not out of bound in chess game and then to see if Queen's move is valid or not. we have to see these 3 thing should work.
In the Queen class, override the isValidMove method
First call the parent's isValidMove to check for the boundaries.
Add more code to check for the Queen's specific move validity.
I have Main class, Game class, Position class, Piece class(Parent class) Queen class(child).
I got 1 and 3 working but can't understand how to get 2nd working it gives me error if i try calling Piece.isValidMove in main before Queen.isValidMove.
my codes as follows
Main.java
public class Main {
public static void main(String[] args) {
Piece piece = new Piece();
Queen queen = new Queen();
Position testPosition = new Position(3,7);
if(queen.isValidMove(testPosition)){
System.out.println("Yes, I can move there.");
}
else {
System.out.println("Nope, can't do!");
}
}
}
Game.java
public class Game {
Piece [][] board;
// Constructor creates an empty board
Game(){
board = new Piece[8][8];
}
}
Position.java
public class Position {
int row;
int column;
// Constructor using row and column values
Position(int r, int c){
this.row = r;
this.column = c;
}
}
Piece.java
public class Piece {
Position position;
boolean isValidMove(Position newPosition){
if(position.row>0 && position.column>0
&& position.row<8 && position.column<8){
return true;
}
else{
return false;
}
}
}
Queen.java
public class Queen extends Piece {
int row;
int column;
boolean isValidMove(Position newPosition){
if(newPosition.column == this.column || newPosition.row == this.row|| Math.abs(newPosition.column - this.column) == Math.abs(newPosition.row - this.row)){
return true;
}
else{
return false;
}
}
}
Thank you.

but can't understand how to get 2nd working it gives me error if i try calling Piece.isValidMove in main before Queen.isValidMove
The task says you need to call the parent's isValidMove in Queen.isValidMove, not in Main. And the syntax you need is super.isValidMove. So in Queen.java, do
boolean isValidMove(Position newPosition){
// combine super.isValidMove(newPosition) and your current code
}
You don't need to change Main.

Related

How should I make my getMove() method interact with my GUI in my chess application?

I'm developing an application in Java to help me land my first job as a junior developer. It's a chess game with a GUI that both human players click on from the same machine.
When it's, say, white's turn to move, the application calls white's getMove(Interface interaction) method until a valid MoveAttempt is returned. Here's the getMove(Interface interaction) method of HumanPlayer:
public MoveAttempt getMove(Interface interaction) {
while(!interaction.selectionMade()) {
}
byte pieceFile = interaction.getPenultimateFile();
byte pieceRank = interaction.getPenultimateRank();
byte toFile = interaction.getUltimateFile();
byte toRank = interaction.getUltimateRank();
return new MoveAttempt(pieceFile, pieceRank, toFile, toRank, getIsWhite());
}
penultimateFile, penultimateRank, ultimateFile and ultimateRank are supposed to store the file (column) and rank (row) of the last two chess tiles clicked. This is achieved through this actionPerformed(ActionEvent event) which Interface has because it implements ActionListener
public void actionPerformed(ActionEvent event) {
LocalizedButton button = (LocalizedButton) event.getSource();
if(penultimateFile == -1) {
penultimateFile = button.getFile();
penultimateRank = button.getRank();
}
else {
ultimateFile = button.getFile();
ultimateRank = button.getRank();
}
}
and by calling this method before each call to getMove(Interface interaction)
public void resetClicks() {
penultimateFile = -1;
penultimateRank = -1;
ultimateFile = -1;
ultimateRank = -1;
}
So the idea is that a move attempt is not made until someone has clicked on two chess squares which is why I have a while loop indefinitely calling selectionMade():
public boolean selectionMade() {
return penultimateFile != -1 && penultimateRank != -1 && ultimateFile != -1 && ultimateRank != -1;
}
This didn't work---pieces didn't move---so in an attempt to see what was happening I put this print statement
System.out.println(interaction.getPenultimateFile() + ", " +
interaction.getPenultimateRank() + ", " +
interaction.getUltimateFile() + ", " +
interaction.getUltimateRank());
into the while loop to see what was going on and now it works---pieces move---except I may have encountered times in which it didn't work but I last I tried I couldn't get it to fail.
I don't want to print anything to the console; what should I do in lieu of having this while loop?
Edit: Putting boolean lol = 0 just above the loop and lol = !lol in the loop doesn't allow the code to work. Neither does calling doNothing().
Edit: Here's the source code: https://github.com/JosephBGriffith/Chess
Right now only the pawns work because I have other bugs that I need to fix. En passant works except the opponent piece doesn't get eliminated.
I would invert the control, so that the UI pushes moves to the game, rather than the game trying to pull moves from the UI.
So your game class might have:
class Game {
boolean move(int fromFile, int fromRank, int toFile, int toRank) { ... }
...
}
If the move wasn't legal (e.g. if it was the other player's turn) then move returns false and the move doesn't occur. That is, the internal state of the Game is unchanged.
And your actionPerformed method becomes:
public void actionPerformed(ActionEvent event) {
LocalizedButton button = (LocalizedButton) event.getSource();
if(penultimateFile == -1) {
penultimateFile = button.getFile();
penultimateRank = button.getRank();
}
else {
game.move(penultimateFile, penultimateRank, button.getFile(), button.getRank());
penultimateFile = -1;
}
}
You could use the return value of move to provide some feedback to the user if the move is illegal.
Something to note about this suggestion is that move is executed on the Swing event thread. In theory this is bad practice, although unless your move method is very slow it won't matter.
Read https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html and consider whether you want to use invokeLater.

GameOver Screen for a Memory game in Java

I am programming a Memory game in java and I want to make a GameOver-Screen with an image from the sprites folder (I already have the image for it and it is an image with .jpg) after all cards are flipped. So when all cards are flipped, the game is actually over and this GameOver-Screen appears. I have no idea how I can do that. The only thing I know is that it should start with public void gameOver(){. Probably it is possible to make something with "if()" and between the brackets you could say that the condition is that all cards are flipped.
// Memory.java
import ch.aplu.jgamegrid.*; // Imports the Library of Gamegrid, on which this code is based
import ch.aplu.util.*;
public class Memory extends GameGrid implements GGMouseListener {
private boolean isReady = true;
private MemoryCard card1;
private MemoryCard card2;
public Memory() {
super(6, 6, 115, null, null, false);
MemoryCard[] cards = new MemoryCard[36];
for (int i = 0; i < 36; i++) {
if (i < 18)
cards[i] = new MemoryCard(i);
else
cards[i] = new MemoryCard(i - 18);
addActor(cards[i], getRandomEmptyLocation());
cards[i].show(1);
}
addMouseListener(this, GGMouse.lPress);
// Application thread used to flip back cards
doRun();
show();
while (true) {
// Wait until there is something to do
Monitor.putSleep();
delay(1000);
// Flip cards back
card1.show(1);
card2.show(1);
isReady = true;
// Rearm mouse events
setMouseEnabled(true);
}
}
// imports the GGMouse package
public boolean mouseEvent(GGMouse mouse) {
Location location = toLocation(mouse.getX(), mouse.getY());
MemoryCard card = (MemoryCard) getOneActorAt(location);
// Card already flipped->no action
if (card.getIdVisible() == 0)
return true;
// Show picture
card.show(0);
if (isReady) {
isReady = false;
card1 = card;
} else {
card2 = card;
// Pair found, let them visible
if (card1.getId() == card2.getId())
isReady = true;
else {
// Disable mouse events until application thread flipped back cards
setMouseEnabled(false);
Monitor.wakeUp();
}
}
return true;
}
public static void main(String[] args) {
new Memory();
}
}
Each time a card is flipped, check if all cards have been flipped. Use a loop - you already have one in your code. For each index in the for loop... ie each card... check if getIdVisible() is 0.
If the card at index i is still hidden, return null and continue running your program is normal. However, if you get all the way through the loop, that means all cards are visible, which means you can call the gameOver() method, which shows the game over screen.
Does that sound like it fits with your program?
Edit:
To check if all cards are flipped, one thing you can do is to make MemeryCard[] cards (up in the constructor) a global variable. Then you can just call this method every time you reveal two cards:
public boolean areAllCardsFlipped() {
// Start looking through each card
for (int i = 0; i < 36; i++) {
// We found a card that is NOT flipped. Stop here, because clearly all cards are not flipped.
if (cards[i].getIdVisible() != 0) {
return false;
}
}
// We have looked at all cards, and we know that each one is flipped. We can return true.
return true;
}
I'd say call this method in mouseEvent() before you return true for mouseEvent(), and if this returns true you can call the gameOver() method.
As for how to handle rendering the image... I don't know the api you're using for this game, so I can't tell you specifically how to do that. But at least with this code you should be able to trigger that gameOver.

Turns issue in java game [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I've created a simple game which a player plays against computer.
I've got an issue in the timing of the turns, the computer should be the first to make a move than the real player should make his move by clicking LeftChoice or RightChoice button.
Here's my problem at code:
public class GameForm extends javax.swing.JFrame {
/**
* Creates new form GameForm
*/
final int SIZE = 10;
int CurrentSize = 10;
int PC_SUM=0;
int HUMAN_SUM=0;
boolean PC_TURN = true;
int[] RandArr = new int[SIZE];
public GameForm() {
initComponents();
}
public void init(){
for(int i = 0 ; i<SIZE;i++){
RandArr[i] = (int)(Math.random()*100)+1;
}
jTextField3.setText("");
jTextField4.setText(Integer.toString(PC_SUM));
jTextField5.setText(Integer.toString(HUMAN_SUM));
}
public void HUMAN_updateLeft(){
HUMAN_SUM+=RandArr[0];
jTextField5.setText(Integer.toString(HUMAN_SUM));
jTextField1.setText(Arrays.toString(RandArr));
CurrentSize--;
int [] NewRand = new int[CurrentSize];
for(int i = 1 ; i<=CurrentSize;i++){
NewRand[i-1] = RandArr[i];
}
RandArr = NewRand;
jTextField2.setText(Arrays.toString(RandArr));
PC_TURN = true;
}
public void HUMAN_updateRight(){
HUMAN_SUM+=RandArr[CurrentSize-1];
jTextField5.setText(Integer.toString(HUMAN_SUM));
jTextField1.setText(Arrays.toString(RandArr));
CurrentSize--;
int [] NewRand = new int[CurrentSize];
for(int i = CurrentSize-1 ; i>=0;i--){
NewRand[i] = RandArr[i];
}
RandArr = NewRand;
jTextField2.setText(Arrays.toString(RandArr));
PC_TURN = true;
}
public static boolean WhoIsBigger(int[] arr){
int even=0,odd=0;
for(int i=0;i<arr.length;i+=2){
if(i%2==0){
even+=arr[i];
odd+=arr[i+1];
}
else{
odd+=arr[i];
even+=arr[i+1];
}
}
return even>odd;
}
public void PC_updateLeft(){
PC_SUM+=RandArr[0];
jTextField4.setText(Integer.toString(PC_SUM));
jTextField1.setText(Arrays.toString(RandArr));
CurrentSize--;
int [] NewRand = new int[CurrentSize];
for(int i = 1 ; i<=CurrentSize;i++){
NewRand[i-1] = RandArr[i];
}
RandArr = NewRand;
jTextField2.setText(Arrays.toString(RandArr));
}
public void PC_updateRight(){
PC_SUM+=RandArr[CurrentSize-1];
jTextField4.setText(Integer.toString(PC_SUM));
jTextField1.setText(Arrays.toString(RandArr));
CurrentSize--;
int [] NewRand = new int[CurrentSize];
for(int i = CurrentSize-1 ; i>=0;i--){
NewRand[i] = RandArr[i];
}
RandArr = NewRand;
jTextField2.setText(Arrays.toString(RandArr));
}
public void PC_TURN(){
if(WhoIsBigger(RandArr))
PC_updateLeft();
PC_updateRight();
}
public void FullGame(){
while(RandArr.length>0){
if(PC_TURN){
PC_TURN();
PC_TURN = false;
}
}
}
//start button listener
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
init();
jTextField2.setText(Arrays.toString(RandArr));
jTextField1.setText("-");
jButton1.setEnabled(false);
FullGame();
}
//left button listener
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
HUMAN_updateLeft();
}
//right button listener
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
HUMAN_updateRight();
}
How can i know that the real player has made his move so it'll change PC_TURN to True and the game will move on?
Firstly, you should follow Java Naming Conventions when it comes to naming your variables. As it stands, PC_TURN looks as though it is a constant, although it is not a constant since you are changing it's value. So a more appropriate name would be pcTurn.
You also seem to have a method called PC_TURN() which I am assuming is the method which causes the computer to take it's turn and do something. So it would be better if this was named something descriptive like takePCTurn(). Notice the use of camelCase throughout. Capital letters at the start of a name should be reserved for classes and interfaces, not variables or methods.
The same goes for your method name
public void FullGame()
should be written as
public void fullGame()
Keeping to coding conventions like this make it easier for others to read and understand your code and keep everything neat and tidy. It's a good habit to get into. :)
I don't know where your left and right buttons are being declared or what you have named them, but you will need to add an event listener to each button which causes something to happen when they are clicked. I also am unsure about the purpose of RandArr.length > 0. You really don't need a loop here since this is an application with a GUI, it is never going to close unless you explicitly tell it to (e.g by clicking the close button). So I will just give you a generic solution.
You basically want the players turn to trigger the computer to take it's turn until some game over condition is met.
Example:
//Assuming this is called when the Start button is clicked
public void fullGame() {
takePCTurn();
}
public void takePCTurn() {
//Do PC's turn logic
//You might want to check if the Computer Won the game here
}
class PlayerTurnListener implements ActionListener() {
public void actionPerformed(ActionEvent e) {
//Do Player's turn logic
//You might want to check if the Player Won the game here
takePCTurn();
}
}
//We can create an instance of our listener and add it to both buttons
PlayerTurnListener playerTurnListener = new PlayerTurnListener();
leftButton.addActionListener(playerTurnListener);
rightButton.addActionListener(playerTurnListener);
So the first thing that happens is fullGame() is called by your Start button which then calls takePCTurn(); causing the computer to take it's turn. Now nothing will happen until the player clicks the left or right button. When they do this, the PlayerTurnListener's actionPerformed() method is called and you can do some logic in there and then takePCTurn(); will be called once again.
Rinse and repeat until gameover.
Hope that helps :)
You should attach a clickListener onto the left and right buttons. Then when the user clicks one that event will be fired. You should change PC_TURN to true there and re-run the loop if needed.
Example:
JButton yourButton = new JButton("Your Button");
yourButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
PC_TURN = true;
// extra code
}
});
If this is a Swing or other GUI then you will need to get rid of the while loop.
Remember that GUI programs are non-linear and are event-driven, and so rather than a restricting while loop which risks completely feezing your GUI, you would change the program's state depending on whose turn it is -- have a variable indicating whose turn it is -- and then change the behavior of the program based on the state.
If you need more specific help, then you're going to need to ask a much more complete question including one with enough code and explanation to allow us to understand your problem better (but not too much code).
Regarding the code you've posted:
Yes, definitely get rid of that while loop.
Your code is hard to understand, mainly because you're variable naming is poor. Rather than using variable names like jTextField1, use names that make logical sense, that make your code "self-debuggin", such as humanScoreField and computerScoreField, etc.
Also learn and follow standard Java naming practices including having all variables start with lower case letters, classes with upper case letters, use camelCase for all except for constants which are all upper-case.
Tell more about just what this code is supposed to be doing, what the buttons and the JTextfields represent, what behaviors you desire, etc...

Non-static method cannot be referenced from a static context (Java) [duplicate]

This question already has answers here:
Calling Non-Static Method In Static Method In Java [duplicate]
(14 answers)
Closed 9 years ago.
I'm newer to programming and keep getting the non-static method cannot be referenced from a static context when calling my floor class from my ant class. I've removed all statics and am still getting this error, if someone could point me in the right direction or let me know what the issue is that would be great, thanks.
public class Ant {
public final int RED = 0, BLUE = 1, NORTH = 0,
EAST = 1, SOUTH = 2, WEST = 3;
public int color;
public Ant(int size, int dir) {
size = size;
dir = startDir;
floor floor = new floor(size);
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public void makeMoves(int numMoves, int dir) {
final int[][] offSet = {/* NORTH */ {-1, 0},
/* EAST */ {0, 1},
/* SOUTH */ {1, 0},
/* WEST */ {0,-1}};
final int[][] newDir = {/* NORTH */ {WEST, EAST},
/* EAST */ {NORTH, SOUTH},
/* SOUTH */ {EAST, WEST},
/* WEST */ {SOUTH, NORTH}};
//set start row, col, and direction
row = col = size/2;
for(int move = 1; move <= numMoves; move ++) {
//make a move based on direction
row = row + offSet[dir][0];
col = col + offSet[dir][1];
//turn based on color of new tile and direction
color = floor.getTileColor(row, col);
dir = newDir[dir][color];
//change color of current tile
floor.changeTileColor(row, col);
}
}//End of makeMoves
}//End Ant class
public class floor {
int [][] grid;
public floor(int size) {
grid = new int[size][size];
}
public int getTileColor(int row, int col) {
return grid[row][col];
}
public void changeTileColor(int row, int col) {
int color = grid[row][col];
}
}
That code doesn't compile for other reasons. For example, in this constructor, startDir isn't defined. And while size is defined, that doesn't do anything. It assigns the parameter size to itself. You really want this.size = size;
public Ant(int size, int dir)
{
size = size;
dir = startDir;
Also, row and col aren't defined anywhere. If you are getting errors about statics, I wonder if you are compiling old code.
public static void main() is a static context. There's only one of it, whereas there is technically one of makeMoves(), say, for each Ant object. Call them on an instance of Ant, or make them static also. That's the gist, simply look up keyword static, and/or context, scope to learn more.
As others have pointed out, the code you're compiling doesn't seem to match the code you posted, because the posted code contains other errors than just static accesses.
However, I think your basic problem (as it regards the question as posed, at least) is that you think you have defined an instance variable in the Ant class for the floor, while in fact you have not. You have just defined a local variable for it in the Ant constructor, which is discarded as soon as the constructor returns.
Then, since you have a naming conflict between the floor class itself and what you probably think is the variable that would hold the Ant's floor, you're trying to call floor.changeTileColor, thinking that it would be invoked on the Ant's instance of floor, but it compiles as if it were a reference to a static method. This is because floor, here, refers to the class floor itself rather than to a variable holding an instance to it.
To solve it, create a floor instance variable in the Ant class instead of just in the constructor (though, suggestedly, under another name, in order to avoid more naming conflicts).

Need help figuring out Basic Chess movement logic

Sorry for wall of text, but currently stumped. I'm not asking to be "spoon feed" since I have the basic idea down for each piece, it's just I'm having a difficult time on how to finish determining my move logic. Allow me to further explain. I'll be posting my code as well for better reference.
I'm coding with a MVC structure. I have a Model which is a 2D array of BoardSquares. Which those BoardSquares keep track of it's location on the board, what piece is in it (if there is one), what color that piece is (if there is one), and if it's empty. Here's the code for it:
public class BoardSquare {
// Private information stored in each BoardSquare
private boolean isSquareEmpty;
private int row;
private int col;
private String space;
private String pColor;
// Constructor to make an empty space on the board
public BoardSquare(int row, int col) {
space = "";
pColor = "";
this.row = row;
this.col = col;
SquareEmpty();
}
//Constructor to get the information of a space with a piece
public BoardSquare(BoardPiece piece, int row, int col) {
this.space = piece.getModelName();
this.pColor = Character.toString((piece.getModelName().charAt(0)));
this.row = row;
this.col = col;
SquareNotEmpty();
}
public String getpColor() {
String temp = getPieceColor(pColor);
return temp;
}
//A bunch of auto generated getters/setters...
// Gets the correct color label for the piece
public String getPieceColor(String info){
String temp;
if(info.equalsIgnoreCase("b")){
temp = "Black";
}
else {
temp = "White";
}
return temp;
}
Currently all my Pieces extend an abstract BoardPiece class which has several abstract methods as well, but my piece knows of it's location on the board, it's name, it's color, and the 2D board array for the way I'm generating the valid moves.
I'm generating them by checking the spaces it can move to and seeing if they are empty and adding them to an ArrayList and comparing and seeing if that list contains the inputted destination.
However I'm having problems thinking of how to stop checking if say Black Rook was on the left side of the board and wanted to move all the way to the Right, but there was a Black Pawn to the right of the Rook preventing it from doing so. I'm trying to generically think of it to make my life easier and I can implement it in the other piece classes as well So here's the Rook's code:
public class Rook extends BoardPiece{
private String name = "Rook";
private String color;
private String modelName;
BoardSquare board[][];
// Both should remain 0 - 7
private int row;
private int col;
public Rook (String modelName, int row, int col, String color, BoardSquare[][] field) {
this.modelName = modelName;
this.row = row;
this.col = col;
this.color = color;
this.board = field;
}
#Override
void move(BoardSquare target) {
if(!getPossibleMove(board).contains(target)){
//Sysout false move
}
}
#Override
Collection<BoardSquare> getPossibleMove(BoardSquare[][] board) {
ArrayList<BoardSquare> validMoves = new ArrayList<BoardSquare>();
for(int i = 0; i < 8; i++){
// Checks every column of the row that the piece is on
if(moveValidator(board[row][i])){
validMoves.add(board[row][i]);
}
// Checks every row of the column that the piece is on
if(moveValidator(board[i][col])){
validMoves.add(board[i][col]);
}
}
return validMoves;
}
#Override
boolean moveValidator(BoardSquare space) {
// Removes the current square the piece is on as a valid move
if(space.getRow() == getRow() && space.getCol() == getCol()){
return false;
}
//Checks if the space is not empty and the piece in the spot is the same color as the piece itself
if(!space.isEmptySquare() && space.getpColor().equalsIgnoreCase(color)){
return false;
}
return true;
}
Like I said any help or push toward the right direction would be appreciated. Sorry for the wall of text but trying to be as clear as I can so that whoever wants to help can fully understand and see my logic.
EDIT: Forgot to note that the Rook has Auto-generated Getters and Setters as well.
I would approach it the most brute-force and intuitive way possible: think of moving the rook one square at a time as it takes its turn and see if it collides with anything. That is, hop it across every square until it gets to the desired spot and check if it's a valid move at each square.
This is a fine approach because
it's easy to understand
it's not expensive until your chess board gets massively huge, so brute force isn't a problem.
it generalizes to all pieces: rooks have to "slide" to their destination, but knights can "jump" or "teleport" over other pieces to their new location, so don't need the intermediate hops.
This sounds close to your current implementation, but you need to stop tracing when you collide. That is, if there is a black pawn in the way, the columns after that pawn are no longer valid spaces, right? In other words, think of the move as an action that the rook takes instead of an independent state space of possible moves, since some spaces are legal moves except that the rook was previously blocked. You need to know where the rook is from and where it is going to determine valid moves, not just if the space is in the same row.
So, reading your code (thanks for posting the context, by the way, it's quite helpful) really all you need to do is not iterate on each square, but iterate moving through each square, and stop the iteration when you get blocked.

Categories

Resources