Sometimes the mousePressed event gets executed , but at other times it won't. It also seems to depend on the time you press it. How do I get it to ALWAYS work?
I'm not sure which part of the code is faulty, so here's the whole class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Board extends JPanel implements ActionListener {
Timer timer = new Timer(500, this);
private boolean[][] board;
private boolean isActive = false;
private int height;
private int width;
private int multiplier = 20;
private JButton btnRun;
private JButton btnRand;
private JButton btnClear;
public Board() {
this(new boolean[20][20]);
}
public Board(final boolean[][] board) {
this.board = board;
height = board.length;
width = board[0].length;
setBackground(Color.black);
btnRun = new JButton("Run");
add(btnRun);
btnRun.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
isActive = !isActive;
btnRun.setText(isActive ? "Pause" : "Run");
}
});
btnRand = new JButton("Random");
add(btnRand);
btnRand.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setBoard(randomBoard());
}
});
btnClear = new JButton("Clear");
add(btnClear);
btnClear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setBoard(clearBoard());
}
});
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
getBoard()[e.getY() / multiplier][e.getX() / multiplier] = !getBoard()[e.getY() / multiplier][e.getX() / multiplier];
}
});
timer.start();
}
public int getMultiplier() {
return multiplier;
}
public boolean[][] getBoard() {
return board;
}
public void setBoard(boolean[][] boardToSet) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
board[i][j] = boardToSet[i][j];
}
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
g.setColor(board[i][j] ? Color.green : Color.gray);
g.fillRect(j * multiplier, i * multiplier, multiplier - 1, multiplier - 1);
}
}
if (isActive) {
timer.start();
}
else {
timer.stop();
repaint();
}
}
public void actionPerformed(ActionEvent e) {
board = nextGeneration();
repaint();
}
public boolean[][] randomBoard() {
Random rand = new Random();
boolean[][] randBoard = new boolean[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
randBoard[i][j] = rand.nextBoolean();
}
}
return randBoard;
}
public boolean[][] clearBoard() {
boolean[][] emptyBoard = new boolean[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
emptyBoard[i][j] = false;
}
}
return emptyBoard;
}
public int countSurrounding(int a, int b) {
int count = 0;
int[][] surrounding = {{a - 1, b - 1},
{a - 1, b },
{a - 1, b + 1},
{a , b - 1},
{a , b + 1},
{a + 1, b - 1},
{a + 1, b },
{a + 1, b + 1}};
for (int[] i: surrounding) {
try {
if (board[i[0]][i[1]]) {
count++;
}
}
catch (ArrayIndexOutOfBoundsException e) {}
}
return count;
}
public boolean[][] nextGeneration() {
boolean[][] nextBoard = new boolean[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
nextBoard[i][j] = board[i][j];
}
}
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (board[i][j] && !(countSurrounding(i, j) == 2 || countSurrounding(i, j) == 3)) {
nextBoard[i][j] = false;
}
else if (!board[i][j] && countSurrounding(i, j) == 3) {
nextBoard[i][j] = true;
}
}
}
return nextBoard;
}
}
Add a System.out statement in mousePressed() and you will see that it is always called:
public void mousePressed(MouseEvent e) {
System.out.println("mousePressed");
getBoard()[e.getY() / multiplier][e.getX() / multiplier] = !getBoard()[e.getY() / multiplier][e.getX() / multiplier];
repaint();
}
Like others suggested in your other very similar question, the problem stems from your use of timers in your paint method.
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
g.setColor(board[i][j] ? Color.green : Color.gray);
g.fillRect(j * multiplier, i * multiplier, multiplier - 1, multiplier - 1);
}
}
//if (isActive) { // take this stuff out...
// timer.start();
//}
//else {
// timer.stop();
// repaint();
//}
}
The paintComponent() method should be used to draw your components only. Do not use it to start/stop timers, make additional calls to repaint(), or otherwise call any other kind of program logic. Rethink your design, especially in paintComponent().
In addition to what whiskeyspider said, if you click on a cell while it's running, you won't see the cell light up until the next generation, and only if that position is considered alive, after processing, in the next generation.
Related
public class ChutesAndLadders2d {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] numbersOnBoard = new int [6][6];
boardSetUpA (numbersOnBoard);
printTwoD(numbersOnBoard);
}
public static void boardSetUpA (int[][]twoD) {
//Square with even size
//even rows
for (int row = 0;row<twoD.length; row ++) {
if (row %2 ==0) {
int num = twoD.length*(twoD.length-row);
for (int col = 0; col<twoD[row].length; col ++ ) {
twoD[row][col] = num;
num--;
}
}//
else {
int num = twoD.length*(twoD.length-(row + 1))+ 1;
for (int col = 0; col<twoD[row].length; col ++ ) {
twoD[row][col] = num;
num++;
}
}
}//for row
}//
public static void printTwoD(int [][] array){
for (int row = 0; row < array.length; row++){
for (int column = 0; column < array[row].length; column++){
System.out.print(array[row][column] + "\t");
}
System.out.println();
}
}
public static void boardDetails(String[][]board) {
for (int row = 0;row<board.length; row++){
for (int col = 0;col<board[row].length; col++){
if( col+2 == row||col+1 == row*2 ){
board[row][col] = "Lad"; // Append value
}
else if (col*2 == row|| row*2 == col){
board[row][col] = "Cht";// Append value
}
else {
board[row][col] = " ";
}
}
board[board.length-1][0] = "Start";
if (board.length%2 ==0) {
board[0][0] = "End";}
else {
board[0][board.length-1]="End";
}
}
}
public static void printBoard (int[][]twoD, String[][]strTwoD) {
//Printing
for (int row = 0;row<twoD.length;row++) {
for (int col = 0;col<twoD[row].length;col++) {
System.out.print(twoD[row][col] + " "+strTwoD[row][col]+"\t\t");
}
System.out.println("\n");
}
}
}
This is the starter code I have for setting up the snakes and ladders game. I also tried to set the chutes/snakes and ladders on the board but it is not printing. How should I fix it and how do I develop this code to have three methods: update the moves of a player once he reaches a snake, a ladder, and once he rolls his die, from one place to another?
Is it possible to implement a Shutes & Ladders game using a 2D Array? For sure! Does that make sense in an object-oriented language such as Java? I dont know ....
What do you need for that?
A square board with e.g. 36 playing fields.
Connections between two playing fields. (shutes and ladders)
Pawns and a dice.
A renderer that outputs the playing field (as text or graphics).
A program that allows input and connects everything to a functioning game.
Here is an example that works with a List instead of an Array. That can certainly be changed if it is necessary for your purposes.
I hope this is of some help to you.
P.S .: After the start, the board is displayed with field numbers. Shutes are shown as red lines. Ladders as green lines. Keys 1-6 on the keyboard simulate rolling the dice..
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.*;
public class ChutesAndLadders2d {
public static void main(String[] args) {
JFrame frame = new JFrame("Chutes and Ladders 2D");
Game game = new ChutesAndLadders2d().new Game();
game.setPreferredSize(new Dimension(400, 400));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setContentPane(game);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#SuppressWarnings("serial")
class Game extends JPanel{
private final Font defaultFont = new Font("Arial", Font.PLAIN, 16);
private final BasicStroke stroke = new BasicStroke(4f);
private static final int SCALE = 64;
// board and pawns
private final Board board = new Board(6);
private final List<Pawn> pawns = new ArrayList<>();
public Game(){
setFocusable(true); // receive Keyboard-Events
addKeyListener(new KeyAdapter(){
#Override
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
if(c >= '1' && c <= '6'){
int steps = Integer.parseInt(Character.toString(c));
Pawn pawn = pawns.get(0);
pawn.move(steps);
Field field = board.get(pawn.fieldIndex);
if(field.targetKind() != Kind.NONE){
pawn.move(field.getTarget().index - field.index);
}
repaint();
}
}
});
board.connect(5, 12); // Ladder 5 -> 12
board.connect(8, 4); // Shute 8 -> 4
board.connect(15, 32); // Ladder 15 -> 32
board.connect(35, 17); // Shute 35 -> 17
board.connect(23, 30); // Ladder 23 -> 30
pawns.add(new Pawn(Color.BLUE, board.size() - 1));
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
setFont(defaultFont);
for(Field field : board){
Point p = field.getLocation();
g2d.drawRect(p.x * SCALE, p.y * SCALE, SCALE, SCALE);
g2d.drawString(field.text, p.x * SCALE + 24, p.y * SCALE + 40);
}
for(Field field : board){
if(field.targetKind() != Kind.NONE){
g2d.setColor(field.targetKind() == Kind.LADDER ? Color.GREEN : Color.RED);
g2d.setStroke(stroke);
Point source = field.getLocation();
Point target = field.getTarget().getLocation();
g2d.drawLine(source.x * SCALE + 40, source.y * SCALE + 24, target.x * SCALE + 40, target.y * SCALE + 24);
}
}
for(Pawn pawn : pawns){
Point loc = board.get(pawn.fieldIndex).getLocation();
g2d.setColor(pawn.color);
g2d.fillOval(loc.x * SCALE + 32, loc.y * SCALE + 32, 16, 16);
}
}
}
class Board implements Iterable<Field>{
private final List<Field> fields = new ArrayList<>();
public Board(int size){
for(int index = 0; index < size * size; index++)
fields.add(new Field(index, size));
}
public Field get(int index){
return fields.get(index);
}
public void connect(int startFieldnumber, int targetFieldnumber){
get(startFieldnumber - 1).setTarget(get(targetFieldnumber - 1));
}
#Override
public Iterator<Field> iterator() {
return fields.iterator();
}
public int size(){
return fields.size();
}
}
class Field{
final int index;
final String text;
final int size;
private Field target;
public Field(int index, int size){
this.index = index;
this.size = size;
text = "" + (index + 1);
}
public void setTarget(Field target){
if(target == this) return;
this.target = target;
}
public Field getTarget(){
return target;
}
public Kind targetKind(){
if(target == null) return Kind.NONE;
return index < target.index ? Kind.LADDER : Kind.SHUTE;
}
public Point getLocation(){
int x = index % size;
int y = index / size;
if(y % 2 != 0) x = size - x - 1;
return new Point(x, size - y - 1);
}
}
class Pawn{
int fieldIndex = 0;
int maxIndex;
Color color;
public Pawn(Color color, int maxIndex){
this.color = color;
this.maxIndex = maxIndex;
}
public void move(int steps){
fieldIndex += steps;
if(fieldIndex < 0) fieldIndex = 0;
if(fieldIndex > maxIndex) fieldIndex = maxIndex;
}
}
enum Kind{
NONE, SHUTE, LADDER
}
}
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I am facing an issue with the paint method in the below program. The error "void Stage.paint(Graphic g, Point mouseloc)" and the error "paint cannot be resolved to a type". I have inputted the correct parameters and have set the fields and constructors properly. The error are in italics.Sorry i am new to coding and hopefully you can help me
import javax.swing.*;
import java.awt.*;
class Main extends JFrame {
class App extends JPanel {
Stage stage;
public App() {
setPreferredSize(new Dimension(900, 720));
stage = new Stage();
}
#Override
public void paint(Graphics g) {
*stage.paint(g, getMousePosition());*
}
}
public static void main(String[] args) throws Exception {
Main window = new Main();
window.run();
}
private Main() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
App canvas = new App();
this.setContentPane(canvas);
this.pack();
this.setVisible(true);
}
public void run() {
while (true) {
this.repaint();
}
}
}
import java.awt.*;
import java.util.Random;
public class Stage {
Grid grid;
Terrain sand;
Terrain oasis;
Terrain palm_tree;
Terrain wall;
Random RandomNo = new Random();
int number;
public Stage() {
grid = new Grid();
for(int i = 0;i<20;i++)
{
for (int j = 0; j < 20; j++) {
number = 1 + RandomNo.nextInt(10);
if (number <= 4) {
sand = new Sand(grid.cellAtColRow(i, j));
} else if (number == 1) {
oasis = new Oasis(grid.cellAtColRow(i, j));
} else if (number == 2) {
wall = new Wall(grid.cellAtColRow(i, j));
} else if (number == 3) {
palm_tree = new PalmTree(grid.cellAtColRow(i, j));
}
}
}
*public paint(Graphics g, Point mouseLoc){*
grid.paint(g, mouseLoc);
sand.paint(g);
oasis.paint(g);
wall.paint(g);
palm_tree.paint(g);
}
}
}
import java.awt.*;
class Grid {
//fields
Cell[][] cells = new Cell[20][20];
// constructor
public Grid(){
for(int i = 0; i < cells.length; i++){
for(int j = 0; j < cells[i].length; j++){
cells[i][j] = new Cell(10+35*i,10+35*j);
}
}
}
// methods
public void paint(Graphics g, Point mousePos){
for(int i = 0; i < cells.length; i++){
for(int j = 0; j < cells[i].length; j++){
cells[i][j].paint(g, mousePos);
}
}
}
public Cell cellAtColRow(int c, int r){
return cells[c][r];
}
}
import java.awt.*;
class Cell extends Rectangle {
// fields
static int size = 35;
//constructors
public Cell(int x, int y){
super(x,y,size,size);
}
//methods
void paint(Graphics g, Point mousePos){
if(contains(mousePos)){
g.setColor(Color.GRAY);
}
else {
g.setColor(Color.WHITE);
}
g.fillRect(x,y,size,size);
g.setColor(Color.BLACK);
g.drawRect(x,y,size,size);
}
public boolean contains(Point p){
if (p != null){
return super.contains(p);
} else {
return false;
}
}
}
Two problems...
First public paint(Graphics g, Point mouseLoc){ is not a valid declaration, you're missing the return type.
It should be public void paint(Graphics g, Point mouseLoc) {
Second, you have a misplaced }, which means that paint is actually been declared inside the constructor...
public Stage() {
grid = new Grid();
for(int i = 0;i<20;i++)
{
for (int j = 0; j < 20; j++) {
number = 1 + RandomNo.nextInt(10);
if (number <= 4) {
sand = new Sand(grid.cellAtColRow(i, j));
} else if (number == 1) {
oasis = new Oasis(grid.cellAtColRow(i, j));
} else if (number == 2) {
wall = new Wall(grid.cellAtColRow(i, j));
} else if (number == 3) {
palm_tree = new PalmTree(grid.cellAtColRow(i, j));
}
}
}
public paint(Graphics g, Point mouseLoc){
grid.paint(g, mouseLoc);
sand.paint(g);
oasis.paint(g);
wall.paint(g);
palm_tree.paint(g);
}
}
It should be more like...
public Stage() {
grid = new Grid();
for(int i = 0;i<20;i++)
{
for (int j = 0; j < 20; j++) {
number = 1 + RandomNo.nextInt(10);
if (number <= 4) {
sand = new Sand(grid.cellAtColRow(i, j));
} else if (number == 1) {
oasis = new Oasis(grid.cellAtColRow(i, j));
} else if (number == 2) {
wall = new Wall(grid.cellAtColRow(i, j));
} else if (number == 3) {
palm_tree = new PalmTree(grid.cellAtColRow(i, j));
}
}
}
}
public void paint(Graphics g, Point mouseLoc){
grid.paint(g, mouseLoc);
sand.paint(g);
oasis.paint(g);
wall.paint(g);
palm_tree.paint(g);
}
I have a 2D array of cell objects which contain a String variable for its "tileCode", when I set the active tile code with the keyboard and then click on the desired cell in the 2D array, it should change that cells tileCode to the current active tile. But after I click on the tile, it immediately switches back to its previous tile code and image.
By default, each tile is set to a floor.
public static JFrame frame = new JFrame("Tool");
public static Panel panel;
public Image wall, floor;
public int rows = 50;
public int cols = 50;
public int xCoor = 20;
public int yCoor = 20;
String activeKey = "f";
Image activeImage = floor;
//Arrays
Rectangle[][] recs = new Rectangle[rows][cols];
Cell[][] cells = new Cell[rows][cols];
public Set <Integer> keysDown = new HashSet<>();
public LevelDesignTool() {
loadImages();
panel = new Panel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1400, 1100);
frame.setFocusable(true);
frame.requestFocus();
frame.setVisible(true);
frame.getContentPane().add(panel);
KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
manager.addKeyEventDispatcher(this);
addMouseListener(this);
myThread thread = new myThread();
thread.start();
}
class Panel extends JPanel {
public void paintComponent(Graphics g) {
Graphics2D g2D = (Graphics2D)g;
//Loading array of Tile Types
ArrayList<String> TileTypes = new ArrayList<>();
try {
Scanner TileFileScanner = new Scanner(new File("TileTypes"));
while(TileFileScanner.hasNext()) {
TileTypes.add(TileFileScanner.nextLine());
}
}
catch(FileNotFoundException e) {
System.err.println("Tile Type file not found.");
}
g.setFont(new Font("Italic",Font.PLAIN, 25));
g.drawString("Press Enter to save to file.", 1050, 50);
//Tile Type key on the rigt side of the screen
int y = 550;
for(int i = 0; i < TileTypes.size(); i++) {
g.drawString(TileTypes.get(i), 1050, y);
y += 30;
}
//Creating 2D array of Rectangles
xCoor = 20;
for(int r = 0; r < rows; r++) {
yCoor = 20;
for(int c = 0; c < cols; c++) {
recs[r][c] = new Rectangle(xCoor, yCoor, 18, 18);
yCoor += 19;
}
xCoor += 19;
}
//Creating 2D array of cells
for(int r = 0; r < rows; r++) {
for(int c = 0; c < cols; c++) {
cells[r][c] = new Cell(recs[r][c], "f", activeImage);
xCoor += 21;
}
xCoor = 0;
yCoor += 21;
}
//Drawing cells
for(int r = 0; r < rows; r++) {
for(int c = 0; c < cols; c++) {
g.fillRect((int)cells[r][c].r.getX(), (int)cells[r][c].r.getY(), (int)cells[r][c].r.getWidth(), (int)cells[r][c].r.getHeight());
g.setColor(Color.BLACK);
}
}
//Drawing the images stored in each cell object
for(int r = 0; r < rows; r++) {
for(int c = 0; c < cols; c++) {
cells[r][c].image = floor;
g.drawImage(cells[r][c].getImage(), cells[r][c].getX(), cells[r][c].getY(), this);
}
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
for(int r = 0; r < rows; r++) {
for(int c = 0; c < cols; c++) {
if (cells[r][c].getRect().contains(e.getX(), e.getY())) {
cells[r][c].tileCode = activeKey;
cells[r][c].image = activeImage;
//System.out.println("click registered");
}
}
}
}
});
}
}
//Must have these implemeted because they are from an interface
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
public void update() throws Exception {
//System.out.println(cells[0][0].getTileCode());
//System.out.println(activeKey);
}
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(event.getID() == KeyEvent.KEY_PRESSED){
keysDown.add(event.getKeyCode());
if(event.getKeyCode() == KeyEvent.VK_F) {
activeKey = "f";
activeImage = floor;
}
if(event.getKeyCode() == KeyEvent.VK_E) {
activeKey = "e";
}
if(event.getKeyCode() == KeyEvent.VK_W) {
activeKey = "w";
activeImage = wall;
}
}
if(event.getID() == KeyEvent.KEY_RELEASED)
keysDown.remove(event.getKeyCode());
return false;
}
class myThread extends Thread {
public void run() {
while(true) {
try {
Thread.sleep(15);
frame.repaint();
update(); //update any game state changes for the next frame
}
catch(Exception e) {
System.out.println(e);
}
}
}
}
private void loadImages() {
floor = new ImageIcon("images/Floor.png").getImage();
wall = new ImageIcon("images/Wall.png").getImage();
}
//Runs code
public static void main(String[] args) {
new LevelDesignTool();
}
}
once I click on a cell, its image should change to the active image and the tile code should change to the active tile code.
problem is that you are initializing your data (and adding a new mouseListener) on every call to paintComponent. That resets all the data to "floor" every time it repaints, which overrides any change you made in the mouse listener. Also, notice that in your "Drawing cells" loop, you reset the image to floor (cells[r][c].image = floor;) just before you draw it. This again resets the data you set in your mouse listener.
The solution is to move your mouseListener and your initialization code into a constructor for Panel, like this:
class Panel extends JPanel {
ArrayList<String> TileTypes = new ArrayList<String>();
public Panel() {
//Loading array of Tile Types
try {
Scanner TileFileScanner = new Scanner(new File("TileTypes"));
while(TileFileScanner.hasNext()) {
TileTypes.add(TileFileScanner.nextLine());
}
} catch(FileNotFoundException e) {
System.err.println("Tile Type file not found.");
}
//Creating 2D array of Rectangles
xCoor = 20;
for(int r = 0; r < rows; r++) {
yCoor = 20;
for(int c = 0; c < cols; c++) {
recs[r][c] = new Rectangle(xCoor, yCoor, 18, 18);
yCoor += 19;
}
xCoor += 19;
}
//Creating 2D array of cells
for(int r = 0; r < rows; r++) {
for(int c = 0; c < cols; c++) {
cells[r][c] = new Cell(recs[r][c], "f", activeImage);
cells[r][c].image = floor;
xCoor += 21;
}
xCoor = 0;
yCoor += 21;
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
for(int r = 0; r < rows; r++) {
for(int c = 0; c < cols; c++) {
if (cells[r][c].getRect().contains(e.getX(), e.getY())) {
cells[r][c].tileCode = activeKey;
cells[r][c].image = activeImage;
//System.out.println("click registered");
}
}
}
}
});
}
public void paintComponent(Graphics g) {
Graphics2D g2D = (Graphics2D)g;
g.setFont(new Font("Italic",Font.PLAIN, 25));
g.drawString("Press Enter to save to file.", 1050, 50);
//Tile Type key on the rigt side of the screen
int y = 550;
for(int i = 0; i < TileTypes.size(); i++) {
g.drawString(TileTypes.get(i), 1050, y);
y += 30;
}
//Drawing cells
for(int r = 0; r < rows; r++) {
for(int c = 0; c < cols; c++) {
g.fillRect((int)cells[r][c].r.getX(), (int)cells[r][c].r.getY(),
(int)cells[r][c].r.getWidth(), (int)cells[r][c].r.getHeight());
g.setColor(Color.BLACK);
}
}
//Drawing the images stored in each cell object
for(int r = 0; r < rows; r++) {
for(int c = 0; c < cols; c++) {
g.drawImage(cells[r][c].getImage(), cells[r][c].getX(), cells[r][c].getY(), this);
}
}
}
}
Also, not part of your question, but you are discarding the interrupted exception in your thread. Do this instead:
public void run() {
while (!Thread.interrupted()) {
try {
Thread.sleep(15);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
I would first like to say that I have extensively looked into this over the past day and I haven't found anything that fits this particular case. I'm in the midst of trying to create a simply Conway's Game of Life Application, and I seem to be having trouble with drawing to a JavaFX Canvas. Everything seems to be configurerd correctly (Canvas added to a layout container, said container added to a scene, and the stage is started) but even after trying different ways of encapsultating the code the Canvas remains to be empty
Here is my code:
public class Life extends Application implements Runnable {
private Grid grid;
private boolean running;
private boolean paused;
private int stepsPerMinute;
#Override
public void start(Stage stage) {
this.grid = new Grid(60, 40);
this.running = true;
this.paused = false;
this.stepsPerMinute = 60;
StackPane root = new StackPane();
root.getChildren().add(grid);
Scene scene = new Scene(root, 1080, 720);
stage.setTitle("Conway's Game of Life");
stage.setScene(scene);
stage.setResizable(false);
stage.setOnCloseRequest(e -> stop());
stage.show();
}
public void run() {
while (running) {
if (!paused) {
try {
Thread.sleep(1000 / stepsPerMinute);
} catch (InterruptedException e) { e.printStackTrace(); }
grid.step();
grid.draw();
}
}
}
#Override
public void stop() {
this.running = false;
// TODO: Dump Stats at end
System.exit(0);
}
public static void main(String[] args) { launch(args); }
public class Grid extends Canvas {
private final int WIDTH = 1080, HEIGHT = 720;
private boolean[][] cellStates;
private int rows, cols;
private int stepNum;
public Grid(int rows, int cols) {
this.rows = rows;
this.cols = cols;
this.stepNum = 0;
randomize();
minWidth(WIDTH);
maxWidth(WIDTH);
prefWidth(WIDTH);
minHeight(HEIGHT);
maxHeight(HEIGHT);
prefHeight(HEIGHT);
}
public Grid(boolean[][] cellStates) {
this.cellStates = cellStates;
this.rows = cellStates.length;
this.cols = cellStates[0].length;
this.stepNum = 0;
}
public void step() {
boolean[][] updatedStates = new boolean[rows][cols];
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++) {
int aliveNeighbors = countAliveNeighbors(i, j);
if (cellStates[i][j]) {
if (aliveNeighbors == 2 || aliveNeighbors == 3)
updatedStates[i][j] = true;
}
else if (aliveNeighbors == 3)
updatedStates[i][j] = true;
}
this.cellStates = updatedStates;
stepNum++;
}
private int countAliveNeighbors(int r, int c) {
int result = 0;
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++) {
if (cellStates[ (rows + r + i) % rows ][ (cols + c + j) % cols ])
result++;
}
return result;
}
public void randomize() {
boolean[][] updatedStates = new boolean[rows][cols];
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++) {
if (Math.random() < 0.08)
updatedStates[i][j] = true;
}
this.cellStates = updatedStates;
}
public void glider(){
this.cellStates = new boolean[rows][cols];
this.cellStates[1][2] = true;
this.cellStates[2][3] = true;
this.cellStates[3][1] = true;
this.cellStates[3][2] = true;
this.cellStates[3][3] = true;
}
public void draw() {
GraphicsContext g = this.getGraphicsContext2D();
int cellWidth = WIDTH / cols, cellHeight = HEIGHT / rows;
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++) {
if (cellStates[i][j])
g.setFill(Color.color(0.0078, 0, 1));
else
g.setFill(Color.color(0.9961, 1, 0.8431));
g.fillRect(j * cellWidth, i * cellHeight, cellWidth, cellHeight);
g.strokeLine(j * cellWidth, 0, j * cellWidth, HEIGHT);
g.strokeLine(0, i * cellHeight, WIDTH, i * cellHeight);
}
}
}
}
I left the imports out of the code for sake of brevity.
Thank you!
I'm trying to make a Connect Four Game in Java by using user input and drawing panel. Two people switch off turns typing the column they want their piece to go in. I'm having trouble making it so discs already placed stay on the board the next turn (because the a new drawing panel pops up with the updated board each time)(we tried using GUI but failed). I am also having trouble switching off turns and making the color change each time. Thank you so much, here is what I have so far.
import java.util.*;
import java.awt.*;
public class ConnectFour{
public static void main(String[] args){
Scanner console = new Scanner(System.in);
char [][] board = new char [7][6];
for (int i = 0; i< 7; i++){
for (int j= 0; j< 6; j++){
board[i][j] = ' ';
}
}
boolean isBlack = true ; //black discs turn
boolean isRed = false ; //red discs turn
boolean playersTurn = true ;
while (playersTurn){
if (isBlack == true ){
System.out.println("Black's Turn");
}
else {
System.out.println("Red's Turn");
}
System.out.print("Choose a column to place your disk (1-7): ");
int column = console.nextInt()-1;
if (column < 0 || column > 7) { //while loop?
System.out.print( "Column needs to be within 1-7"); //try catch?
}
drawBoard(column, board, isBlack, isRed);
// connectedFour(board);
// playersTurn = !playersTurn;
}
// isBlack = !isBlack; INVERT WHOSE TURN IT IS!!! unreachable statement??
}
public static void drawBoard(int column, char [][] board, boolean isBlack, boolean isRed) {
DrawingPanel panel = new DrawingPanel(550,550);
int rowAvailable;
Graphics g = panel.getGraphics();
g.drawLine(0,0,0,500);
g.drawLine(0,0,500,0);
g.drawLine(500,0,500,427);
g.drawLine(0,427,500,427);
for (int i = 0; i< 6; i++){
for (int j= 0; j<= 6; j++){
g.setColor(Color.YELLOW);
g.fillRect(j*71,i*71,71,71);
g.setColor(Color.WHITE);
g.fillOval(j*71,i*71,71,71);
}
}
int x = 0;
int row = 5;
while (board[column][row-x] != ' '){
x++;
}
row = 5-x;
if (isBlack == true) {
g.setColor(Color.BLACK);
board[column][row-x] = 'b';
}
else {
g.setColor(Color.RED);
board[column][row-x] = 'r';
}
// I KNOW THIS FOR LOOP DOES NOT WORK SUCCESSFULLY
for (int i = 0; i< 6; i++){
for (int j= 0; j<= 6; j++){
if(board[i][j] != 'b'){
g.fillOval((i * 71),j*71, 71,71);
}
}
}
// g.fillOval((column * 71),row*71, 71,71); //number 142 is just a test
//board[i][j] = WHOSE TURN IT IS (to update array)
// if(isBlack){
// board[column][row] = 'b';
// }
// else{
// board[column][row] = 'r';
// }
}
//get whose turn it is as parameter?? a color string? boolean?
public static boolean connectedFour( char[][] board){
int verticalCount = 0;
for (int i = 0; i< 6; i++){ //goes down each column //EXCEPTION HERE BECAUSE 0
for( int j=0; j<=6; j++){
if (board[i][j]== board[i-1][j]){
verticalCount ++;
}
}
}
int horizontalCount = 0;
for (int i =0; i<=6; i++){
for (int j =0; j<6; j++){
if (board[i][j-1] == board[i][j]){
horizontalCount++;
}
}
}
int diagonalCount = 0;
//get diagonal here
if (verticalCount >= 4 || horizontalCount >= 4|| diagonalCount >=4){
return true ; //return who the winner is. String?
//
}
else {
return false ;
}
}
}
Don't mix console based input with GUI output, these are two different user paradigms which require different work flows and approaches to manage
Don't use getGraphics, this is not how painting works. Swing has a defined paint process which you should use to ensure you are been notified when an update needs to be performed. See Painting in AWT and Swing and Performing Custom Painting for more details.
The following is a very basic example of how you might work with the API, instead of against it.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.RoundRectangle2D;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class ConnectFour {
public static void main(String[] args) {
new ConnectFour();
}
public ConnectFour() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new GamePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public enum Player {
RED, BLUE, NONE;
}
public class GamePane extends JPanel {
private BoardPane boardPane;
private JLabel label;
private Player player = null;
public GamePane() {
setLayout(new BorderLayout());
boardPane = new BoardPane();
add(boardPane);
label = new JLabel("...");
label.setHorizontalAlignment(JLabel.CENTER);
label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setBorder(new EmptyBorder(10, 10, 10, 10));
add(label, BorderLayout.NORTH);
updatePlayer();
boardPane.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
updatePlayer();
}
});
}
protected void updatePlayer() {
String text = "...";
Color color = null;
if (player == null || player.equals(Player.BLUE)) {
player = Player.RED;
text = "Red";
color = Color.RED;
} else if (player.equals(Player.RED)) {
player = Player.BLUE;
text = "Blue";
color = Color.BLUE;
}
label.setText(text);
label.setBackground(color);
boardPane.setPlayer(player);
}
}
public class BoardPane extends JPanel {
private Player[][] board;
private Player player;
private int hoverColumn = -1;
public BoardPane() {
board = new Player[8][8];
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
board[row][col] = Player.NONE;
}
}
MouseAdapter mouseHandler = new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
hoverColumn = getColumnAt(e.getPoint());
repaint();
}
#Override
public void mouseExited(MouseEvent e) {
hoverColumn = -1;
repaint();
}
#Override
public void mouseClicked(MouseEvent e) {
if (hoverColumn > -1) {
addPieceTo(hoverColumn);
repaint();
}
}
};
addMouseMotionListener(mouseHandler);
addMouseListener(mouseHandler);
}
public void addChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
public void removeChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
public void setPlayer(Player player) {
this.player = player;
}
protected void addPieceTo(int col) {
boolean added = false;
if (col >= 0 && col < board[0].length) {
for (int row = 0; row < board.length; row++) {
if (board[row][col] != Player.NONE) {
if (row >= 0) {
board[row - 1][col] = player;
added = true;
}
break;
}
}
}
if (!added) {
if (board[0][col] == Player.NONE) {
board[board.length - 1][col] = player;
added = true;
}
}
if (added) {
fireStateChanged();
}
repaint();
}
protected void fireStateChanged() {
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
if (listeners != null && listeners.length > 0) {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
}
protected int getColumnAt(Point p) {
int size = Math.min(getWidth() - 1, getHeight() - 1);
int xOffset = (getWidth() - size) / 2;
int yOffset = (getHeight() - size) / 2;
int padding = getBoardPadding();
int diameter = (size - (padding * 2)) / 8;
int xPos = p.x - xOffset;
int column = xPos / diameter;
return Math.min(Math.max(0, column), board[0].length - 1);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected int getBoardPadding() {
return 10;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
int size = Math.min(getWidth() - 1, getHeight() - 1);
int xOffset = (getWidth() - size) / 2;
int yOffset = (getHeight() - size) / 2;
g2d.fill(new RoundRectangle2D.Double(xOffset, yOffset, size, size, 20, 20));
int padding = getBoardPadding();
int diameter = (size - (padding * 2)) / 8;
for (int row = 0; row < board.length; row++) {
int yPos = (yOffset + padding) + (diameter * row);
for (int col = 0; col < board[row].length; col++) {
int xPos = (xOffset + padding) + (diameter * col);
switch (board[row][col]) {
case RED:
g2d.setColor(Color.RED);
break;
case BLUE:
g2d.setColor(Color.BLUE);
break;
default:
g2d.setColor(getBackground());
break;
}
g2d.fill(new Ellipse2D.Double(xPos, yPos, diameter, diameter));
}
}
if (hoverColumn > -1) {
int yPos = (yOffset + padding) + (diameter * 0);
int xPos = (xOffset + padding) + (diameter * hoverColumn);
if (player != null) {
switch (player) {
case RED:
g2d.setColor(Color.RED);
break;
case BLUE:
g2d.setColor(Color.BLUE);
break;
default:
g2d.setColor(getBackground());
break;
}
g2d.fill(new Ellipse2D.Double(xPos, yPos, diameter, diameter));
}
}
g2d.dispose();
}
}
}