So I have been working on my final term project which is a Connect Four game. I ran into this issue where i believe my CheckWin logic should work, put is providing me with no output when i run the program. I have my CheckWin() being called in my actionPerformed and I am stuck as to what to do here. As a side note, is there any way to easily increase the size of text inside of a JButton? I would like to increase the size of the "X's" and "O's". I am relatively new at programming so sorry if these are simple fixes. My code is below:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Connect implements ActionListener {
private JFrame window = new JFrame();
private JPanel myPanel = new JPanel();
private JPanel myPanelB = new JPanel();
private JButton[][] myButtons = new JButton[6][7];
private JButton[] buttons = new JButton[7];
private boolean win = false;
private int count = 5;
private int count2 = 5;
private int count3 = 5;
private int count4 = 5;
private int count5 = 5;
private int count6 = 5;
private int count7 = 5;
private int countA = 0;
private String letter = "";
public boolean checkHorizontalWin(String letter) {
for (int y = 0; y < myButtons.length; y++) {
// going to length-3 to avoid IndexOutOfBounds exception
for (int x = 0; x < myButtons[y].length - 3; x++) {
if (myButtons[y][x].getText().equals(letter)
&& myButtons[y][x + 1].getText().equals(letter)
&& myButtons[y][x + 2].getText().equals(letter)
&& myButtons[y][x + 3].getText().equals(letter)
) {
return true;
}
}
}
return false;
}
public boolean checkVerticalWin(String letter) {
for (int y = 0; y < myButtons.length - 3; y++) {
for (int x = 0; x < myButtons[y].length; x++) {
if (myButtons[y][x].getText().equals(letter)
&& myButtons[y + 1][x].getText().equals(letter)
&& myButtons[y + 2][x].getText().equals(letter)
&& myButtons[y + 3][x].getText().equals(letter)
) {
return true;
}
}
}
return false;
}
public boolean checkDiagonalToTheLeftWin(String letter) {
for (int y = 0; y < myButtons.length - 3; y++) {
for (int x = 0; x < myButtons[y].length - 3; x++) {
if (myButtons[y][x].getText().equals(letter)
&& myButtons[y + 1][x + 1].getText().equals(letter)
&& myButtons[y + 2][x + 2].getText().equals(letter)
&& myButtons[y + 3][x + 3].getText().equals(letter)
) {
return true;
}
}
}
return false;
}
public boolean checkDiagonalToTheRightWin(String letter) {
for (int y = 0; y < myButtons.length - 3; y++) {
for (int x = 3; x < myButtons[y].length; x++) {
if (myButtons[y][x].getText().equals(letter)
&& myButtons[y + 1][x - 1].getText().equals(letter)
&& myButtons[y + 2][x - 2].getText().equals(letter)
&& myButtons[y + 3][x - 3].getText().equals(letter)
) {
return true;
}
}
}
return false;
}
public Connect(){
window.setSize(800,700);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myPanel.setLayout(new GridLayout(1,7));
myPanelB.setLayout(new GridLayout(6,7));
for (int i = 0; i < buttons.length; i ++){
buttons[i] = new JButton();
myPanel.add(buttons[i]);
buttons[i].addActionListener(this);
}
for (int i = 0; i < 6; i ++){
for (int j = 0; j < 7; j ++){
myButtons[i][j] = new JButton();
myPanelB.add(myButtons[i][j]);
}
}
window.add(myPanel, BorderLayout.NORTH);
window.add(myPanelB, BorderLayout.CENTER);
window.setVisible(true);
}
public void actionPerformed(ActionEvent e){
countA++;
if (countA % 2 == 0)
letter = "X";
else
letter = "O";
if (e.getSource() == buttons[0]){
myButtons[count][0].setText(letter);
count --;
}
if (e.getSource() == buttons[1]){
myButtons[count2][1].setText(letter);
count2 --;
}
if (e.getSource() == buttons[2]){
myButtons[count3][2].setText(letter);
count3--;
}
if (e.getSource() == buttons[3]){
myButtons[count4][3].setText(letter);
count4--;
}
if (e.getSource() == buttons[4]){
myButtons[count5][4].setText(letter);
count5--;
}
if (e.getSource() == buttons[5]){
myButtons[count6][5].setText(letter);
count6--;
}
if (e.getSource() == buttons[6]){
myButtons[count7][6].setText(letter);
count7--;
}
if (myButtons[0][0].getText().equals("O") || myButtons[0][0].getText().equals("X")){
buttons[0].setEnabled(false);
}
if (myButtons[0][1].getText().equals("O") || myButtons[0][1].getText().equals("X")){
buttons[1].setEnabled(false);
}
if (myButtons[0][2].getText().equals("O") || myButtons[0][2].getText().equals("X")){
buttons[2].setEnabled(false);
}
if (myButtons[0][3].getText().equals("O") || myButtons[0][3].getText().equals("X")){
buttons[3].setEnabled(false);
}
if (myButtons[0][4].getText().equals("O") || myButtons[0][4].getText().equals("X")){
buttons[4].setEnabled(false);
}
if (myButtons[0][5].getText().equals("O") || myButtons[0][5].getText().equals("X")){
buttons[5].setEnabled(false);
}
if (myButtons[0][6].getText().equals("O") || myButtons[0][6].getText().equals("X")){
buttons[6].setEnabled(false);
if (myButtons[0][6].getText().equals("O") || myButtons[0][6].getText().equals("X")){
buttons[6].setEnabled(false);
if (checkHorizontalWin(letter)
|| checkVerticalWin(letter)
|| checkDiagonalToTheLeftWin(letter)
|| checkDiagonalToTheRightWin(letter)
) {
win = true;
if (win == true) {
JOptionPane.showMessageDialog(null, letter + " has won!");
System.exit(0);
}
}
}
if(win == true){
JOptionPane.showMessageDialog(null, letter + " has won!");
System.exit(0);
} else if(count == 42 && win == false){
JOptionPane.showMessageDialog(null, "tie game");
System.exit(0);
}
}
}
public static void main(String[] args){
new Connect();
}
}
Identation helps.
if (myButtons[0][6].getText().equals("O") || myButtons[0][6].getText().equals("X"))
{
buttons[6].setEnabled(false);
// Missing brace on previous if
// checkXWin methods only invoked inside the above if-statement.
if (checkHorizontalWin(letter)
|| checkVerticalWin(letter)
|| checkDiagonalToTheLeftWin(letter)
|| checkDiagonalToTheRightWin(letter)
) {
win = true;
if (win == true) {
JOptionPane.showMessageDialog(null, letter + " has won!");
ystem.exit(0);
}
}
}
You haven't closed a brace in one of your if statements properly in the actionPerformed method. As a result, your program will only check for a win once the last column is full.
It also seems the condition if (myButtons[0][6].getText().equals("O") || myButtons[0][6].getText().equals("X") is repeated twice. That wouldn't be the cause of your issue but I think you might want to remove one of those statements.
Your brackets on your if statements are incorrectly placed.
if (myButtons[0][6].getText().equals("O") || myButtons[0][6].getText().equals("X")){
buttons[6].setEnabled(false);
if (myButtons[0][6].getText().equals("O") || myButtons[0][6].getText().equals("X")){
buttons[6].setEnabled(false);
On both of theses if statements you have opening brackets but the closing brackets do not come until the end of the actionPerformed method.
This means the code to check for a winner does not get executed unless both of these conditions resulted in true, which is not what you want and I'm pretty sure is impossible...
Related
I am a new to java programming and I am developing a simple a one player TICTACTOE game using swing. Thee are two classes. One main TICTACTOE class which uses an XOButtton class to set up buttons which can listen to click events. I begin by creating an object of this tictactoe class then use this object to call a method called initialCheckButton to find out if the buttons have been clicked 3 timess. If yes it calls another method to find out if the Xs or Os are consecutively displayed.If yes you win. I plan to develop this further but this is just a template. When the GUI dsiplays,clicking on buttons and display of successive Xs or Os does not display the message of the JoptionPane. Any help?
public class TicTacToe extends JFrame {
JPanel p = new JPanel();
boolean done = false;
XOButton buttons[] = new XOButton[9];
public static void main(String args[]) {
TicTacToe t = new TicTacToe();
t.initialCheckButton();
}
public TicTacToe() {
super("TicTacToe");
setSize(400, 400);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
p.setLayout(new GridLayout(3, 3));
for (int i = 0; i < 9; i++) {
buttons[i] = new XOButton();
p.add(buttons[i]);
}
add(p);
setVisible(true);
}
public void initialCheckButton() {
int sum = 0;
while (sum <= 3) {
for (int i = 0; i < 9; i++) {
if (buttons[i].checkButtonO() == 1) {
sum++;
}
if (buttons[i].checkButtonX() == 1) {
sum++;
}
}
}
checkButtonFinal();
}
public void checkButtonFinal() {
for (int i = 0; i < 9; i++)
for (int j = i + 3; j < 9; j++) {
for (int k = j + 3; k < 9; k++) {
if (buttons[i].checkButtonO() == buttons[j].checkButtonO() && buttons[k].checkButtonO() == 1)
JOptionPane.showMessageDialog(null, "Great, you won");
if (buttons[i].checkButtonX() == buttons[j].checkButtonX() && buttons[k].checkButtonX() == 1)
JOptionPane.showMessageDialog(null, "Great, you won");
}
}
for (int i = 0; i < 9; i += 3) {
if (buttons[i].checkButtonO() == buttons[i + 1].checkButtonO() && buttons[i + 2].checkButtonO() == 1)
JOptionPane.showMessageDialog(null, "Great, you won");
if (buttons[i].checkButtonX() == buttons[i + 1].checkButtonX() && buttons[i + 2].checkButtonX() == 1)
JOptionPane.showMessageDialog(null, "Great, you won");
}
for (int i = 0; i < 9; i += 2) {
for (int j = i + 2; j < 9; j += 2)
for (int k = j + 2; k < 9; k += 2) {
if (buttons[i].checkButtonO() == buttons[j].checkButtonO() && buttons[k].checkButtonO() == 1)
JOptionPane.showMessageDialog(null, "Great, you won");
if (buttons[i].checkButtonX() == buttons[j].checkButtonX() && buttons[k].checkButtonX() == 1)
JOptionPane.showMessageDialog(null, "Great, you won");
}
}
for (int i = 0; i < 9; i += 4) {
for (int j = i + 4; j < 9; j += 4)
for (int k = j + 4; k < 9; k += 4) {
if (buttons[i].checkButtonO() == buttons[j].checkButtonO() && buttons[k].checkButtonO() == 1)
JOptionPane.showMessageDialog(null, "Great, you won");
if (buttons[i].checkButtonX() == buttons[j].checkButtonX() && buttons[k].checkButtonX() == 1)
JOptionPane.showMessageDialog(null, "Great, you won");
}
}
}
public static class XOButton extends JButton implements ActionListener {
public int buttonClicked = 0;
public int buttonClickedX = 0;
public int buttonClickedO = 0;
ImageIcon X, O;
byte value = 0;
/*
* 0:nothing 1:X 2:O
*/
public XOButton() {
X = new ImageIcon(this.getClass().getResource("X.png"));
O = new ImageIcon(this.getClass().getResource("O.png"));
this.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
value++;
value %= 3;
switch (value) {
case 0:
setIcon(null);
buttonClicked = 0;
break;
case 1:
setIcon(X);
buttonClickedX = 1;
break;
case 2:
setIcon(O);
buttonClickedO = 1;
break;
}
}
public int checkButtonO() {
return buttonClickedO;
}
public int checkButtonX() {
return buttonClickedX;
}
}
}
The following is a refactored version of your code that includes some documented changes :
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TicTacToe extends JFrame {
private static int ROW = 3, COLS = 3;
private final JPanel p;
private final XOButton buttons[];
//static counter, so it has the same value for all button instances
//used as a toggle between X and O
private static int counter = 0;
public static void main(String args[]) {
new TicTacToe();
}
public TicTacToe() {
super("TicTacToe");
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
buttons = new XOButton[ROW*COLS];
p = new JPanel();
p.setLayout(new GridLayout(3, 3));
initialize();
add(p);
pack();
setVisible(true);
}
private void initialize(){
for (int i = 0; i < 9; i++) {
buttons[i] = new XOButton();
p.add(buttons[i]);
}
}
//restart game
private void restart(){
p.removeAll();
initialize();
revalidate();
}
private void checkButtons() {
//many similar for loops are not easy to follow
//refactor into methods
XOButton[] winningButtons = checkRows();
if( winningButtons != null) {
won(winningButtons);
}
winningButtons = checkCols();
if( winningButtons != null) {
won(winningButtons);
}
winningButtons = checkDIagonals();
if( winningButtons != null) {
won(winningButtons);
}
}
//returns winning buttons, or null
private XOButton[] checkRows() {
for(int row = 0; row < buttons.length ; row +=3 ){
int totalX = buttons[row].buttonClickedX + buttons[row+1].buttonClickedX+ buttons[row+2].buttonClickedX ;
int totalO = buttons[row].buttonClickedO + buttons[row+1].buttonClickedO+ buttons[row+2].buttonClickedO ;
if(totalX >=3 || totalO >=3) return new XOButton[]{buttons[row], buttons[row+1], buttons[row+2]};
}
return null;
}
//returns winning buttons, or null
private XOButton[] checkCols() {
for(int col = 0; col < COLS ; col++ ){
System.out.println(col+"-"+(col+3)+"-"+(col+6));
int totalX = buttons[col].buttonClickedX + buttons[col+3].buttonClickedX+ buttons[col+6].buttonClickedX ;
int totalO = buttons[col].buttonClickedO + buttons[col+3].buttonClickedO+ buttons[col+6].buttonClickedO ;
if(totalX >=3 || totalO >=3) return new XOButton[]{buttons[col], buttons[col+3], buttons[col+6]};
}
return null;
}
//returns winning buttons, or null
private XOButton[] checkDIagonals() {
int totalX = buttons[0].buttonClickedX + buttons[4].buttonClickedX+ buttons[8].buttonClickedX ;
int totalO = buttons[0].buttonClickedO + buttons[4].buttonClickedO+ buttons[8].buttonClickedO ;
if(totalX >=3 || totalO >=3) return new XOButton[]{buttons[0], buttons[4], buttons[8]};
totalX = buttons[2].buttonClickedX + buttons[4].buttonClickedX+ buttons[6].buttonClickedX ;
totalO = buttons[2].buttonClickedO + buttons[4].buttonClickedO+ buttons[6].buttonClickedO ;
if(totalX >=3 || totalO >=3) return new XOButton[]{buttons[2], buttons[4], buttons[6]};
return null;
}
//invoked when there is a winner
private void won(XOButton[] winningButtons) {
for(XOButton button : winningButtons){
button.setBackground(Color.PINK);
}
JOptionPane.showMessageDialog(null, "Great, you won");
restart(); //start new game
}
class XOButton extends JButton implements ActionListener {
private int buttonClicked = 0, buttonClickedX = 0, buttonClickedO = 0;
String X, O; //avoid using unavailable images when posting
public XOButton() {
X = "X";
O = "O";
this.addActionListener(this);
setPreferredSize(new Dimension(40,40));
}
#Override
public void actionPerformed(ActionEvent e) {
if(buttonClicked > 0 ) return; //invoke only on first click
buttonClicked ++;
counter = (counter+1)%2; //changes from 1 to 0 and back to 1
switch (counter) {
case 0:
setText(X);
buttonClickedX = 1;
break;
case 1:
setText(O);
buttonClickedO = 1;
break;
}
checkButtons();//check buttons after every click
}
public int checkButtonO() {
return buttonClickedO;
}
public int checkButtonX() {
return buttonClickedX;
}
}
}
I'm learning how to use processing and tried to make a simple snake game, while doing it it does show (although it was cntrl+c cntrl+v from the first one, which was up) a Weir behavior in for loops specifically for going right or down.
i managed to fix the 'down' problem by simply changing
for(int k=0;k<56;k++)
to
for(int k=55;k<=0;k--)
which is exactly the same thing, isn't it? i am i missing something?
int [][] snakeHead = new int[60][60];
int game = 1;
int value = 0;
String s = "You lost\nPress SHIFT to Restart";
void setup(){
size(600,600);
frameRate(10);
for(int i=0;i<56;i++){
for(int k=0;k<56;k++){
snakeHead[i][k] = 0;
}
}
snakeHead[1][22] = 1;
game = 1;
value = 0;
}
void draw(){
background(0);
fill(255);
rect(20, 20, 560, 560);
if(game == 1){
for(int i=0;i<56;i++){
for(int k=0;k<56;k++){
if(snakeHead[i][k] == 1){
fill(0,255,0);
rect(20+i*10, 20+k*10, 10,10);
}
}
}
if(value == 1){
up();
}else if(value == 2){
down();
}else if(value == 3){
left();
}else if(value == 4){
right();
}
}
else{
textSize(32);
textAlign(CENTER);
fill(0,0,255);
text(s, 300, 300);
}
}
void keyPressed(){
if(key == CODED){
if(keyCode == UP){
value = 1;
}
else if(keyCode == DOWN){
value = 2;
}
else if(keyCode == LEFT){
value = 3;
}
else if(keyCode == RIGHT){
value = 4;
}else if(keyCode == SHIFT){
setup();
}
}
}
void up(){
for(int i=0;i<56;i++){
for(int k=0;k<56;k++){
if(snakeHead[i][k] == 1 && k == 0){
game = 0;
}else if(snakeHead[i][k] == 1){
snakeHead[i][k-1] = 1;
snakeHead[i][k]=0;
}
}
}
}
void down(){
for(int i=0;i<56;i++){
for(int k=0;k<56;k++){
if(snakeHead[i][k] == 1 && k == 55){
game = 0;
}else if(snakeHead[i][k] == 1 && k != 55){
snakeHead[i][k+1] = 1;
snakeHead[i][k] = 0;
}
}
}
}
void right(){
for(int i=0;i<56;i++){
for(int k=0;k<56;k++){
if(snakeHead[i][k] == 1 && i == 55){
game = 0;
}else if(snakeHead[i][k] == 1 && i != 55){
snakeHead[i+1][k] = 1;
snakeHead[i][k]=0;
}
}
}
}
void left(){
for(int i=0;i<56;i++){
for(int k=0;k<56;k++){
if(snakeHead[i][k] == 1 && i == 0){
game = 0;
}else if(snakeHead[i][k] == 1){
snakeHead[i-1][k] = 1;
snakeHead[i][k]=0;
}
}
}
}
Your problem in the right and down that in both you update the head down the loop (with i+1 or j+1) so the else block get execute more then once (in the up and left you doing i-1 and j-1 so it doesn't happens there).
Let look at the right function to demonstrate:
void right(){
for(int i=0;i<56;i++){
for(int k=0;k<56;k++){
if(snakeHead[i][k] == 1 && i == 55){
game = 0;
} else if(snakeHead[i][k] == 1 && i != 55){
snakeHead[i+1][k] = 1; // update the sankeHead to i+1 which will be reached in the next iteration in i so basiclly keep moving right till reach if block
snakeHead[i][k]=0;
}
} // end k loop
} // end i loop
}
To fix this all you need to do is add return because you only want to move the snakeHead once!
so:
void right(){
for(int i=0;i<56;i++){
for(int k=0;k<56;k++){
if(snakeHead[i][k] == 1 && i == 55){
game = 0;
return;
} else if(snakeHead[i][k] == 1 && i != 55){
snakeHead[i+1][k] = 1;
snakeHead[i][k]=0;
return;
}
} // end k loop
} // end i loop
}
I have this class called deepToe_2. Whenever I click on the shortcut key for run, eclipse runs another class called TicTacToe which I had previously ran.
I have tried making changes to run cofig but it still does not seem to work.
Here is my code :
package deepToe;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import javax.swing.*;
import deepToe.deepToe_2.buttonListener;
public class deepToe_2 extends JPanel {
JButton buttons[] = new JButton[9];
int alternate = 0;
String MotherBoard[] = {"","","","","","","","",""};
String board[];
public static void main(String[] args) {
JFrame window = new JFrame("Tic Tac Toe");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(new TicTacToe());
window.setBounds(300,200,300,300);
window.setVisible(true);
}
public deepToe_2()
{
setLayout(new GridLayout(3,3));
initializebuttons();
toss();
}
public void toss(){
Random ran = new Random();
int r = ran.nextInt(2);
if(r == 1){
JOptionPane.showMessageDialog(null, "deepToe goes First.");
alternate++;
deepToe();
}
else {
JOptionPane.showMessageDialog(null, "deepToe goes First.");
alternate++;
deepToe();
}
}
public void deepToe() {
if(alternate == 1) {
buttons[4].setText("O");
}else {
int moves[] = {-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000};
for(int i = 0; i < 9; i++) {
board = MotherBoard;
if(board[i] == "") {
board[i] = "O";
moves[i] = evaluateBoard();
}
}
int high = -999, final_move = -1;
for(int j = 0; j < 9; j++) {
if(moves[j] > high){
high = moves[j];
final_move = j;
}
}
buttons[final_move].setText("O");
}
updateMotherBoard();
if(!(checkResults())) alternate++;
}
public int evaluateBoard() {
int x = 0;
if(canSomeoneWin("O") != -1) x += 2;
if(canSomeoneWin("X") != -1) x -= 2;
return x;
}
public void updateMotherBoard() {
for(int i = 0; i < 9; i++) {
MotherBoard[i] = buttons[i].getText();
}
}
public int canSomeoneWin(String c) {
int x = 0, y = 1, z = 2;
for(int j = 0; j < 3; j++){
if((board[y] == board[z])&&(board[y] == c)&&(board[x] == "")) return x;
if((board[x] == board[z])&&(board[x] == c)&&(board[y] == "")) return y;
if((board[x] == board[y])&&(board[x] == c)&&(board[z] == "")) return z;
x += 3;
y += 3;
z += 3;
}
x = 0; y = 3; z = 6;
for(int j = 0; j < 3; j++){
if((board[y] == board[z])&&(board[y] == c)&&(board[x] == "")) return x;
if((board[x] == board[z])&&(board[x] == c)&&(board[y] == "")) return y;
if((board[x] == board[y])&&(board[x] == c)&&(board[z] == "")) return z;
x++;
y++;
z++;
}
x = 0; y = 4; z = 8;
for(int j = 0; j < 2; j++){
if((board[y] == board[z])&&(board[y] == c)&&(board[x] == "")) return x;
if((board[x] == board[z])&&(board[x] == c)&&(board[y] == "")) return y;
if((board[x] == board[y])&&(board[x] == c)&&(board[z] == "")) return z;
x = 2; z = 6;
}
return -1;
}
public void initializebuttons()
{
for(int i = 0; i <= 8; i++)
{
buttons[i] = new JButton();
buttons[i].setText("");
buttons[i].addActionListener(new buttonListener());
add(buttons[i]);
}
buttons[5].setText("X");
}
public class buttonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
JButton buttonClicked = (JButton)e.getSource();
if((alternate%2 == 0)&&(buttonClicked.getText().equals(""))){
buttonClicked.setText("X");
updateMotherBoard();
if(!(checkResults())) {
alternate++;
deepToe();
}
}
}
}
public boolean checkResults(){
if(checkForWin())
{
if(alternate%2 == 0)
JOptionPane.showConfirmDialog(null, "Human wins. Great Job!!!");
else
JOptionPane.showConfirmDialog(null, "deepToe wins.");
return true;
}else{
if(checkForDraw()){
JOptionPane.showConfirmDialog(null, "Draw. Good game.");
return true;
}
}
return false;
}
public boolean checkForDraw() {
boolean yes = true;
for(int j = 0; j < 9; j++){
if(buttons[j].getText().equals("")) yes = false;
}
return yes;
}
public boolean checkForWin()
{
if( checkAdjacent(0,1) && checkAdjacent(1,2) ) //no need to put " == true" because the default check is for true
return true;
else if( checkAdjacent(3,4) && checkAdjacent(4,5) )
return true;
else if ( checkAdjacent(6,7) && checkAdjacent(7,8))
return true;
else if ( checkAdjacent(0,3) && checkAdjacent(3,6))
return true;
else if ( checkAdjacent(1,4) && checkAdjacent(4,7))
return true;
else if ( checkAdjacent(2,5) && checkAdjacent(5,8))
return true;
else if ( checkAdjacent(0,4) && checkAdjacent(4,8))
return true;
else if ( checkAdjacent(2,4) && checkAdjacent(4,6))
return true;
else
return false;
}
public boolean checkAdjacent(int a, int b)
{
if ( buttons[a].getText().equals(buttons[b].getText()) && !buttons[a].getText().equals("") )
return true;
else
return false;
}
}
It probably IS running this class, but you are inserting the wrong panel in your frame:
window.getContentPane().add(new TicTacToe());
it should be deepToe_2 like in
window.getContentPane().add(new deepToe_2());
since there is no other reference to that class in the poseted code.
Just to be sure change the frame's title:
JFrame window = new JFrame("Deep Toe 2"); // or so
I also would encourage you to (learn to) use the debugger, would b helpful to identify such problems...
Right click either in your class file or the class itself and click Run As -> Java Application
you need just to double click your class and then run the program from where ever you want. you can right click as suggested by kkflf or run it from shortcut key as you used to do.
Hope this will help.
I'm working in artificial intelligence project to develop a TicTacToe 4X4 using Minimax algorithm
I have this existing program that run Minimax algorithm in 3x3 TicTacToe board.
I want to extend it to 4x4 TicTacToe
but I couldn't any idea how I can do it ??
import java.util.*;
//defines the point where to place 1 or 2
class Point {
int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public String toString() {
return "[" + x + ", " + y + "]";
}
}
//defines the score per point -1,0,1
class PointsAndScores {
int score;
Point point;
PointsAndScores(int score, Point point) {
this.score = score;
this.point = point;
}
}
//defince the game board
class Board {
List<Point> availablePoints;
Scanner scan = new Scanner(System.in);
int[][] board = new int[3][3];
public Board() {
}
public boolean isGameOver() {
//Game is over is someone has won, or board is full (draw)
return (hasXWon() || hasOWon() || getAvailableStates().isEmpty());
}
//check if X have won represented by 1
public boolean hasXWon() {
if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == 1) || (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] == 1)) {
//System.out.println("O Diagonal Win");
return true;
}
for (int i = 0; i < 3; ++i) {
if (((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 1)
|| (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 1))) {
// System.out.println("O Row or Column win");
return true;
}
}
return false;
}
//check if O has won represented by 2
public boolean hasOWon() {
if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == 2) || (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] == 2)) {
// System.out.println("X Diagonal Win");
return true;
}
for (int i = 0; i < 3; ++i) {
if ((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 2)
|| (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 2)) {
// System.out.println("X Row or Column win");
return true;
}
}
return false;
}
//check available states in the board
public List<Point> getAvailableStates() {
availablePoints = new ArrayList<>();
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (board[i][j] == 0) {
availablePoints.add(new Point(i, j));
}
}
}
return availablePoints;
}
//put player move in the board
public void placeAMove(Point point, int player) {
board[point.x][point.y] = player; //player = 1 for O, 2 for X..
}
//get best movement according to the board state
public Point returnBestMove() {
int MAX = -100000;
int best = -1;
for (int i = 0; i < rootsChildrenScores.size(); ++i) {
if (MAX < rootsChildrenScores.get(i).score) {
MAX = rootsChildrenScores.get(i).score;
best = i;
}
}
return rootsChildrenScores.get(best).point;
}
//accepts input from user
void takeHumanInput() {
System.out.println("Your move: ");
int x = scan.nextInt();
int y = scan.nextInt();
Point point = new Point(x, y);
placeAMove(point, 2);
}
//display current board
public void displayBoard() {
System.out.println();
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
System.out.print(board[i][j] + " ");
}
System.out.println();
}
}
//get min value
public int returnMin(List<Integer> list) {
int min = Integer.MAX_VALUE;
int index = -1;
for (int i = 0; i < list.size(); ++i) {
if (list.get(i) < min) {
min = list.get(i);
index = i;
}
}
return list.get(index);
}
//get max value
public int returnMax(List<Integer> list) {
int max = Integer.MIN_VALUE;
int index = -1;
for (int i = 0; i < list.size(); ++i) {
if (list.get(i) > max) {
max = list.get(i);
index = i;
}
}
return list.get(index);
}
//declares a list for scores
List<PointsAndScores> rootsChildrenScores;
//excutes minimax algorithm
public void callMinimax(int depth, int turn){
rootsChildrenScores = new ArrayList<>();
minimax(depth, turn);
}
//minimax algorithm
public int minimax(int depth, int turn) {
if (hasXWon()) return +1;
if (hasOWon()) return -1;
//get available states from the board
List<Point> pointsAvailable = getAvailableStates();
if (pointsAvailable.isEmpty()) return 0;
//stores scores
List<Integer> scores = new ArrayList<>();
for (int i = 0; i < pointsAvailable.size(); ++i) {
Point point = pointsAvailable.get(i);
if (turn == 1) { //O's turn select the highest from below minimax() call
placeAMove(point, 1);
int currentScore = minimax(depth + 1, 2);
scores.add(currentScore);//add scores to the list
if (depth == 0)
rootsChildrenScores.add(new PointsAndScores(currentScore, point));
} else if (turn == 2) {//X's turn select the lowest from below minimax() call
placeAMove(point, 2);
scores.add(minimax(depth + 1, 1));
}
board[point.x][point.y] = 0; //Reset this point
}
return turn == 1 ? returnMax(scores) : returnMin(scores);
}
}
//main class
public class TicTacToe {
public static void main(String[] args) {
Board b = new Board();//instantiate board
Random rand = new Random();//instantiate random value
b.displayBoard();//display board
System.out.println("Who's gonna move first? (1)Computer (2)User: ");
int choice = b.scan.nextInt();
if(choice == 1){
Point p = new Point(rand.nextInt(3), rand.nextInt(3));
b.placeAMove(p, 1);
b.displayBoard();
}
while (!b.isGameOver()) {
System.out.println("Your move: ");
Point userMove = new Point(b.scan.nextInt(), b.scan.nextInt());
b.placeAMove(userMove, 2); //2 for X and X is the user
b.displayBoard();
if (b.isGameOver()) {
break;
}
b.callMinimax(0, 1);
for (PointsAndScores pas : b.rootsChildrenScores) {
System.out.println("Point: " + pas.point + " Score: " + pas.score);
}
b.placeAMove(b.returnBestMove(), 1);
b.displayBoard();
}
if (b.hasXWon()) {
System.out.println("Unfortunately, you lost!");
} else if (b.hasOWon()) {
System.out.println("You win! This is not going to get printed.");
} else {
System.out.println("It's a draw!");
}
}
}
You need to introduce an integer variable, let's say n, which will contain the size of the board(i.e. # of cells = n*n). Before a game starts, the player will be asked for the preferred board size, 3 or 4, and the corresponding board will be created. In order for your program to work with 4x4 like it did with 3x3, we will need to place the variable n wherever we have a method or loop that needs to traverse through the board. In other words, instead of 3 we will place n. This will "generalize" our program. For example, within the display method we have 2 for loops that run as long as i and j are smaller than 3. To "generalize" our program to a semi-arbitrary board size(3 or 4), we place an n in place of the 3 so that the loop will run as long as i and j are smaller than n(3 or 4). This change from 3 to n will apply wherever we have a 3 that indicates the size of the board. Another thing we will need to change are the checking methods hasXWon() and hasOWon(). Here, we will need to add an extra section for when the board size is 4 and not 3. This will look more or less the same as it's counterpart with the only difference being that it will check the extra row, column and longer diagonals that exist in a 4x4 board. After inserting these changes, the program now looks like this:
import java.util.*;
//defines the point where to place 1 or 2
class Point {
int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public String toString() {
return "[" + x + ", " + y + "]";
}
}
//defines the score per point -1,0,1
class PointsAndScores {
int score;
Point point;
PointsAndScores(int score, Point point) {
this.score = score;
this.point = point;
}
}
//defince the game board
class board {
List<Point> availablePoints;
Scanner scan = new Scanner(System.in);
public int n;
int[][] board;
public board(int n) {
this.n = n;
board = new int[n][n];
}
public boolean isGameOver() {
//Game is over is someone has won, or board is full (draw)
return (hasXWon() || hasOWon() || getAvailableStates().isEmpty());
}
//check if X have won represented by 1
public boolean hasXWon() {
if(n==3){
if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == 1) || (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] == 1)) {
//System.out.println("O Diagonal Win");
return true;
}
for (int i = 0; i < n; ++i) {
if (((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 1)
|| (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 1))) {
// System.out.println("O Row or Column win");
return true;
}
}
return false;
}
else {
if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == board[3][3]&& board[0][0] == 1) || (board[0][3] == board[1][2] && board[0][3] == board[2][1] && board[0][3] == board[3][0] && board[0][3] == 1)) {
//System.out.println("O Diagonal Win");
return true;
}
for (int i = 0; i < n; ++i) {
if (((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 1)
|| (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 1))) {
// System.out.println("O Row or Column win");
return true;
}
}
return false;
}
}
//check if O has won represented by 2
public boolean hasOWon() {
if(n==3){
if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == 2) || (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] == 2)) {
//System.out.println("O Diagonal Win");
return true;
}
for (int i = 0; i < n; ++i) {
if (((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 2)
|| (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 2))) {
// System.out.println("O Row or Column win");
return true;
}
}
return false;
}
else {
if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == board[3][3]&& board[0][0] == 2) || (board[0][3] == board[1][2] && board[0][3] == board[2][1] && board[0][3] == board[3][0] && board[0][3] == 2)) {
//System.out.println("O Diagonal Win");
return true;
}
for (int i = 0; i < n; ++i) {
if (((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 2)
|| (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 2))) {
// System.out.println("O Row or Column win");
return true;
}
}
return false;
}
}
//check available states in the board
public List<Point> getAvailableStates() {
availablePoints = new ArrayList<>();
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == 0) {
availablePoints.add(new Point(i, j));
}
}
}
return availablePoints;
}
//put player move in the board
public void placeAMove(Point point, int player) {
board[point.x][point.y] = player; //player = 1 for O, 2 for X..
}
//get best movement according to the board state
public Point returnBestMove() {
int MAX = -100000;
int best = -1;
for (int i = 0; i < rootsChildrenScores.size(); ++i) {
if (MAX < rootsChildrenScores.get(i).score) {
MAX = rootsChildrenScores.get(i).score;
best = i;
}
}
return rootsChildrenScores.get(best).point;
}
//accepts input from user
void takeHumanInput() {
System.out.println("Your move: ");
int x = scan.nextInt();
int y = scan.nextInt();
Point point = new Point(x, y);
placeAMove(point, 2);
}
//display current board
public void displayboard() {
System.out.println();
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
System.out.print(board[i][j] + " ");
}
System.out.println();
}
}
//get min value
public int returnMin(List<Integer> list) {
int min = Integer.MAX_VALUE;
int index = -1;
for (int i = 0; i < list.size(); ++i) {
if (list.get(i) < min) {
min = list.get(i);
index = i;
}
}
return list.get(index);
}
//get max value
public int returnMax(List<Integer> list) {
int max = Integer.MIN_VALUE;
int index = -1;
for (int i = 0; i < list.size(); ++i) {
if (list.get(i) > max) {
max = list.get(i);
index = i;
}
}
return list.get(index);
}
//declares a list for scores
List<PointsAndScores> rootsChildrenScores;
//excutes minimax algorithm
public void callMinimax(int depth, int turn){
rootsChildrenScores = new ArrayList<>();
minimax(depth, turn);
}
//minimax algorithm
public int minimax(int depth, int turn) {
if (hasXWon()) return +1;
if (hasOWon()) return -1;
//get available states from the board
List<Point> pointsAvailable = getAvailableStates();
if (pointsAvailable.isEmpty()) return 0;
//stores scores
List<Integer> scores = new ArrayList<>();
for (int i = 0; i < pointsAvailable.size(); ++i) {
Point point = pointsAvailable.get(i);
if (turn == 1) { //O's turn select the highest from below minimax() call
placeAMove(point, 1);
int currentScore = minimax(depth + 1, 2);
scores.add(currentScore);//add scores to the list
if (depth == 0)
rootsChildrenScores.add(new PointsAndScores(currentScore, point));
} else if (turn == 2) {//X's turn select the lowest from below minimax() call
placeAMove(point, 2);
scores.add(minimax(depth + 1, 1));
}
board[point.x][point.y] = 0; //Reset this point
}
return turn == 1 ? returnMax(scores) : returnMin(scores);
}
}
//main class
public class TicTacToe {
public static void main(String[] args) {
//board b = new board();//instantiate board
Random rand = new Random();//instantiate random value
Point p;
Scanner s = new Scanner(System.in);
System.out.println("Choose board size: 3 or 4?");
int n=s.nextInt();
board b = new board(n); //Instantiating board after value of n has been read. This is important because the value of n is required for the instantiation to take place.
System.out.println(b.n);
b.displayboard();//display board
System.out.println("Who's gonna move first? (1)Computer (2)User: ");
int choice = b.scan.nextInt();
if(choice == 1){
if(b.n==3)
p = new Point(rand.nextInt(3), rand.nextInt(3));
else
p = new Point(rand.nextInt(4), rand.nextInt(4));
b.placeAMove(p, 1);
b.displayboard();
}
while (!b.isGameOver()) {
System.out.println("Your move: ");
Point userMove = new Point(b.scan.nextInt(), b.scan.nextInt());
b.placeAMove(userMove, 2); //2 for X and X is the user
b.displayboard();
if (b.isGameOver()) {
break;
}
b.callMinimax(0, 1);
for (PointsAndScores pas : b.rootsChildrenScores) {
System.out.println("Point: " + pas.point + " Score: " + pas.score);
}
b.placeAMove(b.returnBestMove(), 1);
b.displayboard();
}
if (b.hasXWon()) {
System.out.println("Unfortunately, you lost!");
} else if (b.hasOWon()) {
System.out.println("You win! This is not going to get printed.");
} else {
System.out.println("It's a draw!");
}
}
}
Your program is now able to create 4x4 games. There are however two things that you need to do. First, your placeAMove(...) method doesn't check if a cell is occupied before filling it. This may lead to cells being overwritten, so you must change that by checking if a cell is occupied before trying to fill it. The second and more important thing is that although the program is now able to create 4x4 games, it will not be able to carryout a proper game. The reason for this is that the number of nodes(states) created by minimax to find the next move, although manageable in 3x3 games, rises dramatically for 4x4 games. This means that it would take your computer A LOT of time, and by a lot I mean hours, to calculate the computer's second move. Even when I rigged the game(i.e. manually inserted random 1s and 2s in the cells before allowing minimax to be called to choose the computer's move) it still took the computer over 30 seconds to calculate it's move. This renders your game, of course, unplayable in 4x4 mode. There are, of course, ways, such as Memoization or Alpha-Beta Pruning or both together, to overcome this and speed up your algorithm. Here is a previously asked question to get you started on these topics. The chess programming wiki is also a good source of information on such topics, if a bit more complex in it's structure. Here's their entry on Memoization(Here called transposition tables).
This is a class that creates the game connect four in console and drawing panel, and I am having trouble in the connectedFour method where it determines if someone has gotten 4 discs in a row. The problem is, is that I am not sure how to set up my for loops to check through the array for four discs in a row
Here is my code:
import java.util.*;
import java.awt.*;
public class ConnectFour{
public static void main(String[] args){
//board
DrawingPanel panel = new DrawingPanel(550,550);
int rowAvailable;
Graphics g = panel.getGraphics();
g.drawLine(0,0,0,500);
g.drawLine(0,0,500,0);
g.drawLine(500,0,500,427);
g.drawLine(0,427,500,427);
for(int i = 0; i< 6; i++){
for(int j= 0; j<= 6; j++){
g.setColor(Color.YELLOW);
g.fillRect(j*71,i*71,71,71);
g.setColor(Color.WHITE);
g.fillOval(j*71,i*71,71,71);
}
}
//setBlankArray
Scanner console = new Scanner(System.in);
char[][] board = new char[6][7];
for(int j = 0;j <= 6; j++){
for(int i= 0; i < 6; i++){
board[i][j] = ' ';
}
}
boolean isBlack = true;
boolean isRed = false;
int column = 0;
boolean playersTurn = true;
boolean rightNum = false;
//oneTurn
while(getWinner(board, playersTurn)){
//while(playersTurn == true){
rightNum = false;
if(isBlack == true){
// displayCurrentPlayer
System.out.println("Black's Turn");
g.setColor(Color.WHITE);
g.drawString("Red Disc's Turn",200, 450);
g.setColor(Color.BLACK);
g.drawString("Black Disc's Turn",200, 450);
}
else{
// displayCurrentPlayer
System.out.println("Red's Turn");
g.setColor(Color.WHITE);
g.drawString("Black Disc's Turn",200, 450);
g.setColor(Color.RED);
g.drawString("Red Disc's Turn",200, 450);
}
System.out.print("Choose a column to place your disk (1-7): ");
while(rightNum == false){
column = (console.nextInt()) -1;
if(column >= 0 && column < 7 && board[0][column] == ' '){
rightNum = true;
}
else{
System.out.print("Try again: ");
}
}
drawBoard(column, board, isBlack, isRed, board, g);
isBlack = !isBlack;
}
if(isBlack == false){System.out.println("Congratulations Black Player");}
else{System.out.println("Congratulations Red Player");}
// use the while loop to say try again if the column is filled.
}
public static void drawBoard(int column, char[][] board, boolean isBlack, boolean isRed, char[][] availability,Graphics g){
char player = ' ';
if(isBlack == true){
g.setColor(Color.BLACK);
player = 'b';
}
else{
g.setColor(Color.RED);
player = 'r';
}
int x = 0;
int row = 5;
while(board[row-x][column] != ' '){
x++;
}
row = row-x;
g.fillOval((column * 71),(row * 71), 71,71);
board[row][column] = player;
}
public static boolean getWinner(char[][] board, boolean playersTurn){
int verticalCount = 0;
boolean isVertical = false;
for(int i = 6; i >= 0; i--){
verticalCount = 0;
for(int j = 5; j > 0; j--){
if(board[j][i] == board[j-1][i] && board[j][i] != ' '){
verticalCount++;
}
if(verticalCount == 4){
isVertical = true;
}
}
}
int horizontalCount = 0;
boolean isHorizontal = false;
for(int i =1; i <= 5; i++){
for(int j =1; j<6; j++){
if(board[j][i] == board[j][i+1] && board[j][i] != ' '){
horizontalCount++;
}
if(horizontalCount == 3){
isHorizontal = true;
}
}
}
int diagonalCount = 0;
boolean isDiagonal = false;
// for(int i = 0; i<=6; i++){
// for(int j =0; j<6; j++){
// if(board[i][j-1] == board[i][j]){
// diagonalCount++;
// }
// }
// }
if(isVertical || isHorizontal || isDiagonal){
playersTurn = false;
}
else{
playersTurn = true;}
return playersTurn;
}
}
I would implement this by checking if the game-winning condition is met after a disc has been placed. This way you aren't iterating over the entire board after each move.
Regardless, try this:
replace
while (gameWon == false ){
with
while (!connectedFour(board, playersTurn)) {
I don't think this will completely fix your problems as it looks like there are a handful of other things wrong with the code you've posted.