Writing the findWinner() for a tictactoe game - java

I am writing a tictactoe game and I am stuck in writing the findWinner(). The following is what I have but it does not do anything when a player wins any diagonal.
I am using access1 and access2 to evaluate whether all the members of the array are equal or not. Since the loop happens 2 times, if they equal 2, then I return true. Thank you
public static boolean diagonalTest()
{
/*create a TicTacToe object to access private fields*/
TicTacToe temp = new TicTacToe();
/*an ArrayList to store the values*/
ArrayList<Character> major = new ArrayList<Character>();
int k = 0;
while(k < temp.getRow())
{
major.add(temp.getBoard()[k][k]);
k++;
}
/*to test whether the values in the array are equal to each other*/
int access1 = 0;
for(int i = 1; i < major.size(); i++)
if(major.get(0) != ' ' && major.get(0) == major.get(i))
access1++;
ArrayList<Character> minor = new ArrayList<Character>();
k = 0;
while(k < temp.getRow())
{
minor.add(temp.getBoard()[k][temp.getColumn() - 1 - k]);
k++;
}
int access2 = 0;
for(int a = 1; a < minor.size(); a++)
if(minor.get(0) != ' ' && minor.get(0) == minor.get(a))
access2++;
if(access1 == 2 || access2 == 2)
return true;
return false;
}

Related

I'm writing a program that compares two arrays together, but I can't get it to compare arrays with empty elements

My code is pasted below. The program works fine on different types of two-dimensional arrays, where if they're identical it returns "true", and if they're not it returns false. However there is a small bug when both arrays have empty elements in both their dimensions:
int a[][] = {{},{}};
int b[][] = {{},{}};
This input needs to return "true" since the arrays are still identical, however I'm getting an array index out of bounds error. Is there any way I can make my program recognize that these two arrays are still identical?
public class ArrayCompare {
public static void main(String[] args){
int a[][] = {{},{}};
int b[][] = {{},{}};
boolean result = equals(a,b);
System.out.println(result);
}
public static boolean equals(int[][] a, int[][] b) {
boolean boo = true;
if (a != null && b != null) {
if (a.length != b.length || a[0].length != b[0].length || a[1].length != b[1].length)
boo = false;
else
for (int i = 0; i < b.length; i++) {
for(int j =0; j <b.length; j++) {
if (b[i][j] != a[i][j]) {
boo = false;
}
}
}
}else {
boo = false;
}
return boo;
}
}
Add this check to the else statement a[i].length > 0:
else {
for (int i = 0; i < b.length; i++) {
if (a[i].length > 0) { // add check for empty array
for (int j = 0; j < b.length; j++) {
//...
}
}
}
}
P.S.
Your code works fine with some correction. Probably I give you idea, how to improve it. What about this one:
public static boolean equals(int[][] one, int[][] two) {
if (one == null || two == null || one.length != two.length)
return false;
for (int row = 0; row < one.length; row++) {
if (one[row].length != two[row].length)
return false;
for (int col = 0; col < one[row].length; col++)
if (one[row][col] != two[row][col])
return false;
}
return true;
}
There is a small logical flaw in your code. In the nested loop, you should iterate over the elements from each array.
for (int i = 0; i < b.length; i++) {
for(int j =0; j <b[i].length; j++) {// iterate over the number of elements of the current array
if (b[i][j] != a[i][j]) {
boo = false;
}
}
}

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
}

Making Connect Four in Java (Dropping the checker)

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] = ' ';
}
}

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