I am making a Tic-Tac-Toe game in Java. I have four classes:
TicTacTester just calls (creates an object) the TicTacToe class.
The TicTacToe class provides the GUI of the game (it's a subclass of JFrame). It also creates the 9 buttons for the JPanel to display and users to click.
The XOButton class defines what the buttons can do and actionPerformed method.
Lastly, the GameEnd class defines what happens when the game ends (a new JFrame is created to display score and give the user 2 buttons: exit and restart).
The problem is when I try to code the contents of what happens when the user clicks "restart". It is suppose to call the resetBoard() method, which is defined in TicTacToe class. The problem is, I do not know the name of the object created from the TicTacToe class (in the tester class' static void main method I just typed "new TicTacToe", didn't need to define a name). I cannot call resetBoard from a static standpoint (i.e. I can't do TicTacToe.resetBoard(); ) because resetBoard needs to be non-static.
What I've tried:
I've tried including in the constructor of the GameEnd class a TicTacToe object. If I do this, the GameEnd object creator has to go into TicTacToe class, so I can use 'this' keyword. This does not work because the GameEnd object needs to be created when the WinCondition is met, which is checked when a button is clicked in the XOButton class.
But if I put the GameEnd object creator in the XOButton class (where is is right now and, supposedly, where it should be), in the constructor for GameEnd(String s, TicTacToe a), I cannot use 'this' keyword for the TicTacToe object.
This is my button class. Most code is not relevant so it has been hidden.
public class XOButton extends JButton implements ActionListener {
//Hidden code
private void winCheck() {
for(int j = 0; j < 3; j++) {
if(board[j][0] == 1 && board[j][1] == 1 && board[j][2] == 1 || board[0][j] == 1 && board[1][j] == 1 && board[2][j] == 1) {
player1Score++;
GameEnd end = new GameEnd("X wins this round!");
finished = true;
break;
}
else if(board[j][0] == 2 && board[j][1] == 2 && board[j][2] == 2 || board[0][j] == 2 && board[1][j] == 2 && board[2][j] == 2) {
player2Score++;
GameEnd end = new GameEnd("O wins this round!");
finished = true;
break;
}
}
if(board[0][0] == 1 && board[1][1] == 1 && board[2][2] == 1 || board[0][2] == 1 && board[1][1] == 1 && board[2][0] == 1) {
player1Score++;
GameEnd end = new GameEnd("X wins this round!");
finished = true;
}
else if(board[0][0] == 2 && board[1][1] == 2 && board[2][2] == 2 || board[0][2] == 2 && board[1][1] == 2 && board[2][0] == 2) {
player2Score++;
GameEnd end = new GameEnd("O wins this round!");
finished = true;
}
if(turn == 9 && !finished) {
GameEnd end = new GameEnd("This round is a Draw");
finished = true;
}
}
public void resetButton() {
this.setIcon(null);
markSpot(0);
this.clicked = false;
}
public static void resetStatics() {
turn = 0;
finished = false;
}
}
This is the TicTacToe class. Most code is not relevant so it has been hidden.
public class TicTacToe extends JFrame {
//Hidden code
public void resetBoard() {
for(int j = 0; j < 3; j++) {
for(int i = 0; i < 3; i++) {
buttons[j][i].resetButton();
}
}
XOButton.resetStatics();
}
}
This is the GameEnd class. An object of this is created when the WinCondition is met. Most code is not relevant so it has been hidden.
public class GameEnd extends JFrame implements ActionListener {
//Hidden code
public void actionPerformed(ActionEvent e) {
if(e.getSource() == exit) {
System.exit(0);
}
else if(e.getSource() == retry) {
TicTacToe.resetBoard();
}
}
}
//This is the Tester class
public class TicTacTester {
public static void main(String[] args) {
new TicTacToe();
}
}
What I expect to happen is the game board to restart.
It seems like you are breaking the project down too far. If you have a class for a game, keep all of its methods inside that class. The only time I can think of to use separate classes are if you are trying to create this using the Model-View-Controller (MVC) architecture, or the like. This is a common approach for an application using GUI, data access, and controllers.
There might be other times, but this is all I can think of on the top of my head.
From what you are showing, I don't think it applies.
I think this would be a better approach:
TicTacToe.java
public class TicTacToe extends JFrame {
private int scorePlayer1;
private int scorePlayer2;
private boolean initialized; // default = false
// Reset the board
// Reset the markers, etc.
public void resetGame() {}
// Check to see if there is a winner
// If so, announce the winner and return true
// Otherwise, return false.
public boolean winCheck() {}
// Set up frame, buttons, score, etc.
public void newGame(){
// Create however many JPanels you need
// Add it to a single JFrame
// When you're ready...
// and this game has not been initialized for the first time.
// In this example jframe is an instance of JFrame
if (!this.initialized)
jframe.setVisible(true);
}
// Play the game
public void play(){
// For each round,
// a player chooses where to put their "X" or "O"
// add scores, etc.
// Then at the end of each round
if (this.winCheck())
this.resetGame();
}
}
TicTacToeTester.java:
public class TicTacToeTester {
public static void main(String[] args){
TicTacToe game = new TicTacToe();
game.play();
}
}
I hope this helps!
Let me know if you have any questions. :)
Related
i got two different kind of errors in my code.
one is when someone enters a number that's higher than 8 or lower than 0.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 22
at boter_kaas_en_eiren.Board.placeAttempt(Board.java:37)
at boter_kaas_en_eiren.Game.play(Game.java:28)
at boter_kaas_en_eiren.MainClass.main(MainClass.java:12)
the other error is when a player wins and i want to close the scanner so nobody can play anymore.
Exception in thread "main" java.lang.IllegalStateException: Scanner closed
at java.util.Scanner.ensureOpen(Unknown Source)
at java.util.Scanner.findWithinHorizon(Unknown Source)
at java.util.Scanner.nextLine(Unknown Source)
at boter_kaas_en_eiren.Game.play(Game.java:23)
at boter_kaas_en_eiren.MainClass.main(MainClass.java:12)
if somebody could help me i would appriciate it.
game class
package boter_kaas_en_eiren;
import java.util.Scanner;
public class Game {
private Board board;
private boolean gameFinished;
public Game() {
board = new Board();
gameFinished = false;
}
public void play() {
Scanner scan = new Scanner(System.in);
int x = 0;
String nextSymbol = "x";
board.ShowBoard();
while (gameFinished == false) {
String input = scan.nextLine();
int position = Integer.parseInt(input);
boolean highorlow = board.tohighorlow(position);
boolean succes = board.placeAttempt(position, nextSymbol);
if (highorlow) {
if (succes) {
if (nextSymbol.equals("x")) {
nextSymbol = "o";
} else {
nextSymbol = "x";
}
}
}
board.ShowBoard();
if (board.checkWinner("x") == true) {
System.out.println("x wins");
scan.close();
}
if (board.checkWinner("o") == true) {
System.out.println("x wins");
scan.close();
}
}
}
}
main class
package boter_kaas_en_eiren;
public class MainClass {
public static void main(String[] args) {
Game game = new Game();
game.play();
}
}
board class
package boter_kaas_en_eiren;
import java.util.Scanner;
public class Board {
private String[] board;
public Board() {
board = new String[9];
for (int i = 0; i < board.length; i++) {
board[i] = " ";
}
}
public void ShowBoard() {
System.out.println(board[0] + "|" + board[1] + "|" + board[2]);
System.out.println(board[3] + "|" + board[4] + "|" + board[5]);
System.out.println(board[6] + "|" + board[7] + "|" + board[8]);
System.out.println("");
}
public boolean tohighorlow(int position) {
if (position <= 8 && position >= 0) {
return true;
} else {
System.out.println("Invalid!!");
return false;
}
}
public boolean placeAttempt(int position, String symbol) {
if (board[position].equals(" ")) {
board[position] = symbol;
return true;
} else {
System.out.println("invalid!");
return false;
}
}
public boolean checkWinner(String symbol) {
if (board[0].equals(symbol) && board[1].equals(symbol) && board[2].equals(symbol)) {
return true;
} else if (board[3].equals(symbol) && board[4].equals(symbol) && board[5].equals(symbol)) {
return true;
} else if (board[6].equals(symbol) && board[7].equals(symbol) && board[8].equals(symbol)) {
return true;
} else if (board[0].equals(symbol) && board[3].equals(symbol) && board[6].equals(symbol)) {
return true;
} else if (board[1].equals(symbol) && board[4].equals(symbol) && board[7].equals(symbol)) {
return true;
} else if (board[2].equals(symbol) && board[5].equals(symbol) && board[8].equals(symbol)) {
return true;
} else if (board[0].equals(symbol) && board[4].equals(symbol) && board[8].equals(symbol)) {
return true;
} else if (board[2].equals(symbol) && board[4].equals(symbol) && board[6].equals(symbol)) {
return true;
} else {
return false;
}
}
}
If you would thoroughly check the source code lines given in the exceptions, you could probably find the issues yourself. But let's go through it together this time:
ArrayIndexOutOfBoundsException
This means you are trying to access an array element that is simply not there.
In your Game class, you have these two lines:
boolean highorlow = board.tohighorlow(position);
boolean succes = board.placeAttempt(position, nextSymbol);
Looking at tohighorlow(), we find this line:
if (position <= 8 && position >= 0) {
return true;
}
However, this will return true if the number is in the range [0..8]. In other words, the method returns true when your number is neither too high nor too low. Easiest fix is to change the condition like this:
if (position > 8 || position < 0)
Now numbers greater than 8 or lower than 0 will yield true, which seems to be what the method is supposed to do. Alternatively, you could swap the bodies of the if and else.
Regardless of that, you are ignoring the result of this method when you call placeAttempt() in your Game class. That's not good, because looking at placeAttempt() we find this line:
if (board[position].equals(" ")) { /* ... */
This is where your exception originates. You are accessing the board array without checking the position value. Or rather, you did check the position value but did not respect the result of that check here. Hence, if position is -2 or 12, for example, you will run into trouble as those elements do not exist (are out of bounds).
IllegalStateException: Scanner closed
Let's simplify the play() method of your Game class for a second:
public void play() {
Scanner scan = new Scanner(System.in);
/* ... */
while (gameFinished == false) {
String input = scan.nextLine();
/* ... */
boolean highorlow = board.tohighorlow(position);
boolean succes = board.placeAttempt(position, nextSymbol);
/* ... */
if (board.checkWinner("x") == true) {
System.out.println("x wins");
scan.close();
}
if (board.checkWinner("o") == true) {
System.out.println("x wins");
scan.close();
}
}
}
The first thing you do is to create the Scanner. Now, under certain circumstances (the two if at the end), you close the scanner. However, you do that within a loop. After you close the scanner, the loops starts over with its first line:
String input = scan.nextLine();
But you can't get the next line of a closed scanner.
Additional notes
I noticed that you are quite inconsistent in your style. For example, see these three method names: ShowBoard, placeAttempt and tohighorlow. You use different capitalization for each. I strongly suggest to stick to the recommended naming convention, which means camelCase with lower first letter: showBoard, placeAttempt and tooHighOrLow (also notice to vs too).
Hope this helps.
Your array board has the size 9. So if someone enters a number not between 0 and 8 you get an Exception.
You pass the input from the user directly to your function:
board.placeAttempt(position, nextSymbol);
There you do:
if (board[position].equals(" ")) {
So you try to access an invalid position of the array
Class file hereIn my Java code, the Finch robot is named myF.
I need to make myF do the following:
Tap once to move toward an object placed in front of it, with it's beak colour (myF.setLED..) red if the object is stationary and green if that object is moving.
The Finch robot should follow the object around with it's beak lighting red if the object stops and green if that object moves.
Whilst in motion, the Finch should be buzzing, but not too loud. ( myF.buzz(Buzz, BuzzDuration)
However my code isn't working as should, I know there are some mistakes but I do not know how to carry on having tried many times. Please see my code below. Any help will be greatly appreciated.
import edu.cmu.ri.createlab.terk.robot.finch.Finch;
public class Main {
//Variable declaration.
static int Buzz = 300;
static int BuzzDuration = 1200;
static int R = 250;
static int G = 250;
static int velocityLeft = 150;
static int velocityRight = 150;
static int turnLeft = -50;
static int turnRight = -50;
static int time = 0;
static int tappedCount = 0;
//Initialization of Finch
static Finch myF = new Finch();
//Main method
public static void main(String[] args)
//TAP FINCH ONCE FOR IT TO DO EITHER OF THE FOLLOWING:
//Turn red and follow stationary object
//Turn green and follow an object in motion
//Do nothing if no object is in front of Finch
{
//while (myF.isFinchUpsideDown() == false)
{
if
(myF.isTapped() == true && myF.isObstacle() == true)
{
{
//Set Beak LED to Green if object in front is moving.
// *******need to add a conditional statement for whether obstacle in front of finch is moving.
myF.setLED(R,0,0);
//myF.setWheelVelocities(velocityLeft,velocityRight);
myF.buzz(Buzz, BuzzDuration);
if (myF.isObstacleRightSide() == false)
{
myF.setWheelVelocities(0, 255);
}
else if (myF.isObstacleLeftSide() == false)
{
myF.setWheelVelocities(255, 0);
}
else if (myF.isObstacle() == true)
{
myF.stopWheels();
}
}
}
//Beak supposed to be RED if object in front is stationary, Finch should move towards object.
else {
// if
//***beak should stay off unless object is placed ahead of it and/or is moving, respectively
// (myF.isTapped() == false)
{
myF.setLED(0,0,0);
myF.setWheelVelocities(0,0);
//myF.quit();
//myF.stopWheels();
tappedCount = 0;
}
}
}
myF.quit();
// FollowObjectAround();
//RUN AGAIN i.e. "the Move method" whilst running the first algorithms above.
// boolean RunAgain = true;
//
// while(RunAgain) {
//
// Move();
//
// }
} //main(String[] args) ends here.
//FIRST PART SUCCESSFUL
//Next part: follow object incorporating corresponding beak colour
//public Main() {
public static void FollowObjectAround() {
while (true){
//This begins the movement of the finch
//if (myF.isObstacleLeftSide() == false && myF.isObstacleRightSide() == false || myF.isObstacle() == false)
//LED colours are red, green and blue
//myF.setLED(R,0,0);
//myF.setWheelVelocities(velocityLeft, velocityRight);
//^^
//here, the robot runs straight into the object and keeps going.
//might be best to have the finch stop when it reaches the object, proceeding movement if that object moves also.
//Triggers the RunAgain function to true so that the program does not stop in one run so that the Finch will continue to move
boolean RunAgain = true;
while(RunAgain) {
//Calling of the Move method for the Finch movements.
Move();
while
(myF.isTapped()==true && myF.isTapped()==true)
//if (myF.isTapped()==true && myF.isTapped()==true)
{
myF.setLED(0,0,0);
myF.stopWheels();
//break;
}
} // I just added this brace, wasn't there before.
}
//Inside the while, RunAgain loop , there is a conditional statement that makes the program terminate if the Finch has been tapped twice
//if (myF.isTapped()==true && myF.isTapped()==true)
// {
// break;
// }
}
//}
//}
// Method for Finch movements
public static void Move() {
if (myF.isObstacleRightSide() == false && myF.isObstacleLeftSide() == false && myF.isObstacle() == true)
{
MoveStraight();
}
else if (myF.isObstacleRightSide() == false && myF.isObstacleLeftSide() == true)
{
MoveLeft();
}
else if ( myF.isObstacleRightSide() == true && myF.isObstacleLeftSide() == false)
{
MoveRight();
}
else if (myF.isObstacleRightSide()==true && myF.isObstacleLeftSide()==true)
{
StopMoving();
}
}
//=====================================================================================================
//If the finch is moving straight, the light will be green and both of the wheels will move at 150
public static void MoveStraight()
{
myF.setLED(0, G, 0);
myF.setWheelVelocities(velocityLeft, velocityRight);
myF.buzz(Buzz, BuzzDuration);
}
public static void MoveLeft()
{
//If the finch is moving left, the light will be green, the left wheel will move at -50 and the right wheel will move at 150
myF.setLED(0, G, 0);
myF.setWheelVelocities(turnLeft, velocityRight);
myF.buzz(Buzz, BuzzDuration);
}
public static void MoveRight()
//If the finch is moving right, the light will be green the left wheel will move at 150 and the right wheel will move at -50
{
myF.setLED(0, G, 0);
myF.setWheelVelocities(velocityLeft, turnRight);
myF.buzz(Buzz, BuzzDuration);
}
public static void StopMoving()
//if the Finch is not moving, the colour of the light will be red and the buzzing will stop
{
myF.setLED(R, 0 , 0);
myF.stopWheels();
myF.buzz(Buzz, BuzzDuration);
}
}
//while (myF.isFinchUpsideDown() == false)
{
the "{ " here is wrong and here
{
//Set Beak LED to Green if object in front is moving.
// *******need to add a conditional statement for whether obstacle in front of finch is moving.
I am making a blackjack game and was wondering if I could make it so that I had two different actions on a single button.
This is what I have so far on the hit button, but instead of having the second card show on a double click, I want it to show the second card when you press the button again.
public void hit(MouseEvent event) {
if (event.getClickCount() == 1) {
card5 = deck.dealCard();
pcard3.setImage(card5.getImage());
}
if (event.getClickCount() == 2) {
card6 = deck.dealCard();
pcard4.setImage(card6.getImage());
}
}
You can have an iterator whose value can be increased on each click. And for different values set different functionalities. See the code
int i =0;
public void hit(MouseEvent event) {
if (i%2== 0) {
card5 = deck.dealCard();
pcard3.setImage(card5.getImage());
} else if (i%2 == 1) {
card6 = deck.dealCard();
pcard4.setImage(card6.getImage());
}
i++;
}
I have an AP Computer Science assignment to make Tetris using GridWorld. I have to make 4 classes, TetrisBug, TetrisGame, TetrisBlock, and TetrisBlockO.
Here are the codes in that order:
TetrisBug.java
import info.gridworld.actor.*;
import info.gridworld.grid.*;
import java.util.ArrayList;
import java.awt.Color;
public class TetrisBug extends Bug
{
public TetrisBug(Color color)
{
super(color);
setDirection(180);
}
public void move()
{
Grid<Actor> gr = getGrid();
if (gr == null)
return;
Location loc = getLocation();
Location next = loc.getAdjacentLocation(getDirection());
if (gr.isValid(next))
moveTo(next);
else
removeSelfFromGrid();
}
public void act()
{
//this is empty for a reason.
}
}
TetrisGame.java
import info.gridworld.actor.*;
import info.gridworld.grid.*;
import java.util.ArrayList;
import java.awt.Color;
import info.gridworld.*;
public class TetrisGame {
public static ActorWorld world = new ActorWorld(new BoundedGrid<Actor>(19, 17));
public static TetrisBlock currentBlock;
public static int score;
public static void main(String[] args) {
//set up world
for (int i = 0; i < 19; i++) {
world.add(new Location(i,11),new Rock());
world.add(new Location(i,0),new Rock());
}
nextTetrisBlock();
//needed code for keyboard event handling
java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new java.awt.KeyEventDispatcher() {
public boolean dispatchKeyEvent(java.awt.event.KeyEvent event) {
String key = javax.swing.KeyStroke.getKeyStrokeForEvent(event).toString();
if (key.equals("pressed UP"))
currentBlock.rotate();
if (key.equals("pressed RIGHT"))
currentBlock.moveRight();
if (key.equals("pressed DOWN"))
currentBlock.act();
if (key.equals("pressed LEFT"))
currentBlock.moveLeft();
world.show();
return true;
}
});
world.show();
}
/**
* Calls removeCompleteRows and chooses a new TetrisBlock at random
*/
public static void nextTetrisBlock() {
removeCompleteRows();
TetrisBlock randomBlock = new TetrisBlock();//default 2block piece
//choose random block
int randNum = (int)(Math.random()*7)+1;//random number between 1 and 7
//if(randNum == 1)
// randomBlock = new TetrisBlockO();
//if(randNum == 2)
// randomBlock = new TetrisBlockI();
//if(randNum == 3)
// randomBlock = new TetrisBlockT();
//if(randNum == 4)
// randomBlock = new TetrisBlockL();
//if(randNum == 5)
// randomBlock = new TetrisBlock_L();
//if(randNum == 6)
// randomBlock = new TetrisBlockZ();
//if(randNum == 7)
// randomBlock = new TetrisBlock_Z();
currentBlock = randomBlock;
}
/**
* checks each row 1 through 18 (skip row 0) for full rows
* if a row is full, then remove the actor from each cell in that row
* and ask each actor located above the just deleted row to act and
* update the score++
*/
public static void removeCompleteRows() {
int columnsFilled = 0;
Grid grid = world.getGrid();
int row = 0;
//loops through rows only after each column has finished
for(row = grid.getNumRows()-1; row >= 0; row--) { //needed >=
columnsFilled = 0; //need to reinitialize this every iteration
for(int col = 0; col <= grid.getNumCols() - 1; col++) { //needed <=
if (grid.get(new Location(row,col)) != null) {
columnsFilled++;
}
}
if (columnsFilled == 10) {
for(int col = 0; col <= grid.getNumCols(); col++){
world.remove(new Location(row,col));
}
columnsFilled =0;
}
}
}
}
TetrisBlock.java
import info.gridworld.actor.*;
import info.gridworld.grid.*;
import java.util.ArrayList;
import java.awt.Color;
/**
* TetrisBlock is a type of Bug. It will act in GridWorld by moving down
* (direction 180) if it can, otherwise it will ask TetrisGame to make a new
* TetrisBlock for the game.
*/
public class TetrisBlock extends TetrisBug {
/**
* value of the current rotation position {0,1,2 or 3}
*/
protected int rotationPos;
/**
* blocks will have three TetrisBug objects in it... they will be added in the
* constructor
*/
protected ArrayList<TetrisBug> blocks;
/**
* used as a convenient reference to the Grid
*/
protected Grid<Actor> gr;
/**
* default constructor
*/
public TetrisBlock() {
super(Color.blue);
rotationPos = 0;
gr = TetrisGame.world.getGrid();
// ==> LAMEST GAME OVER EVER !!! <==
// if the Grid does not have room for the TetrisBlock.. GameOver
if (gr.get(new Location(0, 5)) != null
|| gr.get(new Location(1, 5)) != null) {
javax.swing.JOptionPane.showMessageDialog(null, "Score: "
+ TetrisGame.score, "GAME OVER!", 0);
System.exit(0);
}
putSelfInGrid(gr, new Location(1, 5));
blocks = new ArrayList<TetrisBug>();
TetrisBug a;
// create TetrisBugs for ArrayList blocks and put them in Grid gr
a = new TetrisBug(Color.blue);
a.putSelfInGrid(gr, new Location(0, 5));
blocks.add(a);
// TetrisBlock subclasses will add two more TetrisBug objects to blocks
}
/**
* TetrisBlock and its TetrisBugs must face down (direction 180) If they can
* move down, they will. Otherwise, it will ask TetrisGame to create a new
* TetrisBlock since this one is stuck at the bottom.
*/
public void act() {
setDirection(180);
for (TetrisBug tb : blocks)
tb.setDirection(180);
if (canMoveDown())
moveDown();
else {
if (!TetrisGame.currentBlock.canMoveDown())
TetrisGame.nextTetrisBlock();
}
}
/**
* Move the TetrisBlock and its TetrisBugs one cell. (they should already be
* facing down) Note: The order in which all the TetrisBugs move is important
* and depends on the current rotationPos.
*/
public void moveDown() {
if (rotationPos == 0) {
move();
blocks.get(0).move();
} else if (rotationPos == 1) {
blocks.get(0).move();
move();
}
}
/**
* Returns true if the TetrisBlock and its TetrisBugs can move (they should
* already be facing down) Otherwise, returns false.
*/
public boolean canMoveDown() {
if (rotationPos == 0)
return canMove();
else if (rotationPos == 1)
return canMove() && blocks.get(0).canMove();
else
return true;
}
/**
* Sets the direction of the TetrisBlock and its TetrisBugs to 90 (right) If
* they can move, they will move one cell (to the right)
*/
public void moveRight() {
setDirection(90);
for (TetrisBug tb : blocks)
tb.setDirection(90);
if (rotationPos == 0) {
if (canMove() && blocks.get(0).canMove()) {
blocks.get(0).move();
move();
}
} else if (rotationPos == 1) {
if (canMove()) {
move();
blocks.get(0).move();
}
}
}
/**
* Sets the direction of the TetrisBlock and its TetrisBugs to 90 (right) If
* they can move, they will move one cell (to the right)
*/
public void moveLeft() {
setDirection(270);
for (TetrisBug tb : blocks)
tb.setDirection(270);
if (rotationPos == 0) {
if (canMove() && blocks.get(0).canMove()) {
blocks.get(0).move();
move();
}
} else if (rotationPos == 1) {
if (canMove() && blocks.get(0).canMove()) {
blocks.get(0).move();
move();
}
}
}
/**
* If the TetrisBlock and its TetrisBugs can rotate, then they will all move
* to their proper location for the given rotation designated by
* rotationPos... Update rotationPos.
*/
public void rotate() {
Location nextLoc;
if (rotationPos == 0) {
// only one block must move
nextLoc = new Location(getLocation().getRow() - 1,
getLocation().getCol() + 1);
if (gr.isValid(nextLoc) && gr.get(nextLoc) == null) {
moveTo(nextLoc);
rotationPos = (rotationPos + 1) % 2;// will be % 4 with 4 blocks
}
} else if (rotationPos == 1) {
nextLoc = new Location(getLocation().getRow() + 1,
getLocation().getCol() - 1);
if (gr.isValid(nextLoc) && gr.get(nextLoc) == null) {
moveTo(nextLoc);
rotationPos = (rotationPos - 1) % 2;// will be % 4 with 4 blocks
}
}
}
}
TetrisBlockO.java
public class TetrisBlockO{
public TetrisBlockO() {
rotationPos = 0;
gr = TetrisGame.world.getGrid();
//GAME OVER!
if (gr.get(new Location(0, 5)) != null
|| gr.get(new Location(1, 5)) != null
|| gr.get(new Location(0, 6)) != null
|| gr.get(new Location(1, 6)) != null) {
javax.swing.JOptionPane.showMessageDialog(null, "Score: " + TetrisGame.score, "GAME OVER!", 0);
System.exit(0);
}
putSelfInGrid(gr, new Location(1, 5));
blocks = new ArrayList<TetrisBrick>();
TetrisBrick a;
a = new TetrisBrick(Color.blue);
a.putSelfInGrid(gr, new Location(0, 5));
blocks.add(a);
TetrisBrick b;
b = new TetrisBrick(Color.blue);
b.putSelfInGrid(gr, new Location(1, 6));
blocks.add(b);
TetrisBrick c;
c = new TetrisBrick(Color.blue);
c.putSelfInGrid(gr, new Location(0, 6));
blocks.add(c);
}
}
The first problem I'm having is in TetrisGame. The last method, to be precise. The grid.length statement is refusing to compile, and when I added a Grid grid = new Grid(); statement, it said it was abstract method and couldn't be instantiated. And compiling any of them give me a compiler warning,
\GridworldTetris\TetrisGame.java uses unchecked or unsafe operations.
Recompile with -Xlint:unchecked for details
The second problem is with the rotate method in TetrisBlock. I am not sure whether it works or not since the TetrisGame wont compile. I cant test it, but a friend of mine keeps telling me it's wrong, though IDK whether to believe him. Some validation would be nice.
Anyway, I have no real time limit on this, but I'd really like to be done with it. Thanks.
~Keelen
UPDATE: Thanks to user3580294 I solved the grid problem. But I found another, GRID DOESNT HAVE A LENGTH METHOD... I know what I was trying to do WOULD work, but cant find a way to do it, besides grid.length, which is invalid. Could someone make me a method that'd successfully remove completed rows? I really am stuck here... And I want to move to the next project...
For your removeCompleteRows() method try this in your if statement:
if (columnsFilled == 10) {
for(int col = 1; col < grid.getNumCols() - 1; col++){
grid.get(new Location( row,col )).removeSelfFromGrid();
}
columnsFilled = 0;
}
I think the World remove() method might work, but generally you won't have access to the World your Actor is on, so using Grid's removeSelfFromGrid() is safer.
Also, I assume you only want to remove the Blocks not your walls so you only want to iterate through Locations your Blocks might occupy, 1 through getNumCols() - 1.
I'm writing a tic-tac-toe game for my Java, I really suck at this so far, but got it to work with the examples he gave us in class. The problem I'm having now is that I realized wants us to have at least TWO classes for this program. I have no idea what he means by that or how I convert the code I've already put together into "Two Classes". From the instructions it looks like he wants the board in one class and the game in another class.
Is there a way to split this up into two classes without totally re-writing the whole thing?
/* Standard applet template
*/
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import javax.swing.*;
public class TicTacToeGame implements ActionListener {
/*Instance Variables*/
private JFrame window = new JFrame("Tic-Tac-Toe Game");
private JButton btn1 = new JButton("");
private JButton btn2 = new JButton("");
private JButton btn3 = new JButton("");
private JButton btn4 = new JButton("");
private JButton btn5 = new JButton("");
private JButton btn6 = new JButton("");
private JButton btn7 = new JButton("");
private JButton btn8 = new JButton("");
private JButton btn9 = new JButton("");
private JLabel lblTitle = new JLabel("Tic Tac Toe Game");
private JLabel lblBlank = new JLabel(" ");
private String letter = "";
private int count = 0;
private boolean win = false;
public TicTacToeGame(){
/*Create Window*/
window.setSize(400,300);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLayout(new GridLayout(3,3));
/*Add Buttons To The Window*/
window.add(btn1);
window.add(btn2);
window.add(btn3);
window.add(btn4);
window.add(btn5);
window.add(btn6);
window.add(btn7);
window.add(btn8);
window.add(btn9);
/*Add The Action Listener To The Buttons*/
btn1.addActionListener(this);
btn2.addActionListener(this);
btn3.addActionListener(this);
btn4.addActionListener(this);
btn5.addActionListener(this);
btn6.addActionListener(this);
btn7.addActionListener(this);
btn8.addActionListener(this);
btn9.addActionListener(this);
/*Make The Window Visible*/
window.setVisible(true);
}
public void actionPerformed(ActionEvent a) {
count++;
/*Calculate Who's Turn It Is*/
if(count == 1 || count == 3 || count == 5 || count == 7 || count == 9){
letter = "<HTML><font color=blue>X</font></HTML>";
} else if(count == 2 || count == 4 || count == 6 || count == 8 || count == 10){
letter = "<HTML><font color=red>O</font></HTML>";
}
/*Display X's or O's on the buttons*/
if(a.getSource() == btn1){
btn1.setText(letter);
btn1.setEnabled(false);
} else if(a.getSource() == btn2){
btn2.setText(letter);
btn2.setEnabled(false);
} else if(a.getSource() == btn3){
btn3.setText(letter);
btn3.setEnabled(false);
} else if(a.getSource() == btn4){
btn4.setText(letter);
btn4.setEnabled(false);
} else if(a.getSource() == btn5){
btn5.setText(letter);
btn5.setEnabled(false);
} else if(a.getSource() == btn6){
btn6.setText(letter);
btn6.setEnabled(false);
} else if(a.getSource() == btn7){
btn7.setText(letter);
btn7.setEnabled(false);
} else if(a.getSource() == btn8){
btn8.setText(letter);
btn8.setEnabled(false);
} else if(a.getSource() == btn9){
btn9.setText(letter);
btn9.setEnabled(false);
}
/*Checks to See Who Won*/
//horizontal win
if( btn1.getText() == btn2.getText() && btn2.getText() == btn3.getText() && btn1.getText() != ""){
win = true;
}
else if(btn4.getText() == btn5.getText() && btn5.getText() == btn6.getText() && btn4.getText() != ""){
win = true;
}
else if(btn7.getText() == btn8.getText() && btn8.getText() == btn9.getText() && btn7.getText() != ""){
win = true;
}
//virticle win
else if(btn1.getText() == btn4.getText() && btn4.getText() == btn7.getText() && btn1.getText() != ""){
win = true;
}
else if(btn2.getText() == btn5.getText() && btn5.getText() == btn8.getText() && btn2.getText() != ""){
win = true;
}
else if(btn3.getText() == btn6.getText() && btn6.getText() == btn9.getText() && btn3.getText() != ""){
win = true;
}
//diagonal wins
else if(btn1.getText() == btn5.getText() && btn5.getText() == btn9.getText() && btn1.getText() != ""){
win = true;
}
else if(btn3.getText() == btn5.getText() && btn5.getText() == btn7.getText() && btn3.getText() != ""){
win = true;
}
else {
win = false;
}
/*Show a dialog if someone wins or the game is tie*/
if(win == true){
JOptionPane.showMessageDialog(null, letter + " WINS!");
} else if(count == 9 && win == false){
JOptionPane.showMessageDialog(null, "Tie Game!");
}
}
public static void main(String[] args){
new TicTacToeGame();
}
}
There are multiple ways to split this class, but since it's not very big, most of them would end up rewriting much of it.
The cleanest way would be to split logic and UI into (at least) two separate classes:
Class TicTacToeGame would implement the logic: it has a method to query who's turn it is, some methods to query the state of the playing field, a method to enter the next move, a method to query the state of the game (playing, end), a method to query who has won and probably a way to register some listeners
Class TicTacToeUI just takes the information of an instance of the other class and displays it. It also calls the appropriate methods when one button is clicked.
The net effect will probably be more code (since the interaction between the two classes will need some code), but the code will be much cleaner and the game class can be tested independently of the UI.
Simple thing you can do is Make second class that implements ActionListener and then use that class to listen to all action events in your program. This is not the way you want that is one for board and one for game but this can be one for operation and one for presentation.
Joachim gave a nice answer. I just want to add that instead of doing this:
/*Display X's or O's on the buttons*/
if(a.getSource() == btn1){
btn1.setText(letter);
btn1.setEnabled(false);
...
} else if(a.getSource() == btn9){
btn9.setText(letter);
btn9.setEnabled(false);
}
You can do this:
JButton btn = (JButton) a.getSource();
btn.setText(letter);
btn.setEnabled(false);
I think your comments are a good hint as to logical splits. Put each section into a separate method so that your actionPerformed method would be something like the following.
public void actionPerformed(ActionEvent a) {
count++;
letter = calculateCurrentPlayer(count);
displayLetterOnButton(a.getSource());
win = checkForWin();
displayGameOver(win, count);
}
Each of the methods called from actionPerformed would then have a small tightly-defined unit of work to perform. These methods could pretty much be copy-and-paste from the sections of your current actionsPerformed method.