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

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

Related

How do I get my program to identify a the string and integer within a given string? [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 2 years ago.
So here's the homework question:
"Write a program that takes a date as input and outputs the date's season. The input is a string to represent the month and an int to represent the day.
Ex: If the input is:
April 11
the output is:
Spring
In addition, check if the string and int are valid (an actual month and day).
Ex: If the input is:
Blue 65
the output is:
Invalid
"
My code is as follows:
'''
String inputMonth;
int inputDay;
inputMonth = scnr.next();
inputDay = scnr.nextInt();
if( ((inputMonth == "March") || (inputMonth == "march")) && ((inputDay >= 20) && (inputDay <= 31))){
System.out.println("Spring");
}
else if( ((inputMonth == "April") || (inputMonth == "april")) && ((inputDay >= 1) && (inputDay <= 30))){
System.out.println("Spring");
}
else if( ((inputMonth == "May") || (inputMonth == "may")) && ((inputDay >= 1) && (inputDay <= 31))){
System.out.println("Spring");
}
else if( ((inputMonth == "June") || (inputMonth == "june")) && ((inputDay >= 1) && (inputDay <= 20))){
System.out.println("Spring");
}
else if( ((inputMonth == "June") || (inputMonth == "june")) && ((inputDay >= 21) && (inputDay <= 30))){
System.out.println("Summer");
}
else if( ((inputMonth == "July") || (inputMonth == "july")) && ((inputDay >= 1) && (inputDay <= 31))){
System.out.println("Summer");
}
else if( ((inputMonth == "August") || (inputMonth == "august")) && ((inputDay >= 1) && (inputDay <= 31))){
System.out.println("Summer");
}
else if( ((inputMonth == "September") || (inputMonth == "september")) && ((inputDay >= 1) && (inputDay <= 21))){
System.out.println("Summer");
}
else if( ((inputMonth == "September") || (inputMonth == "september")) && ((inputDay >= 22) && (inputDay <= 30))){
System.out.println("Autumn");
}
else if( ((inputMonth == "October") || (inputMonth == "october")) && ((inputDay >= 1) && (inputDay <= 31))){
System.out.println("Autumn");
}
else if( ((inputMonth == "November") || (inputMonth == "november")) && ((inputDay >= 22) && (inputDay <= 30))){
System.out.println("Autumn");
}
else if( ((inputMonth == "December") || (inputMonth == "december")) && ((inputDay >= 1) && (inputDay <= 20))){
System.out.println("Autumn");
}
else if( ((inputMonth == "December") || (inputMonth == "december")) && ((inputDay >= 21) && (inputDay <= 31))){
System.out.println("Winter");
}
else if( ((inputMonth == "January") || (inputMonth == "january")) && ((inputDay >= 1) && (inputDay <= 31))){
System.out.println("Winter");
}
else if( ((inputMonth == "February") || (inputMonth == "february")) && ((inputDay >= 1) && (inputDay <= 29))){
System.out.println("Winter");
}
else if( ((inputMonth == "March") || (inputMonth == "march")) && ((inputDay >= 1) && (inputDay <= 19))){
System.out.println("Winter");
}
else{
System.out.println("Invalid");
}
'''
I believe the problem is that it wont read both the string and the integer correctly but I'm not exactly sure why.
Also I know there's probably a shorter way to do this but I don't know how yet, if anyone would like to help me with that too it would be infinitely appreciated.
Thank you in advance
I don't know if this version makes more sense to you or not.
I put the month names, seasons, and date ranges in arrays. Normally, I would have created a class to hold the season name and date range, but I used arrays to keep it simpler.
I commented on the more obscure sections of code. I hope this helps.
package com.ggl.testing;
import java.util.Scanner;
public class Seasons {
static String[] months = { "January", "February", "March", "April",
"May", "June", "July", "August", "September",
"October", "November", "December" };
// Winter has two ranges to make the comparisons easier
static String[] seasons = { "Spring", "Summer", "Autumn", "Winter",
"Winter" };
// Month and day to start the season, month and day to end the season
// Winter has two ranges to make the comparisons easier
// The month number is zero based (0 - 11)
static int[][] ranges = { { 2, 20, 5, 20 }, { 5, 21, 8, 21 },
{ 8, 22, 11, 20 }, { 11, 21, 11, 31 },
{ 0, 1, 2, 19 } };
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[] values = getInput(scanner);
if (values[0] < 0 || values[1] < 0) {
System.out.println("Invalid");
} else {
System.out.println(getSeason(values));
}
scanner.close();
}
static int[] getInput(Scanner scanner) {
int[] output = new int[2];
System.out.print("Type the month and day: ");
String s = scanner.nextLine().trim();
String[] parts = s.split(" ");
output[0] = getMonthIndex(parts[0]);
output[1] = getDay(parts[1]);
return output;
}
static int getMonthIndex(String month) {
for (int i = 0; i < months.length; i++) {
if (month.toLowerCase().equals(months[i].toLowerCase())) {
return i;
}
}
return -1;
}
static int getDay(String number) {
try {
int value = Integer.valueOf(number);
// TODO Check last day of a particular month
if (value < 1 || value > 31) {
return -1;
} else {
return value;
}
} catch (NumberFormatException e) {
return -1;
}
}
static String getSeason(int[] values) {
for (int i = 0; i < ranges.length; i++) {
if ((ranges[i][0] == values[0]) && (ranges[i][1] <= values[1])) {
return seasons[i];
} else if ((values[0] == ranges[i][2]) && (values[1] <= ranges[i][3])) {
return seasons[i];
} else if ((ranges[i][0] < values[0]) && values[0] < ranges[i][2]) {
return seasons[i];
}
}
return "Invalid";
}
}

How to increase efficiency by using for loops?

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

tie breaker condition in Java for tennis game app

I am working on android tennis app and now I need to keep conditions for a tie breaker scores in tennis game.
For example, if the set 1 scores are at 6-6, then the tie breaker game starts from 1-1, 2-2, 3-3 and so on.
Or in other ways, How I can implement the tie-breaker rule in tennis game for the below code
I am thinking about how to keep this condition working on my app but not able to get it. I am new to Java, so any help will be appreciated.
/*
* The method for the Player1 starts below
* */
assert countBtn1 != null;
countBtn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CountA++;
textViewScore.setText(CountA+"--"+textViewCount1.getText()+"--"+textViewCount2.getText());
if (CountA == 1) {
textViewCount1.setText("15");
} else if (CountA == 2 ) {
textViewCount1.setText("30");
} else if (CountA == 3) {
textViewCount1.setText("40");
}
/*
* After the game is reached to the level of 40-0 for player 1, it checks all the rules of the tennis before finishing the Game
* */
else if (CountA == 4) {
if (CountB == 3 && textViewCount2.getText().toString().equals("40") && textViewCount1.getText().toString().equals("40")) {
textViewCount1.setText("AD");
CountA--;
}
if (CountB == 4 && textViewCount2.getText().toString().equals("40") && textViewCount1.getText().toString().equals("40")) {
textViewCount1.setText("AD");
CountA--;
}
if (CountA == 4 && textViewCount1.getText().toString().equals("40") && textViewCount2.getText().toString().equals("15")) {
textViewCount1.setText("0");
textViewCount2.setText("0");
CountA--;
if(set1 != 7) {
set1 = set1 + 1;
textView1.setText("" + set1);
CountA=0;
}
}
if (CountA == 4 && textViewCount1.getText().toString().equals("40") && textViewCount2.getText().toString().equals("30")) {
textViewCount1.setText("0");
textViewCount2.setText("0");
CountA--;
if(set1 != 7) {
set1 = set1 + 1;
textView1.setText("" + set1);
CountA=0;
}
}
else if (CountA == 4 && textViewCount1.getText().toString().equals("AD") && textViewCount2.getText().toString().equals("40")) {
textViewCount1.setText("0");
textViewCount2.setText("0");
CountA--;
if(set1 != 7) {
set1 = set1 + 1;
textView1.setText("" + set1);
CountA=0;
CountB=0;
}
}
else if (CountA == 4 && textViewCount1.getText().toString().equals("40") && textViewCount2.getText().toString().equals("AD")) {
textViewCount1.setText("40");
textViewCount2.setText("40");
CountA--;
}
else if (CountA == 4 && textViewCount1.getText().toString().equals("40") && textViewCount2.getText().toString().equals("0")) {
textViewCount1.setText("0");
textViewCount2.setText("0");
CountA--;
/*
* The below functions checks the incrementation clause of the game for the sets
* */
if((set1 <= 4 && set4 != 6 && set2 == 0 && set5 == 0)
|| (set1 == 5 && set4 !=7 && set2 == 0 && set5 == 0)
|| (set1 == 5 && set4 == 6 && set2 == 0 && set5 == 0)
// || (set1 == 6 && set4 == 6 && set2 == 0 && set5 == 0)
|| (set1 == 6 && set4 == 5 && set2 == 0 && set5 == 0))
{
set1 = set1 + 1;
// tie1++;
// textViewCount1.setText(""+tie1);
textView1.setText("" + set1);
CountA=0;
if((set1 ==6 && set4 <=4 && set2 == 0 && set5 == 0)|| (set1 ==7 && set4 <= 6 && set2 ==0 && set5 == 0))
{
builder.setMessage("Player 1 wins the 1st set")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {}
});
AlertDialog theAlertDialog = builder.create();
theAlertDialog.show();
}
}
else if ( set1 == 6 && set4 == 6 && set2 == 0 && set5 == 0){
for (tie1=100; tie1 <= 1; tie1++){
textViewCount1.setText("" + tie1);
CountA=0;
}
}
else if((set2 <= 5 && set5 != 6 && set3 == 0 && set6 == 0)
|| (set2 == 5 && set5 != 7 && set3 == 0 && set6 == 0)
|| (set2 == 6 && set5 == 5 && set3 == 0 && set6 == 0)
|| (set2 == 6 && set5 == 6 && set3 == 0 && set6 == 0))
{
set2 = set2 + 1;
textView2.setText("" + set2);
CountA=0;
if((set1 == 6 && set4 <=4 && set2 ==6 && set5 <=4 && set3 == 0 && set6 == 0) || (set2 ==7 && set5 <= 6 && set3 ==0 && set6 == 0))
{
//builder.setTitle("Game Over");
builder.setMessage("Player 1 won the Match by winning both the Sets")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
CountA = 0;
CountB = 0;
textView1.setText("0");
textView2.setText("0");
textView3.setText("0");
textView4.setText("0");
textView5.setText("0");
textView6.setText("0");
textViewCount1.setText("0");
textViewCount2.setText("0");
set1 = set2 = set3 = set4 = set5 = set6 = 0;
}
});
AlertDialog theAlertDialog = builder.create();
theAlertDialog.show();
}
else if((set4 ==6 && set1 <=4 && set2 ==6 && set5 <=4 && set3 == 0 && set6 == 0)|| (set2 ==7 && set5 <= 6 && set3 ==0 && set6 == 0))
{
builder.setMessage("Player 1 wins the 2nd Set")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
AlertDialog theAlertDialog = builder.create();
theAlertDialog.show();
}
}
else if((set3 <= 4 && set6 != 6)
|| (set3 == 5 && set6 !=7 )
|| (set3 == 5 && set6 == 6 )
|| (set3 == 6 && set6 == 6 )
|| (set3 == 6 && set6 == 5 ))
{
set3 = set3 + 1;
textView3.setText("" + set3);
CountA=0;
if((set3 ==6 && set6 <=4) || (set3 ==7 && set6 <= 6 ))
{
//builder.setTitle("Game Over");
builder.setMessage("Player 1 won the Match by winning both the Sets")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
CountA = 0;
CountB = 0;
textView1.setText("0");
textView2.setText("0");
textView3.setText("0");
textView4.setText("0");
textView5.setText("0");
textView6.setText("0");
textViewCount1.setText("0");
textViewCount2.setText("0");
set1 = set2 = set3 = set4 = set5 = set6 = 0;
}
});
AlertDialog theAlertDialog = builder.create();
theAlertDialog.show();
}
}
else{
CountA = 0;
}
}
else if (CountA == 5 && textViewCount1.getText().toString().equals("40") && textViewCount2.getText().toString().equals("40")) {
textViewCount1.setText("AD");
textViewCount2.setText("40");
}
}
}
}
);
Well if you have a proper implementation of score like 40-0, 15-15 etc. then it should be straightforward to mirror it into a helper method that handles tiebreak.
As your code is very verbose I can't tell you how to do it line by line, but simply think of the tiebreak as another additional set and implement it the same way you'd implement a set:
i.e. have a counterA and a counterB and if player A wins a point increment his counter, otherwise increment counter for B - and as soon as one of the player's counter reaches the number that has him win the tiebreak (e.g. condition for A to win would be: either counterA == 6 and counterA - counterB >= 2 or counterA == 7 (via if, else if) - that is if I remember tennis rules correctly)
Then only call your tiebreak method as soon as the set score has reached 6-6 (however you choose to do this check is fine) and return the winner of the tiebreak to the method that handles the set functionality.

Avoiding Multiple Function Calls?

I cannot figure out how to make it so it only calls check4 once... this was for a homework assignment last semester and I got 5 points off for calling it multiple times but I would not like to know how to do it (the professor never said how).
I tried moving the check4 to after the if block but it really needs to go in between the last else if and the else which is not possible. The ONLY way the number should print is if all of the steps do not print out a word instead.
public class CheeseCakeFactory_ajh187 {
public static void main(String[] args) {
int counter = 0;
int printNumber = 0; //number that will get changed to one of the terms
while (counter != 15 & printNumber < 210) { //as long as the counter is not 15 and print number is lesss than 210 it will keep looping.
printNumber++;
if (printNumber % 3 ==0 && printNumber % 5 == 0 && printNumber % 7 == 0) {
System.out.print("cheesecakefactory");
}
else if (printNumber % 3 == 0 && printNumber % 5 == 0){
System.out.print("cheesecake");
check4(printNumber);
}
else if (printNumber % 3 == 0 && printNumber % 7 == 0){
System.out.print("cheesefactory");
check4(printNumber);
}
else if (printNumber % 5 == 0 && printNumber % 7 == 0){
System.out.print("factorycake");
check4(printNumber);
}
else if (printNumber % 3 == 0){
System.out.print("cheese");
check4(printNumber);
}
else if (printNumber % 5 ==0){
System.out.print("cake");
check4(printNumber);
}
else if (printNumber % 7 ==0){
System.out.print("factory");
check4(printNumber);
}
else { //if the number is not divisible by any of the other numbers we still have to check for the 4
if (Integer.toString(printNumber).contains("4")) {
System.out.print("hoho");
}
else {
System.out.print(printNumber); //if its not divisible by 4, we just print the number
}
}
System.out.print(" ");
counter++;
if (counter == 15) { //once the counter is 15 we need to put the new items on a new line
System.out.print("\n");
counter = 0; //resets the counter so that we can accomplish this every 15 passes.
}
}
}
public static void check4(int printNumber) {
if (Integer.toString(printNumber).contains("4")) {
System.out.print("hoho");
}
}
}
First, I would update check4 to return a boolean (which you can save). Something like,
public static boolean check4(int printNumber) {
return String.valueOf(printNumber).contains("4");
}
Then you can also save your tests into boolean variables. Something like
boolean mod3 = printNumber % 3 == 0;
boolean mod5 = printNumber % 5 == 0;
boolean mod7 = printNumber % 7 == 0;
if (mod3 || mod5 || mod7) {
if (mod3 && mod5 && mod7) {
System.out.print("cheesecakefactory");
} else {
boolean isCheck4 = check4(printNumber); // <-- call it once
if (mod3 && mod5) {
System.out.print("cheesecake");
} else if (mod3 && mod7) {
System.out.print("cheesefactory");
} else if (mod5 && mod7) {
System.out.print("factorycake");
} else if (mod3) {
System.out.print("cheese");
} else if (mod5) {
System.out.print("cake");
} else if (mod7) {
System.out.print("factory");
} else {
if (!isCheck4) { // <-- it doesn't have a 4, print it.
System.out.print(printNumber);
}
}
if (isCheck4) {
System.out.print("hoho"); // <-- it does have a 4.
}
}
}
I hope I got your problem right so:
you create a global boolean variable named say isMethodCalled witch is false, then in the check4 method you make it true, and simple check if the isMethodCalled is false before calling the method.
boolean isMethodCalled = false;
if(!isMethodCalled) {
check4() // do wathever you need to do to call check4()
}
public static void check4(int printNumber) {
if (Integer.toString(printNumber).contains("4")){
System.out.print("hoho");
}
isMethodCalled = true;
}
Simply use a flag, set it to true initially.
Then, wherever you dont want the check4 to run, set it to false.
after the if-else, check if the flag istrue. if it is, execute 'check4(printNumber)'
public class CheeseCakeFactory_ajh187 {
public static void main(String[] args) {
int counter = 0;
int printNumber = 0; //number that will get changed to one of the terms
int flag=true;
while (counter != 15 & printNumber < 210) { //as long as the counter is not 15 and print number is lesss than 210 it will keep looping.
printNumber++;
if (printNumber % 3 ==0 && printNumber % 5 == 0 && printNumber % 7 == 0) {
System.out.print("cheesecakefactory");
flag=false;
}
else if (printNumber % 3 == 0 && printNumber % 5 == 0){
System.out.print("cheesecake");
}
else if (printNumber % 3 == 0 && printNumber % 7 == 0){
System.out.print("cheesefactory");
}
else if (printNumber % 5 == 0 && printNumber % 7 == 0){
System.out.print("factorycake");
}
else if (printNumber % 3 == 0){
System.out.print("cheese");
}
else if (printNumber % 5 ==0){
System.out.print("cake");
}
else if (printNumber % 7 ==0){
System.out.print("factory");
}
else { //if the number is not divisible by any of the other numbers we still have to check for the 4
if (Integer.toString(printNumber).contains("4")) {
System.out.print("hoho");
}
else {
System.out.print(printNumber); //if its not divisible by 4, we just print the number
}
flag=false;
}
if(flag)
check4(printNumber);
System.out.print(" ");
counter++;
if (counter == 15) { //once the counter is 15 we need to put the new items on a new line
System.out.print("\n");
counter = 0; //resets the counter so that we can accomplish this every 15 passes.
}
}
}
public static void check4(int printNumber) {
if (Integer.toString(printNumber).contains("4")) {
System.out.print("hoho");
}
}
}

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