This tic tac toe game is user vs computer based.
For this assignment, I'm supposed to fill in the missing pieces, which is just finishing up the main and moveAI methods(the other methods are already preset, I just need to call them); there is comments provided where I need to add code to make this tic tac toe game work. I believe that my main method that I have is almost done except for the 2 empty lines under the comments, I'm not sure what they mean by that and also I'm currently stuck on getting my moveAI method to work. This is where I'm supposed to generate random places where the computer will move after I put an X somewhere. I'm not sure how to write something that will check to make sure the spot where the computer moves is available and not already taken by the user. Thanks in advance for the help!
import java.util.Random;
import java.util.Scanner;
public class TicTacToeGame
{
public static void main ( String[] args )
{
Scanner in = new Scanner ( System.in );
char[][] board = new char[ 3 ][ 3 ];
int x, y = -1;
char winner = 'N';
// Initialize the board to spaces
// boolean noWinner = true;
char player = 'X';
for (int r = 0; x < board.length(); r++)
{
for (int c = 0; c < board.length(); c++)
{
board[r][c] = ' ';
}
}
// Print the game board
printBoard(board);
// Keep playing while the game isn't finished
while (winner == 'N')
{
while (x < 0 && x >2 && y <0 && y > 2)
{
System.out.println("Enter the row and column, separated by spaces: ");
x = in.nextInt();
y = in.nextInt();
}
// Get the location from the user and validate it
// Mark the position in the board according to the user's specified location
// Print the board after the user plays
printBoard(board);
// Check to see if the game is finished. If it is, break out of the loop.
// Have the AI make a move
moveAI(board);
// Print the board after the AI plays
printBoard(board);
// Check to see who the winner is
winner = checkWinner(board);
}
// If the winner is 'X' or 'O', print that, otherwise, it is a tie
if (winner == 'X')
System.out.println("X is the winner!");
else if (winner == 'O')
System.out.println("O is the winner!");
else
System.out.println("Tie");
}
/**
* Makes a move for the AI, and marks the board with an 'O'.
*
* #param board The game board
*/
public static void moveAI ( char[][] board )
{
int x,y = -1;
Random r = new Random();
x = r.nextInt(3);
y = r.nextInt(3);
boolean open = false;
// Validate that the random location generated is valid.
while (x < 0 && x >2 && y < 0 && y > 2)
{
x = r.nextInt(3);
y = r.nextInt(3);
}
while (open == false)
{
if (board[r][c] != ' ')
while (x < 0 && x >2 && y < 0 && y > 2)
{
x = r.nextInt(3);
y = r.nextInt(3);
}
}
}
// Keep recalculating the location if the one generated is not
// if (board[r][c] != ' ')
//{
// an empty space.
System.out.print(" ");
// Be sure to mark the position in the board with an 'O'
board[][]=in.nextInt(3) + 'O';
}
/**
* Prints out the tic-tac-toe board
*
* #param board The game board
*/
public static void printBoard ( char[][] board )
{
// Box drawing unicode characters:
char a = '\u250c'; // U+250C : top-left
char b = '\u2510'; // U+2510 : top-right
char c = '\u2514'; // U+2514 : bottom-left
char d = '\u2518'; // U+2518 : bottom-right
char e = '\u252c'; // U+252C : top-vertical-connector
char f = '\u2534'; // U+2534 : bottom-vertical-connector
char g = '\u251c'; // U+251C : left-horizontal-connector
char h = '\u2524'; // U+2524 : right-horizontal-connector
char i = '\u253c'; // U+253C : center plus sign connector
char j = '\u2500'; // U+2500 : horizontal
char k = '\u2502'; // U+2502 : vertical
String l = j + "" + j + "" + j; // Three horizontals
// Print out the game board
System.out.printf ( "\n 0 1 2\n" +
" %c%s%c%s%c%s%c\n" +
"0 %c %c %c %c %c %c %c\n" +
" %c%s%c%s%c%s%c\n" +
"1 %c %c %c %c %c %c %c\n" +
" %c%s%c%s%c%s%c\n" +
"2 %c %c %c %c %c %c %c\n" +
" %c%s%c%s%c%s%c\n\n",
a, l, e, l, e, l, b,
k, board[0][0], k, board[0][1], k, board[0][2], k,
g, l, i, l, i, l, h,
k, board[1][0], k, board[1][1], k, board[1][2], k,
g, l, i, l, i, l, h,
k, board[2][0], k, board[2][1], k, board[2][2], k,
c, l, f, l, f, l, d );
}
/**
* Checks the result of the game
*
* #param board The game board
* #return 'X' if 'X' is the winner
* 'O' if 'O' is the winner
* 'T' if the game is a tie
* 'N' if the game isn't finished
*/
public static char checkWinner( char[][] board )
{
if (board[0][0] == 'X' && board[0][1] == 'X' && board[0][2] == 'X' || // Check row 0
board[1][0] == 'X' && board[1][1] == 'X' && board[1][2] == 'X' || // Check row 1
board[2][0] == 'X' && board[2][1] == 'X' && board[2][2] == 'X' || // Check row 2
board[0][0] == 'X' && board[1][0] == 'X' && board[2][0] == 'X' || // Check col 0
board[0][1] == 'X' && board[1][1] == 'X' && board[2][1] == 'X' || // Check col 1
board[0][2] == 'X' && board[1][2] == 'X' && board[2][2] == 'X' || // Check col 2
board[0][0] == 'X' && board[1][1] == 'X' && board[2][2] == 'X' || // Check diag \
board[0][2] == 'X' && board[1][1] == 'X' && board[2][0] == 'X' || // Check diag /
board[0][0] == 'x' && board[0][1] == 'x' && board[0][2] == 'x' || // Check row 0
board[1][0] == 'x' && board[1][1] == 'x' && board[1][2] == 'x' || // Check row 1
board[2][0] == 'x' && board[2][1] == 'x' && board[2][2] == 'x' || // Check row 2
board[0][0] == 'x' && board[1][0] == 'x' && board[2][0] == 'x' || // Check col 0
board[0][1] == 'x' && board[1][1] == 'x' && board[2][1] == 'x' || // Check col 1
board[0][2] == 'x' && board[1][2] == 'x' && board[2][2] == 'x' || // Check col 2
board[0][0] == 'x' && board[1][1] == 'x' && board[2][2] == 'x' || // Check diag \
board[0][2] == 'x' && board[1][1] == 'x' && board[2][0] == 'x') // Check diag /
{
return 'X';
}
else if (board[0][0] == 'O' && board[0][1] == 'O' && board[0][2] == 'O' || // Check row 0
board[1][0] == 'O' && board[1][1] == 'O' && board[1][2] == 'O' || // Check row 1
board[2][0] == 'O' && board[2][1] == 'O' && board[2][2] == 'O' || // Check row 2
board[0][0] == 'O' && board[1][0] == 'O' && board[2][0] == 'O' || // Check col 0
board[0][1] == 'O' && board[1][1] == 'O' && board[2][1] == 'O' || // Check col 1
board[0][2] == 'O' && board[1][2] == 'O' && board[2][2] == 'O' || // Check col 2
board[0][0] == 'O' && board[1][1] == 'O' && board[2][2] == 'O' || // Check diag \
board[0][2] == 'O' && board[1][1] == 'O' && board[2][0] == 'O' || // Check diag /
board[0][0] == 'o' && board[0][1] == 'o' && board[0][2] == 'o' || // Check row 0
board[1][0] == 'o' && board[1][1] == 'o' && board[1][2] == 'o' || // Check row 1
board[2][0] == 'o' && board[2][1] == 'o' && board[2][2] == 'o' || // Check row 2
board[0][0] == 'o' && board[1][0] == 'o' && board[2][0] == 'o' || // Check col 0
board[0][1] == 'o' && board[1][1] == 'o' && board[2][1] == 'o' || // Check col 1
board[0][2] == 'o' && board[1][2] == 'o' && board[2][2] == 'o' || // Check col 2
board[0][0] == 'o' && board[1][1] == 'o' && board[2][2] == 'o' || // Check diag \
board[0][2] == 'o' && board[1][1] == 'o' && board[2][0] == 'o') // Check diag /
{
return 'O';
}
boolean finished = true;
// If there is a blank space in the board, the game isn't finished yet
for (int i = 0; i < board.length; i++)
for (int j = 0; j < board[ i ].length; j++)
if (board[ i ][ j ] == ' ')
finished = false;
// If the board is finished and 'X' or 'O' wasn't returned, then it is a tie
// Otherwise, the game is not finished yet
if ( finished )
return 'T';
else
return 'N';
}
}
// Get the location from the user and validate it
It looks like you are already doing this in the preceding lines:
// you're validating the input here
while (x < 0 && x >2 && y <0 && y > 2)
{
System.out.println("Enter the row and column, separated by spaces: ");
// you're getting the location from the user here
x = in.nextInt();
y = in.nextInt();
}
You probably still need to check to see if the position the user entered is a position that's already been filled in. You need to look in the array for that. There's a comment in moveAI giving you a hint for this. You check if board[x][y] is a space.
Also, I think you have a bug there because you never reset the values for x and y, so the next time the player's turn comes around the loop will not be entered. x and y still have the last turn's values so the loop condition evaluates to false. I think you can solve this problem by using a do{...}while(...); loop instead of a while(...){...} loop.
// Mark the position in the board according to the user's specified location
This just means put an 'O' in board[x][y].
// Check to see if the game is finished. If it is, break out of the loop.
It looks like checkWinner does this. It returns 'T' if the game is done and 'N' if it's still going.
For the AI code, here is some pseudocode for what I think you should be doing:
1. generate random x, y coordinates
2. check if board[x][y] is already used (there's a comment that tells how)
3. if it's used, go back to 1, otherwise put an 'X' in that space and return
Also, you don't need the loops that check for while (x < 0 && x >2 && y < 0 && y > 2) in the AI code. Random.nextInt(3) already returns a number in the range 0-2.
Related
This is a program tic tac toe. It's a computer operation. I want it to check all conditions. If it meets the condition, it will check again if the position of the computer to work. Can add O or not if it can't add O. had the computer check the next condition completely, if it didn't meet the condition it would randomly add O, but now it doesn't work because it happens that sometimes the computer randomly added it in the first place. and then when the players Played the condition that the computer had to prevent the player from winning, but it had a random O In the previous round, it was unable to fill the O at all, thus preventing it from continuing.
private static void computerNormalTurn(char[][] board) {
Random rand = new Random();
int computerMove;
while (true) {
if(board [2][0] == 'X' && board [2][1] == 'X' ||
board [1][1] == 'X' && board [0][0] == 'X' ||
board [1][2] == 'X' && board [0][2] == 'X'){
if(board[2][2] != ' ') {
continue;
}else{
computerMove = 3;
}
} else if (board [2][0] == 'X' && board [2][2] == 'X' ||
board [1][1] == 'X' && board [0][1] == 'X') {
if(board[2][1] != ' ') {
continue;
}else{
computerMove = 2;
}
} else if (board [2][1] == 'X' && board [2][2] == 'X' ||
board [1][0] == 'X' && board [0][0] == 'X' ||
board [1][1] == 'X' && board [0][2] == 'X' ) {
if(board[2][0] != ' ') {
continue;
}else{
computerMove = 1;
}
} else if (board[2][0] == 'X' && board[0][0] == 'X' ||
board [1][1] == 'X' && board [1][2] == 'X' ) {
if(board[1][0] != ' ') {
continue;
}else{
computerMove = 4;
}
} else if (board [2][0] == 'X' && board [0][2] == 'X' ||
board [2][1] == 'X' && board [0][1] == 'X' ||
board [2][2] == 'X' && board [0][0] == 'X' ||
board [1][0] == 'X' && board [1][2] == 'X' ) {
if(board[1][1] != ' ') {
continue;
}else{
computerMove = 5;
}
} else if (board[2][2] == 'X' && board[0][2] == 'X' ||
board [1][0] == 'X' && board [1][1] == 'X') {
if(board[1][2] != ' ') {
continue;
}else{
computerMove = 6;
}
} else if (board[2][0] == 'X' && board[1][0] == 'X' ||
board [2][2] == 'X' && board [1][1] == 'X' ||
board [0][1] == 'X' && board [0][2] == 'X') {
if(board[0][0] != ' ') {
continue;
}else{
computerMove = 7;
}
} else if (board [2][1] == 'X' && board [1][1] == 'X' ||
board [0][0] == 'X' && board [0][2] == 'X' ) {
if(board[0][1] != ' ') {
continue;
}else{
computerMove = 8;
}
} else if (board[2][0] == 'X' && board[1][1] == 'X' ||
board [2][2] == 'X' && board [1][2] == 'X' ||
board [0][0] == 'X' && board [0][1] == 'X' ) {
if(board[0][2] != ' ') {
continue;
}else{
computerMove = 9;
}
}else {
computerMove = rand.nextInt(9) + 1;
}
if (isValidMove(board, Integer.toString(computerMove))) {
break;
}
}
placeMove(board, Integer.toString(computerMove), 'O');
System.out.println("Computer chose " + computerMove);
}
I think the problem is that if your board is empty the computer will still have a move because of the else condition else { computerMove = rand.nextInt(9)+1; }
Then the following if statement will give a valid move and you will break the while loop and place the move on the board.
So if you want to prevent the computer from playing first, you should make a function that checks if the board is empty and if it is then do nothing.
public boolean isEmpty(){
for(int i = 0; i<3; i++)
for(int j = 0; j<3; j++)
if(board[i][j] != ' ') return false;
return true
}
If needed you can pass the board as a parameter in the function.
Hope I helped. Good luck!
There's a problem with the continues. The continue causes the next iteration. Because nothing changed, the game stays in the same state, the same condition will be met and the loop will continue endless.
Rewrite your conditions, so instead of e.g.
if(board [2][0] == 'X' && board [2][1] == 'X' ||
board [1][1] == 'X' && board [0][0] == 'X' ||
board [1][2] == 'X' && board [0][2] == 'X'){
if(board[2][2] != ' ') {
continue;
}else{
computerMove = 3;
}
} else ...
write
if((board [2][0] == 'X' && board [2][1] == 'X' ||
board [1][1] == 'X' && board [0][0] == 'X' ||
board [1][2] == 'X' && board [0][2] == 'X') &&
board [2][2] == ' '){
computerMove = 3;
} else ...
I have made this very obnoxious way of finding the winner in a tic tac toe game and I was just wondering if there is a simpler way of doing this.
This is the method I currently have, and as you can see it is very redundant and repetitive. Any tips to narrow this down would be amazing. I'm thinking maybe a nested for-loop might work but not entirely sure how to set that up within this.
public static boolean isGameOver(char[][] gameBoard) {
//Testing for Horizontal Win
if(gameBoard[0][0] == 'X' && gameBoard[0][2] == 'X' && gameBoard [0][4] == 'X') {
System.out.println("Player Wins!\n");
playerScore++;
return true;
}
if(gameBoard[0][0] == 'O' && gameBoard[0][2] == 'O' && gameBoard [0][4] == 'O') {
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
}
if(gameBoard[2][0] == 'X' && gameBoard[2][2] == 'X' && gameBoard [2][4] == 'X') {
System.out.println("Player Wins!\n");
playerScore++;
return true;
}
if(gameBoard[2][0] == 'O' && gameBoard[2][2] == 'O' && gameBoard [2][4] == 'O') {
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
}
if(gameBoard[4][0] == 'X' && gameBoard[4][2] == 'X' && gameBoard [4][4] == 'X') {
System.out.println("Player Wins!\n");
playerScore++;
return true;
}
if(gameBoard[4][0] == 'O' && gameBoard[4][2] == 'O' && gameBoard [4][4] == 'O') {
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
}
//Testing for Vertical Win
if(gameBoard[0][0] == 'X' && gameBoard[2][0] == 'X' && gameBoard [4][0] == 'X') {
System.out.println("Player Wins!\n");
playerScore++;
return true;
}
if(gameBoard[0][0] == 'O' && gameBoard[2][0] == 'O' && gameBoard [4][0] == 'O') {
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
}
if(gameBoard[0][2] == 'X' && gameBoard[2][2] == 'X' && gameBoard [4][2] == 'X') {
System.out.println("Player Wins!\n");
playerScore++;
return true;
}
if(gameBoard[0][2] == 'O' && gameBoard[2][2] == 'O' && gameBoard [4][2] == 'O') {
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
}
if(gameBoard[0][4] == 'X' && gameBoard[2][4] == 'X' && gameBoard [4][4] == 'X') {
System.out.println("Player Wins!\n");
playerScore++;
return true;
}
if(gameBoard[0][4] == 'O' && gameBoard[2][4] == 'O' && gameBoard [4][4] == 'O') {
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
}
//Testing for Diagonal Win
if(gameBoard[0][0] == 'X' && gameBoard[2][2] == 'X' && gameBoard [4][4] == 'X') {
System.out.println("Player Wins!\n");
playerScore++;
return true;
}
if(gameBoard[0][0] == 'O' && gameBoard[2][2] == 'O' && gameBoard [4][4] == 'O') {
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
}
if(gameBoard[4][0] == 'X' && gameBoard[2][2] == 'X' && gameBoard [0][4] == 'X') {
System.out.println("Player Wins!\n");
playerScore++;
return true;
}
if(gameBoard[4][0] == 'O' && gameBoard[2][2] == 'O' && gameBoard [0][4] == 'O') {
System.out.println("CPU Wins!\n");
cpuScore++;
return true;
}
//Testing for Tie
if(gameBoard[0][0] != ' ' && gameBoard[0][2] != ' ' && gameBoard[0][4] != ' ' &&
gameBoard[2][0] != ' ' && gameBoard[2][2] != ' ' && gameBoard[2][4] != ' ' &&
gameBoard[4][0] != ' ' && gameBoard[4][2] != ' ' && gameBoard[4][4] != ' ') {
System.out.println("It's a tie!!!\n");
numOfTies++;
return true;
}
return false;
}
Ok, I got a little carried away. But perhaps you could use some ideas presented here. My main goal was to make it so the entire board need not be checked after each move. This is the type of issue that is best considered during the design phase of a program.
I created a TriGroup class (which is essentially a mutable string to hold successive moves.
Then a map is used to hold all the groupings which have a common coordinate.
when a move is made, those groupings have the current player appended.
and check is done to see if that player won.
this program will run by itself using random moves resulting in a victory or a tie.
Some border cases may have been overlooked.
public class TicTacToeCheck {
int moveCount = 0;
static int MAX_MOVES = 27;
class TriGroup {
public String group = "";
#Override
public String toString() {
return group;
}
}
TriGroup row1 = new TriGroup();
TriGroup row2 = new TriGroup();
TriGroup row3 = new TriGroup();
TriGroup col1 = new TriGroup();
TriGroup col2 = new TriGroup();
TriGroup col3 = new TriGroup();
TriGroup diag1 = new TriGroup();
TriGroup diag2 = new TriGroup();
Map<String, List<TriGroup>> commonGroupings = new HashMap<>();
{
commonGroupings.put("00", List.of(row1, col1, diag1));
commonGroupings.put("02", List.of(row1, col2));
commonGroupings.put("04", List.of(row1, col3));
commonGroupings.put("20", List.of(row2, col1));
commonGroupings.put("22", List.of(row2, col2, diag1, diag2));
commonGroupings.put("24", List.of(row2, col3));
commonGroupings.put("40", List.of(row3, col1, diag1));
commonGroupings.put("42", List.of(row3, col2));
commonGroupings.put("44", List.of(row3, col3));
}
public static void main(String[] args) {
new TicTacToeCheck().start();
}
public void start() {
char player = 'X';
Random r = new Random();
outer: while (moveCount < MAX_MOVES) {
commonGroupings.entrySet().forEach(System.out::println);
System.out.println();
int row = r.nextInt(3) * 2;
int col = r.nextInt(3) * 2;
System.out.println("Move: " + row + ", " + col);
player = player == 'X' ? 'O' : 'X';
char val;
switch (val = recordMove(row, col, player)) {
case 'X' -> {
System.out.println("X wins!");
break outer;
}
case 'O' -> {
System.out.println("O wins!");
break outer;
}
case 0 -> {
System.out.println("Tie!");
break outer;
}
default -> {
}
}
}
commonGroupings.entrySet().forEach(System.out::println);
}
public char recordMove(int row, int col, char c) {
moveCount++;
for (TriGroup tri : commonGroupings.get(row + "" + col)) {
if (tri.group.length() > 2) {
// just ignore the row/col and try the next
continue;
}
// update group
tri.group += c;
if (tri.group.equals(c + "" + c + "" + c)) {
return c;
}
}
if (moveCount == MAX_MOVES) {
return 0;
}
return '#';
}
}
This version uses 2 auxiliary, private methods to make the code less repetitive, without changing the behavior of calling isGameOver. The main observation is that there is very little difference between checking for a win by O or checking for one by X - only a single character. So that becomes checkWins. The next observation is that there is a lot of repetition involved in checking 3 positions of the board that are next to each other. If you give me the char to expect, where to start, and where to look next (dcol and drow), that becomes allEqual.
Your code skips over uneven positions of the board; my code does not. I feel that it is an error to mix presentation ("how you show things to users") with model ("how you represent things internally"); so my code is not currently a drop-in replacement for yours, but can quickly be fixed to be such a replacement by tweaking values in checkWins (diagonal down would be 0, 0, 2, 2, and so on).
Note that, efficiency-wise, your code is probably faster. But I find this version to be much shorter, more readable, and therefore easier to debug & maintain.
private static boolean allEqual(char expected, char[][] b,
int row, int col, int drow, int dcol) {
for (int i=0; i<b[0].length; i++) {
if (b[row][col] != expected) return false;
row += drow;
col += dcol;
}
return true;
}
private static boolean checkWins(char playerChar, char[][]b) {
boolean win = allEqual(playerChar, b, 0, 0, 0, 1) // 1st row
|| allEqual(playerChar, b, 1, 0, 0, 1)
|| allEqual(playerChar, b, 2, 0, 0, 1) // 3rd row
|| allEqual(playerChar, b, 0, 0, 1, 0) // 1st col
|| allEqual(playerChar, b, 0, 1, 1, 0)
|| allEqual(playerChar, b, 0, 2, 1, 0) // 3rd col
|| allEqual(playerChar, b, 0, 0, 1, 1) // diagonal down
|| allEqual(playerChar, b, 2, 0, 1,-1); // diagonal up
return win;
}
public static boolean isGameOver(char[][] gameBoard) {
if (checkWins('X', gameBoard)) {
System.out.println("Player Wins!\n");
playerScore ++;
return true;
} else if (checkWins('O', gameBoard)) {
System.out.println("CPU Wins!\n");
cpuScore ++;
return true;
} else {
return false;
}
}
Take a look at this:
https://www.geeksforgeeks.org/tic-tac-toe-game-in-java/
Add the strings of gameBoard[x][y] and check them in a switch statement.
If the compound strings are equals to XXX or OOO, you can return the winner.
For your code something like this:
for (int a = 0; a < 8; a++) {
String line = null;
switch (a) {
case 0:
line = gameBoard[0][0] + gameBoard[0][1] + gameBoard[0][2];
break;
case 1:
line = gameBoard[1][0] + gameBoard[1][1] + gameBoard[1][2];
break;
case 2:
line = gameBoard[2][0] + gameBoard[2][1] + gameBoard[2][2];
break;
case 3:
line = gameBoard[0][0] + gameBoard[1][0] + gameBoard[2][0];
break;
case 4:
line = gameBoard[0][1] + gameBoard[1][1] + gameBoard[2][1];
break;
case 5:
line = gameBoard[0][2] + gameBoard[1][2] + gameBoard[2][2];
break;
case 6:
line = gameBoard[0][0] + gameBoard[1][1] + gameBoard[2][2];
break;
case 7:
line = gameBoard[0][2] + gameBoard[1][1] + gameBoard[2][0];
break;
}
//For X winner
if (line.equals("XXX")) {
return "X";
}
// For O winner
else if (line.equals("OOO")) {
return "O";
}
}
This part of the code is from a school assignment. I got it to work, but I feel like I can simplify it or at least make it look cleaner. However, I have not yet been able to do so. Any suggestions? (It is from a tic tac toe game)
if (board[0][0] == board[0][1] && board[0][1] == board[0][2] && board[0][0] != '-') {
winner = board[0][0];
} else if (board[1][0] == board[1][1] && board[1][1] == board[1][2] && board[1][0] != '-') {
winner = board[1][0];
} else if (board[2][0] == board[2][1] && board[2][1] == board[2][2] && board[2][0] != '-') {
winner = board[2][0];
} else if (board[0][0] == board[1][0] && board[1][0] == board[2][0] && board[0][0] != '-') {
winner = board[0][0];
} else if (board[0][1] == board[1][1] && board[1][1] == board[2][1] && board[0][1] != '-') {
winner = board[0][1];
} else if (board[0][2] == board[1][2] && board[1][2] == board[2][2] && board[0][2] != '-') {
winner = board[0][2];
} else if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[2][0] != '-') {
winner = board[2][0];
} else if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != '-') {
winner = board[0][0];
}
try
if(check(board[0][0],board[0][1],board[0][2]) && board[0][2]!='-')
.....
private boolean check(a,b,c){
return a==b && b==c;
}
also you can see a better solution here
Here is another way of doing it:
int[][] checks = {{0,0,0,1},{1,0,0,1},{2,0,0,1}, // horizontals
{0,0,1,0},{0,1,1,0},{0,2,1,0}, // verticals
{0,0,1,1},{2,0,-1,1}}; // diagonals
char winner = '-';
for (int[] check : checks)
if ((winner = checkWinner(board, check[0], check[1], check[2], check[3])) != '-')
break;
private static char checkWinner(char[][] board, int y, int x, int dy, int dx) {
char c = board[y][x];
return (board[y + dy][x + dx] == c && board[y + dy * 2][x + dx * 2] == c ? c : '-');
}
What about following approach. As I can see, you have limited number of winners: board[0][0], board[1][0], board[2][0], board[0][1], board[2][0]. You can create separate Predicate for each winnger with appropriate name.
Predicate<char[][]> isZeroOneWinner = new Predicate<char[][]>() {
#Override
public boolean test(char[][] board) {
return board[0][1] == board[1][1] && board[1][1] == board[2][1] && board[0][1] != '-';
}
};
I think is is better that multiple if...else.
could you have a look at my code and tell me why it doesn't work as planned
Scanner sc = new Scanner(System.in);
char card1 = ' ';
char card2 = ' ';
int count = 0;
int globalCount = 0;
do {
globalCount++;
card1 = sc.next().charAt(0);
card2 = sc.next().charAt(0);
if ((card1 >= 2 && card1 <= 9 || card1 == 'T' || card1 == 'J' || card1 == 'Q' || card1 == 'K' || card1 == 'A') && (card2 >= 2 && card2 <= 9 || card2 == 'T' || card2 == 'J' || card2 == 'Q' || card2 == 'K' || card2 == 'A')){
if (card1 == 'A' || card1 == 'K' && card2 == 'A' || card2 == 'K') {
count++;
}else {
count = 0;
}
}else {
System.out.println("Invalid cards given!");
}
}while (count < 3);
System.out.println("Number of tries: " + globalCount);
If I input for card1 an number I always get an Invalid cards given even though I think in my if statement I specified that it could take a number as well? Also a little pointer as if I can avoid the repetition of those card1 == 'T' and so on?
Your current condition for card1 and card2
(card1 >= 2 && card1 <= 9 || card1 == 'T' || ...
won't be true for number cards. char type stores the two-byte Unicode value. To check if this value is between character 2 and 9 you have to express the constants in the same way you are comparing symbol cards:
(card1 >= '2' && card1 <= '9' || card1 == 'T' || ...
You can do avoid repeating code by defining all allowed values as String and using String.indexOf(). Your check would be converted to:
"23456789TJQKA".indexOf(char1) >= 0
Try this:
Scanner sc = new Scanner(System.in);
char card1 = ' ';
char card2 = ' ';
int count = 0;
int globalCount = 0;
do {
globalCount++;
card1 = sc.nextLine().charAt(0);
card2 = sc.nextLine().charAt(0);
if (((card1 - '0' >= 2 && card1 - '0' <= 9) || card1 == 'T' || card1 == 'J' || card1 == 'Q' || card1 == 'K' || card1 == 'A') && ((card2 - '0' >= 2 && card2 - '0' <= 9) || card2 == 'T' || card2 == 'J' || card2 == 'Q' || card2 == 'K' || card2 == 'A')){
if (card1 == 'A' || card1 == 'K' && card2 == 'A' || card2 == 'K') {
count++;
}else {
count = 0;
}
}else {
System.out.println("Invalid cards given!");
}
}while (count < 3);
System.out.println("Number of tries: " + globalCount);
This comparison
card1 >= 2
compares the ascii code of the char entered with 2 and not the numeric representation of card1.
So to get this numeric representation you have to subtract the ascii code of '0'.
By subtracting card1-'0' you get the number you entered as opposed to the ascii code you get by only card1, because this what a char is really: an ASCII code from 0 to 255.
Here is the code I have written so far. My game works just fine but the problem I have is if the user inputs a position that's already taken, yes it keeps asking the user for input, but what i would want it to do it say: This position is unavailable and then reask the user until it's good. I thought about a for loop, but with the loop I have, it says it's unavailable even if it is not...I have been on this for days. If someone could give me some hints I would appreciate it.
import java.util.Scanner;
public class A3Q1_40011419 {
//Creating the board for the user input
static char [][] board = {{'1','2','3'}, {'4','5','6'},{'7','8','9'}};
static Scanner keyboard = new Scanner (System.in);
//Keeping track of the turns
public static int turns = 0;
//Drawing the board
public static void drawBoard() {
int row = 0;
int col = 0;
int turn = 0;
for (row = 0; row < board.length; row++){
for (col = 0; col < board[row].length; col++){
System.out.print(board[row][col]);
System.out.print(" ");
}
System.out.println();
}
}
//Asking user for input
public static void getInput (int playerNum) {
char piece;
char location = ' ';
if (playerNum != 1){
System.out.println("Player X - Enter the position you wish to mark.");
location = keyboard.next().charAt(0);
piece = 'X';
}
else{
System.out.println("Player O - Enter the position you wish to mark.");
location = keyboard.next().charAt(0);
piece = 'O';
}
if (location == '1')
if (board[0][0]=='1')
board[0][0] = piece;
else getInput(playerNum);
else if (location == '2')
if (board[0][1] == '2')
board[0][1] = piece;
else getInput(playerNum);
else if (location == '3')
if (board[0][2] == '3')
board[0][2] = piece;
else getInput(playerNum);
else if (location == '4')
if (board[1][0] == '4')
board[1][0] = piece;
else getInput(playerNum);
else if (location == '5')
if (board[1][1] == '5')
board[1][1] = piece;
else getInput(playerNum);
else if (location == '6')
if (board[1][2] == '6')
board[1][2] = piece;
else getInput(playerNum);
else if (location == '7')
if (board[2][0] == '7')
board[2][0] = piece;
else getInput(playerNum);
else if (location == '8')
if (board[2][1] == '8')
board[2][1] = piece;
else getInput(playerNum);
else if (location == '9')
if (board[2][2] == '9')
board[2][2] = piece;
else getInput(playerNum);
else if (location != '1' || location !='2' || location !='3' || location != '4' || location !='5' || location !='6' || location != '7' || location != '8'|| location !='9'){
System.out.println("That is not a valid position - must be between 1 and 9 inclusive.");
getInput(playerNum);
}
for (int i = 0; i<board.length; i++){
for (int j = 0; j<board.length; j++)
/*if (location == '1' || location == '2' || location == '3'|| location == '4' || location == '5'|| location == '6' || location == '7' || location == '8' || location == '9')*/
if (board[i][j] == 'X' || board[i][j] == 'O'){
System.out.println("Position not available"); //This is was i tried to do so far to check is the position was available on the board. Not working
}
getInput(playerNum);
}
}
//Checking if position available
public static void isAvailable(){ //This is a method i thought of creating to check if the position was available but I have not used it yet.
char location_1 = ' ';
char location_2 = ' ';
char location_3 = ' ';
char location_4 = ' ';
char location_5 = ' ';
char location_6 = ' ';
char location_7 = ' ';
char location_8 = ' ';
char location_9 = ' ';
}
/*Checking if there is a winner by checking if the cells in the board are equal to each other
*and checking if the cell isn't empty. If one isn't empty and they're all equal, then
none of them is empty.*/
public static char isWinner() {
if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0]!='1')
return board[0][0];
else if (board[0][0] == board[1][0] && board[0][0] == board[2][0] && board[0][0]!='1')
return board[0][0];
else if (board[0][0]==board[0][1] && board[0][0]==board[0][2] && board[0][0]!='1')
return board[0][0];
else if (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] !='3')
return board[0][2];
else if (board[0][2] == board[1][2] && board[0][2] == board[2][2] && board[0][2] != '3')
return board[0][2];
else if (board[2][0] == board [2][1] && board[2][0] == board[2][2] && board[2][0] != '7')
return board[2][0];
else if (board[1][0] == board [1][1] && board[1][0] == board[1][2] && board[1][0] != '4')
return board[1][0];
else if (board[0][1] == board[1][1] && board[0][1] == board[2][1] && board[0][1] != '2')
return board[0][1];
else
return 'Y';
}
//New board for a new game
public static void newBoard() {
board[0][0] = '1';
board[0][1] = '2';
board[0][2] = '3';
board[1][0] = '4';
board[1][1] = '5';
board[1][2] = '6';
board[2][0] = '7';
board[2][1] = '8';
board[2][2] = '9';
}
//Main method
public static void main(String[] args) {
int game = 0;
int playerNum = 1;
String answer;
do {
turns = 0;
newBoard();
while (isWinner() == 'Y') {
drawBoard();
isWinner();
playerNum *= -1;
getInput(playerNum);
turns++;
System.out.println(turns);
if (turns == 9) {
break;
}
}
drawBoard();
if (isWinner() == 'X')
System.out.println("Player X wins");
else if (isWinner()=='O')
System.out.println("Player O wins");
else
System.out.println("It's a tie!");
System.out.println("Would you like to play another game?");
answer = keyboard.next().toLowerCase();
}
while (answer.equals("yes"));
}
}
I would suggest:
You move your check for available position before inserting the new input.
Instead of a loop to check all positions of the grid, you check only the position the player is asking.
Please find a working code below:
public class A3Q1_40011419 {
//Creating the board for the user input
static char [][] board = {{'1','2','3'}, {'4','5','6'},{'7','8','9'}};
static Scanner keyboard = new Scanner (System.in);
//Keeping track of the turns
public static int turns = 0;
//Drawing the board
public static void drawBoard() {
int row = 0;
int col = 0;
int turn = 0;
for (row = 0; row < board.length; row++){
for (col = 0; col < board[row].length; col++){
System.out.print(board[row][col]);
System.out.print(" ");
}
System.out.println();
}
}
//Asking user for input
public static void getInput (int playerNum) {
char piece;
char location = ' ';
if (playerNum != 1){
System.out.println("Player X - Enter the position you wish to mark.");
location = keyboard.next().charAt(0);
piece = 'X';
}
else{
System.out.println("Player O - Enter the position you wish to mark.");
location = keyboard.next().charAt(0);
piece = 'O';
}
//------------------------
// Your new check
int locationInt = Integer.parseInt("" + location);
int x = (locationInt-1)/3;
int y = ((locationInt-1)%3);
if (board[x][y] == 'X' || board[x][y] == 'O'){
System.out.println("Position not available"); //This is was i tried to do so far to check is the position was available on the board. Not working
getInput(playerNum);
return;
}
//------------------------
if (location == '1')
if (board[0][0]=='1')
board[0][0] = piece;
else getInput(playerNum);
else if (location == '2')
if (board[0][1] == '2')
board[0][1] = piece;
else getInput(playerNum);
else if (location == '3')
if (board[0][2] == '3')
board[0][2] = piece;
else getInput(playerNum);
else if (location == '4')
if (board[1][0] == '4')
board[1][0] = piece;
else getInput(playerNum);
else if (location == '5')
if (board[1][1] == '5')
board[1][1] = piece;
else getInput(playerNum);
else if (location == '6')
if (board[1][2] == '6')
board[1][2] = piece;
else getInput(playerNum);
else if (location == '7')
if (board[2][0] == '7')
board[2][0] = piece;
else getInput(playerNum);
else if (location == '8')
if (board[2][1] == '8')
board[2][1] = piece;
else getInput(playerNum);
else if (location == '9')
if (board[2][2] == '9')
board[2][2] = piece;
else getInput(playerNum);
else if (location != '1' || location !='2' || location !='3' || location != '4' || location !='5' || location !='6' || location != '7' || location != '8'|| location !='9'){
System.out.println("That is not a valid position - must be between 1 and 9 inclusive.");
getInput(playerNum);
}
}
//Checking if position available
public static void isAvailable(){ //This is a method i thought of creating to check if the position was available but I have not used it yet.
char location_1 = ' ';
char location_2 = ' ';
char location_3 = ' ';
char location_4 = ' ';
char location_5 = ' ';
char location_6 = ' ';
char location_7 = ' ';
char location_8 = ' ';
char location_9 = ' ';
}
/*Checking if there is a winner by checking if the cells in the board are equal to each other
*and checking if the cell isn't empty. If one isn't empty and they're all equal, then
none of them is empty.*/
public static char isWinner() {
if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0]!='1')
return board[0][0];
else if (board[0][0] == board[1][0] && board[0][0] == board[2][0] && board[0][0]!='1')
return board[0][0];
else if (board[0][0]==board[0][1] && board[0][0]==board[0][2] && board[0][0]!='1')
return board[0][0];
else if (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] !='3')
return board[0][2];
else if (board[0][2] == board[1][2] && board[0][2] == board[2][2] && board[0][2] != '3')
return board[0][2];
else if (board[2][0] == board [2][1] && board[2][0] == board[2][2] && board[2][0] != '7')
return board[2][0];
else if (board[1][0] == board [1][1] && board[1][0] == board[1][2] && board[1][0] != '4')
return board[1][0];
else if (board[0][1] == board[1][1] && board[0][1] == board[2][1] && board[0][1] != '2')
return board[0][1];
else
return 'Y';
}
//New board for a new game
public static void newBoard() {
board[0][0] = '1';
board[0][1] = '2';
board[0][2] = '3';
board[1][0] = '4';
board[1][1] = '5';
board[1][2] = '6';
board[2][0] = '7';
board[2][1] = '8';
board[2][2] = '9';
}
//Main method
public static void main(String[] args) {
int game = 0;
int playerNum = 1;
String answer;
do {
turns = 0;
newBoard();
while (isWinner() == 'Y') {
drawBoard();
isWinner();
playerNum *= -1;
getInput(playerNum);
turns++;
System.out.println(turns);
if (turns == 9) {
break;
}
}
drawBoard();
if (isWinner() == 'X')
System.out.println("Player X wins");
else if (isWinner()=='O')
System.out.println("Player O wins");
else
System.out.println("It's a tie!");
System.out.println("Would you like to play another game?");
answer = keyboard.next().toLowerCase();
}
while (answer.equals("yes"));
}
}