Making Connect Four in Java (Dropping the checker) - java

Right now I'm making Connect Four in Java. I'm currently working on being able to drop the checker but I'm running into some problems. This is my code so far:
private static char board[][];
private static final int BOARD_WIDTH = 7;
private static final int BOARD_HEIGHT = 6;
private static boolean gameEnd = false;
public static void main(String[] args)
{
// Element #0 in the two-dimensional 'board' array is not used
// so that the column numbers selected by the players match
// with the actual internal element numbers of the array
board = new char[BOARD_HEIGHT + 1][BOARD_WIDTH + 1];
Scanner input = new Scanner(System.in);
char turn = 'x';
int dropColumn = 0;
System.out.println("TWO PLAYER CONNECT FOUR GAME!");
InitializeBoard();
while (gameEnd == false)
{
DisplayBoard();
dropColumn = GetDropColumn(turn, input);
if (turn == 'x')
turn = 'o';
else
turn = 'x';
if (DropChecker(turn, dropColumn) == true)
board[BOARD_HEIGHT][dropColumn] = turn;
}
}
// Set all elements of the two-dimensional 'board' array to spaces
private static void InitializeBoard()
{
char a = ' ';
for (int i = 0; i < board.length; i++)
{
board[i][0] = a;
}
for (int e = 0; e < board.length; e++)
{
board[0][e] = a;
}
}
// Display the game board (the board itself, along with the elements of
// the two-dimensional 'board' array); note that the lines of the game
// board are NOT stored in the two-dimensional 'board' array
private static void DisplayBoard()
{
for (int row = 0; row < board.length; row++)
{
for (int col = 0; col < board.length; col++)
{
System.out.print("|");
System.out.printf("%3c", board[row][col]);
}
System.out.println();
}
}
// Get (from the appropriate player) the number (1 – 'BOARD_WIDTH') of
// the column in which a checker should be dropped, and then return that
// number; if the player does not enter an integer, report the error and
// keep asking for a column number until an integer is entered; note that
// the check for an invalid column number (< 1 or > 'BOARD_WIDTH') can be
// performed in this method or in 'main', from where this method is called
private static int GetDropColumn(char turn, Scanner input)
{
int numInput = 0;
int realInput = 0;
while (realInput == 0)
{
try
{
System.out.println("Player " + turn + "'s turn: In which column would you like to place a checker? (1-7)");
numInput = input.nextInt();
if (numInput < 1 || numInput > BOARD_WIDTH)
{
numInput = 0;
System.out.println("The number was out of bounds. Please try again.");
}
}
catch (NumberFormatException e)
{
System.out.println("Invalid input. Please try again.");
}
realInput = numInput;
}
return realInput;
}
// "Drop" a checker into the designated column by setting the
// appropriate element of the two-dimensional 'board' array to
// either an 'x' or an 'o'; if the "drop" was successful, this
// method returns "true"; an attempt to "drop" the checker into
// a full column results in "false" being returned
private static boolean DropChecker(char turn, int dropColumn)
{
int count = 0;
while (count < BOARD_HEIGHT)
{
if (board[BOARD_HEIGHT - count][dropColumn] == ' ')
{
return true;
}
count++;
}
return false;
}
My problem currently is that the program won't drop the checker on the board. After I enter column 6, the program returns the board but the checker has not been dropped. What am I missing/doing wrong here?

There are a few issues with your code
The turn of the player's is reversed, so what you need to do is change the player AFTER they drop the piece, not before
The initialize board method is off, just use two for loops to initialize it
The index of placing the checker was incorrect, so start with the index at the bottom and then decrement whenever the space isn't "empty" (== ' ')
1.Main Game Loop Refactor
while (gameEnd == false)
{
DisplayBoard();
dropColumn = GetDropColumn(turn, input);
if (DropChecker(turn, dropColumn) == true)
{
turn = 'x' == turn ? 'o' : 'x'; //ternary operator works great
}
}
2.Initialize Method refactor
private static void InitializeBoard()
{
char a = ' ';
for (int i = 0; i < board.length; i++)
{
for (int e = 0; e < board[i].length; e++)
board[i][e] = a;
}
}
3.Drop Checker Method Refactor
private static boolean DropChecker(char turn, int dropColumn)
{
int indexToPaceChecker = BOARD_HEIGHT;
while (indexToPaceChecker >= 0)
{
if (board[indexToPaceChecker][dropColumn] == ' ')
{
//drop the checker, that's what this method is supposed to do anyways :)
board[indexToPaceChecker][dropColumn] = turn;
return true;
}
indexToPaceChecker--;
}
return false;
}
I'd also recommend using private static final char emptySpace = ' '; that way in your code you can intitialize the board like board[i][e] = emptySpace;, and check for an empty space like if (board[indexToPaceChecker][dropColumn] == emptySpace). It's cleaner and easier to make changes if you wanted a different board fill.

DropChecker() just checks if there is a free place in the column. Instead you should return which line is the lowest one (the one with the highest index), if there is no you could return -1.
You are setting the wrong row with the following line: board[BOARD_HEIGHT][dropColumn] = turn this puts turn into last line.
You are also not initializing your board array (if you not initialize it, it's not the same as ' ', which is also a char)
This should work for you:
private static int DropChecker(char turn, int dropColumn) {
int count = 0;
while (count < BOARD_HEIGHT) {
if (board[BOARD_HEIGHT - count][dropColumn] == ' ') {
count++;
}
else {
return --count;
}
}
}
You set the place in the board with this:
board[DropChecker(turn, dropColumn)][dropColumn]
Add this lines at the beginning of main, right after board = new char[][] :
for(int i = 0; i < BOARD_HEIGHT; i++) {
for(int j = 0; j < BOARD_WIDTH; j++) {
board[i][j] = ' ';
}
}

Related

Java Program to Determine if there are any Duplicate Rows in the Matrix of a 2-Dimensional Array?

So, as the title says, I'm trying to put together a program that will compare the rows of a 2-dimensional array and determine if any rows are identical.
This has to be accomplished in two parts; determining whether any rows are identical and determining how many rows are identical. I'm trying to use a Boolean method to determine whether there are any identical rows and a separate method to determine how many rows are identical if the Boolean method returns true.
For example, if the array were:
1 2 3
2 3 1
1 2 3
Then the Boolean method would return true and the output would be:
The matrix has 2 identical rows.
The issue is that I don't know how I should set up the Boolean method; if I could figure that much out, the rest of the program would be simple to figure out.
How can I set up the Boolean method for this?
Here's the code I've come up with so far if anyone needs it:
public class IdenticalRows {
public static void main(String[] args) {
Scanner KBin = new Scanner(System.in);
char run;
int ROW, COL;
System.out.println("Would you like to begin? (Y/N)");
run = KBin.next().charAt(0);
do {
if(run!='y' && run!='Y' && run!='n' && run!='N') {
System.out.println("Please only type 'y' or 'Y' to begin or type 'n' or 'N' to close the program.");
System.out.println("Would you like to begin? (Y/N)");
run = KBin.next().charAt(0);
}
}while(run!='y' && run!='Y' && run!='n' && run!='N');
do {
System.out.println("Please enter the number of rows:");
ROW = KBin.nextInt();
do {
if (ROW<=0) {
System.out.println("Entry invalid; must be a positive integer greater than 0.");
System.out.println("Please enter the number of rows:");
ROW = KBin.nextInt();
}
}while(ROW<=0);
System.out.println("Please enter the number of columns:");
COL = KBin.nextInt();
do {
if (COL<=0) {
System.out.println("Entry invalid; must be a positive integer greater than 0.");
System.out.println("Please enter the number of columns:");
COL = KBin.nextInt();
}
}while(COL<=0);
int[][] testDuplicates = new int[ROW][COL];
randArray (testDuplicates, MIN, MAX);
System.out.println("Thematrix is:");
printArray(testDuplicates);
System.out.println(" ");
boolean presence = duplicates(testDuplicates);
if (presence=true) {
countDuplicates(testDuplicates);
}
else if (presence=false) {
System.out.println("There are no identical rows in this matrix.");
}
System.out.println("Would you like to run the program again? (Y/N)");
run = KBin.next().charAt(0);
}while(run=='y' || run=='Y');
}
public static void randArray(int[][] matrix, int low, int up) {//Establishes the values of the elements of the array
Random rand = new Random();
for (int r = 0; r < matrix.length; r++) {
for (int c = 0; c < matrix[r].length; c++) {
matrix[r][c] = rand.nextInt(up-low+1)+low;
}
}
}
public static void printArray(int[][] matrix) {//Prints the elements of the array in a square matrix
for (int r = 0; r < matrix.length; r++) {
for (int c = 0; c < matrix[r].length; c++) {
System.out.printf("%5d",matrix[r][c]);
}
System.out.println(" ");
}
}
public static boolean duplicates(int[][] list) {//Determines if any row(s) of elements ever repeat
for (int r=0; r<list.length; r++) {
for (int c=0; c<list[r].length; c++) {
}
}
return false;
}
public static void countDuplicates(int[][] matrix) {
for (int r=0; r<matrix.length; r++) {
for (int c=0; c<matrix[r].length; c++) {
}
}
}
public static final int MAX=3;
public static final int MIN=1;
}
Thank you in advance to anyone who can help!
First of all write the method that compares two rows:
private static boolean areIdentical(int[] a1, int[] a2) {
if(a1.length != a2.length) return false;
for(int i = 0; i < a1.length; i++) {
if(a1[i] != a2[i]) return false;
}
return true;
}
Now you can use this method to compare the rows. Just take every row from the array and compare it with every row below. Something like the next:
public static boolean duplicates(int[][] list) {
for (int j = 0; j < list.length; j++) {
if(j == list.length-1) return false; //don't need to compare last row
for (int i = j + 1; i < list.length; i++) {
if(areIdentical(list[j], list[i])) return true;
}
}
return false;
}
You can easily modify this code to count duplicates.

Tic-Tac-Toe Program Design Level 1 in Java

I need assistance on how to start 'playing' the game like if the user inputs any number from 1-9 that number will be replaced by 'X' or 'O'.
Here is my code so far:
import java.util.Scanner;
public class TicTacToe {
public static char[][] board = new char[3][3];
public static void main(String[] args){
Scanner kb = new Scanner(System.in);
Player player1 = new Player("John");
Player player2 = new Player("Jill");
initBoard();
int turn = 1;
int choice = 0;
while(choice != -1){
printBoard();
Player currentPlayer = player1;
if(turn % 2 == 0){
currentPlayer = player2;
}
System.out.print(currentPlayer + ", pick a box: ");
if(choice == 1){
board[0][0] = 'X';
}
turn++;
choice = kb.nextInt();
}
}
public static void initBoard(){
for(int r = 0; r < board.length; r++){
for(int c = 0; c < board[r].length; c++){
board[r][c] = (char)((r*3)+(c+1)+48);
}
}
}
public static void printBoard(){
for(int r = 0; r < board.length; r++){
for(int c = 0; c < board[r].length; c++){
System.out.print(board[r][c]+" ");
}
System.out.println();
}
}
}
class Player{
String name;
int wins = 0;
int losses = 0;
int draws = 0;
public Player(String s){
name = s;
}
public String toString(){
return name;
}
}
Note: I'm not asking anyone to complete my homework for me, I just need a hint on how to place the 'X's and 'O's and to check to see if one of the boards has already an 'X' or 'O'.
I suppose that you are asking how to convert 1-9 into matrix indices.
In such case, if you the matrix
`
|0|1|2| -----> j - column
|1|2|3| 0
|4|5|6| 1
|7|8|9| 2
`
You could find the pattern that allows you to convert numbers to indicies.
i = (input - 1) / 3;
j = (input - 1) % 3;
You are on the right track, you can do something like:
if (board[row][col] != 'X' || board[row][col] != 'O'){ //Position is currently a number since it isn't X or O
// do something here since move is valid
}
You can also also initialize your board to ' ' instead of the actual numbers, then check if the board spot is equal to a space or not.
public static void initBoard(){
for(int r = 0; r < board.length; r++){
for(int c = 0; c < board[r].length; c++){
board[r][c] = ' '; // space here instead of numbers
}
}
}
if (board[row][col] == ' '){ // Board spot is a space so spot has not been played on
// do something here since move is valid
}

How to check and end a 2d array of noughts and crosses (Java)

I have made a noughts and crosses game using 2D arrays and loops (code is below).I want to end the game once the array is full. I've tried an if statement such as if (board[row][col] = '.') however i'm told this is incompatible as it can't be converted to a boolean. Another idea i have is to count the data entries and end it after 9 goes. However, im new to java and struggling to do these can anyone tell me how to end the game once the array is full?
public static void main(String[] args) {
// TODO code application logic here
Scanner scanner = new Scanner(System.in);
// declare and intitialise the board
char[][] board = new char[3][3];
// initialise all the elements to '.' we use this to indicate that a
// square is empty, because a space character would not be visible
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
board[row][col] = '.';
}
}
//The first player is X
int placeRow;
int placeCol;
char thisPlayer = 'X';
boolean finished = false;
while (!finished) {
//Display the board
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
System.out.print(board[row][col]);
}
System.out.println();
}
// Ask the user where to place the next character
System.out.println("Character to be placed is " + thisPlayer);
System.out.print("Enter the row at which you wish to place it> ");
placeRow = scanner.nextInt();
System.out.print("Enter the column at which you wish to place it> ");
placeCol = scanner.nextInt();
if (placeRow < 0 || placeRow > 2 || placeCol < 0 || placeCol > 2 ) {
finished=true;
}
while (!finished) {
//Display the board
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
}
System.out.println();
}
board[placeRow][placeCol] = thisPlayer;
thisPlayer = (thisPlayer == 'X') ? 'O' : 'X';
break;
}
}
}
Incompatible types in an if clause
I've tried an if statement such as if (board[row][col] = '.') however i'm told this is incompatible as it can't be converted to a boolean.
You've been told that, because = is the assignment operator.
In order to check equality you should use == equal to operator:
if (board[row][col] == '.') {
/* do smth */
}
I suggest reading the following articles on operators:
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
How to stop execution when the board is full
count the data entries and end it after 9 goes
You have the right idea, you just go through the board at the end of every iteration (just as you do when printing it's content), and check with != not equal operator whether the cells contain anything but dots.
// your external loop
while (!finished) {
/* Displaying the board, prompting for inputs */
// Calculating number of data entries across the board
int dataEntries = 0;
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
if (board[row][col] != '.') {
dataEntries ++;
}
}
}
// Break loop if there are 9 data entries
if (dataEntries > 8) {
System.out.println("Board is full, game over.");
break;
}
}

Stuck in Sudoku backtracking solver (Java)

I have been trying to figure out my mistake in the Sudoku backtracking solver for three days. The problem is from leetcode Sudoku Solver.
My solver is based on the deduction in the attached picture. The problem is that my board is changed even if a path from root to leaf is invalid.
In other words, after it goes through an invalid path, the values it attempted are fixed in my original board. However, I only update my original board when its children returns true ( see the part in helper method: // put a number and generate children).
Basically, for each '.', I generate all possibilities from 1 to 9, construct a temp board which fills the current '.' with one possibility, then call helper of the next '.' with temp board. I know it is not good to store a same size boardTemp for each possible child because of space cost, but my main concern now is to solve the problem first before optimizing the cost.
All in all, why is my board changing even if all children is not valid?
For example, base on the initial board
..9748...; 7........; .2.1.9...;
..7...24.; .64.1.59.; .98...3..;
...8.3.2.; ........6; ...2759..;
I got the final result after I run:
139748652; 745326189; 826159437;
35769.24.; .64.1.59.; .98...3..;
...8.3.2.; ........6; ...2759..;
public void sudokuSolver(char[][] board) {
for (int i = 0 ; i < board.length ; i++) {
for (int j = 0 ; j < board.length ; j++) {
if (board[i][j] == '.') {
// find the first '.' as root
helper(i, j, board);
return;
}
}
}
}
private boolean helper(int row, int col, char[][] board) {
// case 2. check if it has following '.' and store its position
boolean hasNext = false;
boolean nextSearching = false;
int nextRow = row;
int nextCol = col;
for (int i = 0 ; i < board.length ; i++) {
for (int j = 0; j < board.length ; j++) {
if (nextSearching && !hasNext && board[i][j] == '.') {
hasNext = true; // there is next!
nextRow = i;
nextCol = j;
}
if (i == row && j == col) {
nextSearching = true;
}
}
}
// exit condition: last '.'
if (!hasNext) {
for (char put = '1' ; put <= '9' ; put ++) {
if (isValid(row, col, board, put)) {
return true;
}
}
return false;
}
// put a number and generate children
for (char put = '1' ; put <= '9' ; put ++) {
if (isValid(row, col, board, put)) {
char[][] boardTemp = board;
boardTemp[row][col] = put;
boolean valid = helper(nextRow, nextCol, boardTemp);
if (valid) {
// board is supposed to change only when valid is true.
board[row][col] = put;
return true;
}
}
}
return false;
}
private boolean isValid(int row, int col, char[][] board, char c) {
// go through each row, column, and subblock to determine if c is a valid choice based on current board.
for (int jCol = 0 ; jCol < 9 ; jCol ++) {
if (board[row][jCol] == c) {
return false;
}
}
for (int iRow = 0 ; iRow < 9 ; iRow ++) {
if (board[iRow][col] == c) {
return false;
}
}
for (int i = row/3*3 ; i < row/3*3 + 3 ; i++) {
for (int j = col/3*3 ; j < col/3*3 + 3 ; j++) {
if (board[i][j] == c) {
return false;
}
}
}
return true;
}
There is no difference between using boardTemp and board. char[][] boardTemp = board means they point to the same memory... What you missed in your original code is the else part in after you put an invalid number:
for (char put = '1' ; put <= '9' ; put ++) {
if (isValid(row, col, board, put)) {
char[][] boardTemp = board; // board and boardTemp are essentially the same thing
boardTemp[row][col] = put;
boolean valid = helper(nextRow, nextCol, boardTemp);
if (valid) {
// board is supposed to change only when valid is true.
board[row][col] = put;
return true;
}
// THIS IS WHAT YOU MISSED!!
// if you don't reset the '.' back, your later backtrack will not work
// because you put an invalid number on your board and you will never find a solution
boardTemp[row][col] = '.';
}
}

Using Recursion in java

I'm working on the Conway's game of life program. I have the first two generations of cells printed out, but I can not get anymore printed. So I decided to use recursion so multiple batches of cells can be printed. My NewCells method creates the second generation. I thought that If I were to repeat said method by returning NewCells(c) instead of c, It would print out different results, but it prints out the same batch of cells over and over again.
public class Life {
public static boolean[][] NewCells(boolean[][] c)
{
int N = 5;
int o=0;
int p=0;
int livecnt = 0; //keeps track of the alive cells surrounding cell
int store = 0; //amount of surrounding cells for each individual cell
int livestore[] = new int[N*N];
System.out.println("Next Generation");
// Checks for the amount of "*" surrounding (o,p)
for (o=0; o < N; o++)
{
for (p=0; p<N; p++)
{
for (int k=(o-1); k <= o+1; k++)
{
for (int l =(p-1); l <=p+1; l++)
{
if ( k >= 0 && k < N && l >= 0 && l < N) //for the border indexes.
{
if (!(k== o && l==p)) //so livecnt won't include the index being checked.
{
if (c[k][l] == true)
{
livecnt++;
}
}
}
}
}
livestore[store]= livecnt;
livecnt = 0;
store++;
}
}
//Prints the next batch of cells
int counter= 0;
for (int i2 = 0; i2 <N; i2++)
{
for (int j2 = 0; j2 < N; j2++)
{
if (c[i2][j2] == false)
{
if (livestore[counter] ==3)
{
c[i2][j2]=true;
System.out.print("* ");
}
else
System.out.print("- ");
}
else if (c[i2][j2] == true)
{
if (livestore[counter] ==1)
{
c[i2][j2]= false;
System.out.print("- ");
}
else if (livestore[counter] >3)
{
c[i2][j2]= false;
System.out.print("- ");
}
else
System.out.print("* ");
}
counter++;
}
System.out.println();
}
return NewCell(c);
}
/*************************************************************************************************************************************************/
public static void main(String[] args)
{
int N = 5;
boolean[][] b = new boolean[N][N];
double cellmaker = Math.random();
int i = 0;
int j = 0;
int o=0;
int p=0;
int livecnt = 0; //keeps track of the alive cells surrounding cell
int store = 0; //amount of surrounding cells for each individual cell
int livestore[] = new int[N*N];
System.out.println("First Generation:");
// Makes the first batch of cells
for ( i = 0; i < N ; i++)
{
for ( j = 0; j< N; j++)
{
cellmaker = Math.random();
if (cellmaker > 0.5) // * = alive; - = dead
{
b[i][j]=true;
System.out.print( "* ");
}
if (cellmaker < 0.5)
{ b[i][j] = false;
System.out.print("- ");
}
}
System.out.println();
}
boolean[][] newcells = new boolean[N][N];
newcells = NewCells(b);
}
}
I do not think recursion is a good idea for this application. It leads to a StackOverflowError because each generation pushes another call stack frame. Recursion, as this program uses it, has no advantage over iteration.
Instead, put the main method call to NewCells in a loop. That way, you can run as many iterations as you like, regardless of stack size.
You are not calling NewCell from within NewCell, which is how recursion works.
I'm assuming it's not a typo in your question, but rather a lack of understanding of what it is and how it works, I recommend some reading on recursion in Java.
After you understand the basics, come back here for more help!

Categories