This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
issue with my main method in my connect4 game
Hi,
on my connect4 game, whenever i click on any square it places the oval on that specific square, how do i get it so that it places the oval on the lowest square in that column so that it can stack up?
package Game;
import java.util.ArrayList;
public class ConnectFourBoard {
// This constant is used to indicate the width and height, in cells,
// of the board. Since we want an 8x8 board, we'll set it to 8.
private static final int WIDTH = 8;
private static final int HEIGHT = 8;
private ConnectFourCell[][] currentPlayer;
// The current state the Othello board is defined with these two
// fields: a two-dimensional array holding the state of each cell,
// and a boolean value indicating whether it's the black player's
// turn (true) or the white player's turn (false).
private ConnectFourCell[][] cells;
private boolean isBlueTurn;
// Since the board is a model and it needs to notify views of changes,
// it will employ the standard "listener" mechanism of tracking a list
// of listeners and firing "events" (by calling methods on those
// listeners) when things change.
private ArrayList<ConnectFourListener> listeners;
public ConnectFourBoard()
{
// Arrays, in Java, are objects, which means that variables of
// array types (like cells, which has type OthelloCell[][]) are
// really references that say where an array lives. By default,
// references point to null. So we'll need to create an actual
// two-dimensional array for "cells" to point to.
cells = new ConnectFourCell[WIDTH][HEIGHT];
listeners = new ArrayList<ConnectFourListener>();
reset();
isBlueTurn = true;
}
public void reset(){
for (int i = 0; i<WIDTH ; i++){
for (int j = 0; j<HEIGHT; j++){
cells[i][j] = ConnectFourCell.NONE;
}
}
isBlueTurn = true;
}
public void addConnectFourListener(ConnectFourListener listener)
{
listeners.add(listener);
}
public void removeConnectFourListener(ConnectFourListener listener)
{
if (listeners.contains(listener))
{
listeners.remove(listener);
}
}
// These are fairly standard "fire event" methods that we've been building
// all quarter, one corresponding to each method in the listener interface.
private void fireBoardChanged()
{
for (ConnectFourListener listener : listeners)
{
listener.boardChanged();
}
}
private void fireGameOver()
{
for (ConnectFourListener listener : listeners)
{
listener.gameOver();
}
}
// isBlackTurn() returns true if it's the black player's turn, and false
// if it's the white player's turn.
public boolean isBlueTurn()
{
return isBlueTurn;
}
public int getWidth()
{
return WIDTH;
}
public int getHeight(){
return HEIGHT;
}
// getBlackScore() calculates the score for the black player.
public int getBlackScore()
{
return getScore(ConnectFourCell.BLUE);
}
// getWhiteScore() calculates the score for the white player.
public int getWhiteScore()
{
return getScore(ConnectFourCell.RED);
}
// getScore() runs through all the cells on the board and counts the
// number of cells that have a particular value (e.g., BLACK or WHITE).
// This method uses the naive approach of counting them each time
// it's called; it might be better to keep track of this score as we
// go, updating it as tiles are added and flipped.
private int getScore(ConnectFourCell cellValue)
{
int score = 0;
for (int i = 0; i < WIDTH; i++)
{
for (int j = 0; j < HEIGHT; j++)
{
if (cells[i][j] == cellValue)
{
score++;
}
}
}
return score;
}
// getWhiteScore() calculates the score for the white player.
public int getRedScore()
{
return getScore(ConnectFourCell.RED);
}
public int getBlueScore() {
// TODO Auto-generated method stub
return getScore(ConnectFourCell.BLUE);
}
public ConnectFourCell getCell(int x, int y)
{
if (!isValidCell(x, y))
{
throw new IllegalArgumentException(
"(" + x + ", " + y + ") is not a valid cell");
}
return cells[x][y];
}
/**
* The drop method.
*
* Drop a checker into the specified HEIGHT,
* and return the WIDTH that the checker lands on.
*/
int drop(int HEIGHT) {
if (hasWon()) {
return -1;
}
for ( ; WIDTH<6 && HEIGHT != 0; WIDTH++) { };
if (WIDTH==6) {
// if the WIDTH is 6, it went through all 6 WIDTHs
// of the cells, and couldn't find an empty one.
// Therefore, return false to indicate that this
// drop operation failed.
return -1;
}
// fill the WIDTH of that HEIGHT with a checker.
cells[HEIGHT][WIDTH] = currentPlayer[HEIGHT][WIDTH];
// alternate the players
//currentPlayer = (currentPlayer%2)+1;
return WIDTH;
}
/**
* The toString method
*
* Returns a String representation of this
* Connect Four (TM) game.
*/
public String toString() {
String returnString = "";
for (int WIDTH=5; WIDTH>=0; WIDTH--) {
for (int HEIGHT=0; HEIGHT<7; HEIGHT++) {
returnString = returnString + cells[HEIGHT][WIDTH];
}
returnString = returnString + "\n";
}
return returnString;
}
/**
* The hasWon method.
*
* This method returns true if one of the
* players has won the game.
*/
public boolean hasWon()
{
// First, we'll establish who the current player and the opponent is.
//ConnectFourCell
ConnectFourCell myColor =
isBlueTurn() ? ConnectFourCell.BLUE : ConnectFourCell.RED;
ConnectFourCell otherColor =
isBlueTurn() ? ConnectFourCell.RED : ConnectFourCell.BLUE;
return true;
}
public void validMove( ){
}
public void makeAMove(int x, int y){
//System.out.println(x+" "+y);
// cells[x][y] = ConnectFourCell.BLUE;
//Check who's turn it is. Set to that color.
ConnectFourCell myColor = null;
if ( isBlueTurn == true){
myColor = myColor.BLUE;
}
else {
myColor = myColor.RED;
}
cells[x][y] = myColor;
//Check if it's a valid move. If there is a piece there. can't
// Look at the column. play piece in the highest available slot
//Check if there are 4 in a row.
for (int WIDTH=0; WIDTH<6; WIDTH++) {
for (int HEIGHT=0; HEIGHT<4; HEIGHT++) {
if (!(cells[HEIGHT][WIDTH] == ConnectFourCell.NONE) &&
cells[HEIGHT][WIDTH] == cells[HEIGHT+1][WIDTH] &&
cells[HEIGHT][WIDTH] == cells[HEIGHT+2][WIDTH] &&
cells[HEIGHT][WIDTH] == cells[HEIGHT+3][WIDTH]) {
}
}
}
// check for a vertical win
for (int WIDTH=0; WIDTH<3; WIDTH++) {
for (int HEIGHT=0; HEIGHT<7; HEIGHT++) {
if (!(cells[HEIGHT][WIDTH] == ConnectFourCell.NONE) &&
cells[HEIGHT][WIDTH] == cells[HEIGHT][WIDTH+1] &&
cells[HEIGHT][WIDTH] == cells[HEIGHT][WIDTH+2] &&
cells[HEIGHT][WIDTH] == cells[HEIGHT][WIDTH+3]) {
}
}
}
// check for a diagonal win (positive slope)
for (int WIDTH=0; WIDTH<3; WIDTH++) {
for (int HEIGHT=0; HEIGHT<4; HEIGHT++) {
if (!(cells[HEIGHT][WIDTH] == ConnectFourCell.NONE) &&
cells[HEIGHT][WIDTH] == cells[HEIGHT+1][WIDTH+1] &&
cells[HEIGHT][WIDTH] == cells[HEIGHT+2][WIDTH+2] &&
cells[HEIGHT][WIDTH] == cells[HEIGHT+3][WIDTH+3]) {
}
}
}
// check for a diagonal win (negative slope)
for (int WIDTH=3; WIDTH<6; WIDTH++) {
for (int HEIGHT=0; HEIGHT<4; HEIGHT++) {
if (!(cells[HEIGHT][WIDTH] == ConnectFourCell.NONE) &&
cells[HEIGHT][WIDTH] == cells[HEIGHT+1][WIDTH-1] &&
cells[HEIGHT][WIDTH] == cells[HEIGHT+2][WIDTH-2] &&
cells[HEIGHT][WIDTH] == cells[HEIGHT+3][WIDTH-3]) {
}
}
}
fireBoardChanged();
isBlueTurn = !isBlueTurn;
}
private boolean isValidCell(int x, int y)
{
return x >= 0 && x < WIDTH
&& x>= 0 && x<HEIGHT
&& y >= 0 && y < WIDTH
&& y>= 0 && y<HEIGHT;
}
}
package UI;
import java.awt.*;
import javax.swing.*;
import UI.ConnectFourBoardPanel;
import Game.ConnectFourBoard;
import Game.ConnectFourListener;
public class ConnectFourFrame extends JFrame implements ConnectFourListener {
// Variables
private ConnectFourBoard board;
private JLabel scoreLabel;
private ConnectFourBoardPanel boardPanel;
private JLabel statusLabel;
public ConnectFourFrame()
{
// The frame builds its own model.
board = new ConnectFourBoard();
// We want the frame to receive notifications from the board as its
// state changes.
System.out.println(this);
board.addConnectFourListener(this);
setTitle("Informatics 45 Spring 2011: ConnectFour Game");
setSize(700, 700);
setResizable(true);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
getContentPane().setBackground(Color.BLACK);
buildUI();
refreshUI();
}
private void buildUI()
{
GridBagLayout layout = new GridBagLayout();
getContentPane().setLayout(layout);
Font labelFont = new Font("SansSerif", Font.BOLD, 18);
scoreLabel = new JLabel();
scoreLabel.setForeground(Color.WHITE);
scoreLabel.setFont(labelFont);
layout.setConstraints(
scoreLabel,
new GridBagConstraints(
0, 0, 1, 1, 1.0, 0.0,
GridBagConstraints.CENTER,
GridBagConstraints.NONE,
new Insets(10, 10, 10, 10), 0, 0));
getContentPane().add(scoreLabel);
boardPanel = new ConnectFourBoardPanel(board);
layout.setConstraints(
boardPanel,
new GridBagConstraints(
0, 1, 1, 1, 1.0, 1.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets(10, 10, 10, 10), 0, 0));
getContentPane().add(boardPanel);
statusLabel = new JLabel();
statusLabel.setForeground(Color.WHITE);
statusLabel.setFont(labelFont);
layout.setConstraints(
statusLabel,
new GridBagConstraints(
0, 2, 1, 1, 1.0, 0.0,
GridBagConstraints.CENTER,
GridBagConstraints.NONE,
new Insets(10, 10, 10, 10), 0, 0));
getContentPane().add(statusLabel);
}
private void refreshUI()
{
// Refreshing the UI means to change the text in each of the
// two labels (the score and the status) and also to ask the
// board to repaint itself.
scoreLabel.setText(
"Blue: " + board.getBlueScore() +
" Red: " + board.getRedScore());
if ( board.isBlueTurn() == false){
statusLabel.setText("Blue's Turn: ");
}
if ( board.isBlueTurn() == true){
statusLabel.setText("Red's Turn: ");
}
boardPanel.repaint();
}
// These are the ConnectFourBoardListener event-handling methods.
public void boardChanged()
{
// When the board changes, we'll refresh the entire UI. (There
// are times when this approach is too inefficient, but it will
// work fine for our relatively simple UI.)
refreshUI();
}
public void gameOver()
{
// When the game is over, we'll pop up a message box showing the final
// score, then, after the user dismisses the message box, dispose of
// this window and end the program.
JOptionPane.showMessageDialog(
this,
"Game over!\nFinal score: " + scoreLabel.getText(),
"Game Over",
JOptionPane.INFORMATION_MESSAGE);
dispose();
}
}
Welcome to StackOverflow. You're question is fine - but pasting your whole program, in general, is a bad idea. You should describe your program, and include the snippet where you calculate how the ovals are filled in.
Having said that, here's a crack at the answer :
- You want to look at the tile thats currently selected, and if the tile underneath it is occupied, fill in that cell. If its not occupied, set the current tile to the underneath tile, and repeat. You want to do this until you get to the bottom row.
The answer above doesn't incude checking if the selected tile is already occupied, but I'm sure you can easily figure that out.
Related
I am creating a TicTacToe game with 2 boards, only one is playable to the user. If a user clicks on cell[2][3] on grid 1 a token will be drawn on grid 1 and on cells[2][3] on grid 2. I was thinking of using a HashMap to assign indexes to each cell. Like cell[2][3] and cells[2][3] would each be assigned to index 9. How would I implement this is my code? Would I even use a Hashmap for what I am trying to do? I am unfamiliar with this concept so I might just be overthinking this.
Note: Cell[][] is the cells for grid 1 and Cells[][] are for grid 2. Cells[][] have randomized indexes in it so it can be randomly assigned to the board.
Edit: If I want to link cell(2)(3) and cells(2)(3) I would change integer to Cell when I initialize hashmap. Then I would do HMap. put(cell[2][3], cells[2][3]) right?
Code:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.border.LineBorder;
import java.util.Random;
import java.util.HashMap;
public class Bull extends JFrame{
private char currentPlayer = ' ';
// Creates array of cells called Cell[][] cell
private Cell[][] cell = new Cell[3][3];
// Creates array of cells called Sale[][] cells
private Cells[][] cells = new Cells[3][3];
// Creates a boolean array
private boolean t[][] = new boolean[3][3];
// Creates index array
private int z[] = new int[8];
//Initializes Random
Random rand = new Random();
// Initializes variables which will be used to create random ints
int f;
int g;
// Initializes JlblStatus
private JLabel jlblStatus = new JLabel(" ");
private JLabel jlblIndex = new JLabel(" ");
// Method that builds the JFrame and JPanels
public Bull(){
// Do I change Integer to array?
HashMap<Integer, Integer> HMap = new HashMap<Integer, Integer>();
// Title of the JFrame
JFrame frame = new JFrame("Shadow Tic Tac Toe Game");
// Makes the JFrame full screen
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
// If x button is clicked than the JFrame closes
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Initializes JPanel1
JPanel panel1 = new JPanel();
// Initializes JPanel2
JPanel panel2 = new JPanel();
// Adds panel1 which will hold the first TicTacToe game.
panel1.setLayout(new GridLayout(3,3,0,0));
for(int d = 0; d < 3; d++){
for(int c = 0; c < 3; c++){
panel1.add(cell[d][c] = new Cell());
// Sets size of the cells in JPanel1
cell[d][c].setPreferredSize(new Dimension(250,250));
}
}
panel2.setLayout(new GridLayout(3,3,0,0));
int n = 0;
while(n < 9){
f=rand.nextInt(3);
g=rand.nextInt(3);
while(t[f][g] == false){
t[f][g] = true;
panel2.add(cells[f][g] = new Cells());
cells[f][g].setPreferredSize(new Dimension(250,250));
System.out.println(f);
System.out.println("\t" + g);
n++;
}
}
// Adds Panel1 to the JFrame
frame.add(panel1, BorderLayout.WEST);
// Adds Panel2 to the JFrame
frame.add(panel2, BorderLayout.EAST);
// Updates the status of the game here (win/lose/draw/whose turn it is
frame.add(jlblStatus, BorderLayout.SOUTH);
// Sets size of the message area at the bottom of the frame
jlblStatus.setPreferredSize(new Dimension(100,100));
// Shows the Instructions of the game
Instructions();
// Calls method Chose() which allows the player to chose which token they will play as
Chose();
frame.pack();
// Sets it so the JFrame is visible to the user
frame.setVisible(true);
}
// Method that creates the Instructions for the game. Will be shown to the user prior to the user picking his token
public void Instructions(){
JOptionPane.showMessageDialog(null,"INSTRUCTIONS" + "\nThis game is called a 'Shadow Tic Tac Toe Game'. In this game there will be two Tic Tac Toe game boards, though only one is playable. \nBut you can win on either board. Lets say you place your token on the center tile at cell(2,3). \nAn X will be drawn on that spot on board 1 and on a randomized spot on the second game board at cell(2,3). \nYou will be able to see the cell indexes before you click on a cell so you can form a strategy");
}
// Method that lets the user chose his/her token
public void Chose(){
int f = 2;
// While f == 2 the loop will run
while(f == 2){
String input = JOptionPane.showInputDialog("CHOSE" + "\nPlease select your token. \nPress 1 for X and 2 for O.");
// Reads in the user input. Input put into a variable called pawn
int pawn = Integer.parseInt(input);
// If user input 1 his/her token will be X. F will equal 3 so the loop does not run again
if(input.equals("1")){
currentPlayer = 'X';
f = 3;
// If user input 2 his/her token will be O. F will equal 3 so the loop does not run again
}else if(input.equals("2")){
currentPlayer = 'O';
f = 3;
// If user does not enter in either a 1 or 2 an error message will appear. f wil equal 2 so the loop runs again and asks the user to chose his/her token again
}else{
JOptionPane.showMessageDialog(null,"ERROR INVALID RESPONSE");
f = 2;
}
}
}
public class Cells extends JPanel{
private char tok = ' ';
public Cells(){
// Sets the border for the cells to the color black
setBorder(new LineBorder(Color.black,1));
}
public void setTok(char d){
tok = d;
repaint();
}
public char getTok(){
return tok;
}
protected void Paint(Graphics g){
super.paint(g);
if(tok == 'X'){
g.drawLine(10,10,getWidth() - 10, getHeight()-10);
g.drawLine(getWidth()-10,10,10,getHeight()-10);
}else if (tok == 'O'){
g.drawOval(10,10,getWidth()-20, getHeight()-20);
}
}
}
public class Cell extends JPanel{
private char token = ' ';
public void setToken(char c){
token = c;
repaint();
}
public char getToken(){
return token;
}
public Cell(){
// Sets the border for the cells to the color black
setBorder(new LineBorder(Color.black, 1));
addMouseListener(new MyMouseListener());
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (token == 'X') {
g.drawLine(10,10, getWidth() - 10, getHeight() - 10);
g.drawLine(getWidth() - 10,10,10, getHeight() - 10);
}
else if (token == 'O') {
g.drawOval(10, 10, getWidth() - 20, getHeight() - 20);
}
}
private class MyMouseListener extends MouseAdapter{
public void mouseClicked(MouseEvent e){
// If cell is empty and game is not over
if (token == ' ' && currentPlayer != ' ') {
setToken(currentPlayer); // Set token in the cell
for(int d = 0; d < 3; d++){
for(int c = 0; c < 3; c++){
if(cell[d][c].getToken() == 'X'){
cells[d][c].setTok('X');
}else if(cell[d][c].getToken() == 'O'){
cells[d][c].setTok('O');
}else if(cell[d][c].getToken() == ' '){
cells[d][c].setTok(' ');
}
}
}
//setTok(currentPlayer);
if(Won(currentPlayer)){
jlblStatus.setText("The game is over! " + currentPlayer + " won the game! Congragulations " + currentPlayer + " !");
currentPlayer = ' ';
}else if(Full()){
jlblStatus.setText("The game is over, it ends in a draw!");
currentPlayer = ' ';
}else{
if(currentPlayer == 'X'){
currentPlayer = 'O';
}else{
currentPlayer = 'X';
}
jlblStatus.setText("It is " + currentPlayer + " 's turn");
}
}
}
}
}
public boolean Full(){
for(int d = 0; d < 3; d++)
for(int c = 0; c < 3; c++)
if(cell[d][c].getToken() == ' ')
return false;
return true;
}
public boolean Won(char token){
for(int d = 0; d < 3; d++){
if(cell[d][0].getToken() == token && cell[d][1].getToken() == token && cell[d][2].getToken() == token){
return true;
}
}
for(int c = 0; c < 3; c++){
if(cell[0][c].getToken() == token && cell[1][c].getToken() == token && cell[2][c].getToken() == token){
return true;
}
}
if(cell[0][0].getToken() == token && cell[1][1].getToken() == token && cell[2][2].getToken() == token){
return true;
}
if(cell[0][2].getToken() == token && cell[1][1].getToken() == token && cell[2][0].getToken() == token){
return true;
}
return false;
}
public static void main(String [] args){
new Bull();
}
}
So essentially you want to map a cell on one grid (that the player can play on) to some cell on another grid (the shadow grid)?
You could do this just using another 2D array that stores what indices a cell maps to in the other grid, but you would need to return a point object containing x and y coordinates. But that method is sorta annoying to keep track of and has its limitations.
If you want to do it with a HashMap<Point, Point> of one Point in one grid to a Point in another grid, then you would have to override hashCode() and equals() of Point and do something like this:
HashMap<Point, Point> mapPointToPoint = new HashMap<>();
// (0,0) maps to shadow grid (1,2)
mapPointToPoint.put(new Point(0,0), new Point(1,2));
mapPointToPoint.put(new Point(0,1), new Point(2,1));
// ... more mappings for all the cells
// to get
Point pointInPlayableGrid = new Point(0,0);
Point pointInShadowGrid = mapPointToPoint.get(pointInPlayableGrid);
// pointInShadowGrid == (1,2) since that's what it was mapped to
However, if you wanted to have multiple shadow grids then you'd need to have a map from points in the playable grid to the points in the shadow grids for each shadow grid.
So instead, since you already have the Cell class, why not just have each Cell store a List<Cell> of all the cells that it maps to. This is also very flexible because you could even have a single playable Cell map to multiple cells in a single shadow grid, and on hover of the playable Cell you could just go through the list of shadow Cells it maps to and highlight them too.
public class Cell extends JPanel{
private Cell shadowCell;
public void setCellThisMapsTo(Cell otherCell){ this.shadowCell = otherCell; }
public Cell getCellThisMapsTo(){ return shadowCell; }
// ... all the other stuff
}
// ... wherever you initialize the playable and shadow grid
// get a list of the shadow Cells, randomized order
Cell[][] shadowGrid; // however you init this
Cell[][] playableGrid; // however you init this
LinkedList<Cell> shadowCells = new LinkedList<>();
for(int x = 0; x < 3; x++){
for(int y = 0; y < 3; y++){
shadowCells.add(shadowGrid[x][y]);
}
}
Collections.shuffle(shadowCells);
for(int x = 0; x < 3; x++){
for(int y = 0; y < 3; y++){
Cell playableCell = playableGrid[x][y];
Cell shadowCell = shadowCells.removeFirst();
playableCell.setCellThisMapsTo(shadowCell );
}
}
// Now all the playable cells map to a random shadow cell
Cell playableCell = playableGrid[0][0];
Cell shadowCell = playableCell.getCellThisMapsTo();
The shadow Cells will not map to any other cells, so shadowCell.getCellThisMapsTo() would return null. But this method would makes it easy to map playable cells to shadow cells and keep track of them, without even using a HashMap nor having to keep track of Points mapping to Points.
Here is my definition for Point. If you want to put something in a hash map based on its values (rather than its object reference), then it is important to override hashCode() and equals():
class Point {
public final int x;
public final int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
// !!! OVERRIDE hashCode() and equals() so you can use this properly in a HashMap !!!
#Override
public int hashCode() {
int hash = 7;
hash = 71 * hash + this.x;
hash = 71 * hash + this.y;
return hash;
}
#Override
public int equals(Object o) {
if (obj == null)
return false;
if (this == obj)
return true;
if (getClass() != o.getClass())
return false;
Point p = (Point) o;
return this.x == p.x && this.y == p.y;
}
}
I am trying to make a replica of the Game of Life using swing, I admit i have used code from some 1 else as i am trying to get my head around it and then proceed with my own implementation. I have some understanding of their code, yet i wanted to implements 2 additional features to their code. However i am finding that the way it is written is posing problems as i wanted to add a MouseListener(To make a cell come to life when clicked) and WindowListener(To make a start,pause and resume button).
I do understand how they work to some extent, yet i need your help to get my headaround it.
Here is the code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.Transient;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
#SuppressWarnings("serial")
public class ConwaysGameOfLife extends JPanel implements MouseListener{
private int[][] cellsGrid; // grid is the size of the 2d array
private static final Random rnd = new Random(); // make a new random generator
private int generationCounter; // counter for the generation
public ConwaysGameOfLife(int width, int height) {
this.cellsGrid = new int[width / 4][height / 4];// divides by 4 whatever the width and height set is
setupGrid();
}// new method for creating the game with input sizes for the size of the game window
/*The grid consists fully of cells, the grid size is divided by 4 to make the cells
* setupGrid makes the grid of cells
*
* */
private void setupGrid() {
for (int[] row : cellsGrid) {
for (int j = 0; j < row.length; j++) {
if (rnd.nextDouble() < 0.92)
continue;
row[j] = rnd.nextInt(2);
//
}
}
}
/*
* applies the rule to the existing cells changing their state depending on the position to neighbors set in the rules
* */
public void updateGrid() {
for (int i = 0; i < cellsGrid.length; i++) {
for (int j = 0; j < cellsGrid[i].length; j++) {
applyRule(i, j);
}
}
}
// Rules of game of life cells iterations
private void applyRule(int i, int j) {
int left = 0, right = 0, up = 0, down = 0;
int dUpperLeft = 0, dUpperRight = 0, dLowerLeft = 0, dLowerRight = 0;
//this shows the 8 possible neighbors in terms of position
if (j < cellsGrid.length - 1) {
right = cellsGrid[i][j + 1];
if(i>0)
dUpperRight = cellsGrid[i - 1][j + 1];
if (i < cellsGrid.length - 1)
dLowerRight = cellsGrid[i + 1][j + 1];
}
if (j > 0) {
left = cellsGrid[i][j - 1];
if (i > 0)
dUpperLeft = cellsGrid[i - 1][j - 1];
if (i< cellsGrid.length-1)
dLowerLeft = cellsGrid[i + 1][j - 1];
}
if (i > 0)
up = cellsGrid[i - 1][j];
if (i < cellsGrid.length - 1)
down = cellsGrid[i + 1][j];
int sum = left + right + up + down + dUpperLeft + dUpperRight
+ dLowerLeft
+ dLowerRight;
if (cellsGrid[i][j] == 1) {
if (sum < 2)
cellsGrid[i][j] = 0;
if (sum > 3)
cellsGrid[i][j] = 0;
}
else {
if (sum == 3)
cellsGrid[i][j] = 1;
}
}
#Override
#Transient
public Dimension getPreferredSize() {
return new Dimension(cellsGrid.length * 4, cellsGrid[0].length * 4);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Color gColor = g.getColor();
g.drawString("Generation: " + generationCounter++, 0, 10);
for (int i = 0; i < cellsGrid.length; i++) {
for (int j = 0; j < cellsGrid[i].length; j++) {
if (cellsGrid[i][j] == 1) {
g.setColor(Color.black); // change colour
g.fillRect(j * 8, i * 8, 8, 8); // change size of cells
}
}
}
g.setColor(gColor);
//paint the cells to a colour
}
public static void main(String[] args) {
final ConwaysGameOfLife c = new ConwaysGameOfLife(800, 800);
JFrame frame = new JFrame();
frame.getContentPane().add(c);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setVisible(true);
JButton start=new JButton("START");
/* This method specifies the location and size
* of button. In method setBounds(x, y, width, height)
* x,y) are cordinates from the top left
* corner and remaining two arguments are the width
* and height of the button.
*/
start.setBounds(80,0,80,20);
//Adding button onto the frame
//frame.add(start);
new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.add(start);
c.updateGrid();
c.repaint();
}
}).start();
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
}
First of all, The button flickers, and only appears when hovered over with the mouse, still flickering. Then i want the iterations to begin after start button is pressed, and pause button to pause it, and resume(Have a decent idea how it would work, but not how to implement it with the structure of swing that is done in this code.)
Secondly, I wanted the cells to come to life when they are pressed with the mouse, But, i am unsure how to implement the mouseListener to do this.
I tried something like cellsGrid[i][j] = 1; when clicked by mouse but i get errors, which is due to my lack of understanding of the implementation of cellsGrid.
I am not expecting solutions to the problem, I would like some guidance to understand the Listeners better and maybe how to make this simpler to understand for me. Thank You :)
Your simulation has a model that is a grid of cells; it has a view that paints an 8 x 8 square to represent a cell in the grid. As suggested here, you can map model and view coordinates using linear interpolation. In particular, given the following proportions, you can cross-multiply and solve for the missing coordinate.
view.x : panelWidthInPixels :: model.x : modelXRange
view.y : panelHeightInPixels :: model.y : modelYRange
For reference, this complete example maps mouse coordinates to pixel coordinates in an image. A complete example of John Conway’s Game of Life in Java Swing is cited here.
Hey everyone thanks for all the help so far !. I have finally finished this project and it runs fine in eclipse but when I export it I get this error from stack trace also any help on how this could be improved in terms of architecture is much appreciated.
Exception is Exception in thread "LWJGL Application" com.badlogic.gdx.utils.GdxRuntimeExcepti
on: com.badlogic.gdx.utils.GdxRuntimeException: File not found: assets\font.fnt
It runs fine in eclipe but fails when exported
public class ConnectFourApplication extends Game implements ApplicationListener {
private Screen screen;
private Game game;
public static void main(String[] args) {
new LwjglApplication(new ConnectFourApplication(), "PennyPop", 1280, 720,
true);
}
public ConnectFourApplication(){
game = this;
}
#Override
public void create() {
screen = new MainScreen(game);
setScreen(screen);
screen.show();
}
#Override
public void dispose() {
screen.hide();
screen.dispose();
}
/** Clears the screen with a white color */
private void clearWhite() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}
#Override
public void pause() {
screen.pause();
}
#Override
public void render() {
clearWhite();
super.render();
}
#Override
public void resize(int width, int height) {
screen.resize(width, height);
}
#Override
public void resume() {
screen.resume();
}
public class MainScreen implements Screen {
private final Stage stage;
private final SpriteBatch spriteBatch;
//Parameter for drawing the buttons
private final BitmapFont font;
private final TextureAtlas buttons;
private final Button SFXButton;
private final Button APIButton;
private final Button GameButton;
private final Skin images;
//Parameter for Sound
private final com.badlogic.gdx.audio.Sound SFXClick;
//Parameter for the api call
private final String WeatherUrl;
private final HttpRequest request;
private final City SanFrancisco;
//The screen to load after the game button is hit
private Screen gamescreen;
private Game game;
public MainScreen(Game game) {
this.game = game;
//Set up our assets
spriteBatch = new SpriteBatch();
stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false, spriteBatch);
font = new BitmapFont(Gdx.files.internal("assets/font.fnt"),
Gdx.files.internal("assets/font.png"), false);
buttons = new TextureAtlas("assets/GameButtons.pack");
images = new Skin(buttons);
images.addRegions(buttons);
SFXButton = new Button(images.getDrawable("sfxButton"));
SFXButton.setPosition(295, 310);
APIButton = new Button(images.getDrawable("apiButton"));
APIButton.setPosition(405, 310);
GameButton = new Button(images.getDrawable("gameButton"));
GameButton.setPosition(515, 310);
SFXClick = Gdx.audio.newSound(Gdx.files.internal("assets/button_click.wav"));
//Add our actors to the stage
stage.addActor(SFXButton);
stage.addActor(APIButton);
stage.addActor(GameButton);
//Set up our Url request to be used when clicking the button
WeatherUrl = "http://api.openweathermap.org/data/2.5/weather?q=San%20Francisco,US";
request = new HttpRequest(HttpMethods.GET);
request.setUrl(WeatherUrl);
SanFrancisco = new City("Unavailable","Unavailable","0","0"); //init san fran to be displayed before they have clicked the button
}
#Override
public void dispose() {
spriteBatch.dispose();
stage.dispose();
}
#Override
public void render(float delta) {
stage.act(delta);
stage.draw();
//Begin sprite batch
spriteBatch.begin();
//Set our on click listeners for our buttons
if (SFXButton.isPressed())
SFXClick.play();
if(APIButton.isPressed())
{
CallApi();
}
if(GameButton.isPressed())
LoadGame();
//Set font color and render the screen
font.setColor(Color.RED);
font.draw(spriteBatch, "PennyPop", 455 - font.getBounds("PennpyPop").width/2,
460 + font.getBounds("PennyPop").height/2);
font.setColor(Color.BLACK);
font.draw(spriteBatch, "Current Weather", 900 - font.getBounds("PennpyPop").width/2,
460 + font.getBounds("PennyPop").height/2);
font.setColor(Color.LIGHT_GRAY);
font.draw(spriteBatch, SanFrancisco.Name, 940 - font.getBounds("PennpyPop").width/2,
420 + font.getBounds("PennyPop").height/2);
font.setColor(Color.RED);
font.draw(spriteBatch, SanFrancisco.CurrentCondition, 950 - font.getBounds("PennpyPop").width/2,
300 + font.getBounds("PennyPop").height/2);
font.draw(spriteBatch, SanFrancisco.Temperature + " Degrees,", 920 - font.getBounds("PennpyPop").width/2,
270 + font.getBounds("PennyPop").height/2);
font.draw(spriteBatch, SanFrancisco.WindSpeed, 1200 - font.getBounds("PennpyPop").width/2,
270 + font.getBounds("PennyPop").height/2);
//End or sprite batch
spriteBatch.end();
}
//Handles calling our API
public void CallApi(){
//Sends our stored HTTPRequest object
Gdx.net.sendHttpRequest(request, new HttpResponseListener() {
#Override
public void handleHttpResponse(HttpResponse httpResponse) {
//Uses our private response reader object to give us a the JSON from the api call
JSONObject json = HttpResponseReader(httpResponse);
//Gets the name of the city
SanFrancisco.Name = (String) json.get("name");
//Parsed through our returned JSON for the weather key
JSONArray WeatherArray = (JSONArray) json.get("weather");
//Gets the actual weather dictionary
JSONObject Weather = (JSONObject) WeatherArray.get(0);
//Finally get the value with the key of description and assign it
//To the San Fran current conditions field
SanFrancisco.CurrentCondition = (String) Weather.get("description");
//Gets the actual main dictionary
JSONObject main = (JSONObject) json.get("main");
//Finally get the values based on the keys
SanFrancisco.Temperature = (String) Double.toString((double) main.get("temp"));
//Finally get the wind speed
JSONObject wind = (JSONObject) json.get("wind");
SanFrancisco.WindSpeed = (String) Double.toString((double) wind.get("speed"));
}
#Override
public void failed(Throwable t) {
Gdx.app.log("Failed ", t.getMessage());
}
});
}
//When the button game button is clicked should load the connect four game
public void LoadGame(){
game.setScreen(new GameScreen(game));
}
//Converts our HttpResponse into a JSON OBject
private static JSONObject HttpResponseReader(HttpResponse httpResponse){
BufferedReader read = new BufferedReader(new InputStreamReader(httpResponse.getResultAsStream()));
StringBuffer result = new StringBuffer();
String line = "";
try {
while ((line = read.readLine()) != null) {
result.append(line);
}
JSONObject json;
try {
json = (JSONObject)new JSONParser().parse(result.toString());
return json;
} catch (ParseException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
public void resize(int width, int height) {
stage.setViewport(width, height, false);
}
#Override
public void hide() {
Gdx.input.setInputProcessor(null);
}
#Override
public void show() {
Gdx.input.setInputProcessor(stage);
render(0);
}
#Override
public void pause() {
// Irrelevant on desktop, ignore this
}
#Override
public void resume() {
// Irrelevant on desktop, ignore this
}
public class GameScreen implements Screen {
//Our stage and sprites
private final Stage gamestage;
private final SpriteBatch gamesprites;
//Parameter for drawing the pieces
private final BitmapFont gamefont;
private final TextureAtlas pieces;
private final Skin piecesskin;
//this will be the sprite and texture for our red connect four buttons
private Texture redtexture;
private Sprite redsprite;
//this will be the sprite and texture for our red connect four buttons
private Texture yellowtexture;
private Sprite yellowsprite;
//Setup the board
//renders the line
private ShapeRenderer boardlineshape;
//setup the line locations
private int linestartx;
private int linestarty;
private int lineendx;
private int lineendy;
private int linexdistance;
private int lineydistance;
//for this game we will define a board size as the amount of lines the board should contain
private double boardsize;
//Lines required to win
private int linestowin;
private String playersturnstring;
private OrthographicCamera camera;
//Holds all the parameters for our players
//Keeps track of who's turn it is, if 0 player one if 1 player two
private int playersturn;
//Holds the location of all of player ones pieces
//Needs to be two Dimensional to hold x and y values
private int[][] playeronepieces;
private int playeronepieceindex;
//Holds the location of all of player twos pieces
//Needs to be two Dimensional to hold x and y values
private int[][] playertwopieces;
private int playertwopieceindex;
//make the number of pieces per player variable so it can be changed for the future
private int numberofpiecesperplayer;
private Game game;
public boolean gameover;
private boolean isready;
private int[][] RowsAndColumns;
private int columnvalue = 538;
public GameScreen(Game game){
this.game = game;
//Set up our assets
gamesprites = new SpriteBatch();
gamestage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false, gamesprites);
//Sets up our font
gamefont = new BitmapFont(Gdx.files.internal("assets/font.fnt"),
Gdx.files.internal("assets/font.png"), false);
pieces = new TextureAtlas("assets/GameButtons.pack");
piecesskin = new Skin(pieces);
piecesskin.addRegions(pieces);
//set up our camera
camera= new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.update();
//sets up our red connect four piece
redtexture = new Texture(Gdx.files.internal("assets/red.png"));
redsprite = new Sprite(redtexture);
//sets up our yellow connect four piece
yellowtexture = new Texture(Gdx.files.internal("assets/yellow.png"));
yellowsprite = new Sprite(yellowtexture);
//setup the board
SetUpGameBoard(8,4,Color.BLACK);
linestartx = 300;
linestarty = 100;
lineendx = 300;
lineendy = 600;
linexdistance = 100;
lineydistance = 100;
//setup the pieces
numberofpiecesperplayer = 60;
//initialize anything else we need for the game
playersturnstring = "";
//start with player one's turn
playersturn = 0;
//setup or pieces locations as blank
playeronepieces = new int[2][numberofpiecesperplayer]; //create two arrays one for x values one for y
playeronepieceindex = 0;
playertwopieces = new int[2][numberofpiecesperplayer]; //create two arrays one for x values one for y
playertwopieceindex = 0;
gameover = false;
isready = false;
linestowin = 4;
}
//Should initialize our game board
public void SetUpGameBoard(int boardsize,int linestowin, Color linecolor){
this.boardsize = boardsize;
this.linestowin = linestowin;
boardlineshape = new ShapeRenderer();
boardlineshape.setProjectionMatrix(camera.combined);
boardlineshape.setColor(linecolor);
//holds the board cells
RowsAndColumns = new int[2][(int) boardsize];
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
#Override
public void hide() {
Gdx.input.setInputProcessor(null);
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void render(float delta) {
//set the stage
gamestage.act(delta);
gamestage.draw();
//if the mouse is clicked and the game is not over send us back to the main screen
if (Gdx.input.justTouched() && gameover == true){
//if the game is over and the user clicks send us back to the main screen
game.setScreen(new MainScreen(game));
}
if(isready){
//if the mouse is clicked and the game is not over add a piece to player one
if (Gdx.input.justTouched() && gameover != true){
AddPiece(Gdx.input.getX(), Gdx.input.getY());
}
}
//Draw our board
boardlineshape.begin(ShapeType.Line);
///Draw all of the lines for our board
DrawBoard(linestartx,linestarty,lineendx,lineendy);
boardlineshape.end();
//Starts our game sprite batch
gamesprites.begin();
//Draw all of player ones pieces
DrawPlayerOnePieces();
//Draw all of player twos pieces
DrawPlayerTwoPieces();
gamefont.draw(gamesprites, playersturnstring, 515, 650);
//End our game sprite batch
gamesprites.end();
//Lastly check to make sure our the game is not over
CheckForGameOver();
isready = true;
}
//draw the board
private void DrawBoard(int linestartx, int linestarty, int lineendx, int lineendy){
camera.update();
boardlineshape.setProjectionMatrix(camera.combined);
//For each line in our board draw a line
for(int i =0; i < boardsize; i++)
{
//first we will draw the vertical lines then we will change to the horizontal lines
boardlineshape.line(linestartx, linestarty,lineendx, lineendy);
//if the x value exceeds a certian amount then change to the horizontal lines
//increment the start x position to draw another line
linestartx += linexdistance;
lineendx += lineydistance;
//if the x start is over 1200 we have drawn the last vertical line so switch to th
//horizontal lines
if(linestartx > 1000)
{
//set our x values and render our horizontal lines
lineendx = linestartx - linexdistance;
linestartx = this.linestartx;
linestarty = this.linestarty;
lineendy = this.linestarty;
for(int index =0; index < boardsize -2; index++){
//increment the start y position to draw another line
boardlineshape.line(linestartx, linestarty,lineendx, lineendy);
linestarty += lineydistance;
lineendy += lineydistance;
}
}
}
}
//Draws all the current pieces for player one
private void DrawPlayerOnePieces(){
//For all of player one's pieces
for(int i = 0; i < playeronepieces[1].length;i++)
{
//of its not an empty piece draw it
if(playeronepieces[0][i] != 0){
gamesprites.draw(redtexture, playeronepieces[0][i], playeronepieces[1][i]);
}
}
}
//Draws all the current pieces for player two
private void DrawPlayerTwoPieces(){
//For all of player two's pieces
for(int i = 0; i < playertwopieces[1].length;i++)
{
//of its not an empty piece draw it
if(playertwopieces[0][i] != 0){
gamesprites.draw(yellowtexture, playertwopieces[0][i], playertwopieces[1][i]);
}
}
}
//Adds a piece to whichever players current turn it is
private void AddPiece(int clickx, int clicky){
RestPlayersTurn(playersturn);
int computedx = GetComputedX(clickx,linestartx);
int computedy = GetComputedY(clicky,linestarty);
if(playeronepieceindex != 60)
{
//makes sure they are clicking inside our board and that there is not already a piece on that part of the board
if(
(clickx > linestartx && clickx < linestartx + ((boardsize - 1) * linexdistance))&&
(clicky > linestarty && clicky < lineendy)&&
(CheckIfPieceExists(computedx,computedy,playeronepieces) == false) &&
(CheckIfPieceExists(computedx,computedy,playertwopieces) == false)
)
{
if(playersturn == 0)
{
playeronepieces[0][playeronepieceindex] = computedx; //set the x value
playeronepieces[1][playeronepieceindex] = 700 - computedy; //set the y value
playeronepieceindex++;
playersturnstring = "Player Two's turn";
gamefont.setColor(Color.YELLOW);
}
else if(playersturn == 1)
{
playertwopieces[0][playertwopieceindex] = computedx; //set the x value
playertwopieces[1][playertwopieceindex] = 700 - computedy; //set the y value
playertwopieceindex++;
playersturnstring = "Player One's turn";
gamefont.setColor(Color.RED);
}
//every time we add a piece change the players turn
playersturn++;
}
}
}
//puts our x value in the center of its cell
public int GetComputedX(int touchx, int linestartx){
//compute our x depending on the nearest line
int lineendx = linestartx + linexdistance;
//for the images width
int imagewidth = redtexture.getWidth();
for(int i = 0; i < boardsize; i++)
{
//if the touched x is in this range than assign the computed x value to
//half the cell
if(touchx > linestartx && touchx < lineendx){
touchx = (lineendx - (linexdistance/2)) - (imagewidth/2);
break;
}
linestartx += linexdistance;
lineendx += linexdistance;
}
return touchx;
}
//puts our y value in the center of the cell
public int GetComputedY(int touchy, int linestarty)
{
//compute our x depending on the nearest line
int lineendy = linestarty + lineydistance;
//for the images width
int imageheight = redtexture.getHeight();
//computer our x depending on the nearest line
for(int i =0; i < boardsize; i++)
{
//if the touched x is in this range than assign the computed x value to
//half the cell
if(touchy > linestarty && touchy < lineendy){
touchy = ((lineendy - (lineydistance/2)) + (imageheight/4));
break;
}
linestarty += lineydistance;
lineendy += lineydistance;
}
return touchy;
}
//Sets the next players turn
private void RestPlayersTurn(int playerturn){
if(playerturn == 2){
playersturn = 0;
}
}
//check for game over
private void CheckForGameOver(){
//check if player one has a connect four
CheckForConnectFourHorizontal();
CheckForConnectFourVertical();
CheckForConnectFourDiagonal();
}
private void CheckForConnectFourHorizontal(){
int rowvalue = 318;
int columnvalue = 534;
//for each column on the board check the row for a horizontal connect four for player one
for(int i = 0; i < RowsAndColumns[1].length; i++)
{
CheckRowForConnectFour(rowvalue,columnvalue,playeronepieces);
rowvalue = 318;
columnvalue = columnvalue - 100;
}
rowvalue = 318;
columnvalue = 534;
//for each column on the board check the row for a horizontal connect four for player two
for(int i = 0; i < RowsAndColumns[1].length; i++)
{
CheckRowForConnectFour(rowvalue,columnvalue,playertwopieces);
rowvalue = 318;
columnvalue = columnvalue - 100;
}
}
private void CheckForConnectFourVertical(){
int rowvalue = 318;
int columnvalue = 534;
//for each column on the board check the row for a horizontal connect four
for(int i = 0; i < RowsAndColumns[1].length; i++)
{
CheckColumnForConnectFour(rowvalue,columnvalue,playeronepieces);
rowvalue = rowvalue + 100 ;
columnvalue = 534;
}
rowvalue = 318;
columnvalue = 534;
//for each column on the board check the row for a horizontal connect four
for(int i = 0; i < RowsAndColumns[1].length; i++)
{
CheckColumnForConnectFour(rowvalue,columnvalue,playertwopieces);
rowvalue = rowvalue + 100 ;
columnvalue = 534;
}
}
private void CheckForConnectFourDiagonal(){
int rowvalue = 318;
int columnvalue = 534;
int originalrowvalue = 318;
//finally do this for every column
for(int index = 0; index < RowsAndColumns[0].length; index++ ){
//for each row on the board check the next four diagonal
for(int i = 0; i < RowsAndColumns[1].length; i++)
{
CheckDiagonalSegment(rowvalue,columnvalue,playeronepieces);
rowvalue = rowvalue + 100;
}
rowvalue = originalrowvalue;
columnvalue -= 100;
}
rowvalue = 318;
columnvalue = 534;
originalrowvalue = 318;
//finally do this for every column
for(int index = 0; index < RowsAndColumns[0].length; index++ ){
//for each row on the board check the next four diagonal
for(int i = 0; i < RowsAndColumns[1].length; i++)
{
CheckDiagonalSegment(rowvalue,columnvalue,playertwopieces);
rowvalue = rowvalue + 100;
}
rowvalue = originalrowvalue;
columnvalue -= 100;
}
}
private void CheckRowForConnectFour(int rowvalue, int columnvalue, int[][] playerpieces){
int consecutivepiecesinrow = 0;
int nonmatchedpieces = 0;
//for all the rows in this column
for(int index = 0; index < playerpieces[0].length; index++){ //go through the row
//for all of the pieces check to see if one matches this spot on the grid
for(int i = 0; i < playerpieces[0].length;i++)
{
//if both of these match this is a cell is occupied by a red peiece
if(playerpieces[0][i] == rowvalue && playerpieces[1][i] == columnvalue )
{
//add to the counter
consecutivepiecesinrow++;
nonmatchedpieces = 0;
break; //we found a piece here so break to the outer loop
}
else{ //if we found one add them to our counter otherwise if none of the items
//match then it doesnt exist in this array
nonmatchedpieces++;
}
}
//if the red player has no piece on this cell
if(nonmatchedpieces == playerpieces[0].length)
{
consecutivepiecesinrow = 0;
nonmatchedpieces = 0;
}
//if we hit for matched then end the game
if(consecutivepiecesinrow == 4){
playersturnstring = "Game Over";
gamefont.setColor(Color.RED);
gameover = true;
}
//check the next cell
rowvalue += 100;
}
}
private void CheckColumnForConnectFour( int rowvalue, int columnvalue, int[][] playerpieces)
{
int consecutivepiecesinrow = 0;
int nonmatchedpieces = 0;
//for all the rows in this column
for(int index = 0; index < RowsAndColumns[1].length; index++){ //go through the column
//for all of the pieces check to see if one matches this spot on the grid
for(int i = 0; i < playerpieces[1].length;i++)
{
//if both of these match this is a cell is occupied by a red peiece
if(playerpieces[0][i] == rowvalue && playerpieces[1][i] == columnvalue )
{
//add to the counter
consecutivepiecesinrow++;
nonmatchedpieces = 0;
break; //we found a piece here so break to the outer loop
}
else{ //if we found one add them to our counter otherwise if none of the items
//match then it doesnt exist in this array
nonmatchedpieces++;
}
}
//if the red player has no piece on this cell
if(nonmatchedpieces == playerpieces[0].length)
{
consecutivepiecesinrow = 0;
nonmatchedpieces = 0;
}
//if we hit for matched then end the game
if(consecutivepiecesinrow == 4){
playersturnstring = "Game Over";
gamefont.setColor(Color.RED);
gameover = true;
}
//check the next cell
columnvalue -= 100;
}
}
private void CheckDiagonalSegment(int rowvalue, int columnvalue, int[][] playerpieces){
CheckForForwardDiagonal(rowvalue,columnvalue,playerpieces);
CheckForBackwardDiagonal(rowvalue,columnvalue,playerpieces);
}
private void CheckForForwardDiagonal(int rowvalue, int columnvalue,int[][] playerpieces){
int consecutivepiecesinrow = 0;
int nonmatchedpieces = 0;
//check for four to the right
for(int index = 0; index < RowsAndColumns[0].length; index++){ //for every square in the diagonal
for(int i = 0; i < playeronepieces[0].length;i++) // for every player peice check for a red
{
//if both of these match this is a cell is occupied by a red peiece
if(playerpieces[0][i] == rowvalue && playerpieces[1][i] == columnvalue )
{
//add to the counter
consecutivepiecesinrow++;
nonmatchedpieces = 0;
break; //we found a piece here so break to the outer loop
}
else{ //if we found one add them to our counter otherwise if none of the items
//match then it doesnt exist in this array
nonmatchedpieces++;
}
}
//if the red player has no piece on this cell
if(nonmatchedpieces == playerpieces[0].length)
{
consecutivepiecesinrow = 0;
nonmatchedpieces = 0;
}
//if we hit for matched then end the game
if(consecutivepiecesinrow == 4){
playersturnstring = "Game Over";
gamefont.setColor(Color.RED);
gameover = true;
}
rowvalue += 100;
columnvalue -= 100;
}
}
public void CheckForBackwardDiagonal(int rowvalue, int columnvalue,int[][] playerpieces){
int consecutivepiecesinrow = 0;
int nonmatchedpieces = 0;
//checks the diagonal to the left
for(int index = 0; index < RowsAndColumns[0].length; index++){ //for every square in the diagonal
for(int i = 0; i < playerpieces[0].length;i++) // for every player peice check for a red
{
//if both of these match this is a cell is occupied by a red peiece
if(playerpieces[0][i] == rowvalue && playerpieces[1][i] == columnvalue )
{
//add to the counter
consecutivepiecesinrow++;
nonmatchedpieces = 0;
break; //we found a piece here so break to the outer loop
}
else{ //if we found one add them to our counter otherwise if none of the items
//match then it doesnt exist in this array
nonmatchedpieces++;
}
}
//if the red player has no piece on this cell
if(nonmatchedpieces == playerpieces[0].length)
{
consecutivepiecesinrow = 0;
nonmatchedpieces = 0;
}
//if we hit for matched then end the game
if(consecutivepiecesinrow == 4){
playersturnstring = "Game Over";
gamefont.setColor(Color.RED);
gameover = true;
}
rowvalue -= 100;
columnvalue -= 100;
}
}
//checks if a piece is already in this position on the board
public boolean CheckIfPieceExists(int row,int column,int[][] playerpieces){
//for all of the pieces check to see if one matches this spot on the grid
for(int i = 0; i < playerpieces[0].length;i++)
{
//if both of these match this is a cell is occupied by a red peiece
if(playerpieces[0][i] == row && playerpieces[1][i] == column )
{
//there is already a piece here
return true;
}
}
return false;
}
#Override
public void resize(int arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void show() {
//set the processor to the new screen
Gdx.input.setInputProcessor(gamestage);
//render our game screen
render(0);
}
The Problem is related to that line
font = new BitmapFont(Gdx.files.internal("assets/font.fnt"),
Gdx.files.internal("assets/font.png"), false);
The file search patch (and classpath) is handled in a different way when starting applications from within your eclipse workspace.
The font is not exported (or not present) in your installed application.
1)
Try to print the file path to console or debug your application. I assume that the file-root is different.
2)
the font is not exported correctly and has to be aded to the build.properties
It runs fine in eclipe but fails when exported
The correct way to export is:
File -> Export -> Java -> Runnable JAR file.
Be sure to check:
Package required libraries into Generated JAR.
That way, your assets will be packaged in the jar and the font will be found.
I have a chessboard, made by overriding the paint() method of a class extending Panel. I highlight all the possible squares a chess piece can go to on the board, and store the pixel values of the upper left corners of the highlighted squares in the:
private ArrayList<Integer> highlightedSquares = new ArrayList<Integer>();
topLeftVal is an array with all of the top left corner values of the squares. In the mouseClicked method of the mouseAdapter, I want to know when a highlighted square (and only a highlighted square) is clicked, and then call repaint(). However, for some reason the program also accepts many squares that are not highlighted.
Here is the code (I apologize for the formatting):
public void mouseClicked(MouseEvent e){
clickPointX = e.getX();
clickPointY = e.getY();
//iterate through highlightedSquares and if the clicked pt is in one of them, repaint
int q = 0;
int xCoor = 0, yCoor = 0;
for(int a : highlightedSquares){
if(q % 2 == 0)
xCoor = a;
else{
yCoor = a;
if((xCoor <= clickPointX) && (clickPointX <= (xCoor + 80)) && (yCoor <= clickPointY) && (clickPointY <= (yCoor + 80))){ //I think this line is causing the problem?
_pixX=xCoor;
_pixY=yCoor;
for(int i = 0; i < topLeftVal.length;i++){
if(topLeftVal[i] == _pixX)
_x = i;
if(topLeftVal[i] == _pixY)
_y = i;
}
repaint();
break;
} //end of if inside else
} //end of else
q++;
} //end of foreach
} //end of mouseClicked
Here is an example implementation where I defined two classes -- Board and Square. Board is derived from JPanel. Square represents a single square on the board. My mouse click listener displays a message which indicates whether or not the clicked upon square is highlighted. Hopefully this will give you a good idea of how to modify your code to achieve the desired result.
public class TestMain {
public static void main(String[] args) throws Exception {
new TestMain().run();
}
public void run() {
// create and show a JFrame containing a chess board
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Board board = new Board();
board.getSquare(2, 4).setHighlighted(true);
board.getSquare(3, 4).setHighlighted(true);
window.getContentPane().add(board, BorderLayout.NORTH);
window.pack();
window.setVisible(true);
}
// *** Board represents the chess board
private class Board extends JPanel {
// *** the constructor creates the squares and adds a mouse click listener
public Board() {
setPreferredSize(new Dimension(squareSize * 8, squareSize * 8));
// create the squares
boolean rowStartRedFlag = true;
for (int row = 0; row < 8; row++) {
boolean redFlag = rowStartRedFlag;
for (int column = 0; column < 8; column++) {
squares [row] [column] = new Square(this, row, column, redFlag);
redFlag = !redFlag;
}
rowStartRedFlag = !rowStartRedFlag;
}
// add mouse click listener
this.addMouseListener(new MouseClickListener());
}
// *** mouse click listener
private class MouseClickListener extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent e) {
Square square = getSquareAt(e.getX(), e.getY());
String msg = square.isHighlighted() ? "Square is highlighted" : "Square is not highlighted";
JOptionPane.showMessageDialog(null, msg);
}
}
// ** override paint
#Override
public void paint(Graphics g) {
draw ((Graphics2D) g);
}
// *** draw every square on the board
public void draw(Graphics2D g) {
for (int row = 0; row < squares.length; row++) {
for (int column = 0; column < squares [row].length; column++) {
squares [row] [column].draw(g);
}
}
}
// *** get square given row and column
public Square getSquare(int row, int column) {
return squares [row] [column];
}
// *** get square from coords
public Square getSquareAt(int x, int y) {
int column = getColumnAtX(x);
int row = getRowAtY(y);
return squares [row] [column];
}
// *** get column # given x
public int getColumnAtX(int x) {
int column = x / squareSize;
return Math.min(Math.max(column, 0), 7);
}
// *** get row # given x
public int getRowAtY(int y) {
int row = y / squareSize;
return Math.min(Math.max(row, 0), 7);
}
// ** get left x given column
public int getLeftFromColumn(int column) {
return column * squareSize;
}
// ** get top y give row
public int getTopFromRow(int row) {
return row * squareSize;
}
// *** get size of square side
public int getSquareSize() {
return squareSize;
}
private int squareSize = 25; // length of square side
private Square [][] squares = new Square [8][8];
}
// *** Squalre represents one square on the board
private class Square {
// ** constructor creates the square
public Square(Board board, int row, int column, boolean redFlag) {
this.board = board;
this.column = column;
this.row = row;
if (redFlag) {
color = Color.RED;
colorHighlighted = Color.PINK;
} else {
color = Color.BLACK;
colorHighlighted = Color.LIGHT_GRAY;
}
}
// ** set highlight flag
public void setHighlighted(boolean value) {
highlighted = value;
}
// *** see if square is highlighted
public boolean isHighlighted() {
return highlighted;
}
// *** draw the square
public void draw(Graphics2D g) {
Color fillColor = highlighted ? colorHighlighted : color;
g.setColor(fillColor);
int x = board.getLeftFromColumn(column);
int y = board.getTopFromRow(row);
int size = board.getSquareSize();
g.fillRect(x, y, size, size);
}
private Board board;
private Color color;
private Color colorHighlighted;
private int column;
private boolean highlighted = false;
private int row;
}
}
I am creating a reversi (othello) game on Java. Included below are my functions for when tiles need to flip to the left, right, below, or above the selected piece. For some reason, whenever a vertical flip is initiated, it ALWAYS works correctly. But, when a horizontal flip is initiated, sometimes it does nothing (when it should do something), or flips over blank tiles that are not supposed to be flipped. The gameboard is an 8 by 8 matrix using an extended JButton called BlankPiece. I will post that in addition to the functions. Can anyone suggest a more efficient / better way to run this game without bugs? Any help is greatly appreciated! If you need clarification, just ask.
public void checkFlipDown(BlankPiece temp)
{
for(int j = temp.getRow() - 1; j>=0; j--){
// j equals the square right above the clicked one, and it keeps going up until it hits the top of the board
if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() != temp.pieceType())){
//if the spot right above the clicked one is not black AND it is the other player's color,
continue;
// keep going with the block statement
}
if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() == temp.pieceType())){
// if the spot right above is not black AND it is the same player's color,
for(int i = temp.getRow(); i >= j; i--)
// i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
{
// change the colors of all colors in the clicked color's column and rows in between the other border piece
gameboard[i][temp.getCol()].change(temp.pieceType());
}
}
else
{
// if no other border pieces exist, go out of the loop
break;
}
}
}
public void checkFlipUp(BlankPiece temp)
{
for(int j = temp.getRow() + 1; j<=7; j++){
// j equals the square right below the clicked one, and it keeps going down until it hits the bottom of the board
if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() != temp.pieceType())){
//if the spot right above the clicked one is not black AND it is the other player's color,
continue;
// keep going with the block statement 2,4 jj = 3,4,5,6,7
}
if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() == temp.pieceType())){
// if the spot right above is not black AND it is the same player's color,
for(int i = temp.getRow(); i <= j; i++)
// i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
{
// change the colors of all colors in the clicked color's column and rows in between the other border piece
gameboard[i][temp.getCol()].change(temp.pieceType());
}
}
else
{
break;
}
}
}
public void checkFlipLeft(BlankPiece temp)
{
for(int j = temp.getCol() + 1; j<=7; j++){
// j equals the square right below the clicked one, and it keeps going down until it hits the bottom of the board
if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() != temp.pieceType())){
//if the spot right above the clicked one is not black AND it is the other player's color,
continue;
// keep going with the block statement 2,4 jj = 3,4,5,6,7
}
if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() == temp.pieceType())){
// if the spot right above is not black AND it is the same player's color,
for(int i = temp.getCol(); i <= j; i++)
// i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
{
// change the colors of all colors in the clicked color's column and rows in between the other border piece
gameboard[temp.getRow()][i].change(temp.pieceType());
}
}
else
{
break;
}
}
}
public void checkFlipRight(BlankPiece temp)
{
for(int j = temp.getCol() - 1; j>=0; j--){
// j equals the square to the right of the clicked one, and it keeps going down until it hits the bottom of the board
if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() != temp.pieceType())){
//if the spot right above the clicked one is not black AND it is the other player's color,
continue;
// keep going with the block statement 2,4 jj = 3,4,5,6,7
}
if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() == temp.pieceType())){
// if the spot right above is not black AND it is the same player's color,
for(int i = temp.getCol(); i >= j; i--)
// i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
{
// change the colors of all colors in the clicked color's column and rows in between the other border piece
gameboard[temp.getRow()][i].change(temp.pieceType());
}
}
else if (gameboard[j][temp.getRow()].pieceType() == 0)
{
break;
}
}
}
So those are my four functions (one for west, east, north, and south). BlankPiece is below:
import java.awt.Color;
import javax.swing.*;
public class BlankPiece extends JButton
{
private final ImageIcon bbutton = new ImageIcon("bbutton.png");
private final ImageIcon gbutton = new ImageIcon("gbutton.jpg");
private final ImageIcon pbutton = new ImageIcon("pbutton.png");
private int x;
private int y;
BlankPiece(int x, int y)
{
this.setBackground(Color.BLACK);
this.setIcon(bbutton);
this.x = x;
this.y = y;
}
public void setGreen()
{
this.setBackground(Color.BLACK);
this.setIcon(gbutton);
}
public void setPurple()
{
this.setBackground(Color.BLACK);
this.setIcon(pbutton);
}
public int getRow() {
// TODO Auto-generated method stub
return x;
}
public int getCol() {
return y;
}
public void resetImage(int count)
{
if (count % 2 == 0)
{
this.setIcon(gbutton);
}
else
{
this.setIcon(pbutton);
}
}
public boolean isSet()
{
String image = "" + this.getIcon();
if((image.equals("pbutton.png")) || (image.equals("gbutton.jpg")))
{
}
return false;
}
public int pieceType()
{
if(getIcon().equals(pbutton)) // purple
{
return -1;
}
else if(getIcon().equals(bbutton)) // blank
{
return 0;
}
else // green
{
return 1;
}
}
public void change(int i) {
if (i == -1)
{
setIcon(pbutton);
}
else if(i == 1)
{
setIcon(gbutton);
}
else
{
setIcon(bbutton);
}
}
}
The problem is not that any checkflip isn't called (they are all called with the same correct parameters), but something in checkFlipRight or CheckFlipLeft functions...
EDIT: full working example by request.
Make a folder with TWO files
One is called Reversi.java
and the other is BlankPiece.java
REVERSI.JAVA:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Reversi extends JPanel {
BlankPiece [][] gameboard = new BlankPiece[8][8];
JPanel toparea = new JPanel();
JPanel gamearea = new JPanel();
JPanel greenarea = new JPanel();
JPanel purplearea = new JPanel();
JPanel logo = new JPanel();
JLabel logoarea = new JLabel();
JLabel greenlogo = new JLabel();
JLabel purplelogo = new JLabel();
ImageIcon blackicon = new ImageIcon("bbutton.png");
ImageIcon icon = new ImageIcon("reversilogo.png");
ImageIcon dgreen = new ImageIcon("DarkGreen.png");
ImageIcon lgreen = new ImageIcon("LightGreen.png");
ImageIcon dpurple = new ImageIcon("DarkPurple.png");
ImageIcon lpurple = new ImageIcon("LightPurple.png");
int count = 0;
int jplus = 0;
public Reversi()
{
gamearea.setLayout(new GridLayout(8,8));
for (int row = 0; row < gameboard.length; row++)
{
for(int col = 0; col < gameboard.length; col++)
{
gameboard[row][col] = new BlankPiece(row, col);
gamearea.add(gameboard[row][col]);
gameboard[row][col].addActionListener(new ButtonListener());
}
}
logoarea.setPreferredSize(new Dimension(304,73));
toparea.setLayout(new BorderLayout());
this.setLayout(new BorderLayout());
toparea.setBackground(new Color(97,203,242));
gamearea.setBackground(new Color(83,35,215));
logo.setBackground(new Color(97,203,242));
logoarea.setIcon(icon);
greenlogo.setIcon(dgreen);
purplelogo.setIcon(lpurple);
toparea.add(greenlogo, BorderLayout.WEST);
toparea.add(purplelogo, BorderLayout.EAST);
toparea.add(logo, BorderLayout.CENTER);
logo.add(logoarea);
this.add(toparea, BorderLayout.NORTH);
this.add(gamearea, BorderLayout.CENTER);
gameboard[3][3].setGreen();
gameboard[3][4].setPurple();
gameboard[4][3].setPurple();
gameboard[4][4].setGreen();
}
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
BlankPiece temp = (BlankPiece)e.getSource(); // #1
int row = temp.getRow(); // #2
System.out.println(row);
int col = temp.getCol();
System.out.println(col);
temp.isSet();
// col and row are the column and row of blankpiece that was clicked
String image = "" + temp.getIcon();
if((image.equals("pbutton.png")) || (image.equals("gbutton.jpg")))
{
JOptionPane.showMessageDialog(null, "This spot is already occupied by " +
"a piece. Please pick an empty tile.");
}
else
{
temp.resetImage(count++);
System.out.println("About to check");
checkFlipDown(gameboard[row][col]);
checkFlipUp(gameboard[row][col]);
checkFlipLeft(gameboard[row][col]);
checkFlipRight(gameboard[row][col]);
}
if (count % 2 == 0)
{
greenlogo.setIcon(dgreen);
purplelogo.setIcon(lpurple);
}
else
{
greenlogo.setIcon(lgreen);
purplelogo.setIcon(dpurple);
}
}
}
public void checkFlipDown(BlankPiece temp)
{
for(int j = temp.getRow() - 1; j>=0; j--){
// j equals the square right above the clicked one, and it keeps going up until it hits the top of the board
if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() != temp.pieceType())){
//if the spot right above the clicked one is not black AND it is the other player's color,
continue;
// keep going with the block statement
}
if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() == temp.pieceType())){
// if the spot right above is not black AND it is the same player's color,
for(int i = temp.getRow(); i >= j; i--)
// i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
{
// change the colors of all colors in the clicked color's column and rows in between the other border piece
gameboard[i][temp.getCol()].change(temp.pieceType());
}
}
else
{
// if no other border pieces exist, go out of the loop
break;
}
}
}
public void checkFlipUp(BlankPiece temp)
{
for(int j = temp.getRow() + 1; j<=7; j++){
// j equals the square right below the clicked one, and it keeps going down until it hits the bottom of the board
if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() != temp.pieceType())){
//if the spot right above the clicked one is not black AND it is the other player's color,
continue;
// keep going with the block statement 2,4 jj = 3,4,5,6,7
}
if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() == temp.pieceType())){
// if the spot right above is not black AND it is the same player's color,
for(int i = temp.getRow(); i <= j; i++)
// i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
{
// change the colors of all colors in the clicked color's column and rows in between the other border piece
gameboard[i][temp.getCol()].change(temp.pieceType());
}
}
else
{
break;
}
}
}
public void checkFlipLeft(BlankPiece temp)
{
for(int j = temp.getCol() + 1; j<=7; j++){
// j equals the square right below the clicked one, and it keeps going down until it hits the bottom of the board
if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() != temp.pieceType())){
//if the spot right above the clicked one is not black AND it is the other player's color,
continue;
// keep going with the block statement 2,4 jj = 3,4,5,6,7
}
if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() == temp.pieceType())){
// if the spot right above is not black AND it is the same player's color,
for(int i = temp.getCol(); i <= j; i++)
// i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
{
// change the colors of all colors in the clicked color's column and rows in between the other border piece
gameboard[temp.getRow()][i].change(temp.pieceType());
}
}
else
{
break;
}
}
}
public void checkFlipRight(BlankPiece temp)
{
for(int j = temp.getCol() - 1; j>=0; j--){
// j equals the square to the right of the clicked one, and it keeps going down until it hits the bottom of the board
if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() != temp.pieceType())){
//if the spot right above the clicked one is not black AND it is the other player's color,
continue;
// keep going with the block statement 2,4 jj = 3,4,5,6,7
}
if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() == temp.pieceType())){
// if the spot right above is not black AND it is the same player's color,
for(int i = temp.getCol(); i >= j; i--)
// i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
{
// change the colors of all colors in the clicked color's column and rows in between the other border piece
gameboard[temp.getRow()][i].change(temp.pieceType());
}
}
else if (gameboard[j][temp.getRow()].pieceType() == 0)
{
break;
}
}
}
}
BLANKPIECE.JAVA
import java.awt.Color;
import javax.swing.*;
public class BlankPiece extends JButton
{
private final ImageIcon bbutton = new ImageIcon("bbutton.png");
private final ImageIcon gbutton = new ImageIcon("gbutton.jpg");
private final ImageIcon pbutton = new ImageIcon("pbutton.png");
private int x;
private int y;
BlankPiece(int x, int y)
{
this.setBackground(Color.BLACK);
this.setIcon(bbutton);
this.x = x;
this.y = y;
}
public void setGreen()
{
this.setBackground(Color.BLACK);
this.setIcon(gbutton);
}
public void setPurple()
{
this.setBackground(Color.BLACK);
this.setIcon(pbutton);
}
public int getRow() {
// TODO Auto-generated method stub
return x;
}
public int getCol() {
return y;
}
public void resetImage(int count)
{
if (count % 2 == 0)
{
this.setIcon(gbutton);
}
else
{
this.setIcon(pbutton);
}
}
public boolean isSet()
{
String image = "" + this.getIcon();
if((image.equals("pbutton.png")) || (image.equals("gbutton.jpg")))
{
}
return false;
}
public int pieceType()
{
if(getIcon().equals(pbutton)) // purple
{
return -1;
}
else if(getIcon().equals(bbutton)) // blank
{
return 0;
}
else // green
{
return 1;
}
}
public void change(int i) {
if (i == -1)
{
setIcon(pbutton);
}
else if(i == 1)
{
setIcon(gbutton);
}
else
{
setIcon(bbutton);
}
}
}
Unfortunately I wasn't able to run your code since it uses images and without them it is impossible to tell what part is working or not. However I have a suggestion for a different approach which I think it would help you to solve the problem (please pay attention to the ideas described and not necessarily to the code).
Problem description: (as I understand it) When a player puts a piece of one color on the board (there are two colors in the game, one for each player), the system needs to traverse all blocks along all directions (there are 8 of them) until it encounters one of the following:
a piece of the same color: in this case all in-between pieces of opposite color are flipped to the player's color (i.e. they are "captured")
a blank piece/block: in this case no color flipping occurs
an edge of the board: again no flipping occurs.
The above description implies that the problem can be divided further to smaller problems that we need to solve first.
Problems to solve:
how can we identify "directions"
how can we traverse along a direction considering each time the next block
how can we identify pieces that are supposed to be captured
how can we identify the edge of the board
Your approach tries to solve all the above problems together. This makes it complicated. Furthermore the same work is repeated for different directions which does not need to be the case. As per the above description, no special action is required for a specific direction. If we solve the problem for a single direction then it should be solved for all.
Suggested approach: Below you can find the algorithm to use (pseudo-code) to find all the pieces to capture. Note how the piece itself tries to solve the problem and propagates the work to the next piece until all captured pieces are found. This way you don't solve the problem yourself. You just describe it correctly to your objects. I have put comments inline to explain what each class is supposed to be. I hope it is clear and useful to you.
// Convenient class to hold together a row and a column pair
public class Index { ... }
// Checks if an index falls out of board edges
public static boolean isValid(Index index) {...}
// Holds the array of pieces. Has method to get a piece by index
public class Board { ... }
public enum ColorType { BLANK, WHITE, BLACK; } // the types of a Piece
// The possible directions to traverse
public enum Direction {
UP_LEFT, UP, UP_RIGHT, RIGHT, BOTTOM_RIGHT, BOTTOM, BOTTOM_LEFT, LEFT;
// given an index it returns the next index along the same direction
public Index next(Index index) {
switch (this) {
case UP_LEFT:
return new Index(index.row() - 1, index.column() - 1);
case BOTTOM:
return new Index(index.row() + 1, index.column());
... // similar for the rest of cases
}
}
}
public class Piece {
private Board board;
private ColorType color = ColorType.BLANK;
private Index index;
....
// Should be called privately when the piece is put on the board and from BLANK becomes WHITE or BLACK
private void checkCaptures() {
Direction[] directions = Direction.values();
for (Direction direction : directions) {
// get next piece's index along the direction
Index nextIndex = direction.next(this.index);
if ( isValid(nextIndex) ) { // if the index is not valid (i.e. edge of the board) ignore it
// get next piece in the same direction
Piece piece = board.getPiece(nextIndex);
// find all pieces that should be captured in this direction
List<Piece> candidatesToCapture = new ArrayList<Piece>();
piece.findCaptureCandidates(candidatesToCapture, this.color, direction);
for (Piece candidate : candidatesToCapture) {
// flip the color (WHITE to BLACK and vice-versa)
candidate.capture();
}
}
}
}
private void findCaptureCandidates(List<Piece> captured, ColorType firstColor, Direction d) {
Index next = d.next(this.index);
if (this.color == firstColor) {
// This piece has the same color with the first one.
// No need to search further for this direction. All pieces collected in the list
// between the first one and this one, have opposite color and should be captured.
} else if (this.color == ColorType.BLANK) {
// found a blank piece. Stop the search and clear any captured pieces found so far
captured.clear();
} else {
// this piece has the opposite color of the first
if ( isValid(next) ) {
// this is not the last piece in this direction.
// Since it has a flipped color it is a candidate for capturing
captured.add(this);
// ask the next piece recursively to also check itself
Piece piece = board.getPiece(next);
piece.findCaptureCandidates(captured, firstColor, d);
} else {
// next index is not valid i.e. we have reached board edge.
// Stop the search and clear any captured pieces found so far
captured.clear();
}
}
}
}