How to increase efficiency by using for loops? - java

I am a beginner java programmer and I am making a simple TicTacToe game using 2D arrays and these are my if statements to check if player 1, or player 2 has won. I believe that this can be simplified by using for loop(s) however I do not understand how to use that method.
if ((grid[0][0] == 1 && grid[0][1] == 1 && grid[0][2] == 1)
|| (grid[1][0] == 1 && grid[1][1] == 1 && grid[1][2] == 1)
|| (grid[2][0] == 1 && grid[2][1] == 1 && grid[2][2] == 1)
|| (grid[0][0] == 1 && grid[1][1] == 1 && grid[2][2] == 1)
|| (grid[0][2] == 1 && grid[1][1] == 1 && grid[2][0] == 1)
|| (grid[0][0] == 1 && grid[1][0] == 1 && grid[2][0] == 1)
|| (grid[0][1] == 1 && grid[1][1] == 1 && grid[2][1] == 1)
|| (grid[0][2] == 1 && grid[1][2] == 1 && grid[2][2] == 1)
&& won == false) {
title.setText("X wins!");
won = true;
} else if ((grid[0][0] == 2 && grid[0][1] == 2 && grid[0][2] == 2)
|| (grid[1][0] == 2 && grid[1][1] == 2 && grid[1][2] == 2)
|| (grid[2][0] == 2 && grid[2][1] == 2 && grid[2][2] == 2)
|| (grid[0][0] == 2 && grid[1][1] == 2 && grid[2][2] == 2)
|| (grid[0][2] == 2 && grid[1][1] == 2 && grid[2][0] == 2)
|| (grid[0][0] == 2 && grid[1][0] == 2 && grid[2][0] == 2)
|| (grid[0][1] == 2 && grid[1][1] == 2 && grid[2][1] == 2)
|| (grid[0][2] == 2 && grid[1][2] == 2 && grid[2][2] == 2)
&& won == false) {
title.setText("O wins!");
won = true;
}
Below is the modified code that uses far less if statments and conditions.
public static boolean hasWon(int[][] grid) {
for (int a = 1; a <= 2; a++) {
for (int b = 0; b < grid.length; b++) {
// Checking for win in horizontal, then vertical, then diagonal
if (grid[b][0] == a && grid[b][1] == a && grid[b][2] == a) {
won = true;
} else if (grid[0][b] == a && grid[1][b] == a && grid[2][b] == a) {
won = true;
} else if ((grid[0][0] == a && grid[1][1] == a && grid[2][2] == a
|| (grid[0][2] == a && grid[1][1] == a && grid[2][0] == a))) {
won = true;
}
}
}
}

In order to help you reach a solution on your own I'll give you some hints for now.
Hint #1: Think about what it means to win. A player must get 3 of their tokens in a row - horizontal, vertical, or diagonal. Think about how that can be represented in your program.
Hint #2: Think about how you can break the problem into smaller more manageable pieces. Think about what each winning scenario has in common and separate that logic into a method that you can call multiple times.
Hint #3: Consider what makes each winning scenario unique and how you might use your grid to produce a representation of the spaces you want to examine that is easier to check for a win.
If you're not sure about how for loops work or other aspects of the Java Language you can find tutorials on Oracle's site

Yes you are right. For loops are the way to go. Here is one way you could implement it.
public class tictactoe {
public static void main(String[] args) {
int[][] grid = {{1, 2, 1},
{1, 2, 1},
{2, 0, 1}};
boolean won = hasWon(grid);
}
public static boolean hasWon(int[][] grid){
for (int player = 1; player <= 2; player++){
boolean playerWon = false;
for(int i = 0; i < 3; i++){
//Horizonal win
playerWon = (grid[i][0] == player && grid[i][1] == player && grid[i][2] == player) || playerWon;
//Vertical Win
playerWon = (grid[0][i] == player && grid[1][i] == player && grid[i][2] == player) || playerWon;
}
//Diagonal Win
playerWon = (grid[0][0] == player && grid[1][1] == player && grid[2][2] == player) || playerWon;
playerWon = (grid[0][2] == player && grid[1][1] == player && grid[2][0] == player) || playerWon;
if(playerWon){
if(player == 1){
System.out.println("X wins!");
return true;
}
else{
System.out.println("O wins!");
return true;
}
}
}
//neither have won
return false;
}
}

Not a direct answer for the question. (as this is not "check all at once" style)
To simplify,
1. Check when a cell is clicked.
2. Condition depends on the place of a cell which is clicked and who clicked the cell.
3. If someone wins, end the game.
code sample
// Part of codes.(not tested.)
// Each cell has three states (0, 1, or 2)
int player = 1; // (Not written here but) switch this each turn (1 or 2)
// In some place (activity.onCreate() etc)
{
// For on click event(0, 0)
cell_0_0.setOnClickListener(
new View.OnClickListener()
{
#Override
public void onClick(View v)
{
grid[0][0] = player;
final boolean isEnd = checkEnd_0_0();
if (isEnd) {
// Call some function to end the game.
// Calling title.setText() in game end function maybe good.
// (as not needed to write many times.)
if (player == 1) {
title.setText("X wins!");
} else {
title.setText("O wins!");
}
} else {
switchPlayer(); // Not written in this code.
}
}
};
);
...
}
// Call this on cell(0, 0) click event
// Returns true if someone wins.
boolean checkEnd_0_0() {
// Omit checking grid[0][0] is 1 or 2 as it is clear.
// Check horizontal.
if (grid[0][1] == player) {
if (grid[0][2] == player) {
return true; // This is the case shown in question.
}
}
// Check other cases (vertical, diagonal)
...
// No match.
return false;
}

Related

How can I keep it running after checking the if condition?

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 ...

Sorting through 2D array for Tic Tac Toe winner

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";
}
}

checking for specific indexes in a 2D array to announce winner

I have a bingo game I am trying to code, I got hit with some logic problems and I am also looking for a way to tidy up the following code.
(a Bingo game is won by crossing out the numbers in a straight line (diagonally straight line also counts.))
My current code for the 5x5 grid to check for straight "XX"s. Checks for all 5 straight rows and 2 diagonally straights.
public static void bingoCheck(String[][] card1, String[][] card2) {
//check for player 1 bingo.
if ((card1[0][0] == "XX") && (card1[0][1] == "XX") && (card1[0][2] == "XX") && (card1[0][3] == "XX") && (card1[0][4] == "XX")) {
System.out.print("Bingo! Player 1 wins!");
} else if ((card1[1][0] == "XX") && (card1[1][1] == "XX") && (card1[1][2] == "XX") && (card1[1][3] == "XX") && (card1[1][4] == "XX")){
System.out.print("Bingo! Player 1 wins!");
} else if ((card1[2][0] == "XX") && (card1[2][1] == "XX") && (card1[2][2] == "XX") && (card1[2][3] == "XX") && (card1[2][4] == "XX")){
System.out.print("Bingo! Player 1 wins!");
} else if ((card1[3][0] == "XX") && (card1[3][1] == "XX") && (card1[3][2] == "XX") && (card1[3][3] == "XX") && (card1[3][4] == "XX")){
System.out.print("Bingo! Player 1 wins!");
} else if ((card1[4][0] == "XX") && (card1[4][1] == "XX") && (card1[4][2] == "XX") && (card1[4][3] == "XX") && (card1[4][4] == "XX")){
System.out.print("Bingo! Player 1 wins!");
} else if ((card1[0][4] == "XX") && (card1[1][3] == "XX") && (card1[2][2] == "XX") && (card1[3][1] == "XX") && (card1[4][0] == "XX")){
System.out.print("Bingo! Player 1 wins!");
} else if ((card1[4][4] == "XX") && (card1[3][3] == "XX") && (card1[2][2] == "XX") && (card1[1][1] == "XX") && (card1[0][0] == "XX")){
System.out.print("Bingo! Player 1 wins!");
}
// player 2 check
else if ((card2[0][0] == "XX") && (card2[0][1] == "XX") && (card2[0][2] == "XX") && (card2[0][3] == "XX") && (card2[0][4] == "XX")) {
System.out.print("Bingo! Player 2 wins!");
} else if ((card2[1][0] == "XX") && (card2[1][1] == "XX") && (card2[1][2] == "XX") && (card2[1][3] == "XX") && (card2[1][4] == "XX")){
System.out.print("Bingo! Player 2 wins!");
} else if ((card2[2][0] == "XX") && (card2[2][1] == "XX") && (card2[2][2] == "XX") && (card2[2][3] == "XX") && (card2[2][4] == "XX")){
System.out.print("Bingo! Player 2 wins!");
} else if ((card2[3][0] == "XX") && (card2[3][1] == "XX") && (card2[3][2] == "XX") && (card2[3][3] == "XX") && (card2[3][4] == "XX")){
System.out.print("Bingo! Player 2 wins!");
} else if ((card2[4][0] == "XX") && (card2[4][1] == "XX") && (card2[4][2] == "XX") && (card2[4][3] == "XX") && (card2[4][4] == "XX")){
System.out.print("Bingo! Player 2 wins!");
} else if ((card2[0][4] == "XX") && (card2[1][3] == "XX") && (card2[2][2] == "XX") && (card2[3][1] == "XX") && (card2[4][0] == "XX")){
System.out.print("Bingo! Player 2 wins!");
} else if ((card2[4][4] == "XX") && (card2[3][3] == "XX") && (card2[2][2] == "XX") && (card2[1][1] == "XX") && (card2[0][0] == "XX")){
System.out.print("Bingo! Player 2 wins!");
} else {
//back to getting user input
userIn(card1, card2);
}
}
The logic problem. I want to be able to announce 2 winners at the same time if both grids get the straight line.
This is how the output is right now, both cards got straight lines at the same time but the code only announces Player 2 as the winner only.
Player 1's card:
24 XX 8 1 25
12 XX 7 17 15
5 XX 20 19 13
14 XX XX 4 3
10 XX 11 21 9
Player 2's card:
24 21 17 15 XX
10 3 8 XX 20
14 7 XX 12 5
25 XX 13 19 11
XX 4 9 1 XX
Bingo! Player 2 wins!
Expecting output :
Player 1's card:
24 XX 8 1 25
12 XX 7 17 15
5 XX 20 19 13
14 XX XX 4 3
10 XX 11 21 9
Player 2's card:
24 21 17 15 XX
10 3 8 XX 20
14 7 XX 12 5
25 XX 13 19 11
XX 4 9 1 XX
Bingo! Player 1 wins!
Bingo! Player 2 wins!
If there is any way to tidy up/easier to write code then that'd be great too.
How to check for repeated numbers? If user already used a number then it should print out a message telling them that and then giving them back the input to type again. Here's my current code.
public static void userIn(String[][] card1, String[][] card2) {
public static void userIn(String[][] card1, String[][] card2) {
String str = "";
System.out.print("Game host call (0 to exit): ");
choice = sc.nextInt();
// for user to exit the game
if (choice == 0) {
System.exit(0);
} else {
//check for out of bounds numbers
while (choice < 0 || choice > 25) {
System.out.println("The number must be between 1 to 25, please call again!");
System.out.print("Game host call (0 to exit): ");
choice = sc.nextInt();
}
//change user input to String
str = Integer.toString(choice);
//check if user input matches that on cards
for (i = 0;i <=4; i++) {
for (j = 0;j <=4; j++) {
if (str.equals(card1[i][j])) {
card1[i][j] = "XX";
}
if (str.equals(card2[i][j])) {
card2[i][j] = "XX";
}
}
}
//print player 1 card
System.out.println(player1);
for (i = 0; i < card1.length; i++) {
for (j = 0; j < card1.length; j++) {
System.out.printf(" %2s ", card1[i][j]);
}
System.out.print("\n");
}
// line break
System.out.print("\n");
//print player 2 card
System.out.println(player2);
for (i = 0; i < card2.length; i++) {
for (j = 0; j < card2.length; j++) {
System.out.printf(" %2s ", card2[i][j]);
}
System.out.print("\n");
}
// go to check if any player won.
bingoCheck(card1, card2);
}
}
This will do the job
Edited: For vertical checks & declaring 2 winners at once
public static void bingoCheck(String[][] card1, String[][] card2) {
boolean player1 = checkWinner(card1);
boolean player2 = checkWinner(card2);
if (player1) {
System.out.println("Bingo! Player 1 wins!");
}
if (player2) {
System.out.println("Bingo! Player 2 wins!");
}
if (!(player1 || player2)) {
userIn(card1, card2);
}
}
private static boolean checkWinner(String[][] cards) {
boolean isAllCrossed = true;
int row = 0, col = 0;
// check horizontals
for (row = 0; row < cards.length; row++) {
isAllCrossed = true;
// check if whole row have XX
for (col = 0; col < cards[0].length; col++) {
if (!card[row][col].equals("XX")) {
isAllCrossed = false;
break;
}
}
if (isAllCrossed) return true;
}
// check verticals
for (col = 0; col < cards[0].length; col++) {
isAllCrossed = true;
// check if whole column have XX
for (row = 0; row < cards.length; row++) {
if (!card[row][col].equals("XX")) {
isAllCrossed = false;
break;
}
}
if (isAllCrossed) return true;
}
// check digonal from top left to bottom right
isAllCrossed = true;
row = col = 0;
while (row < cards.length) {
if (!card[row][col].equals("XX")) {
isAllCrossed = false;
break;
}
}
row++;
col++;
}
if (isAllCrossed) return true;
// check digonal from top right to bottom left
isAllCrossed = true;
row = 0;
col = cards[0].length - 1;
while (row < cards.length) {
if (!card[row][col].equals("XX")) {
isAllCrossed = false;
break;
}
row++;
col--;
}
return isAllCrossed;
}
General rule in writing a code is that you should extract code that repeats into separate function and use it, instead of repeating its body many times.
In your case many things repeat.
Notice that you have exactly the same code for checking each player's board. That's the first thing that you should extract to a separate method and just call it with board of each user.
You are repeating logic for checking each row. You are also repeating code that's checks each column. You should extract two methods, i.e. checkRow and checkColumn and call it in the for loop for each row/column. Diagonal case can be handled as 3rd method.
Checking all elements in one row/column should be done with a for loop, instead of manually checking each position individually.
Just to summarize: the core rule, that you should have applied here is: don't repeat yourself (DRY).

Tic Tac Toe Java - Tie Game Programming

I have made a code that checks for wins but i cannot seem to find a away to make it check for ties, any help will be useful! I also cannot find a way to make it so X or O's are not placed over in the same spot
I tried to make it so that if all the rows or columns did not equal to 60 or 90 it would determine it was a tie, but i later realized that the program would think its a tie after every turn as the rows or columns do not equal 60 or 90
import hsa.Console;
import java.awt.*;
import java.util.*;
public class tictactoe88
{ static Console c;
public static void main(String[]args)
{ c = new Console();
//Drawing the tic tac toe table
c.setColor(Color.black);
c.drawLine(450,250,450,475);
c.drawLine(550,250,550,475);
c.drawLine(350,325,650,325);
c.drawLine(350,400,650,400);
//Declaring variables
int location;
String name1, name2, endGame;
boolean stillPlaying = true;
String[][] names = new String[3][3];
int[][] chart =
{
{1,2,3},
{4,5,6},
{7,8,9},
};
//Showing players what number corresponds to tic tac toe board
c.println("1 2 3");
c.println("4 5 6");
c.println("7 8 9");
//Asking players for their names
c.print("Player One : ");
name1 = c.readLine ();
c.print("Player Two : ");
name2 = c.readLine ();
//Starting of main loop
while(stillPlaying)
{
c.setCursor(6,0);
c.println("Where would you like to place the 'X' " + name1);
//Making sure the number entered is valid
while(true)
{
try
{ String locationStr = c.readLine();
location = Integer.parseInt(locationStr);
break;
}
catch(NumberFormatException e)
{ c.println("Bad number, please try again.");
}
}
//Drawing the 'X' and adjusting the 2d array's correspomding to the number entered
{
if (location == 1)
{
c.drawLine(350,250,450,325);
c.drawLine(450,250,350,325);
chart [0][0] = 20;
}
else if (location == 2)
{
c.drawLine(450,250,550,325);
c.drawLine(550,250,450,325);
chart [0][1] = 20;
}
else if(location == 3)
{
c.drawLine(550,250,650,325);
c.drawLine(650,250,550,325);
chart [0][2] = 20;
}
else if (location == 4)
{
c.drawLine(350,325,450,400);
c.drawLine(350,400,450,325);
chart [1][0] = 20;
}
else if (location == 5)
{
c.drawLine(450,325,550,400);
c.drawLine(450,400,550,325);
chart [1][1] = 20;
}
else if (location == 6)
{
c.drawLine(550,325,650,400);
c.drawLine(550,400,650,325);
chart [1][2] = 20;
}
else if (location == 7)
{
c.drawLine(350,400,450,475);
c.drawLine(350,475,450,400);
chart [2][0] = 20;
}
else if (location == 8)
{
c.drawLine(450,400,550,475);
c.drawLine(450,475,550,400);
chart [2][1] = 20;
}
else if (location == 9)
{
c.drawLine(550,400,650,475);
c.drawLine(550,475,650,400);
chart [2][2] = 20;
}
}
This is currently how it checks for a winner,
//Checks the winner by all 8 possibilities
if (chart[0][0]+chart[0][1]+chart[0][2] == 60||
chart[1][0]+chart[1][1]+chart[0][2] == 60||
chart[2][0]+chart[2][1]+chart[2][2] == 60||
chart[0][0]+chart[1][1]+chart[2][2] == 60||
chart[2][0]+chart[1][1]+chart[0][2] == 60||
chart[0][0]+chart[1][0]+chart[2][0] == 60||
chart[0][1]+chart[1][1]+chart[2][1] == 60||
chart[0][2]+chart[1][2]+chart[2][2] == 60)
{break;}
c.setCursor(8,0);
c.println("Where would you like to place 'O' " + name2);
//Making sure the number entered is valid
while(true)
{
try
{ String locationStr = c.readLine();
location = Integer.parseInt(locationStr);
break;
}
catch(NumberFormatException e)
{ c.println("Bad number, please try again.");
}
}
{
//Drawing the 'O' and adjusting the 2d array's correspomding to the number entered
if (location == 1)
{
c.drawOval(350,250,100,75);
chart [0][0] = 30;
}
else if (location == 2)
{
c.drawOval(450,250,100,75);
chart [0][1] = 30;
}
else if(location == 3)
{
c.drawOval(550,250,100,75);
chart [0][2] = 30;
}
else if (location == 4)
{
c.drawOval(350,325,100,75);
chart [1][0] = 30;
}
else if (location == 5)
{
c.drawOval(450,325,100,75);
chart [1][1] = 30;
}
else if (location == 6)
{
c.drawOval(550,325,100,75);
chart [1][2] = 30;
}
else if (location == 7)
{
c.drawOval(350,400,100,75);
chart [2][0] = 30;
}
else if (location == 8)
{
c.drawOval(450,400,100,75);
chart [2][1] = 30;
}
else if (location == 9)
{
c.drawOval(550,400,100,75);
chart [2][2] = 30;
}
This is currently how it checks for a winner,
//Checks the winner by all 8 possibilities
if (chart[0][0]+chart[0][1]+chart[0][2] == 90||
chart[1][0]+chart[1][1]+chart[0][2] == 90||
chart[2][0]+chart[2][1]+chart[2][2] == 90||
chart[0][0]+chart[1][1]+chart[2][2] == 90||
chart[2][0]+chart[1][1]+chart[0][2] == 90||
chart[0][0]+chart[1][0]+chart[2][0] == 90||
chart[0][1]+chart[1][1]+chart[2][1] == 90||
chart[0][2]+chart[1][2]+chart[2][2] == 90)
{break;}
}
}
This is how it ends the game,
//Ends the game by saying who teh winner is
if (chart[0][0]+chart[0][1]+chart[0][2] == 60||
chart[1][0]+chart[1][1]+chart[0][2] == 60||
chart[2][0]+chart[2][1]+chart[2][2] == 60||
chart[0][0]+chart[1][1]+chart[2][2] == 60||
chart[2][0]+chart[1][1]+chart[0][2] == 60||
chart[0][0]+chart[1][0]+chart[2][0] == 60||
chart[0][1]+chart[1][1]+chart[2][1] == 60||
chart[0][2]+chart[1][2]+chart[2][2] == 60)
{c.setCursor(10,0);
c.println("Congratulations "+name1+" you are the winner!");}
else if (chart[0][0]+chart[0][1]+chart[0][2] == 90||
chart[1][0]+chart[1][1]+chart[0][2] == 90||
chart[2][0]+chart[2][1]+chart[2][2] == 90||
chart[0][0]+chart[1][1]+chart[2][2] == 90||
chart[2][0]+chart[1][1]+chart[0][2] == 90||
chart[0][0]+chart[1][0]+chart[2][0] == 90||
chart[0][1]+chart[1][1]+chart[2][1] == 90||
chart[0][2]+chart[1][2]+chart[2][2] == 90)
{c.setCursor(10,0);
c.println("Congratulations "+name2+" you are the winner!");}

Connect4 game with 2D arrays diagonal check

So Im pretty new at java and i have an assignment to create a connect 4 game. I create a board 6 rows and 7 columns full of characters like this one -> '-', when the user inputs the desire column it replaces the '-' with a B or R (Red or black checker) well whatever this is just a background. Everything works except for the part that my code for checking diagonals its awfully long, i couldnt figure out a way to go through all the possible 4 sets of diagonals in which a player can win, except by doing each one in a different for loop... I know its horrible hope you can help me to do it shorter :(
this is the code for diagonal check: (lol only looking at it makes me feel sad)
public class Connect4 {
public static void main(String[] args) {
//Create board
Scanner input = new Scanner(System.in);
char[][] grid = new char[6][7];
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
grid[i][j] = '-';
}
}
public static void checkWinner(char[][] grid) {
try{
//A LOT OF FOR LOOPS FOR DIAGONAL CHECKS
for (int i = 5; i > 1; i-- ) {
for(int j = 0; j < 4; j++) {
if ( grid[i][j] == 'R' &&
grid[i-1][j+1] == 'R' &&
grid[i-2][j+2] == 'R' &&
grid[i-3][j+3] == 'R') {
System.out.println("Player 1 Wins!");
System.exit(0);
}
else if ( grid[i][j] == 'B' &&
grid[i-1][j+1] == 'B' &&
grid[i-2][j+2] == 'B' &&
grid[i-3][j+3] == 'B') {
System.out.println("Player 2 Wins!");
System.exit(0);
}
}
}
for (int i = 5; i > 1; i--) {
for (int j = 1; j < 4; j++) {
if (grid[i][j] == 'R' &&
grid[i-1][j+1] == 'R' &&
grid[i-2][j+2] == 'R' &&
grid[i-3][j+3] == 'R') {
System.out.println("Player 1 Wins!");
System.exit(0);
}
else if (grid[i][j] == 'B' &&
grid[i-1][j+1] == 'B' &&
grid[i-2][j+2] == 'B' &&
grid[i-3][j+3] == 'B') {
System.out.println("Player 2 Wins!");
System.exit(0);
}
}
}
for (int i = 0; i < 4; i++) {
for (int j = 4; j < 7; j++) {
if ( grid[i][j] == 'R' &&
grid[i+1][j-1] == 'R' &&
grid[i+2][j-2] == 'R' &&
grid[i+3][j-3] == 'R') {
System.out.println("Player 1 Wins!");
System.exit(0);
}
else if (grid[i][j] == 'B' &&
grid[i+1][j-1] == 'B' &&
grid[i+2][j-2] == 'B' &&
grid[i+3][j-3] == 'B') {
System.out.println("Player 2 Wins!");
System.exit(0);
}
}
}
for (int i = 1; i < 2; i++) {
for (int j = 6; j > 5; j--) {
if ( grid[i][j] == 'R' &&
grid[i+1][j-1] == 'R' &&
grid[i+2][j-2] == 'R' &&
grid[i+3][j-3] == 'R') {
System.out.println("Player 1 Wins!");
System.exit(0);
}
else if (grid[i][j] == 'B' &&
grid[i+1][j-1] == 'B' &&
grid[i+2][j-2] == 'B' &&
grid[i+3][j-3] == 'B') {
System.out.println("Player 2 Wins!");
System.exit(0);
}
}
}
for (int i = 4; i < 5; i++){
for (int j = 2; j < 3; j++){
if (grid[i][j] == 'R' &&
grid[i-1][j+1] == 'R' &&
grid[i-2][j+2] == 'R' &&
grid[i-3][j+3] == 'R') {
System.out.println("Player 1 Wins!");
System.exit(0);
}
else if (grid[i][j] == 'B' &&
grid[i-1][j+1] == 'B' &&
grid[i-2][j+2] == 'B' &&
grid[i-3][j+3] == 'B') {
System.out.println("Player 2 Wins!");
System.exit(0);
}
}
}
for (int i = 0; i < 4; i++) {
for (int j = 3; j > 0; j--) {
if (grid[i][j] == 'R' &&
grid[i+1][j+1] == 'R' &&
grid[i+2][j+2] == 'R' &&
grid[i+3][j+3] == 'R') {
System.out.println("Player 1 Wins!");
System.exit(0);
}
else if (grid[i][j] == 'B' &&
grid[i+1][j+1] == 'B' &&
grid[i+2][j+2] == 'B' &&
grid[i+3][j+3] == 'B') {
System.out.println("Player 2 Wins!");
System.exit(0);
}
}
}
for(int i =0; i < 1; i++) {
for (int j = 0; j <1; j++) {
if (grid[i][j] == 'R' &&
grid[i+1][j+1] == 'R' &&
grid[i+2][j+2] == 'R' &&
grid[i+3][j+3] == 'R') {
System.out.println("Player 1 Wins!");
System.exit(0);
}
else if (grid[i][j] == 'B' &&
grid[i+1][j+1] == 'B' &&
grid[i+2][j+2] == 'B' &&
grid[i+3][j+3] == 'B') {
System.out.println("Player 2 Wins!");
System.exit(0);
}
}
}
for (int j = 0; j < 1; j++) {
for(int i =1 ; i < 3; i++) {
if (grid[i][j] == 'R' &&
grid[i+1][j+1] == 'R' &&
grid[i+2][j+2] == 'R' &&
grid[i+3][j+3] == 'R') {
System.out.println("Player 1 Wins!");
System.exit(0);
}
else if (grid[i][j] == 'B' &&
grid[i+1][j+1] == 'B' &&
grid[i+2][j+2] == 'B' &&
grid[i+3][j+3] == 'B') {
System.out.println("Player 2 Wins!");
System.exit(0);
}
}
}
for (int j = 3; j < 4; j++) {
for (int i = 0; i < 3; i++) {
if (grid[i][j] == 'R' &&
grid[i+1][j+1] == 'R' &&
grid[i+2][j+2] == 'R' &&
grid[i+3][j+3] == 'R') {
System.out.println("Player 1 Wins!");
System.exit(0);
}
else if (grid[i][j] == 'B' &&
grid[i+1][j+1] == 'B' &&
grid[i+2][j+2] == 'B' &&
grid[i+3][j+3] == 'B') {
System.out.println("Player 2 Wins!");
System.exit(0);
}
}
}
for (int i = 2; i < 3; i++) {
for (int j = 2; j > 0; j--) {
if (grid[i][j] == 'R' &&
grid[i+1][j+1] == 'R' &&
grid[i+2][j+2] == 'R' &&
grid[i+3][j+3] == 'R') {
System.out.println("Player 1 Wins!");
System.exit(0);
}
else if (grid[i][j] == 'B' &&
grid[i+1][j+1] == 'B' &&
grid[i+2][j+2] == 'B' &&
grid[i+3][j+3] == 'B') {
System.out.println("Player 2 Wins!");
System.exit(0);
}
}
}
for (int i = 1; i < 2; i++) {
for (int j = 2; j < 3; j++){
if (grid[i][j] == 'R' &&
grid[i+1][j+1] == 'R' &&
grid[i+2][j+2] == 'R' &&
grid[i+3][j+3] == 'R') {
System.out.println("Player 1 Wins!");
System.exit(0);
}
else if (grid[i][j] == 'B' &&
grid[i+1][j+1] == 'B' &&
grid[i+2][j+2] == 'B' &&
grid[i+3][j+3] == 'B') {
System.out.println("Player 2 Wins!");
System.exit(0);
}
}
}
for (int i = 1; i < 2; i++) {
for (int j = 1; j < 2; j++){
if (grid[i][j] == 'R' &&
grid[i+1][j+1] == 'R' &&
grid[i+2][j+2] == 'R' &&
grid[i+3][j+3] == 'R') {
System.out.println("Player 1 Wins!");
System.exit(0);
}
else if (grid[i][j] == 'B' &&
grid[i+1][j+1] == 'B' &&
grid[i+2][j+2] == 'B' &&
grid[i+3][j+3] == 'B') {
System.out.println("Player 2 Wins!");
System.exit(0);
}
}
}
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("Exception thrown :" + e);
}
}
Instead of checking every possible bit on the board, play the game based on how humans play it - It's only connect 4 when someone drops in a piece that then forms a line of four tiles. So: don't check every possible tile, use the tile that just got dropped in, and only check for lines involving that tile:
does this new tile form a horizontal? that means checking column-3 through column+3 to cover all possible horizontals.
does this new tile form a vertical? that means only checking the three tiles below it.
does this new tile form a diagonal? that means checking {column-3, row-2} through {column+3, row+3} to cover all possible diagonals. We could even check for this at the same time we're checking for horizontals, because it traverses the same column-3 through column+3 range.
You already know what "color" the tile has, so your checks (in fake code) would simply be of the form:
boolean matched = false;
int stretch = 0;
do {
checkTile = ...;
matched = checkedTile.color.equals(droppedTile.color);
if (matched) {
if (stretch == 3) playerWins()
stretch++;
}
} while(matched);
If the largest stretch of tiles you find that have the same color is 4, done. If not, no connect-4.
That said, this is a homework assignment: S.O. is here for you when you have a problem while programming, but we're not here to do your homework for you. If you get stuck, ask your fellow students or even your teacher. The internet isn't the only place to ask help, especially when you're taking a course.
Instead of coding it in a if-statement, I would e.g for the \ diagonal simply start at the position of the coin and count in direction right-lower, how many of the same color are there until the color changes, or the border is reached. Same in the left-upper direction.
At the end I would simply check if the sum of both counts plus one is greater or equal 4.
Same method for the / diagonal.
Warning: Your implementation of - and | have no array-boundary checks yet. I would recommend the counting approach for them too.
P.s. And to make your code more clear, put each check in a separate methood:
isHorizonallWin(x,y,color,grid)
isVerticalWin(x,y,color,grid)
isLdiagonalLeftUpper2RightLowerWin(x,y,color,grid)
isLdiagonalRightUpper2leftLowerWin(x,y,color,grid)

Categories