Issues with MouseListener - java

I would really like some help with this game I am making. I have tried for the longest time and the solution eludes me. It doesn't do very much at the moment. Basically, I need the mouse listener to look for a left click and change the direction of the snake one way, and the other for a right click. But I can't seem to get the listener set up correctly. Excuse me if my coding is poor or if there is a better solution to something I am doing, I haven't been coding for that long.
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.*;
import java.awt.Color;
import java.util.*;
import java.awt.event.*;
public class SnakeGame implements MouseListener{
static int delta = 10;
public static void main(String[] args) {
JFrame f = new JFrame("Snake Game"){
#Override
public void paint(Graphics g){
ArrayList<Integer> snakeX = new ArrayList<Integer>();
ArrayList<Integer> snakeY = new ArrayList<Integer>();
ArrayList<Integer> food = new ArrayList<Integer>();
char direction = 'e';
int tail = 2;
int foodX;
int foodY;
boolean game = true;
boolean check = false;
boolean recheck = true;
snakeX.add(0,20);
snakeX.add(1,10);
snakeX.add(2,0);
snakeY.add(0,0);
snakeY.add(1,0);
snakeY.add(2,0);
Random rnd = new Random();
do{
foodX = (rnd.nextInt(750/delta)+1) * delta;
foodY = (rnd.nextInt(750/delta)+1) * delta;
//System.out.println(foodX + " : " + foodY);
for(int i = 0; i < snakeX.size(); i++){
if(recheck){
if(foodX != snakeX.get(i).intValue() && foodY != snakeY.get(i).intValue()){
check = true;
recheck = false;
}
else{
check = false;
recheck = true;
}
}
}
}while(!check);
food.add(0, foodX);
food.add(1, foodY);
while (game){
g.fillRect(0,0,759,781);
drawSnake(snakeX, snakeY, food, g);
moveSnake(snakeX, snakeY, direction, game, food, g);
drawFood(food, g);
for(long delay = 0; delay < 75000000; delay++);
}
}
};
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(768,790);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public void mousePressed(MouseEvent e){
}
public void mouseEntered(MouseEvent e){
}
public void mouseReleased(MouseEvent e){
}
public void mouseClicked(MouseEvent e){
}
public void mouseExited(MouseEvent e){
}
public static void drawFood(ArrayList<Integer> food, Graphics g){
g.setColor(Color.red);
g.fillRect(food.get(0).intValue()+9, food.get(1).intValue()+31, delta, delta);
}
public static void drawSnake(ArrayList<Integer> snakeX, ArrayList<Integer> snakeY, ArrayList<Integer> food, Graphics g){
g.setColor(Color.black);
g.fillRect(0,0,760,782);
drawFood(food, g);
g.setColor(Color.white);
for(int i = 0; i < snakeX.size(); i++){
g.fillRect(snakeX.get(i)+9, (int) snakeY.get(i)+31, delta, delta);
}
}
public static void checkContact(ArrayList<Integer> snakeX, ArrayList<Integer> snakeY, Boolean game){
for(int i = 1; i < snakeX.size(); i++){
if(snakeX.get(i) == snakeX.get(0) && snakeY.get(i) == snakeY.get(0))
game = false;
}
}
public static void checkFood(ArrayList<Integer> snakeX, ArrayList<Integer> snakeY, ArrayList<Integer> food, Graphics g){
if(snakeX.get(0).intValue() == food.get(0).intValue() && snakeY.get(0).intValue() == food.get(1).intValue()){
setFood(food, snakeX, snakeY);
snakeX.add(snakeX.get(snakeX.size()-1).intValue()-delta);
snakeY.add(snakeY.get(snakeY.size()-1).intValue()-delta);
}
}
public static void setFood(ArrayList<Integer> food, ArrayList<Integer> snakeX, ArrayList<Integer> snakeY){
boolean check = false;
boolean recheck = true;
Random rnd = new Random();
int foodX;
int foodY;
do{
foodX = (rnd.nextInt(750/delta)+1) * delta;
foodY = (rnd.nextInt(750/delta)+1) * delta;
//System.out.println(foodX + " : " + foodY);
for(int i = 0; i < snakeX.size(); i++){
if(recheck){
if(foodX != snakeX.get(i).intValue() && foodY != snakeY.get(i).intValue()){
check = true;
recheck = false;
}
else{
check = false;
recheck = true;
}
}
}
}while(!check);
food.set(0, foodX);
food.set(1, foodY);
}
public static void moveSnake(ArrayList<Integer> snakeX, ArrayList<Integer> snakeY, char direction, Boolean game, ArrayList<Integer> food, Graphics g){
if(snakeX.get(0).intValue() < 740 && snakeX.get(0).intValue() >= 0 && snakeY.get(0).intValue() < 740 && snakeY.get(0).intValue() >= 0){
if(direction == 'e'){
int temp = snakeX.get(0).intValue();
int temp2 = 0;
snakeX.set(0, temp+delta);
for(int i = 1; i < snakeX.size(); i++){
temp2 = snakeX.get(i);
snakeX.set(i,temp);
temp = temp2;
}
int tempY = snakeY.get(0).intValue();
int tempY2 = 0;
snakeY.set(0, tempY);
for(int i = 1; i < snakeY.size(); i++){
tempY2 = snakeY.get(i);
snakeY.set(i,tempY);
tempY = tempY2;
}
}
else if(direction == 'n'){
int temp = snakeX.get(0).intValue();
int temp2 = 0;
snakeX.set(0, temp);
for(int i = 1; i < snakeX.size(); i++){
temp2 = snakeX.get(i);
snakeX.set(i,temp);
temp = temp2;
}
int tempY = snakeY.get(0).intValue();
int tempY2 = 0;
snakeY.set(0, tempY+delta);
for(int i = 1; i < snakeY.size(); i++){
tempY2 = snakeY.get(i);
snakeY.set(i,tempY);
tempY = tempY2;
}
}
else if(direction == 'w'){
int temp = snakeX.get(0).intValue();
int temp2 = 0;
snakeX.set(0, temp-delta);
for(int i = 1; i < snakeX.size(); i++){
temp2 = snakeX.get(i);
snakeX.set(i,temp);
temp = temp2;
}
int tempY = snakeY.get(0).intValue();
int tempY2 = 0;
snakeY.set(0, tempY);
for(int i = 1; i < snakeY.size(); i++){
tempY2 = snakeY.get(i);
snakeY.set(i,tempY);
tempY = tempY2;
}
}
else if(direction == 's'){
int temp = snakeX.get(0).intValue();
int temp2 = 0;
snakeX.set(0, temp);
for(int i = 1; i < snakeX.size(); i++){
temp2 = snakeX.get(i);
snakeX.set(i,temp);
temp = temp2;
}
int tempY = snakeY.get(0).intValue();
int tempY2 = 0;
snakeY.set(0, tempY-delta);
for(int i = 1; i < snakeY.size(); i++){
tempY2 = snakeY.get(i);
snakeY.set(i,tempY);
tempY = tempY2;
}
}
checkFood(snakeX, snakeY, food, g);
checkContact(snakeX, snakeY, game);
}
drawSnake(snakeX, snakeY, food, g);
}
}

Your game loop (the part of your code that says while(game)) which is supposed to run until the game is over is a little misplaced. Because that loop is infinite on purpose it will never reach the lines after it that set up values for the frame. These statements:
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(768,790);
f.setLocationRelativeTo(null);
f.setVisible(true);
Need to be placed before the loop. Then to properly register the frame's mouse listener you have to add it to your frame like this:
f.addMouseListener(this);
This works because SnakeGame can be considered a MouseListener because it implements that interface.
Bonus Tip:
The correct way to pause execution is to use a swing timer, not have a for loop run a bunch of times.
Read this for more information about using timers.
Hope that Helps!

You must add the mouse listener f.addMouseListener(this); Your code is really hard to read as it's all done inside main. You should first start a new instance of your class and use its constructor
public SnakeGame(){
//code here
}
It's a lot to explain look up how to structure your classes.

Related

How to lessen memory usage when using many ArraysLists in Java

I'm making a program to play Misere Nim, and I'm running into some problems with memory. I use ArrayLists to hold the possible moves that could be done, and this is causing an OutOfMemory exception. How can I lessen the memory I use when using ArrayLists? Should I be clearing something after every run?
EDIT: added copy method
EDIT: full project can be found at https://github.com/DatOneRam/ScienceFair
do
{
int tempWin = board.playRound();
if (tempWin == 0)
stratWins++;
else
randWins++;
}
while (rounds <= 10000);
public int playRound()
{
Board board = new Board();
NimBot strat = new NimBot(board);
NimBot rand = new NimBot(board);
do
{
strat.makeStrategicMove();
if (board.hasEnded())
break;
rand.makeRandomMove();
}
while (!board.hasEnded());
return board.getPlayer();
}
public void makeStrategicMove()
{
ArrayList<int[]> goodMoves = board.getGoodMoves();
Random rand = new Random();
int[] move;
if (goodMoves.size() != 0)
{
move = goodMoves.get(rand.nextInt(goodMoves.size()));
}
else
{
ArrayList<int[]> simpleMoves = board.getSimpleMoves();
move = simpleMoves.get(rand.nextInt(simpleMoves.size()));
}
board.setPosition(move);
}
public void makeRandomMove()
{
ArrayList<int[]> moves = board.getMoves();
Random rand = new Random();
int[] move = moves.get(rand.nextInt(moves.size()));
board.setPosition(move);
}
public ArrayList<int[]> getMoves()
{
ArrayList<int[]> x = new ArrayList<int[]>();
int j = 0, i = 1;
x.add(0, copy(position));
do
{
x.add(i, copy(position));
if (x.get(i-1)[j] == 0)
j++;
x.get(i)[j] = x.get(i-1)[j] - 1;
i++;
if (x.get(i-1)[j] == 0)
{
j++;
if (j == 5)
{
break;
}
}
}
while(x.get(i - 1)[j] != 0);
for (int r = 0; r < x.size(); r++)
{
x.get(r)[4] = toggle(x.get(r)[4]);
}
x.remove(0);
//resize(x);
return x;
}
public ArrayList<int[]> getSimpleMoves()
{
ArrayList<int[]> x = new ArrayList<int[]>(4);
for (int i = 0; i < 4; i++)
{
x.add(copy(position));
x.get(i)[i] = position[i] - 1;
x.get(i)[4] = toggle(x.get(i)[4]);
if (x.get(i)[i] < 0)
x.get(i)[i] = 0;
}
//resize(x);
return x;
}
public int[] copy(int[] y)
{
int[] z = new int[y.length];
for (int i = 0; i < y.length; i++)
z[i] = y[i];
return z;
}
I apologize if I put too much code here, I wasn't sure how to shorten it.

Array index out of bounds while traversing edge members of array

I am creating a random maze generator in Java using the recursive backtracker algorithm. I need to set the edges of my maze cell data array to have been already visited by the algorithm so that it won't step out of bounds. The problem is probably staring me right in the face, I just cannot see where my error is.
Here is the whole error message:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 30
at mazeMaker.Maze.initBoundries(Maze.java:55)
at mazeMaker.Maze.<init>(Maze.java:46)
at mazeMaker.Main.main(Main.java:8)
I have tried tracing the error as best I could and experimented with changing my variables. The program relies on multiple class files, so I think it would be best just to show the whole thing.
Main.java
package mazeMaker;
public class Main
{
public static void main(String[] args)
{
Maze mainMaze = new Maze(20, 30);
}
}
Maze.java
package mazeMaker;
import java.util.Random;
import java.util.Stack;
public class Maze
{
public int xSize = 0;
public int ySize = 0;
public int totalDimensions = 0;
Random randomGenerator = new Random();
public Cell[][] cellData;
public Stack<Cell> cellStack = new Stack<Cell>();
Cell tempCell; // Temporary variable used for maze generation
public Maze(int xSize, int ySize)
{
cellData = new Cell[xSize][ySize];
this.xSize = xSize;
this.ySize = ySize;
this.totalDimensions = this.xSize * this.ySize;
// Initialize array objects
for (int i = 0; i < this.xSize; i++)
{
for (int j = 0; j < this.ySize; j++)
{
cellData[i][j] = new Cell();
}
}
// Assign x and y positions
for (int i = 0; i < this.xSize; i++)
{
for (int j = 0; j < this.ySize; j++)
{
cellData[i][j].xPos = i;
cellData[i][j].yPos = j;
}
}
initBoundries();
}
private void initBoundries()
{
// Initialize the border cells as visited so we don't go out of bounds
for (int col = 0; col < this.xSize; col++)
{
cellData[0][col].hasBeenVisited = true;
cellData[this.ySize][col].hasBeenVisited = true;
}
for (int row = 0; row < this.ySize; row++)
{
cellData[row][0].hasBeenVisited = true;
cellData[row][this.xSize].hasBeenVisited = true;
}
}
private void generateMaze(int x, int y)
{
// Set current cell as visited
cellData[x][y].hasBeenVisited = true;
// While there are unvisited neighbors
while (!cellData[x][y+1].hasBeenVisited || !cellData[x+1][y].hasBeenVisited || !cellData[x][y-1].hasBeenVisited || !cellData[x-1][y].hasBeenVisited)
{
// Select a random neighbor
while (true)
{
int r = randomGenerator.nextInt(4);
if (r == 0 && !cellData[x][y+1].hasBeenVisited)
{
cellStack.push(cellData[x][y]);
cellData[x][y].hasNorthWall = false;
cellData[x][y+1].hasSouthWall = false;
generateMaze(x, y + 1);
break;
}
else if (r == 1 && !cellData[x+1][y].hasBeenVisited)
{
cellStack.push(cellData[x][y]);
cellData[x][y].hasEastWall = false;
cellData[x+1][y].hasWestWall = false;
generateMaze(x+1, y);
break;
}
else if (r == 2 && !cellData[x][y-1].hasBeenVisited)
{
cellStack.push(cellData[x][y]);
cellData[x][y].hasSouthWall = false;
cellData[x][y-1].hasNorthWall = false;
generateMaze(x, y-1);
break;
}
else if (r == 3 && !cellData[x-1][y].hasBeenVisited)
{
cellStack.push(cellData[x][y]);
cellData[x][y].hasWestWall = false;
cellData[x-1][y].hasEastWall = false;
generateMaze(x-1, y);
break;
}
}
}
// There are no unvisited neighbors
tempCell = cellStack.pop();
generateMaze(tempCell.xPos, tempCell.yPos);
}
// Begin generating maze at top left corner
private void generateMaze()
{
generateMaze(1,1);
}
}
Cell.java
package mazeMaker;
public class Cell
{
public boolean isCurrentCell;
public boolean hasBeenVisited;
public boolean hasNorthWall;
public boolean hasSouthWall;
public boolean hasEastWall;
public boolean hasWestWall;
public int xPos;
public int yPos;
}
cellData[this.ySize][col].hasBeenVisited = true;
You have initialized your cellData as cellData[20][30], but in the above-mentioned line you are calling cellData[30][col]. Instead of 30, the first bracket should have a value from 0 to 19, because the row size is 20.
My guess is from this code in initBoundries()
// Initialize the border cells as visited so we don't go out of bounds
for (int col = 0; col < this.xSize; col++)
{
cellData[0][col].hasBeenVisited = true;
cellData[this.ySize][col].hasBeenVisited = true;
}
this.ySize after initialize (from constructor) has value 30.

Bar demonstration of Shaker sort sorts all bars at once -Java

I found this code here in the accepted answer: Java swing repainting while computing: animating sorting algorithm
And I've been trying to modify it so it works for shaker sort but my code sorts the whole thing all at once.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collections;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class ShakerSortAnimate extends JPanel {
private static final int NUM_OF_ITEMS = 20;
private static final int DIM_W = 400;
private static final int DIM_H = 400;
private static final int HORIZON = 350;
private static final int VERT_INC = 15;
private static final int HOR_INC = DIM_W / NUM_OF_ITEMS;
private JButton startButton;
private Timer timer = null;
private JButton resetButton;
Integer[] list;
int currentIndex = NUM_OF_ITEMS - 1;
public ShakerSortAnimate() {
list = initList();
timer = new Timer(200, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (isSortingDone()) {
((Timer) e.getSource()).stop();
startButton.setEnabled(false);
} else {
sortOnlyOneItem();
}
repaint();
}
});
//button to run the program
startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
//resets screen
resetButton = new JButton("Reset");
resetButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
list = initList();
currentIndex = NUM_OF_ITEMS - 1;
repaint();
startButton.setEnabled(true);
}
});
add(startButton);
add(resetButton);
}
//boolean checks when array is sorted
public boolean isSortingDone() {
return currentIndex == 0;
}
//initializes the array
public Integer[] initList() {
Integer[] nums = new Integer[NUM_OF_ITEMS];
for (int i = 1; i <= nums.length; i++) {
nums[i - 1] = i;
}
Collections.shuffle(Arrays.asList(nums)); //shuffles array
return nums;
}
//draws each bar
public void drawItem(Graphics g, int item, int index) {
int height = item * VERT_INC;
int y = HORIZON - height;
int x = index * HOR_INC;
g.fillRect(x, y, HOR_INC, height);
}
//My shaker sort code
public void sortOnlyOneItem()
{
boolean swapped = true;
int start = 0;
int end = currentIndex;
while (swapped==true)
{
swapped = false;
for (int i = start; i < end; ++i)
{
if (list[i] > list[i + 1])
{
int temp = list[i];
list[i] = list[i+1];
list[i+1] = temp;
swapped = true;
}
}
if (swapped==false)
break;
swapped = false;
end = end-1;
for (int i = end; i >=start; i--)
{
if (list[i] > list[i+1])
{
int temp = list[i];
list[i] = list[i+1];
list[i+1] = temp;
swapped = true;
}
}
start = start + 1;
}
currentIndex--; //currentIndex is updated each time shaker sort runs
}
//draws all bars
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < list.length; i++) {
drawItem(g, list[i], i);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(DIM_W, DIM_H);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Sort");
frame.add(new ShakerSortAnimate());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
I do realize that my Shaker Sort code has to do it for each comparison, not the entire thing but honestly, I don't even know how to begin to code that. If anyone of you here knows how to code each comparison in shaker sort, can you help me out?
Btw, I posted the entire thing so you can try running this as well.
Thanks in advance!
So, you need this...
public void sortOnlyOneItem()
{
boolean swapped = true;
int start = 0;
int end = currentIndex;
while (swapped==true)
{
swapped = false;
for (int i = start; i < end; ++i)
{
if (list[i] > list[i + 1])
{
int temp = list[i];
list[i] = list[i+1];
list[i+1] = temp;
swapped = true;
}
}
if (swapped==false)
break;
swapped = false;
end = end-1;
for (int i = end; i >=start; i--)
{
if (list[i] > list[i+1])
{
int temp = list[i];
list[i] = list[i+1];
list[i+1] = temp;
swapped = true;
}
}
start = start + 1;
}
currentIndex--; //currentIndex is updated each time shaker sort runs
}
To only run ONCE per call. It's not doing that right now because if the while-loop, so, we need to get rid of that.
In doing so, the second loop should only be run if swapped is true AND the currentIndex should only be decremented if swapped is still true
Which brings us to something like...
public void sortOnlyOneItem() {
boolean swapped = true;
int start = 0;
int end = currentIndex;
for (int i = start; i < end; ++i) {
if (list[i] > list[i + 1]) {
int temp = list[i];
list[i] = list[i + 1];
list[i + 1] = temp;
swapped = true;
}
}
if (swapped) {
swapped = false;
end = end - 1;
for (int i = end; i >= start; i--) {
if (list[i] > list[i + 1]) {
int temp = list[i];
list[i] = list[i + 1];
list[i + 1] = temp;
swapped = true;
}
}
}
if (swapped) {
currentIndex--; //currentIndex is updated each time shaker sort runs
}
}
Which still isn't quite right, as the two for-loops can make multiple changes.
Instead, we need a iteration which will only make, at most, two changes, one at the start and one at the end
Which, might, look something like...
protected void swap(int a, int b) {
int tmp = list[a];
list[a] = list[b];
list[b] = tmp;
}
int endIndex = NUM_OF_ITEMS - 1;
//My shaker sort code
public void sortOnlyOneItem() {
int startIndex = 0;
while (startIndex < NUM_OF_ITEMS - 1 && list[startIndex] < list[startIndex + 1]) {
startIndex++;
}
if (startIndex < NUM_OF_ITEMS - 1 && list[startIndex] > list[startIndex + 1]) {
swap(startIndex, startIndex + 1);
int end = endIndex;
while (end > 0 && list[end - 1] < list[end]) {
end--;
}
if (end > 0 && list[end - 1] > list[end]) {
swap(end - 1, end);
} else {
endIndex--;
}
} else {
endIndex = 0;
}
}
Now, this basically looks for the two indices which might be changeable (at the start and end) and swaps them if possible. When you can iterate from the start to the end without making a change, the sort is finished.
Now, I make no claims over if this is accurate or not, only that it does the best effort to mimic the algorithm you supplied

(Java) Minesweeper clone not correctly revealing squares?

so basically I've been making a minesweeper clone in Java. I had it working perfectly until I added the game win and lose parts and the big opening print. Now when I run it some of the spots that are next to zero's don't get revealed, even though they should. I can't figure out where the bug is though. Here's my code:
/**
* A program to play Scat Scout...
*/
import static java.lang.System.*; // so you can write out.println() instead of System.out.println()
import java.util.*;
class ScatScout {
static final int boardSize = 10;
static final Random rand = new Random();
static final boolean SCAT = true;
static final boolean CLEAR = false;
static int clearCounter = 100;
static boolean gameWon = false;
static boolean gameLost = false;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
boolean[][] board = new boolean[boardSize+2][boardSize+2]; // scat or no scat
boolean[][] exposed = new boolean[boardSize+2][boardSize+2]; // showing or hidden
int[][] counts = new int[boardSize+2][boardSize+2]; // number of neighbors with scat
if (args.length > 0) {
rand.setSeed(Integer.parseInt(args[0]));
}
System.out.println("comment explaining game");
createScat(board); //initialize the board
compareScat(board, counts); //find how many scat are next to each spot
while(!gameWon&&!gameLost){ //keep going until game win or loss
printBoard(board, counts, exposed);
System.out.println("Enter two integers (row and column):");
expose(input.nextInt()+1, input.nextInt()+1, board, exposed, counts);
if (gameLost){
for (int i = 1; i<= board.length-2; i++){
for (int j = 1; j<= board.length-2; j++){
if (!board[i][j]){
exposed[i][j] = true;
}
}
}
printBoard(board, counts, exposed);
System.out.print("You stepped in it! Yucky!"); //game lose
break;
}
gameWon = true; //game is one if all blanks but the bombs are exposed
for(int i = 1; i<= board.length-2; i++){
for(int j = 1; j<= board[0].length-2; j++){
if(!exposed[i][j]&&!board[i][j]){
gameWon=false; //otherwise continue loop
}
}
}
if (gameWon){
System.out.print("You cleared the scat! Congrats!"); //game win message
break;
}
}
input.close();
}
public static void printBoard(boolean[][] board, int[][] counts, boolean[][] exposed){ //initialize board
int numRows = counts.length;
int numCols = counts[0].length;
System.out.println(" 0123456789"); //print the border
for(int i=1; i<=numRows-2; i++){
System.out.print(i-1 + " "); //border
for(int j=1; j<=numCols-2; j++){
if (exposed[i][j] == true){
System.out.print(counts[i][j]); //print the scat near a spot if it's exposed
}
else{
System.out.print("*"); //print unknown spot
}
}
System.out.print(" ");
System.out.print(i-1); //border
System.out.println(" ");
}
System.out.println(" 0123456789"); //border
}
public static void createScat(boolean[][] board){ //randomly seed scat into field
for(int i=1; i<= board.length-2; i++){
int x = rand.nextInt(board.length-3)+1;
int y = rand.nextInt(board.length-3)+1;
if(x!=0&&x!=11&&y!=0&&y!=11&&board[x][y]==CLEAR){
board[x][y]=SCAT; //scat in this random spot
}
}
}
public static void compareScat(boolean[][] board, int[][] counts){ //checks #scat in surrounding spots
int numRows = counts.length;
int numCols = counts[0].length;
for(int i=1; i<=numRows-2; i++){
for(int j=1; j<=numCols-2; j++){
for(int ii=i-1; ii<=i+1; ii++){
for(int jj=j-1; jj<=j+1; jj++){
if(board[ii][jj]==SCAT){ //this looks at all scat in all directions around the original spot
counts[i][j]=counts[i][j]+1; //adds to the counter if scat found around it
}
}
}
}
}
}
static void expose(int c, int r, boolean[][] board, boolean[][] exposed, int[][] counts) { //exposes chosen spot
if (exposed[r][c]) return; // nothing to do
if (board[r][c]== SCAT){
gameLost=true; //lose game if choose a spot with scat
}
exposed[r][c] = true; // expose any neighbors that have zero counts
if (counts[r][c] > 0) return;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
int x = r+i;
int y = c+j;
if (!(i==1 && j==1) && x >= 1 && x < board.length-1 && y >= 1 && y < board[x].length-1) {
if (counts[x][y] == 0) {
expose(x, y, board, exposed, counts);
}
else {
exposed[x][y] = true;
}
}
}
}
}
}

Java method call in method of another class

This is the main class:
public class Sudoku extends JFrame {
MenuBar Bar;
MenuItem itemFile[];
MenuItem itemHelp[];
Menu file;
Menu help;
public Sudoku() {
super("Sudoku");
setLayout(new FlowLayout());
setResizable(false);
itemFile =new MenuItem[2];
itemHelp =new MenuItem[2];
itemFile[0]=new MenuItem("New");
itemFile[1]=new MenuItem("Exit");
itemHelp[0]= new MenuItem("Rules");
itemHelp[1]= new MenuItem("Creators");
file=new Menu("File");
help=new Menu("Help");
file.add(itemFile[0]);
help.add(itemHelp[0]);
file.add(itemFile[1]);
help.add(itemHelp[1]);
Bar =new MenuBar();
Bar.add(file);
Bar.add(help);
setMenuBar(Bar);
setDefaultCloseOperation(EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout());
Game game = new Game();
ButtonController buttonController = new ButtonController(game);
ButtonPanel buttonPanel = new ButtonPanel();
buttonPanel.setController(buttonController);
add(buttonPanel, BorderLayout.EAST);
SudokuPanel sudokuPanel = new SudokuPanel();
SudokuController sudokuController = new SudokuController(sudokuPanel, game);
sudokuPanel.setGame(game);
sudokuPanel.setController(sudokuController);
add(sudokuPanel, BorderLayout.CENTER);
game.addObserver(buttonPanel);
game.addObserver(sudokuPanel);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public boolean action(Event evt, Object arg){
if(evt.target instanceof MenuItem){
String text=(String)arg;
System.out.println("Selected="+arg);
if(text.equals("Exit"))
System.exit(0);
else if(text.equals("New"))
// Get newGame() of Game class to run here.
}
return true;
}
This is the Game class:
package sudoku.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Observable;
public class Game extends Observable {
private int[][] solution;
private int[][] game;
private boolean[][] check;
private int selectedNumber;
private boolean help;
public Game() {
newGame();
check = new boolean[9][9];
help = true;
}
public void newGame() {
solution = generateSolution(new int[9][9], 0);
game = generateGame(copy(solution));
setChanged();
notifyObservers(UpdateAction.NEW_GAME);
}
public void checkGame() {
selectedNumber = 0;
for (int y = 0; y < 9; y++) {
for (int x = 0; x < 9; x++)
check[y][x] = game[y][x] == solution[y][x];
}
setChanged();
notifyObservers(UpdateAction.CHECK);
}
public void setHelp(boolean help) {
this.help = help;
setChanged();
notifyObservers(UpdateAction.HELP);
}
public void setSelectedNumber(int selectedNumber) {
this.selectedNumber = selectedNumber;
setChanged();
notifyObservers(UpdateAction.SELECTED_NUMBER);
}
public int getSelectedNumber() {
return selectedNumber;
}
public boolean isHelp() {
return help;
}
public boolean isSelectedNumberCandidate(int x, int y) {
return game[y][x] == 0 && isPossibleX(game, y, selectedNumber)
&& isPossibleY(game, x, selectedNumber) && isPossibleBlock(game, x, y, selectedNumber);
}
public void setNumber(int x, int y, int number) {
game[y][x] = number;
}
public int getNumber(int x, int y) {
return game[y][x];
}
public boolean isCheckValid(int x, int y) {
return check[y][x];
}
private boolean isPossibleX(int[][] game, int y, int number) {
for (int x = 0; x < 9; x++) {
if (game[y][x] == number)
return false;
}
return true;
}
private boolean isPossibleY(int[][] game, int x, int number) {
for (int y = 0; y < 9; y++) {
if (game[y][x] == number)
return false;
}
return true;
}
private boolean isPossibleBlock(int[][] game, int x, int y, int number) {
int x1 = x < 3 ? 0 : x < 6 ? 3 : 6;
int y1 = y < 3 ? 0 : y < 6 ? 3 : 6;
for (int yy = y1; yy < y1 + 3; yy++) {
for (int xx = x1; xx < x1 + 3; xx++) {
if (game[yy][xx] == number)
return false;
}
}
return true;
}
private int getNextPossibleNumber(int[][] game, int x, int y, List<Integer> numbers) {
while (numbers.size() > 0) {
int number = numbers.remove(0);
if (isPossibleX(game, y, number) && isPossibleY(game, x, number) && isPossibleBlock(game, x, y, number))
return number;
}
return -1;
}
private int[][] generateSolution(int[][] game, int index) {
if (index > 80)
return game;
int x = index % 9;
int y = index / 9;
List<Integer> numbers = new ArrayList<Integer>();
for (int i = 1; i <= 9; i++) numbers.add(i);
Collections.shuffle(numbers);
while (numbers.size() > 0) {
int number = getNextPossibleNumber(game, x, y, numbers);
if (number == -1)
return null;
game[y][x] = number;
int[][] tmpGame = generateSolution(game, index + 1);
if (tmpGame != null)
return tmpGame;
game[y][x] = 0;
}
return null;
}
private int[][] generateGame(int[][] game) {
List<Integer> positions = new ArrayList<Integer>();
for (int i = 0; i < 81; i++)
positions.add(i);
Collections.shuffle(positions);
return generateGame(game, positions);
}
private int[][] generateGame(int[][] game, List<Integer> positions) {
while (positions.size() > 0) {
int position = positions.remove(0);
int x = position % 9;
int y = position / 9;
int temp = game[y][x];
game[y][x] = 0;
if (!isValid(game))
game[y][x] = temp;
}
return game;
}
private boolean isValid(int[][] game) {
return isValid(game, 0, new int[] { 0 });
}
private boolean isValid(int[][] game, int index, int[] numberOfSolutions) {
if (index > 80)
return ++numberOfSolutions[0] == 1;
int x = index % 9;
int y = index / 9;
if (game[y][x] == 0) {
List<Integer> numbers = new ArrayList<Integer>();
for (int i = 1; i <= 9; i++)
numbers.add(i);
while (numbers.size() > 0) {
int number = getNextPossibleNumber(game, x, y, numbers);
if (number == -1)
break;
game[y][x] = number;
if (!isValid(game, index + 1, numberOfSolutions)) {
game[y][x] = 0;
return false;
}
game[y][x] = 0;
}
} else if (!isValid(game, index + 1, numberOfSolutions))
return false;
return true;
}
private int[][] copy(int[][] game) {
int[][] copy = new int[9][9];
for (int y = 0; y < 9; y++) {
for (int x = 0; x < 9; x++)
copy[y][x] = game[y][x];
}
return copy;
}
}
I want when I click "New" from my menubar (its action is in the main class), the newGame(); method of the Game class to be executed. I've tried many ways but all failed .. it's such a headache...
Any ideas ?
In the constructor you create an instance of the Game object - but it goes out of scope at the end of the method. You should keep a reference in the Sudoku class:
public class Sudoku extends JFrame {
...
private Game game;
public Sudoku() {
...
game = new Game();
Then:
public boolean action(Event evt, Object arg) {
if(evt.target instanceof MenuItem) {
String text=(String)arg;
System.out.println("Selected="+arg);
if(text.equals("Exit")) {
System.exit(0);
} else if(text.equals("New")) {
game.newGame();
}
}
return true;
}
Add a "Game" object as a member class of your main class, then you can access its methods anywhere in your class:
public class Sudoku extends JFrame {
private Game game;
// rest of your Sudoku class code as it currently is, but change:
Game game = new Game();
// to:
this.game = new Game();
// In your 'action' method, you can now call like this:
this.game.newGame();

Categories