Here is my code. I am trying to check for the winner. I am only a beginner, so please make it easy. I wanted the board to change sizes. So, I want the check for winner can get use to the size, it will not just check the 9 blocks.
import java.util.*;
public class TicTacToe {
private String[][] board;
private Scanner console;
public TicTacToe(String[][] table, Scanner console) {
this.board = table;
this.console = console;
}
public void makeTable() {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
board[i][j] = "_";
}
}
}
public void printTable() {
System.out.print(" ");
for (int i = 0; i < board.length; i++) {
System.out.print(" " + i);
}
System.out.println();
for (int i = 0; i < board.length; i++) {
System.out.print(i + "│");
for (int j = 0; j < board[i].length; j++) {
System.out.print(board[i][j] + "│");
}
System.out.println();
}
}
public void play(Scanner console) {
int turn = 0;
String player = "_";
makeTable();
printTable();
while (turn != 9) {
int x = console.nextInt();
int y = console.nextInt();
while (x >= board.length || y >= board[1].length) {
System.out.println("Out of bounce, try again!!!");
x = console.nextInt();
y = console.nextInt();
}
while (board[y][x] != "_") {
System.out.println("Occupied, try again!!!");
x = console.nextInt();
y = console.nextInt();
}
if (turn % 2 == 0) {
player = "X";
} else {
player = "O";
}
board[y][x] = player;
turn++;
printTable();
}
}
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
String[][] board = new String[3][3];
TicTacToe ttt = new TicTacToe(board, console);
ttt.play(console);
}
}
A winning move can only happen when a piece is placed on the board, so you only need to check winning combinations that involve the piece that was just placed on the board.
For example, if the current state of the board is:
O X O
X X
O
And O places their piece in the middle of the board:
O X O
X O X
O
Then you only need to check the winning combinations that involve this middle piece, namely both diagonals, and the middle column and middle row (4 combinations) out of the total number of winning combinations (8 combinations).
Thus, tracking the last move made is essential to effectively determining if the board is in a winning state.
EDIT
As one person already mentioned, what you're essentially doing is checking to see if the last played move is a winning move. As a result, there really isn't any need to brute force check every row, column, and diagonal systematically to see if there's a winning position or to create some sort of list or table of solutions to check the current board against.
All you really need to do is check the row, column, and diagonal (if the move was on a diagonal) that the move was played on and see if the winning condition is met there.
// Takes the row and column coordinates of the last move made
// and checks to see if that move causes the player to win
public boolean isWinner(int row, int col){
String Player = board[row][col];
int r = row;
int c = col;
boolean onDiagonal = (row == col) || (col == -1 * row + (board.length-1));
boolean HorizontalWin = true, VerticalWin = true;
boolean DiagonalWinOne = true; DiagonalWinTwo = true;
// Check the rows and columns
for(int n = 0; n < board.length; n++){
if(!board[r][n].equals(Player))
HorizontalWin = false;
if(!board[n][c].equals(Player))
VerticalWin = false;
}
// Only check diagonals if the move is on a diagonal
if(onDiagonal){
// Check the diagonals
for(int n = 0; n < board.length; n++){
if(!board[n][n].equals(Player))
DiagonalWinOne = false;
if(!board[n][-1*n+(board.length-1)].equals(Player))
DiagonalWinTwo = false;
}
}
else{
DiagonalWinOne = false;
DiagonalWinTwo = false;
}
boolean hasWon = (HorizontalWin || VerticalWin || DiagonalWinOne || DiagonalWinTwo);
return hasWon;
}
ORIGINAL
A few people have already answered this question, but here's my answer just for the heck of it.
Also, in your play method, you have a while loop to check to make sure that the user doesn't specify a move that is out-of-bounds, but then afterwards you have another while loop check to make sure that the move is in an empty space. You'll still probably want to check to make sure that their new move is also within the boundaries otherwise your loop condition will throw an ArrayOutOfBoundsException.
public boolean isWinner(String player){
// Check for N-in-a-row on the rows and columns
for(int i = 0; i < board.length; i++){
boolean verticalWin = true, horizontalWin = true;
for(int j = 0; j < board.length; j++){
if(!board[i][j].equals(player)))
horizontalWin = false;
if(!board[j][i].equals(player))
verticalWin = false;
if(!(horizontalWin || verticalWin))
break;
}
if(horizontalWin || verticalWin)
return true;
}
// If there was a N-in-a-row on the rows or columns
// the method would have returned by now, so we're
// going to check the diagonals
// Check for N-in-a-row on both the diagonals
boolean diagonalWinOne = true, diagonalWinTwo = true;
for(int n = 0; n < board.length; n++){
diagonalWinOne = true;
diagonalWinTwo = true;
int row = board.length - 1 - n;
if(!board[n][n].equals(player))
diagonalWinOne = false;
if(!board[row][n].equals(player))
diagonalWinTwo = false;
if(!(diagonalOne || diagonalTwo))
break;
}
// If either one of the diagonals has N-in-a-row, then there's a winner
if(diagonalWinOne || diagonalWinTwo)
return true;
// Otherwise, no one has won yet
else
return false;
}
Ok here is how I did it when I made tic-tac-toe. I used Strings
Create a 2D array that contains all the possible winning combinations
Create two String variables, one for each player.
Display the board on the table
Number each of the blocks from 1 to 9 starting at the top left corner
Whenever the either of the user clicks on the board, append the number to the player String
Now, here comes the magic part, checking the winner:
6. For every click on the board, start iterating on the 2d winning combination. Here is how you check if somebody has won:
String[][] winningCombo = ... initialization ...
for( int i = 0 ; i < winningCombo.length; i++){
for(j = 0; j < winningCombo[i].length; j ++){
char c1 = winningCombo[i][j].charAt(0);
char c2 = winningCombo[i][j].charAt(1);
char c3 = winningCombo[i][j].charAt(2);
if(currentPlayerString.contains(c1) && currentPlayerString.contains(c2) && currentPlayerString.contains(c3)){
// currentPlayer has won if he has all the 3 positions of a winning combo
}
}
}
So, if you may consider an alternative approach, you can use that. I used Swing for UI and used GridLayout to layout the various JPanel.
just check rows, cols and both diagonals:
import java.util.Scanner;
public class TTT {
private String[][] board;
private Scanner console;
private int size;
public TTT(String[][] table, Scanner console, int size) {
this.board = table;
this.console = console;
this.size = size;
}
public void makeTable() {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
board[i][j] = "_";
}
}
}
public void printTable() {
System.out.print(" ");
for (int i = 0; i < board.length; i++) {
System.out.print(" " + i);
}
System.out.println();
for (int i = 0; i < board.length; i++) {
System.out.print(i + "│");
for (int j = 0; j < board[i].length; j++) {
System.out.print(board[i][j] + "│");
}
System.out.println();
}
}
public void play(Scanner console) {
int turn = 0;
String player = "_";
makeTable();
printTable();
while (turn != 9) {
int x = console.nextInt();
int y = console.nextInt();
while (x >= board.length || y >= board[1].length) {
System.out.println("Out of bounce, try again!!!");
x = console.nextInt();
y = console.nextInt();
}
while (board[y][x] != "_") {
System.out.println("Occupied, try again!!!");
x = console.nextInt();
y = console.nextInt();
}
if (turn % 2 == 0) {
player = "X";
} else {
player = "O";
}
board[y][x] = player;
turn++;
printTable();
if(check()){
System.out.println("Player "+player+" won!");
break;
}
}
}
public boolean check(){
//check diagonals
if(check00ToNN()){
return true;
}
if(check0NToN0()){
return true;
}
for(int i = 0 ; i< size ; i++){
if(checkCol(i)){
return true;
}
if(checkRow(i)){
return true;
}
}
return false;
}
public boolean checkRow(int index){
for(int i = 1 ; i< size ; i++){
if(board[i-1][index]!=board[i][index]||board[i][index]=="_"){
return false;
}
}
return true;
}
public boolean checkCol(int index){
for(int i = 1 ; i< size ; i++){
if(board[index][i-1]!=board[index][i]||board[index][i]=="_"){
return false;
}
}
return true;
}
public boolean check00ToNN(){
for(int i = 1 ; i< size ; i++){
if(board[i-1][i-1]!=board[i][i]||board[i][i]=="_"){
return false;
}
}
return true;
}
public boolean check0NToN0(){ //diagonal
for(int i = 1 ; i< size ; i++){
if(board[i-1][size-i-1]!=board[i][size-i]||board[i][size-i]=="_"){
return false;
}
}
return true;
}
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
int size = 3;
String[][] board = new String[size][size];
TTT ttt = new TTT(board, console,size);
ttt.play(console);
}
}
i just look if there is a winner, since i know who had the last turn, i know who it is.
check() calls the real checkmethods.
i added size since it is scalable.
Related
I am attempting to make an unbeatable Tic Tac Toe game using a simplified minimax algorithm. The code looks like this:
private static int findBestMove(String[][] board, boolean comp) {
// comp returns true if the computer is the one looking for the best move
// findBestMove is always called by the program as findBestMove(board, true)
// since the computer is the only one that uses it
// If the board in its current state is a win for the
// player, return -1 to indicate a loss
if (playerWon(board)) return -1;
// If the board in its current state is a win for the
// computer, return 1 to indicate a win
if (compWon(board)) return 1;
// If the board in its current state is a tie
// return 0 to indicate a tie
if (tie(board)) return 0;
// Set the default possible outcome as the opposite of what
// the respective player wants
int bestPossibleOutcome = comp ? -1 : 1;
// Loop through the board looking for empty spaces
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++)
// Once an empty space is found, create a copy of the board
// with that space occupied by the respective player
if (board[i][j].equals(" ")) {
String[][] newBoard = new String[3][3];
for (int a = 0; a < 3; a++) {
System.arraycopy(board[a], 0, newBoard[a], 0, 3);
}
newBoard[i][j] = comp ? "O" : "X";
// Recursively call findBestMove() on this copy
// and see what the outcome is
int outCome = findBestMove(newBoard, !comp);
// If this is the computer's turn, and the outcome
// is higher than the value currently stored as the
// best, replace it
if (comp && outCome > bestPossibleOutcome) {
bestPossibleOutcome = outCome;
// r and c are instance variables that store the row
// and column of what the computer's next move should be
r = i;
c = j;
// If this is the player's turn, and the outcome
// is lower than the value currently stored as the
// best, replace it
} else if (!comp && outCome < bestPossibleOutcome) {
bestPossibleOutcome = outCome;
}
}
}
}
// Return the ultimate value deemed to be the best
return bestPossibleOutcome;
}
The idea is that after I run this program, the instance variables r and c should contain the row and column, respectively, of the computer's best move. However, the program only successfully prevents a loss about half the time, and I can't tell if the other half is luck, or if the program is actually working.
I am aware that the computer will respond to every scenario exactly the same way each game. That is fine.
In the event anyone would like to run the program, I have included the full class below:
import java.util.Scanner;
public class TicTacToe {
private static int r;
private static int c;
private static void printBoard(String[][] board) {
System.out.println(" 0 1 2");
System.out.println("0 " + board[0][0] + " | " + board[0][1] + " | " + board[0][2] + " ");
System.out.println(" ---+---+---");
System.out.println("1 " + board[1][0] + " | " + board[1][1] + " | " + board[1][2] + " ");
System.out.println(" ---+---+---");
System.out.println("2 " + board[2][0] + " | " + board[2][1] + " | " + board[2][2] + " ");
}
private static boolean playerWon(String[][] board) {
return playerHasThreeInCol(board) || playerHasThreeInDiag(board) || playerHasThreeInRow(board);
}
private static boolean playerHasThreeInRow(String[][] board) {
for (int i = 0; i < 3; i++) {
if (board[i][0].equals(board[i][1]) && board[i][0].equals(board[i][2]) && board[i][0].equals("X")) return true;
}
return false;
}
private static boolean playerHasThreeInCol(String[][] board) {
for (int i = 0; i < 3; i++) {
if (board[0][i].equals(board[1][i]) && board[0][i].equals(board[2][i]) && board[0][i].equals("X")) return true;
}
return false;
}
private static boolean playerHasThreeInDiag(String[][] board) {
if (board[0][0].equals(board[1][1]) && board[0][0].equals(board[2][2]) && board[0][0].equals("X")) return true;
return board[0][2].equals(board[1][1]) && board[0][2].equals(board[2][0]) && board[0][2].equals("X");
}
private static boolean compWon(String[][] board) {
return compHasThreeInCol(board) || compHasThreeInDiag(board) || compHasThreeInRow(board);
}
private static boolean compHasThreeInRow(String[][] board) {
for (int i = 0; i < 3; i++) {
if (board[i][0].equals(board[i][1]) && board[i][0].equals(board[i][2]) && board[i][0].equals("O")) return true;
}
return false;
}
private static boolean compHasThreeInCol(String[][] board) {
for (int i = 0; i < 3; i++) {
if (board[0][i].equals(board[1][i]) && board[0][i].equals(board[2][i]) && board[0][i].equals("O")) return true;
}
return false;
}
private static boolean compHasThreeInDiag(String[][] board) {
if (board[0][0].equals(board[1][1]) && board[0][0].equals(board[2][2]) && board[0][0].equals("O")) return true;
return board[0][2].equals(board[1][1]) && board[0][2].equals(board[2][0]) && board[0][2].equals("O");
}
private static boolean tie(String[][] board) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j].equals(" ")) return false;
}
}
return true;
}
private static int findBestMove(String[][] board, boolean comp) {
if (playerWon(board)) return -1;
if (compWon(board)) return 1;
if (tie(board)) return 0;
int bestPossibleOutcome = comp ? -1 : 1;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j].equals(" ")) {
String[][] newBoard = new String[3][3];
for (int a = 0; a < 3; a++) {
System.arraycopy(board[a], 0, newBoard[a], 0, 3);
}
newBoard[i][j] = comp ? "O" : "X";
int outCome = findBestMove(newBoard, !comp);
if (comp && outCome > bestPossibleOutcome) {
bestPossibleOutcome = outCome;
r = i;
c = j;
} else if (!comp && outCome < bestPossibleOutcome) {
bestPossibleOutcome = outCome;
}
}
}
}
return bestPossibleOutcome;
}
private static void go() {
Scanner input = new Scanner(System.in);
String[][] board = new String[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = " ";
}
}
printBoard(board);
for (int i = 0;; i++) {
if (i % 2 == 0) {
while (true) {
System.out.println("Enter position: ");
String position = input.nextLine();
int row, column;
try {
row = Integer.parseInt(position.substring(0, 1));
column = Integer.parseInt(position.substring(1, 2));
} catch (Exception e) {
System.out.println("Invalid entry. ");
continue;
}
if (row < 0 || row > 2 || column < 0 || column > 2) {
System.out.println("That position is not on the board. ");
continue;
}
if (!board[row][column].equals(" ")) {
System.out.println("That space is already taken. ");
continue;
}
board[row][column] = "X";
break;
}
} else {
System.out.println("\nMy move: ");
findBestMove(board, true);
board[r][c] = "O";
}
printBoard(board);
if (playerWon(board)) {
System.out.println("You win!");
break;
} else if (compWon(board)) {
System.out.println("I win!");
break;
} else if (tie(board)) {
System.out.println("Tie game");
break;
}
}
}
public static void main(String[] args) {
go();
}
}
I'm not asking for anyone to rewrite the whole thing for me, but if you can point out any obvious mistakes or point me in the right direction, that would be appreciated. I am also open to any suggestions or comments that you may have.
I haven't extensively tested it yet, but I believe that I resolved the issue. The new code looks like this:
private static void findBestMove(String[][] board) {
double bestMove = Double.NEGATIVE_INFINITY;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j].equals(" ")) {
board[i][j] = "O";
double score = minimax(board, false);
board[i][j] = " ";
if (score > bestMove) {
bestMove = score;
r = i;
c = j;
}
}
}
}
}
private static double minimax(String[][] board, boolean comp) {
if (playerWon(board)) {
return -1;
}
if (compWon(board)) {
return 1;
}
if (tie(board)) return 0;
double bestScore;
if (comp) {
bestScore = Double.NEGATIVE_INFINITY;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j].equals(" ")) {
board[i][j] = "O";
double score = minimax(board, false);
board[i][j] = " ";
bestScore = Math.max(score, bestScore);
}
}
}
} else {
bestScore = Double.POSITIVE_INFINITY;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j].equals(" ")) {
board[i][j] = "X";
double score = minimax(board, true);
board[i][j] = " ";
bestScore = Math.min(score, bestScore);
}
}
}
}
return bestScore;
}
I abstracted the minimax algorithm away from the next move coordinate setter, which I think may have made a difference. Otherwise, it is very similar.
So I've been looking into creating a simple tic-tac-toe game where the human player plays against an ai run by the minimax algorithm. I have spent the last few days trying to figure these two bugs out but I cant for the life of me seem to. for one, the ai seems sort of predictable and not very good. Secondly, the only way it seems to work is if the ai goes first, if I have the human player go first, the ai just continues to fill the next available spot. Any help would be super appreciated.
Here's my code:
import java.util.Scanner;
public class Game
{
static String player = "X";
static String opponent = "O";
int row;
int col;
public Game(int x, int y)
{
row = x;
col = y;
}
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
String [][] board = new String [3][3];
fillBoard(board);
while(true) //Infinite loop only for testing, will change back
{
getBestMove(board);
printBoard(board);
playerTurn(board, input);
printBoard(board);
//System.out.println("Best move: " + bestMove.row + " " + bestMove.col);
}
//input.close();
}
static int checkState(String [][] board)
{
for (int row = 0; row<3; row++) //Rows
{
if (board[row][0] == board[row][1] &&
board[row][1] == board[row][2])
{
if (board[row][0]==player)
return -10;
else if (board[row][0]==opponent)
return +10;
}
}
for (int col = 0; col<3; col++) //Columns
{
if (board[0][col]==board[1][col] &&
board[1][col]==board[2][col])
{
if (board[0][col]==player)
return -10;
else if (board[0][col]==opponent)
return +10;
}
}
if (board[0][0]==board[1][1] && board[1][1]==board[2][2]) //Diagonal
{
if (board[0][0]==player)
return -10;
else if (board[0][0]==opponent)
return +10;
}
else if (board[0][2]==board[1][1] && board[1][1]==board[2][0]) //Diagonal
{
if (board[0][2]==player)
return -10;
else if (board[0][2]==opponent)
return +10;
}
return 0;
}
public static void getBestMove(String[][] board)
{
int bestValue = -1000;
Game bestMove = new Game(-1,-1);
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
if(board[i][j] == "-")
{
board[i][j] = player;
int currentValue = minimax(board, 0, false);
board[i][j] = "-";
if(currentValue > bestValue)
{
bestMove.row = i;
bestMove.col = j;
bestValue = currentValue;
}
}
}
}
board[bestMove.row][bestMove.col]= opponent;
}
public static int minimax(String [][] board, int depth, boolean isMaximizer)
{
if(checkState(board) != 0)
return checkState(board);
if(checkRemainingPlays(board) == false)
return 0;
if(isMaximizer)
{
int highest = -1000;
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
if(board[i][j] == "-")
{
board[i][j] = player;
highest = Math.max(highest, minimax(board, depth + 1, !isMaximizer));
board[i][j] = "-";
}
}
}
return highest;
}
else
{
int lowest = 1000;
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
if(board[i][j] == "-")
{
board[i][j] = opponent;
lowest = Math.min(lowest, minimax(board, depth + 1, !isMaximizer));
board[i][j] = "-";
}
}
}
return lowest;
}
}
public static void playerTurn(String [][] board , Scanner input)
{
input = new Scanner(System.in);
System.out.println("Player 1: ");
System.out.println("Please enter the index of desired spot (I) ");
int desiredIndexI = input.nextInt();
System.out.println("Please enter the index of desired spot (J) ");
int desiredIndexJ = input.nextInt();
while(board[desiredIndexI][desiredIndexJ] != "-")
{
System.out.println("Please enter the index of desired spot (I) ");
desiredIndexI = input.nextInt();
System.out.println("Please enter the index of desired spot (J) ");
desiredIndexJ = input.nextInt();
}
board[desiredIndexI][desiredIndexJ] = player;
}
public static boolean checkRemainingPlays(String [][] board)
{
for(int i = 0; i < board.length; i++)
{
for(int j = 0; j < board[i].length; j++)
{
if (board[i][j] == "-")
return true;
}
}
return false;
}
public static void printBoard(String [][] board)
{
for(int i = 0; i < board.length; i++)
{
if(i <= 2 && i > 0)
System.out.println("----------");
for(int j = 0; j < board[i].length; j++)
{
if(j < 2)
System.out.print(board[i][j] + " | ");
if(j == 2)
System.out.println(board[i][j]);
}
}
}
public static void fillBoard(String [][] board)
{
for(int i = 0; i < board.length; i++)
{
for(int j = 0; j < board[i].length; j++)
{
board[i][j] = "-";
}
}
}
}
At first, I'd like to start with the good news. Solving Tic Tac Toe with the minimax algorithm is a great training for beginners in Artificial Intelligence. The problem isn't to easy and it teaches well what AI planning is. Using Java for realizing the game plus the solver is also a good choice, because the language runs everywhere, supports object-oriented programming and is reasonable fast to execute.
Now I'd like to introduce the critical aspects. The first problem is, that AI related problems are quite different from normal computing tasks. If the sourcecode is about painting a AWT Java GUI to the screen, or about how to send a parameter to a class, I'm sure the question can be answered easily. In most cases, AI topics doesn't fail because of programming issues which means how to use a certain programming language but because of the underlying algorithm.
The discussion space in which AI problems are described and solved isn't within the programming domain but within the Gutenberg galaxy. Which means, around TicTacToe gameplaying with Artificial Intelligence and for the Minimax algorithm, there are at least 1000 papers, books and powerpoint presentations available. The task for the newbie isn't to write Java sourcecode, but to read and cite these sources. This helps other to understand the problem and provide detailed feedback.
I know, this moral instruction isn't answering the original question but the aim was to explain why I've pressed the button “migrate the question to https://ai.stackexchange.com/”. In this forum the question will get an answer quickly.
I have coded for Sudoku puzzle in Java. The thing is my code has limitation for giving inputs for 9*9 grid. How do I make my code adaptable for all the grids. Please have patience. I am new to java.
What changes do I need to make so that the code can run on all grid sizes?The grid is square not a rectangle.
class Solution {
public void solveSudoku(char[][] board) {
if(solveSudoku2(board)) {
return;
}
}
public boolean solveSudoku2(char[][] board) {
boolean isEmpty = true;
int row = -1;
int col = -1;
int n = board.length;
//this code is used to check if there exists any empty cell in sudoku board
//if there is any empty cell, that means we are not done yet and we need to solve it further,
// so we cannot return true at any point until all the cells are full
//by empty cell, I mean cells having '.' as the value
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[0].length; j++) {
if(board[i][j] == '.') {
row = i;
col = j;
isEmpty = false;
break;
}
}
if(!isEmpty) {
break;
}
}
if(isEmpty) {
return true;
}
//loop for all the numbers and start placing in the empty cells
//numbers start from 1 to n
for(int num = 1; num <= n; num++) {
//convert number to char
char char_num = (char)(num + '0');
//check if the number we are adding satisfies all the sudoku rules,
// if it does, then we place that number in the cell
if(checkSafe(board,char_num,row,col)) {
board[row][col] = (char)(num + '0');
//using this number in place row,col, we check for all the other empty places and see if the board is returning true or not
// if the board is not filled that means that we need to use other number in row,col place.
//hence backtrack.
if(solveSudoku2(board)) {
return true;
} else {
board[row][col] = '.';
}
}
}
return false;
}
public boolean checkSafe(char[][] board, char num, int row, int col) {
//checkk if num is present in the row
for(int i = 0; i< board.length; i++ ) {
if(board[row][i] == num) {
return false;
}
}
for(int j = 0; j < board[0].length; j++) {
if(board[j][col] == num) {
return false;
}
}
int checknum = (int)Math.sqrt(board.length);
//check for the current grid. grid will be basically checknum*checknum matrix. where every matrix will start from startrow to startrow + checknum having checknum length.
// so, we we have row = 0, then matrix will start from 0 to 2, i.e. the first 3x3 matrix.
// however, we have row = 2, then also the matrix will start from 0 to 2 - the first 3x3 matrix.
//however, if row = 3, then we will start our matrix from 3 and cotinute upto 5.
int startrow = row - row % checknum;
int startcol = col - col % checknum;
for(int k = startrow; k < startrow + checknum; k++) {
for(int l = startcol; l < startcol + checknum; l++) {
if(board[k][l] == num) {
return false;
}
}
}
return true;
}
}
I can't get the game to call it a draw or win diagonally, I'm almost done but I can't figure it out. I've tried everything. I can win the game in straight lines but diagonally doesn't seem to finish in the loop. And I'm not sure if it ever reaches the loop for the full board or completes it even though it should.
import java.util.Scanner; //Used for player's input in game
public class TicTacToe
{
//instance variables
private char[][] board; //Tic Tac Toe Board, 2d array
private boolean xTurn; // true when X's turn, false if O's turn
private Scanner input; // Scanner for reading input from keyboard
//Constants for creation of gameboard
public final int ROWS = 3; //total rows
public final int COLS = 3; //total columns
public final int WIN = 3; //amount needed to win
public TicTacToe()
{
//creates the board
board = new char[ROWS][COLS];
for(int r = 0; r < ROWS; r++)
{
for(int c = 0; c < COLS; c++)
{
board[r][c] = ' ';
}
}
//X's turn when game starts
xTurn = true;
//creates our input object for the turn player
input = new Scanner(System.in);
}
//shows game board
public void displayBoard()
{
int colNum = 0; //number of columns
int rowNum = 0; //number of rows
//creates column labels
System.out.println(" \n");
System.out.println(" Columns ");
for (int num = 0; num < COLS; num++)
{
System.out.print(" " + colNum);
colNum++;
}
//creates vertical columns and spaces between each spot
System.out.println(" \n");
for (int row = 0; row < ROWS; row++)
{
//numbers rows
System.out.print(" " + rowNum + " ");
rowNum++;
for (int col = 0; col < COLS; ++col)
{
System.out.print(board[row][col]); // print each of the cells
if (col != COLS - 1)
{
System.out.print(" | "); // print vertical partition
}
}
System.out.println();
//creates seperation of rows
if (row != ROWS - 1)
{
System.out.println(" ------------"); // print horizontal partition
}
}
//labels row
System.out.println("Rows \n");
}
//displays turn player
public void displayTurn()
{
if (xTurn)
{
System.out.println("X's Turn");
}
else
{
System.out.println("O's Turn");
}
}
//allows you to make move
public boolean playerMove()
{
boolean invalid = true;
int row = 0;
int column = 0;
while(invalid)
{
System.out.println("Which row (first) then column (second) would you like to \n"
+ "play this turn? Enter 2 numbers between 0-2 as \n"
+ "displayed on the board, seperated by a space to \n"
+ "choose your position.");
if (input.hasNextInt())
{
row = input.nextInt();
if (row > ROWS - 1|| row < 0)
{
System.out.println("Invalid position");
playerMove();
}
else if (row >= 0 && row <= ROWS - 1 && column >= 0 && column <= COLS - 1)
{
if (board[row][column] != ' ')
{
System.out.println("Spot is taken \n");
}
else
{
invalid = false;
}
}
if(input.hasNextInt())
{
column = input.nextInt();
if (column > COLS - 1|| column < 0)
{
System.out.println("Invalid position");
playerMove();
}
//checks if spot is filled
else if (row >= 0 && row <= ROWS - 1 && column >= 0 && column <= COLS - 1)
{
if (board[row][column] != ' ')
{
System.out.println("Spot is taken \n");
}
else
{
invalid = false;
}
}
}
}
//fills spot if not taken
if (xTurn)
{
board[row][column] = 'X';
}
else
{
board[row][column] = 'O';
}
}
return displayWinner(row,column);
}
public boolean displayWinner(int lastR, int lastC)
{
boolean winner = false;
int letter = board[lastR][lastC];
//checks row for win
int spotsFilled = 0;
for (int c = 0; c < COLS; c++)
{
if(board[lastR][c] == letter)
{
spotsFilled++;
}
}
if (spotsFilled == WIN)
{
winner = true;
}
//checks columns for win
spotsFilled = 0;
for (int r = 0; r < ROWS; r++)
{
if(board[r][lastC] == letter)
{
spotsFilled++;
}
}
if (spotsFilled == WIN)
{
winner = true;
}
//checks diagonals for win
spotsFilled = 0;
for (int i = 0; i < WIN; i++)
{
if(board[i][i] == letter)
{
spotsFilled++;
}
}
if(spotsFilled == WIN)
{
winner = true;
}
//checks other diagonal
spotsFilled = 0;
for(int i = 0; i < WIN; i++)
{
if(board[i][COLS - ( i + 1)] == letter)
{
spotsFilled++;
}
}
if(spotsFilled == WIN)
{
winner = true;
}
return winner;
}
//checks if board is full
public boolean fullBoard()
{
int filledSpots = 0;
for(int r = 0; r < ROWS; r++)
{
for (int c = 0; c < COLS; c++)
{
if (board[r][c] == 'X' || board[r][c] == 'O')
{
filledSpots++;
}
}
}
return filledSpots == ROWS*COLS;
}
//plays game
public void playGame()
{
boolean finish = true;
System.out.println("Are your ready to start?");
System.out.println("1 for Yes or 0 for No? : ");
if (input.hasNextInt())
{
int choice = input.nextInt();
if(choice > 1 || choice < 0)
{
System.out.println("Invalid choice");
playGame();
}
else if (choice == 1)
{
while (finish)
{
displayBoard();
displayTurn();
if (playerMove())
{
displayBoard();
if (xTurn)
{
System.out.println("X won");
displayBoard();
}
else
{
System.out.println("O won");
displayBoard();
}
}
else if (fullBoard())
{
displayBoard();
System.out.println("Draw");
}
else
{
//no winner, switching turns
xTurn=!xTurn;
}
}
}
}
else
{
System.out.println("Input not valid");
}
}
}
and the tester
public class TicTacToeTester {
/**
* #param
* args the command line arguments
*/
public static void main(String[] args) {
TicTacToe tictactoe = new TicTacToe();
tictactoe.playGame();
}
}
I'm having a setback in the code for a Tic Tac Toe Java program. Every time I run it, the game board prints 3 times and o the second time, the X's all fill in a line saying that player X wins. I've been trying to figure it out, but I still can't find the problem going on with it. What I'm asking is, what is the main problem of the code printing out more than it needs to and to stop filling in the lines?
I hope I format this correctly.
import java.util.Scanner;
public class TicTacToeWork {
//Variable declaration.
public static char[][] GameBoard = new char[3][3];
public static Scanner keyboard = new Scanner(System.in);
public static int column, row;
public static char PlayerTurn = 'X';
public static void main(String args[]) {
for (int i = 0; i > 3; i++) {
for (int j = 0; j < 3; j++) {
GameBoard[i][j] = '_';
}
}
System.out.println("Enter coordinates of row then column to choose your space.");
Playing();
}
public static void Playing() {
boolean PlayerPlaying = true;
while (PlayerPlaying) {
boolean playing = true;
while (playing) {
row = keyboard.nextInt() - 1;
column = keyboard.nextInt() - 1;
GameBoard[row][column] = PlayerTurn;
if (EndGame(row, column)) {
playing = false;
System.out.println("Game over player " + PlayerTurn + " wins!");
}
BoardPrint();
if (PlayerTurn == 'X') {
PlayerTurn = 'O';
} else {
PlayerTurn = 'X';
}
}
}
}
public static void BoardPrint() {
//Print out the game board.
for (int i = 0; i < GameBoard.length; i++) {
for (int n = 0; n < 3; n++) {
System.out.println();
for (int j = 0; j < 3; j++) {
if (j == 0) {
System.out.print("| ");
}
System.out.print(GameBoard[i][j] + " | ");
}
}
System.out.println();
}
System.out.println();
}
public static boolean EndGame(int RowMove, int ColumnMove) {
//Deciding factors on who wins and ties.
if (GameBoard[0][ColumnMove] == GameBoard[1][ColumnMove]
&& GameBoard[1][ColumnMove] == GameBoard[2][ColumnMove]) {
return true;
}
if (GameBoard[RowMove][0] == GameBoard[1][RowMove]
&& GameBoard[RowMove][0] == GameBoard[RowMove][2]) {
return true;
}
if (GameBoard[0][0] == GameBoard[1][1] && GameBoard[0][0] == GameBoard[2][2]
&& GameBoard[1][1] != '_') {
return true;
}
if (GameBoard[0][2] == GameBoard[1][1] && GameBoard[0][2] == GameBoard[2][0]
&& GameBoard[1][1] != '_') {
return true;
} else {
return false;
}
}
}
Your BoardPrint method is all wrong. You have to do something like this..
public static void BoardPrint() {
System.out.println("-------------");
for (int i = 0; i < 3; i++) {
System.out.print("| ");
for (int j = 0; j < 3; j++) {
System.out.print(GameBoard[i][j] + " | ");
}
System.out.println();
System.out.println("-------------");
}
You are also going to have to redo your check for a win.
A little hint.. you are not using a Boolean method correctly. This line if(EndGame(row, column)) is saying if EndGame is true stop the game. The way you have your method set up it is not doing the check correctly. You would have to say "if not true" - so it would look like this if(!EndGame(row, column)) There are a couple of other errors but this should give you a good start on completing the project.