Creating a Four in a Row grid in Java - java

Hi all,
I'm fairly new to using GUI in java and I'm supposed to create a grid. However, I'm not very sure how to use JLabels, JFrames etc or how to even start. As such, can someone explain it in a 'simplified' manner or briefly go over how to start? The description is as follows:
Write the class GUICF that inherits CFGame. ConsoleCF is a graphical implementation of the
Connect Four game. GUICF should have the following fields, contructors, methods, and inner
class.
The private field
private GameBoard this board;
represents the graphics for the 6 × 7 board, but not the buttons.
The constructor
public GUICF(CFPlayer ai)
sets up and starts a human vs. AI game, where the red player (the player who goes first) is randomly
decided.
The constructor
public GUICF(CFPlayer ai1, CFPlayer ai2)
sets up and starts an AI vs. AI game, where the red player (the player who goes first) is randomly
decided.
A human vs. AI game and an AI vs. AI game creates slightly different GUIs. A human vs. AI game
will have a graphical interface like Figure 1. At each turn, the AI makes the move automatically
and the human player’s move is specified through clicking a button. An AI vs. AI game will have
a graphical interface like Figure 2. When you click the “Play” the next AI makes the next move.
The private method playGUI
private boolean playGUI(int c)
plays the column c. So the internal game logic inherited from CFGame and the displayed board
represented in this_board must be updated. If c is a column that can be played, play the column
and return true. Otherwise return false and do not update the state of the game.
Write the private class
private class GameBoard extends javax.swing.JPanel {
private GameBoard() {
// initialize empty board
...
}
private void paint(int x, int y, int color) {
//paints specified coordinate red or black
...
}
}
that represents the game board. In real life, the game pieces are circular, but in GameBoard they
can be square. These square pieces can be done with 6*7=42 JLabels and a GridLayout. (You
may want to use setOpaque(...) with the JLabels.)
The GameBoard does not include the buttons.
So far, my code is essentially useless, but here it is anyway:
package hw4;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
public class GUICF extends CFGame{
private GameBoard this_board;
private class GameBoard extends javax.swing.JPanel {
private JFrame frame;
private int x = 7;
private int y = 6;
private GameBoard() {
frame = new JFrame("CF");
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(6, 7));
for(int i = 0; i < y; i++) {
for(int j = 0; j < x; j++) {
JLabel shape = new JLabel();
shape.setOpaque(true);
shape.setBorder(BorderFactory.createLineBorder(Color.BLACK));
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
panel.add(shape);
}
}
add(panel, BorderLayout.CENTER);
panel.setVisible(true);
frame.setContentPane(panel);
frame.setSize(700, 600);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void paint(int x, int y, int color) {
}
}
}
Any assistance is much appreciated.

Related

java-The threads in my griddlayout have reversed coordinates

I have made a Snake project in which I used a grid layout
with width 20 and height 20. The problem is that when I want to access any square in the panel, it gets the square with the reversed coordinates. For example: when I use lightMeUp() method, which can change the color of the square, if I choose to color the square with coordinates (1,2) it will color instead (2,1) , and not only that but
other functions inside my project are also affected like this. Like for example when I try to color the positions which are traversed by the snake I have to reverse the coordinates in order to get the right squares colored. I will leave here some code that will show how I built the grid and the threads:
import java.awt.GridLayout;
import java.util.ArrayList;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
public class Window extends JFrame{
public static ArrayList<ArrayList<DataOfSquare>> Grid;
public static int width=20;
public static int height=20;
public Window() {
//Creates the arraylist that'll contain the threads
Grid=new ArrayList<ArrayList<DataOfSquare>>();
ArrayList<DataOfSquare> data;
//Creates Threads and its data and adds it to the arrayList
for(int i=0;i<height;i++) {
data=new ArrayList<DataOfSquare>();
for(int j=0;j<width;j++) {
DataOfSquare c=new DataOfSquare(2);
data.add(c);
}
Grid.add(data);
}
//Setting up the layout of the panel
getContentPane().setLayout(new GridLayout(20,20,5,5));
//Start and pauses all threads, then adds every square of each thread to the panel
for(int i=0;i<height;i++) {
for(int j=0;j<width;j++) {
getContentPane().add(Grid.get(i).get(j).square);
}
}
//initial position of the snake
Tuple position=new Tuple(5,5);
//passing this value to the controller
ThreadsController c=new ThreadsController(position);
//Let's start the game
c.start();
//Links the window to the keyboardListener
this.addKeyListener((KeyListener) new KeyboardListener());
}
}'
I also have other classes inside this project, but I don`t think they have anything to do with this problem so I showed just the code responsible for the grid layout.
There are no errors in my code, the code is doing well if I reverse the coordinates but I just do not understand why it is working like this.
What do I have to do in order to have the coordinates in the right place ?

How do I figure out where I am clicking on a JFrame?

I am trying to make a chess engine as a fun project, but for that I really want to make a GUI. The problem is that I have no experience with this, so I am a little stuck. I managed to create the board, but there are two things I have no idea how to do and looking online just confuses me further.
How do I add the pieces to the board, based on what the board looks like in the computers memory. (so for example if the engine makes a move, I want that move to also happen on the gui, how would I link the two?)
How do I figure out what square the user is clicking on in the gui?
This is the code I have so far for the gui, it's not much, but it's honest work
private final JFrame gameFrame;
private Board board;
public Table() {
this.board = new Board();
this.gameFrame = new JFrame("Chess");
this.gameFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
this.gameFrame.setSize(527, 550);
JPanel panel = new JPanel() {
#Override
public void paint(Graphics g) {
boolean white = true;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (white) {
g.setColor(new Color(240, 217, 181));
}
else {
g.setColor(new Color(181, 136, 99));
}
g.fillRect(j * 64, i * 64, 64, 64);
white = !white;
}
white = !white;
}
}
};
this.gameFrame.add(panel);
this.gameFrame.setVisible(true);
}
I know I am probably asking questions with complicated answers, but I am just looking for something I can look up or some general directions
One way and perhaps the the most useful is to implement a mouseListenerand then get the x y position from one of the methods.
Write a class to extend MouseAdapter.
override the desired empty methods.
then add an instance of that class to the frame via addMouseListener (and perhaps addMouseMotionListener).
Then when you do some action with the mouse, you can get the coordinnates from the MouseEvent. It helps to put some print statements in each method to observe what is going on (what method is processing what mouse movement).
The above will serve to demonstrate the process. But later on you should actually add the listener on a JPanel and add the JPanel to the frame.

Can I make a map for my game as a Component in Java?

This is my code.
package gui;
import java.awt.Component;
import world.Terrain;
import world.World;
public class Map extends Component
{
private World world;
private Terrain[][] terrainMap;
private static final long serialVersionUID = 1L;
/*
* I want to make a map that can be added to the JFrame of this game that will visually show the world map of this game
*/
private void generateMap()
{
for(int x = 0; x < world.regions.length; x++)
{
for(int y = 0; y < world.regions[x].length; y++)
{
terrainMap[x][y] = world.regions[x][y].getTerrain();
}
}
}
}
This method should take the relevant information from the world I want to map for the purposes of this general world map, and this class extends Component, so I should be able to add it to the JFrame. The question is, how do I make it so that it renders a visual map as an actual component when I boot this game?
To be more specific. I am making a mostly text based game but I want a somewhat low quality world map of the game. I wanted to make it as a Component, like JLabels, or Buttons, but a custom world map. How do I design it so it will actually appear on screen?

OOP desing, Java Swing, chess game, instanceof

OK, I'm in the process of making a simple java swing chess game. This question is more about OOP design then Java Swing.
I have the following:
I have a Panel class that implements JPanel.
I then have an abstract class Piece that extends from my Panel class
Then I have my classes for the different Pieces: Pawn, King, Bishop etc that extend from my Pieces class
In my main ChessGame Class:
I am using an array of Panel to store the layout of my board
So the array will store, Panel objects, for board places with no pieces on it.
And it will store, the subclasses such as Pawn, Queen, Bishop etc (board places with pieces)
So, the top left square (0,0) maps to myArray[0][0]
My problem is that, to check if the place is empty or has chess pieces in it I have to use:
if(panels[x][y] instanceof Piece){
((Piece)panels[x][y]).makeMove();
}
What I'm asking is this terrible design? I know I should try and stay away from instanceof.
What would be a better approach?
Thanks.
You shouldn't combine the Model code (Piece) with the view code (JPanels). If you ever want to change how the board is displayed you have to change how pieces are stored!
A better design might be to separate Piece from JPanels. Then you can use a single JPanel to display a matrix of Pieces : Pieces[8][8].
My problem is that, to check if the place is empty or has chess pieces in it I have to use:
If you use a matrix, you can just have a null cell or use the Null Object Pattern to have an "empty" piece.
EDIT
Each cell in the piece matrix is a square in the board so piece[0][0] would be the top corner of the board (A8).
To paint the board your paintComponent() method would have to iterate over this matrix and draw each cell appropriately. There are several ways to implement this:
You would need to do a similar instanceof check to draw each type of piece differently
Make a new intermediate "paint strategy" object using the strategy pattern. This may require a matrix of strategy objects instead of piece objects. You may still need to do instance of checks, but maybe only the once to create the strategy objects.
After considering your problem, and knowing the problem domain, I would actually suggest the following...
In your class Panel implement a function int hasMass() as follows...
public int hasMass() {
return 0;
}
In your class Piece override that function as follows...
public int hasMass() {
if (isWhite()) // white pieces are negative.
return -1;
return 1; // black pieces positive.
}
Now you can check if the square has a piece, whether another given piece could take it... (because they have opposite polarity)... e.g. mass + mass == 0 means a capture, != 0 means the panel was empty. And of course an absolute value of 2 (for mass) would mean the move was illegal.
OK, ill start by throwing away the option of setting null to indicate that place is empty (you can do it ofc but using the Empty class is just 'better' in a way).
So let's say you have array of Panels representing your game board:
Panel[][] board;
Now for ilustration, how your class hierarchy could look like:
abstract class Panel extends JPanel { ... }
class Empty extends Panel { ... }
abstract class Piece extends Panel { ... }
class Pawn extends Piece { ... }
...
My Panel class is my Empty class is it not?
Not sure if i understand you, but let's have a look on what extends means exactly: in the show nmodel every Piece is also a Panel or every Pawn is also a Piece, so every Pawn can do all the same things as Piece (for example, 4 is complex number as well as natural number or real number, so in a way, you could say that real numbers extend complex numbers, since every real number is also a complex number)
So now you can have some nice abstract getTexture() method declared in Panel implemenented in Empty class and in all Piece subclasses, and when drawing a Panel, you dont need to look if it is empty or not.
Instead of creating (I assume) almost identical classes for each piece (Rook, Pawn, Queen etc.), you could just keep the original Piece class, make it non abstract and add a PieceType field to it. PieceType is just an enum that tells what type of piece (if any) is placed there. Instead of using instanceof, now you can check using panels[i][j].getType() == PieceType.ROOK. At least that's what I'm doing in my implementation :)
I'm also using JLabel instead of JPanel for my 8x8 board.
Instead of splitting panel to 8x8 smaller panels, you must draw the board and the pieces on a canvas. Later the players will eventually be dragging to move pieces on board. Also you could look for Bitboard presentation in chess game, although this presentation is only required for chess engines which are able to "think" for fast calculations, it is still useful when you have to check if the move that player is trying to make is correct.
Posible Bitboard:
public class BitBoard
{
public static final int P = 0;
public static final int N = 2;
public static final int B = 4;
public static final int R = 6;
public static final int Q = 8;
public static final int K = 10;
public static final int p = 1;
public static final int n = 3;
public static final int b = 5;
public static final int r = 7;
public static final int q = 9;
public static final int k = 11;
// empty field
public static final int empty = 12;
// number of pieces , squares
public static final int nPieces = 12;
public static final int nSquares = 64;
public static final int whitePieces = 12;
public static final int blackPieces = 13;
public static final int nBoards = 14;
public static long squareBits[];
// static member initialization
static
{
squareBits = new long[64];
long square = 1;
square = square << 8 * 8 - 1;
for (int i = 0; i < 64; i++) {
squareBits[i] = square >>> i;
}
}
long bitBoards[];
public BitBoard() {
bitBoards = new long[nBoards];
}
public boolean initBoard()
{
// Put the pieces on the board
EmptyBoard();
addPiece(0, r);
addPiece(1, n);
addPiece(2, b);
addPiece(3, q);
addPiece(4, k);
addPiece(5, b);
addPiece(6, n);
addPiece(7, r);
for (int i = 8; i < 16; i++) {
addPiece(i, p);
}
for (int i = 48; i < 56; i++) {
addPiece(i, P);
}
addPiece(56, R);
addPiece(57, N);
addPiece(58, B);
addPiece(59, Q);
addPiece(60, K);
addPiece(61, B);
addPiece(62, N);
addPiece(63, R);
return true;
}
public boolean addPiece(int whichSquare, int whichPiece)
{
bitBoards[whichPiece] |= squareBits[whichSquare];
bitBoards[nPieces + (whichPiece % 2)] |= squareBits[whichSquare];
return true;
}
private boolean removePiece(int whichSquare, int whichPiece)
{
bitBoards[whichPiece] ^= squareBits[whichSquare];
bitBoards[nPieces + (whichPiece % 2)] ^= squareBits[whichSquare];
return true;
}
private boolean EmptyBoard()
{
for (int i = 0; i < nBoards; i++)
{
bitBoards[i] = 0;
}
return true;
}
}
I would keep a structure of the pieces separate from the rendered board.
For example, I would make the chess pieces pure models w/o knowledge of hit they're rendered.
Pieces (baseclass)
+- Pawn
+- Knight
+- King
+- Queen
+- ..etc
This will allow you to keep an array of Pieces only, where empty squares are null.
For simplicity sake, I'd just have a matrix of peices:
Peices[][] board = new Pieces[8][8];
(of course an initialization method to traverse your 'board' and populate the board w/ the initial positions)
I would then have a visible board constructed of JPanels; a class called "Chess" to manage game; and the actual rendering of the tile/panel in the move function. Imagine:
// what a move might look like when initializing your panels
piece = board [0][0];
Chess.move(piece, 0 ,0); //responsible for clearing the old panel and rendering the panel at target location.
When the user interacts w/ your game..they click your panels..which will give you the panel coordinates. You use the same coordinates w/ your 'board' to determine what the piece is..how it can move etc..
Something like that...
I would just represent the game board using objects...for simplicity. Easiest to understand..and besides..computers are plenty fast now.

No visual appearing

I am working on a java game for class where we implement a game of nim. I thought that I was nearing completion but when I ran the program, nothing appears. It just says build successful and quits. I never get to see the game or play it. Below is my code for the application.
package Nim;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Nim extends JFrame implements ActionListener {
// Number of stickSpace that is needed for the sticks;
int rowspace = 3;
// Buttons for the human to click to take turns playing witht the computer.
private JButton humanMove,
computerMove;
// whatRow = what row the user would like to remove from
// howMany = how many sticks to take from each row
private JComboBox whatRow,
howMany;
// Creates an array of JTextFields with the rowspace as a size.
private JTextField[] stickSpace = new JTextField[rowspace];
// Creates the game;
private Nimgame nimgame;
public void Nim(){
//As requireed, we use a loop to fill the array.
for(int i=0; i<rowspace ;i++){
stickSpace[i] = new JTextField(5);
}
// Creates pulldown menus for the user to select the whatRow s/he
// wants to choose from, and another for howMany s/he wants to take.
whatRow = new JComboBox();
howMany = new JComboBox();
// Add the options to the pulldown menus so the player can choose.
// 0-2 because the array index starts at 0. 1-3 for the amount of sticks.
for(int p=0; p<=3; p++){
if(p<3){
whatRow.addItem(p);
}
if(p>0){
howMany.addItem(p);
}
}
// Adds the text "Human Turn" and "CPU Turn" to the buttons used for turns.
humanMove = new JButton("Human Turn");
computerMove = new JButton("CPU Turn");
// Adds a listener to the buttons to signal the game its time to act.
humanMove.addActionListener(this);
computerMove.addActionListener(this);
// Creates a gridlayout (3,2) with 3 rows and two columns.
JPanel gridpanel = new JPanel(new GridLayout(3,2));
// Labels the rows so the player knows it starts at row Zero - Three.
gridpanel.add(new JLabel("Row Zero", JLabel.LEFT));
gridpanel.add(stickSpace[0]);
gridpanel.add(new JLabel("Row One", JLabel.LEFT));
gridpanel.add(stickSpace[1]);
gridpanel.add(new JLabel("Row Two", JLabel.LEFT));
gridpanel.add(stickSpace[2]);
// Creates another gridlayout this time with 4 rows and 2 columns.
// This sill be used to add the comboboxes, labels, and buttons.
JPanel mainPanel = new JPanel(new GridLayout(4,2));
mainPanel.add(new JLabel("Remove from Row:", JLabel.RIGHT));
mainPanel.add(whatRow);
mainPanel.add(new JLabel("# To Remove:", JLabel.RIGHT));
mainPanel.add(howMany);
mainPanel.add(humanMove);
mainPanel.add(computerMove);
// This adds the gridpanel and the main panel to the visual
// application, but they are still not visiable at this moment.
getContentPane().add(gridpanel, BorderLayout.NORTH);
getContentPane().add(mainPanel, BorderLayout.SOUTH);
// This sections sets the title, size, position on screen, sets it visiable,
// sets the background color, and makes it exit on close of the visual application.
setTitle("The Game of Nim");
setSize(300, 250);
setBackground(Color.yellow);
setVisible(true);
// Creates the actual game to play.
nimgame = new Nimgame();
// Prints out the sticks in each row.
for(int p=0; p<3; p++){
stickSpace[p].setText(nimgame.addSticks(p));
}
}
// Method to handle when an action lister find an action event
public void actionPerformed(ActionEvent e){
// Checks if the humanMove button has been pressed
if(e.getSource() == humanMove){
int foo = whatRow.getSelectedIndex();
int bar = howMany.getSelectedIndex()+1;
nimgame.stickRemove(foo, bar);
for(int p=0; p<3; p++){
stickSpace[p].setText(nimgame.addSticks(p));
}
}
// Checks if the computerMove button has been pressed.
if(e.getSource() == computerMove){
nimgame.computerRandom();
for(int p=0; p<3; p++){
stickSpace[p].setText(nimgame.addSticks(p));
}
}
// Checks to see if the game is over or not.
if(nimgame.isDone()){
JOptionPane.showMessageDialog(null, "Game Over Player Player" + nimgame.whoWon());
}
}
public static void main(String[] args) {
Nim NIM = new Nim();
}
}
Any idea why nothing would be showing up? I figured I forgot to setVisible, but that wasn't the case. Any help would be much appreciated.
public void Nim(){
This isn't a constructor, it's a void method declaration with an awfully confusing name. As you don't declare a constructor at all, you have an implicit default constructor which is called here:
Nim NIM = new Nim();
but the default constructor doesn't do what you'd expect, so you don't see anything. To fix this, change the aforementioned method definition to a constructor definition by removing void:
public Nim() {

Categories

Resources