tictactoe minmax recursion causing confusion - java

I read a number of tic tac toe examples using the minmax algorithm but haven't found a good one that really explains what's going on. I've written one that works but need help understanding a small section of the recursion process.
If you load the code below, enter your name, O (not zero), and 0 (zero) you'll get the results I'm looking at. After the computer moves stop the program and look at the console.log.
If you look at the console output, you see the line best 0 7 [[0, 7]] that happens just before the return statement. Where is the next line coming from 0 simulateMove = 6 scoreMove[1] = 7 depth = 2
The other question is why on line 423 do I need scoreMoveAvailable[i][1] = simulateMove; instead of scoreMoveAvailable[i][1] = scoreMove[1];
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Random;
import java.util.Arrays;
public class TicTacToeV2{
private static final int boardRowDim = 3;
private static final int boardColDim = 3;
private String[][] board;
private String playerName;
private String playerMark;
private String computerMark;
private boolean humanGoes;
private boolean winner;
private boolean draw
private int gameTargetScore;
private boolean output = true;
private boolean toSeed = true;
private ArrayList<Integer> availableMoves;
public TicTacToeV2(String name, boolean whoGoesFirst){
availableMoves = new ArrayList<Integer>();
board = new String[boardRowDim][boardColDim];
for (int i = 0; i < board.length; i++){
for(int j = 0; j < board[0].length; j++){
board[i][j] = ((Integer)(double2single(i,j))).toString();
availableMoves.add(double2single(i,j));
}
}
playerName = name;
humanGoes = whoGoesFirst;
playerMark = "X";
computerMark = "O";
gameTargetScore = 15;
if(!humanGoes){
playerMark = "O";
computerMark = "X";
gameTargetScore = - 15;
}
winner = false;
draw = false;
}
public static void main(String[] args)throws Exception{
System.out.println("\u000C");
Scanner kboard = new Scanner(System.in);
printHeader();
System.out.print(" Please enter your name ; ");
String name = kboard.next();
name = capitalize(name);
System.out.print("\n\n X's go first. " + name + ", please enter your mark ('X' or 'O')");
String mark = kboard.next().toUpperCase();
boolean whoPlaysFirst = (mark.equals("X")) ? true : false;
TicTacToeV2 myGame = new TicTacToeV2(name,whoPlaysFirst);
myGame.playGame(kboard);
}
public void playGame(Scanner kboard)throws Exception{
Integer move = null;
boolean goodMove;
String kboardInput = null;
Scanner input;
int[] cell2D = new int[2];
Random random = new Random();
int nextComputerMove;
if(toSeed){
board = seedBoard();
availableMoves = seedAvailable(board);
int x = 0;
int o = 0;
for(int i = 0; i < 3;i++){
for(int j = 0;j < 3;j++){
if(board[i][j].equals("X"))x++;
else if(board[i][j].equals("O"))o++;
}
}
if((x - o) == 1) humanGoes = true;
else if((x - o) == 0) humanGoes = false;
else{
System.out.println("Fatal Error: seed bad");
System.exit(0);
}
System.out.println("humangoes = " + humanGoes + x + o);
}
while(!winner && !draw){
printHeader();
goodMove = false;
drawBoard(board);
if(!humanGoes && availableMoves.size() < 9){
System.out.println("That's a great move, I'll have to think about this");
Thread.sleep(2000);
}
if(humanGoes){
while(!goodMove){
System.out.print("\n\n Please enter a number for your move : ");
kboardInput = kboard.next();
input = new Scanner(kboardInput);
if(input.hasNextInt()){
move = input.nextInt();
if(move == 99){
System.out.println("You found the secret exit code");
Thread.sleep(2000);
printHeader();
System.out.println("bye");
System.exit(0);
}
goodMove = checkMove(move);
if(!goodMove)System.out.println(" WARNING: Incorrect input, try again");
}else{
System.out.println(" WARNING: Incorrect input, try again");
}
}
cell2D = single2Double(move);
board[cell2D[0]][cell2D[1]] = playerMark;
}else{
//nextComputerMove = random.nextInt(availableMoves.size());
//move = availableMoves.get(nextComputerMove);
String[][] currentBoard = new String[boardRowDim][boardColDim];
currentBoard = copyBoard(board);
ArrayList<Integer> currentAvailableMoves= new ArrayList<Integer>();
currentAvailableMoves = copyAvailableMoves(availableMoves);
//System.out.println(System.identityHashCode(currentAvailableMoves));
int[] bestScoreMove = new int[2];
bestScoreMove = findBestMove(currentBoard,currentAvailableMoves,true,0,kboard);
move = availableMoves.get(availableMoves.indexOf(bestScoreMove[1]));
cell2D = single2Double(move);
board[cell2D[0]][cell2D[1]] = computerMark;
}
humanGoes = humanGoes ? false:true;
availableMoves = updateAvailableMoves(move,availableMoves);
if (Math.abs(score(board)) == 15) winner = true;
if (availableMoves.size() == 0) draw = true;
if(winner || draw){
printHeader();
drawBoard(board);
}
if(score(board) == gameTargetScore)System.out.println(playerName + " you are too good for me. \n" +
"Congratulations you won!!\n\n");
else if(score(board) == -gameTargetScore)System.out.println("IWONIWONIWONohboyIWONIWONIWON");
else if(draw)System.out.println("Good game. It's a draw!");
}
}
public void drawBoard(String[][] someBoard){
String mark = " ";
Integer row,col;
String type;
for( int i = 0;i < 15; i++){
System.out.print(" ");
for (int j = 0; j < 27; j++){
mark = " ";
if(i==5 || i == 10)mark = "-";
if(j==8 || j == 17)mark = "|";
row = i/5;
col = j/9;
type = someBoard[row][col];
if(type == "X"){
if( ((i%5 == 1 || i%5 == 3) &&
(j%9 == 3 || j%9 == 5)) ||
(i%5 == 2 &&
j%9 == 4))mark = "X";
}else if(type == "O"){
if( ((i%5 == 1 || i%5 == 3) &&
(j%9 == 3 || j%9 == 4 || j%9 == 5)) ||
((i%5 == 2) &&
(j%9 == 3 || j%9 == 5))) mark = "O";
}else{
if( i%5 == 2 && j%9 == 4){
mark = ((Integer)(row * 3 + col)).toString();
}
}
System.out.print(mark);
}
System.out.println();
}
System.out.println("\n\n\n");
}
public boolean checkMove(Integer move){
/*
* to sanitize user input we have to check if what
* they entered is an available square
*/
boolean goodMove = false;
for(Integer available : availableMoves){
if (available == move) goodMove = true;
}
return goodMove;
}
public int score(String[][] newBoard){
int row;
int newCol;
int score = 0;
for (int strategy = 0; strategy < 8; strategy++){
score = 0;
for (int col = 0; col < 3; col++){
if(strategy < 3){ //rows
row = strategy ;
newCol = col;
}else if (strategy < 6){ //cols
row = col;
newCol = strategy - 3;
}else{//diag
int diag = strategy - 6;
row = col - 2 * diag * (col - 1);
newCol = col;
}
if(newBoard[row][newCol].equals("X")){
score+=5;
}else if(newBoard[row][newCol].equals("O")){
score+=-5;
}
}
score = (Math.abs(score)== 15) ? score : 0;
if(Math.abs(score) == 15) break;
}
return score;
}
public String[][] copyBoard(String[][] originalBoard){
String[][] duplicateBoard = new String[boardRowDim][boardColDim];
for (int i = 0;i < boardRowDim; i++){
for(int j = 0; j < boardColDim; j++){
duplicateBoard[i][j] = originalBoard[i][j];
}
}
return duplicateBoard;
}
public String[][] updateBoard(Integer move, String mark, String[][]oldBoard){
String[][] currentBoard = new String[boardRowDim][boardColDim];
int[] cell2D = new int[2];
currentBoard = copyBoard(oldBoard);
cell2D = single2Double(move);
currentBoard[cell2D[0]][cell2D[1]] = mark;
return currentBoard;
}
public ArrayList<Integer> copyAvailableMoves(ArrayList<Integer> originalAvailableMoves){
ArrayList<Integer> duplicateAvailableMoves = new ArrayList<Integer>();
for(int i = 0; i < originalAvailableMoves.size();i++){
duplicateAvailableMoves.add(originalAvailableMoves.get(i));
}
return duplicateAvailableMoves;
}
public ArrayList<Integer> updateAvailableMoves(Integer move, ArrayList<Integer> oldAvailableMoves){
ArrayList<Integer> currentAvailableMoves = new ArrayList<Integer>();
currentAvailableMoves = copyAvailableMoves(oldAvailableMoves);
currentAvailableMoves.remove(move);
return currentAvailableMoves;
}
public String[][] seedBoard(){
String[][] sampleBoard ={{"0","O","X"},{"X","4","O"},{"6","7","X"}};
//String[][] sampleBoard ={{"X","O","O"},{"3","4","X"},{"6","7","8"}};
return sampleBoard;
}
public ArrayList<Integer> seedAvailable(String[][] seedBoard){
ArrayList seedMoves = new ArrayList<Integer>();
int index = -1;
for(int i = 0; i < 3;i++){
for (int j = 0; j < 3; j++){
if(!seedBoard[i][j].equals("X") && !seedBoard[i][j].equals("O")){
index = i*3 + j;
seedMoves.add(index);
}
}
}
//System.out.println(seedMoves);
return seedMoves;
}
public int[] findBestMove(String[][] currentBoard, ArrayList<Integer> currentAvailableMoves,boolean currentComputerMoves,int depth,Scanner kboard){
ArrayList<Integer> simulateAvailableMoves = new ArrayList<Integer>();
String[][] simulateBoard = new String[boardRowDim][boardColDim];
//System.out.println(System.identityHashCode(currentAvailableMoves));
int[] scoreMove = new int[2]; //return array with score and associated move
int[] cell2D = new int[2]; //array holding i and j of board to place Mark (X or O)
int computerTargetScore = (computerMark.equals("X")) ? 15:-15;
/*
* scoreMoveAvailable is an array that holds scores for each available move
* inside loop. The bestScoreMove will be the min or max of this array
* depending on whether it's X's or O's turn to move
*/
int[][] scoreMoveAvailable = new int[currentAvailableMoves.size()][2];
Integer simulateMove = null; //current move inside loop
Boolean simulateComputerMoves = null;
for(int i = 0; i < currentAvailableMoves.size(); i++){
scoreMoveAvailable[i][0] = 0; //score
scoreMoveAvailable[i][1] = -1; // square 0 - 8
}
if(output)System.out.println("on enter available moves " + currentAvailableMoves);
for (int i = 0; i < currentAvailableMoves.size() ;i++){
simulateAvailableMoves = copyAvailableMoves(currentAvailableMoves);
simulateBoard = copyBoard(currentBoard);
simulateComputerMoves = currentComputerMoves;
if(output)System.out.println("in loop available moves " + i + " " + simulateAvailableMoves);
simulateMove = simulateAvailableMoves.get(i);
simulateAvailableMoves = updateAvailableMoves(simulateMove,simulateAvailableMoves);
cell2D = single2Double(simulateMove);
if(simulateComputerMoves){
if(output)System.out.println("computer moves " + simulateMove);
simulateBoard[cell2D[0]][cell2D[1]] = computerMark;
simulateComputerMoves = false;
if(score(simulateBoard) == computerTargetScore || simulateAvailableMoves.size() == 0){
scoreMove[0] = score(simulateBoard);
scoreMove[1] = simulateMove;
if(output)System.out.println("score computer" + Arrays.toString(scoreMove) +" computer moves = " + simulateMove + " i = " + i);
if(output)drawBoard(simulateBoard);
}else{
depth++;
if(output)System.out.println("computer calling findbest " +simulateAvailableMoves);
if(output)drawBoard(simulateBoard);
scoreMove = findBestMove(simulateBoard,simulateAvailableMoves,simulateComputerMoves,depth,kboard);
}
}else{
if(output)System.out.println("human moves" + simulateMove);
simulateBoard[cell2D[0]][cell2D[1]] = playerMark;
simulateComputerMoves = true;
if(score(simulateBoard) == (-computerTargetScore) || simulateAvailableMoves.size() == 0){
scoreMove[0] = score(simulateBoard);
scoreMove[1] = simulateMove;
if(output)System.out.println("score human "+ Arrays.toString(scoreMove) +" human moves " + simulateMove + " i = " + i);
if(output)drawBoard(simulateBoard);
}else{
depth++;
if(output)System.out.println("human calling findbest " + simulateAvailableMoves);
if(output)drawBoard(simulateBoard);
scoreMove = findBestMove(simulateBoard,simulateAvailableMoves,simulateComputerMoves,depth,kboard);
}
}
if(output)System.out.println(i + " simulateMove = " + simulateMove + " scoreMove[1] = " + scoreMove[1] + " depth = " + depth);
// drawBoard(simulateBoard);
scoreMoveAvailable[i][0] = scoreMove[0] ;
scoreMoveAvailable[i][1] = simulateMove;
if(output)System.out.println("score array = " + i + " " + Arrays.deepToString(scoreMoveAvailable));
}
int[] bestScoreMove = new int[2];
bestScoreMove[0] = scoreMoveAvailable[0][0]; //set bestScoreMove to first element in arraylist
bestScoreMove[1] = scoreMoveAvailable[0][1];
if(output)System.out.println("****************************************");
if( (currentComputerMoves && computerMark.equals("X") ) || (!currentComputerMoves && computerMark.equals("O") ) ) {
for (int i = 0; i < scoreMoveAvailable.length;i++){
if(scoreMoveAvailable[i][0] > bestScoreMove[0]){
bestScoreMove[0] = scoreMoveAvailable[i][0] ;
bestScoreMove[1] = scoreMoveAvailable[i][1];
}
if(output)System.out.printf("MAX X scores and moves = %d %d %d %s\n",i,scoreMoveAvailable[i][0],scoreMoveAvailable[i][1],"XXX");
}
if(output)System.out.println("\n");
}else{
for (int i = 0; i < scoreMoveAvailable.length;i++){
if(scoreMoveAvailable[i][0] < bestScoreMove[0]){
bestScoreMove[0] = scoreMoveAvailable[i][0] ;
bestScoreMove[1] = scoreMoveAvailable[i][1];
}
if(output)System.out.printf("MIN O scores and moves =%d %d %d %s\n",i,scoreMoveAvailable[i][0],scoreMoveAvailable[i][1],"OOO");
}
if(output)System.out.println("\n");
}
if(output)System.out.println("best " + bestScoreMove[0] + " " + bestScoreMove[1] + " " + Arrays.deepToString(scoreMoveAvailable));
return bestScoreMove;
}
/*
* just some static methods to help make things easy
*/
public static void printHeader(){
System.out.println("u000C Welcome to TicTacToe\n" +
" where you can match wits\n" +
" against the computer\n" +
"(the real challenge is making it a draw)\n");
}
public static int double2single(int row, int col){
int singleCell = 0;
singleCell = boardRowDim * row + col;
return singleCell;
}
public static int[] single2Double(int cell){
int[] cell2D = new int[2];
cell2D[0] = cell / boardColDim;
cell2D[1] = cell % boardColDim;
return cell2D;
}
public static String capitalize(String word){
word = word.substring(0,1).toUpperCase() + word.substring(1);
return word;
}
}

Note that the below diagram assumes that you are not doing "depth++", but just using "depth + 1" in the recursive call. The former is a benign bug in your code, which leads to printing misleading depths.
findBestMove is first invoked when bestScoreMove = findBestMove... is used to find the computer's move. Based on the seeded board and human taking "0", the moves now available are 4, 6, and 7.
First, the computer simulates moving 4
This creates a recursive call, adding a frame to the function stack. The human now has 6 and 7 as possible moves. Since 6 is first, the human "tries" 6 first. In this simulation now, it's computer/4 -> human/6
Again, a frame is added to the function stack for the recursive call from the human "running a simulation". Now, there's one move left: the computer takes 7. This is where best 0 7 [[0, 7]] is printed.
After the last recursive call returns, the function stack is popped, and we're again where the human is moving 6, and that's where 0 simulateMove = 6.. is printed.
You can use a debugger to show more detailed information about the stack, but here is some extra advice (mostly to make functions shorter) to make it easier to debug:
There's a lot of Thread.sleep(2000); right after a println. You can wrap these two lines in a function
In many but not all places, the logic assumes a board size of 3x3, e.g. && availableMoves.size() < 9). It's inconsistent, and this logic can be confusing. To make it clear, you can create a function "noMovesMade()" that computes this based on the available variables.
Additionally, if(!humanGoes && availableMoves.size() < 9){ can simply go in the "else" block (since that already implies it's the computer's turn)
if((x - o) == 1) humanGoes = true; is assuming that the human is playing "O" when the rest of the code does not assume this.
There are a lot of cases variables are initialized, assigned, and then reassigned without being used. For example, String[][] currentBoard = new String[boardRowDim][boardColDim]; currentBoard = copyBoard(board); is redundant, and the same with bestScoreMove.
Arrays.copyOf can be used to copy arrays (in the inner loop of the copyBoard, for example)
ArrayList.contains can be used instead of iterating through the array in checkMove
humanGoes = humanGoes ? false:true; can be shortened to humanGoes = !humanGoes

Related

How to show 2 or more duplicates with this array using java?

i would like to display 2 or more duplicated customers using joptionpane. It is working if there is only 1 duplicate customer but unfortunately the message dialogue wasnt showing if there is 2 or more duplicated customer. Here is my code.
public static void main(String[] args) {
int number;
number = Integer.parseInt(JOptionPane.showInputDialog("Enter the number of customers: "));
int[] one = new int[number];
int[] two = new int[number];
for (int i = 0; i < number; i++) {
one[i] = Integer.parseInt(JOptionPane.showInputDialog("Customer number: "));
}
int y = 0;
for (int i = 0; i < one.length - 1; i++) {
for (int w = i + 1; w < one.length; w++) {
if (one[i] == one[w]) {
two[y] = one[w];
y = y + 1;
break;
}
}
for (int p = 0; p < y - 1; p++) {
if (one[p] == two[p - 1]) {
y = y - 1;
break;
}
}
}
if (y == 0) {
JOptionPane.showMessageDialog(null, "\nHONEST CUSTOMERS");
} else if (y != 0) {
JOptionPane.showMessageDialog(null, "Duplicates:");
for (int o = 0; o < y; o++) {
JOptionPane.showMessageDialog(null, "Customer #" + two[o]);
//jop.showMessageDialog(null, "Duplicates: Customer #" + two[l]);
//}
}
}
}
}
How can i show the message dialogue if i want to show 2 or more duplicated customers? thank you for the help.
Break down your code into the following:
A function that takes the two lists and return a list of pairs of duplicates.
A function that takes the list of duplicates and create a string stating: "Duplicates: value1, value2..."
Show message box.
here is an solution for your problem using Collections:
public static Integer[] getDuplicates(Integer[] list) {
List<Integer> duplicates = new ArrayList<>(Arrays.asList(list));
Set<Integer> seen = new HashSet<>(Arrays.asList(list));
for (Integer i : seen) {
duplicates.remove(i);
}
Set<Integer> uniqueDuplicate = new HashSet<>(duplicates);
return uniqueDuplicate.toArray(Integer[]::new);
}
public static void main(String[] args) {
int number;
number = Integer.parseInt(JOptionPane.showInputDialog("Enter the number of customers: "));
Integer[] one = new Integer[number];
for (int i = 0; i < number; i++) {
one[i] = Integer.parseInt(JOptionPane.showInputDialog("Customer number: "));
}
Integer[] two = getDuplicates(one);
if (two.length == 0) {
JOptionPane.showMessageDialog(null, "\nHONEST CUSTOMERS");
} else {
JOptionPane.showMessageDialog(null, "Duplicates:");
for (int o = 0; o < two.length; o++) {
JOptionPane.showMessageDialog(null, "Customer #" + two[o]);
// jop.showMessageDialog(null, "Duplicates: Customer #" + two[l]);
// }
}
}
}

Arrange the numbers by subtracting

I have a java problem that I don't know how to solve the program is :
two number must got from user n,k.
I need to find a permuation of numbers from 1 to N such that the difference between two items >=k for example :
we get the numbers (n = 5 and k = 2 )
and the answer must be 1,4,2,5,3 :
and for (n=2 and k = 2) there is not answer because the difference between 1 and two is 1(1,2 or 2,1).
I hope you understand what I want.
and I write some codes that are wrong:
public static void main(String[] args) {
Scanner user_input = new Scanner(System.in);
int n = user_input.nextInt();
int k = user_input.nextInt();
int a ;
if (n%2==0) a = (n-2)/2; else a = (n-1)/2 ;
if (k!=a) {System.out.println("Impossible"); return;}
int h = k+1;
int value = 0;
int t = 1;
boolean b = true;
String res = "1 ";
while (value<n-1) {
value++;
if (b){
t = t + h;
res = res + t + " ";
b = false;
}else {
t = t-k;
res = res + t + " ";
b = true;
}
}
System.out.println(res);
}
Here is the code
public class HelloWorld{
public static void calculationMethod(int n, int k) {
if(n<2 || n/2 < k) {
System.out.println("Impossible");
return;
}
else {
int i = (int)Math.ceil(n/2.0);
int j = n;
int start = i;
boolean flag = true;
while(i>=1 || j>start) {
if(flag) {
System.out.print(i + " " );
i--;
flag = false;
}
else {
System.out.print(j + " " );
j--;
flag = true;
}
}
}
}
public static void main(String []args){
calculationMethod(7,3);
}
}
The idea is to divide your range(n) in half. If k>n/2 then it is not possible to construct any such sequence.
If that is not the case, then have 2 pointers one at the middle of your range and one at the end of the range. and print them alternatively decrementing both pointers until u reach the beginning.
Feel free to improve the code.
public void calculationMethod(int n, int k) {
ArrayList<Integer> intList = new ArrayList<>();
for (int i = 1; i <= n; i++) {
int a = i;
int b = i + 2;
if (!intList.contains(a) && a<=n) {
intList.add(a);
}
if (!intList.contains(b) && b<=n) {
intList.add(b);
}
}
String mValues= TextUtils.join(",",intList);
Log.i("values", mValues);
}

Matching array values with variables

In this code I have an array with 5 elements and each element contains a value. Below in the while loop, I'm trying to give the user 3 attempts to guess what number is contained in the array (the user enters their guesses). My problem is that I don't know how to make match the user's guess (stored in a variable choose) with the array values caja[i] to print whether the user won or lost depending on a correct or incorrect guess respectively.
public static void main(String[] args)
{
int[] caja = new int [5];
caja[0] = 1;
caja[1] = 3;
caja[2] = 5;
caja[3] = 7;
caja[4] = 9;
System.out.println("Mostrando todos los numeros del arreglo");
for (int i = 0; i < caja.length; i++)
{
System.out.println(caja[i]);
}
System.out.println();
int electionGame = 3;
int o = 0;
while(electionGame > 0)
{
Scanner sc = new Scanner(System.in);
int choose = sc.nextInt();
for (int i = 0; i < caja.length; i++)
{
o = o + 1;
if(choose == caja[i])
{
System.out.println("Ganastes");
break;
}
else
{
System.out.println("Perdiestes");
break;
}
}
electionGame--;
}
}
}
Your problem is that you break out of your loop in every case:
if(choose == caja[i])
{
System.out.println("Ganastes");
break;
}
else
{
System.out.println("Perdiestes");
break;
}
Instead of doing this (and printing the result after only the first comparison), you should have a Boolean indicating whether the number was found in the array:
int electionGame = 3;
boolean found = false; //indicates whether user has found right number
while (electionGame > 0 && !found) {
Scanner sc = new Scanner(System.in);
int choose = sc.nextInt();
for (int i = 0; i < caja.length && !found; i++) {
if (choose == caja[i]) {
found = true;
}
}
electionGame--;
if (found) {
System.out.println("you won");
} else {
System.out.println("nope");
}
}
This way, you can check the variable and tell the user whether he won or lost.
Here are some additional suggestions. The answer by Alex (https://stackoverflow.com/a/36133864/6077352) is good. Please note the comments in the code.
import java.util.Scanner;
/** https://stackoverflow.com/q/36133524/6077352 */
public class GuessNumber {
public static void main(String[] args) {
int[] caja = new int[5];
caja[0] = 1;
caja[1] = 3;
caja[2] = 5;
caja[3] = 7;
caja[4] = 9;
System.out.println("Mostrando todos los numeros del arreglo");
for (int i = 0; i < caja.length; i++) {
System.out.println(caja[i]);
}
System.out.println();
int tries = 3;
Scanner sc = new Scanner(System.in);// no need to create scanners in loop
while (tries-- > 0) {// count down tries
System.out.print("Please guess a number... ");
int guess = sc.nextInt();
boolean win = false;// flag to determine if won
for (int i : caja) {// iterate through array and check if guess is inside
win |= (i == guess);// when inside: win=true
}
System.out.println("Answer right? " + win);
System.out.println();
}
}
}
So if the user can attempt to get any of the values of the array you might to change your while loop to this one:
while (electionGame > 0) {
Scanner sc = new Scanner(System.in);
int choose = sc.nextInt();
boolean ganaste = false;
for (int i = 0; i < caja.length; i++) {
o = o + 1;
if (choose == caja[i]) {
ganaste = true;
break;
}
}
if (ganaste)
System.out.println("Ganastes");
else
System.out.println("Perdiestes");
electionGame--;
}

Sorting Java Multidimensional Array

I'm trying to sort the contents of an array and while it seems to be working (no runtime errors; is performing sort tasks), the first 10 rows, while sorted, are not in order with the rest of the rows.
class coordSort.java
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
public class coordSort {
#SuppressWarnings({ "unchecked", "unused" })
public static void main (String args[]) throws IOException {
String xCoord, yCoord;
int coordSum;
Scanner input = new Scanner(System.in);
//Get x coordinate from user
System.out.print("Enter x coordinate: ");
xCoord = input.next();
//Get x coordinate from user
System.out.print("Enter y coordinate: ");
yCoord = input.next();
boolean sort = false;
char[] a = xCoord.toCharArray();
char[] b = yCoord.toCharArray();
//validate user input is a digit
if ( (Character.isDigit(a[0])) ) {
if(Character.isDigit(b[0]) ){
//digits entered - begin processing all coordinate values
sort = true;
}
}
//If validation failed, inform user
if(!sort){
System.out.println("Please enter a positive numeric value.");
}
if(sort){
//determine SUM of user entered coordinates
coordSum = Integer.parseInt(xCoord) + Integer.parseInt(yCoord);
//define coordinate array
String[][] coordUnsortedArray = new String[26][3];
int counter;
int commaCount;
String xCoordIn, yCoordIn;
int intXCoordIn, intYCoordIn, sumCoordIn, coordDiff;
//define input file
FileInputStream fileIn = new FileInputStream("coords.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fileIn));
for (int j = 0; j < coordUnsortedArray.length; j++){
counter = 0;
commaCount = 0;
//line from file to variable
String coordSet = reader.readLine();
//look for the second "," to determine end of x coordinate
for(int k = 0; k < coordSet.length(); k++){
if (coordSet.charAt(k) == ',') {
commaCount++;
counter++;
if (commaCount == 2){
break;
}
}else{
counter++;
}
}
//define x coordinate
xCoordIn = (coordSet.substring(2,(counter - 1)));
intXCoordIn = Integer.parseInt(xCoordIn);
//define y coordinate
yCoordIn = (coordSet.substring((counter),coordSet.length()));
intYCoordIn = Integer.parseInt(yCoordIn);
//coordinate calculations
sumCoordIn = Integer.parseInt(xCoordIn) + Integer.parseInt(yCoordIn);
coordDiff = sumCoordIn - coordSum;
//load results to array
coordUnsortedArray[j][0] = xCoordIn;
coordUnsortedArray[j][1] = yCoordIn;
coordUnsortedArray[j][2] = Integer.toString(coordDiff);
//Output Array (BEFORE SORTING)
//System.out.println((j + 1) + ") " + coordUnsortedArray[j][0] + " : " + coordUnsortedArray[j][1] + " : " + coordUnsortedArray[j][2]);
}
System.out.println("\n");
fileIn.close();
String[][] coordsSorted = new String[26][3];
//Sort array coordDiff, column 3
Arrays.sort(coordUnsortedArray, new ColumnComparator(2));
//Print the sorted array
for(int i = 0; i < coordUnsortedArray.length; i++){
String[] row = coordUnsortedArray[i];
System.out.print((i + 1) + ") ");
for(int j = 0; j < row.length; j++) {
//System.out.print(row[j] + " | ");
coordsSorted[i][j] = row[j];
System.out.print(coordsSorted[i][j] + " : ");
}
System.out.print("\n");
}
}
}
}
class sortCoords.java --
import java.util.Comparator;
#SuppressWarnings("rawtypes")
class ColumnComparator implements Comparator {
int columnToSort;
ColumnComparator(int columnToSort) {
this.columnToSort = columnToSort;
}
//overriding compare method
public int compare(Object o1, Object o2) {
String[] row1 = (String[]) o1;
String[] row2 = (String[]) o2;
//compare the columns to sort
return row1[columnToSort].compareTo(row2[columnToSort]);
}
//overriding compare method
public int compare1(Object o1, Object o2) {
String[] row1 = (String[]) o1;
String[] row2 = (String[]) o2;
//compare the columns to sort
return row1[columnToSort].compareTo(row2[columnToSort]);
}
}
I am trying to sort the array in numerical order by the 3rd column. The unsorted array is populated by a text file containing something like:
a,44,67
b,31,49
c,93,6
I am performing calculations on the array compared to user input and populating the array as follows:
44,67,101
31,49,70
93,6,89
I would like the sortedArray to output the following:
31,49,70
93,6,89
44,67,101
One possible confusion here:
return row1[columnToSort].compareTo(row2[columnToSort])
This is a string comparison, not a numerical one. If you sort based on strings, you will get different results than if you do by numbers - ie "1","10","100","9" vs 1,9,10,100
Check out Integer.parseInt and if you can't figure out the rest, feel free to ask more questions.
As spinning_plate stated. You need to compare their int values i.e. you need a cast there
int num1 = Integer.parseInt(row1[columnToSort]);
int num2 = Integer.parseInt(row2[columnToSort]);
if(num1 > num2)
return 1;
else
return 0;
Place this code in the compareTo method and check. Swap the return statements to sort in reverse order.
Also, adding some error checking in the compareTo method will make the code more efficient.
Ok, so after the assistance provided here, below is the solution that we found. Thanks again for the help everyone! Hopefully the code below helps someone else out.
Code for class1 --
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
public class coordSort {
#SuppressWarnings({ "unchecked" })
public static void main (String args[]) throws IOException {
String xCoordChar, yCoordChar;
int xCoord, yCoord, coordSum;
Scanner input = new Scanner(System.in);
//Get x coordinate from user
System.out.print("Enter x coordinate: ");
xCoordChar = input.next();
//Get x coordinate from user
System.out.print("Enter y coordinate: ");
yCoordChar = input.next();
boolean sort = false;
char[] a = xCoordChar.toCharArray();
char[] b = yCoordChar.toCharArray();
//validate user input is a digit
if ( (Character.isDigit(a[0])) ) {
if(Character.isDigit(b[0]) ){
//digits entered - begin processing all coordinate values
sort = true;
}
}
//If validation failed, inform user
if(!sort){
System.out.println("Please enter a positive numeric value.");
}
if(sort){
//Parse user input characters to Integers
xCoord = Integer.parseInt(xCoordChar);
yCoord = Integer.parseInt(yCoordChar);
//determine SUM of user entered coordinates
coordSum = xCoord + yCoord;
//define coordinate array
int[][] coordUnsortedArray = new int[26][3];
int counter;
int commaCount;
String xCoordIn, yCoordIn;
int intXCoordIn, intYCoordIn, sumCoordIn, coordDiff;
//define input file
FileInputStream fileIn = new FileInputStream("coords.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader (fileIn));
for (int j = 0; j < coordUnsortedArray.length; j++){
counter = 0;
commaCount = 0;
//line from file to variable
String coordSet = reader.readLine();
//look for the second "," to determine end of x coordinate
for(int k = 0; k < coordSet.length(); k++){
if (coordSet.charAt(k) == ',') {
commaCount++;
counter++;
if (commaCount == 2){
break;
}
}else{
counter++;
}
}
//define x coordinate
xCoordIn = (coordSet.substring(2,(counter - 1)));
intXCoordIn = Integer.parseInt(xCoordIn);
//define y coordinate
yCoordIn = (coordSet.substring((counter),coordSet.length()));
intYCoordIn = Integer.parseInt(yCoordIn);
//coordinate calculations
sumCoordIn = Integer.parseInt(xCoordIn) + Integer.parseInt (yCoordIn);
coordDiff = sumCoordIn - coordSum;
if (coordDiff < 0){
coordDiff = coordDiff * (-1);
}
//load results to array
coordUnsortedArray[j][0] = intXCoordIn;
coordUnsortedArray[j][1] = intYCoordIn;
coordUnsortedArray[j][2] = coordDiff;
}
fileIn.close();
System.out.print("\n");
System.out.println("Array Before Sorting:");
System.out.println("=====================");
//Array Before Sorting
for(int i = 0; i < coordUnsortedArray.length; i++){
int[] row = coordUnsortedArray[i];
System.out.print((i + 1) + ") ");
for(int j = 0; j < (row.length - 1); j++) {
coordUnsortedArray[i][j] = row[j];
if(j < 1){
System.out.print(coordUnsortedArray [i] [j] + ",");
}else{
System.out.println(coordUnsortedArray [i] [j]);
}
}
}
System.out.print("\n");
System.out.print("\n");
//Sort array coordDiff, column 3
Arrays.sort(coordUnsortedArray, new ColumnComparator(2));
System.out.println("Array After Sorting:");
System.out.println("====================");
//Original Array After Sorting
for(int i = 0; i < coordUnsortedArray.length; i++){
int[] row = coordUnsortedArray[i];
System.out.print((i + 1) + ") ");
for(int j = 0; j < (row.length - 1); j++) {
coordUnsortedArray[i][j] = row[j];
if(j < 1){
System.out.print(coordUnsortedArray[i][j] + ",");
}else{
System.out.println(coordUnsortedArray [i] [j]);
}
}
}
}
}
}
Code for class2 --
import java.util.Comparator;
#SuppressWarnings("rawtypes")
class ColumnComparator implements Comparator {
int columnToSort;
ColumnComparator(int columnToSort) {
this.columnToSort = columnToSort;
}
//Compare method
public int compare(Object o1, Object o2) {
int[] row1 = (int[]) o1;
int[] row2 = (int[]) o2;
int intRow1 = (row1[columnToSort]);
int intRow2 = (row2[columnToSort]);
return new Integer(intRow1).compareTo(new Integer(intRow2));
}
}

UVa 630 kept getting wrong answer [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 11 years ago.
I have been working on the UVa 630 problem for 2 days, http://acm.uva.es/p/v6/630.html
I have written a working code, however constantly getting the wrong answer result after the submission, my program works fine for the given input format and generate correct result, could someone please take a look at my code and find what's wrong with it please.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
class Main {
String[] init;
String[] sorted;
int voca = 0;
String[] test;
private String x;
private String y;
ArrayList<ArrayList> initial = new ArrayList<ArrayList>();
char[] charArray;
String input;
void initSort(String i) {
input = i;
charArray = input.toCharArray();
}
char[] get() {
return charArray;
}
void sort(int low, int high) {
int i = low;
char pivot = charArray[low];
for (int j = low + 1; j < high; j++) {
if (charArray[j] < pivot) {
if (j > i + 1) {
exchange(i + 1, j);
}
i++;
}
}
exchange(low, i);
if (i > low + 1)
sort(low, i);
if (i + 2 < high)
sort(i + 1, high);
}
void exchange(int i, int j) {
char temp = charArray[i];
charArray[i] = charArray[j];
charArray[j] = temp;
}
// ********************************************
void begin() {
// System.out.println("begin test");
int numOfdataSet;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try {
numOfdataSet = Integer.parseInt(in.readLine());
do {
ArrayList currentSet = new ArrayList();
int numberOfdic;
String tempStringV;
String tempStringT;
int i = 0;
try {
String emptyLine = in.readLine();
numberOfdic = Integer.parseInt(in.readLine());
;
currentSet.add(emptyLine);
currentSet.add(Integer.toString(numberOfdic));
// System.out.println("enter numberOfdic is " +
// numberOfdic);
while (i < numberOfdic) {
tempStringV = in.readLine();
currentSet.add(tempStringV);
i++;
}
// System.out.println("input test word");
tempStringT = in.readLine();
currentSet.add(tempStringT);
while (!tempStringT.equals("END")) {
tempStringT = in.readLine();
currentSet.add(tempStringT);
}
} catch (IOException e) {
e.printStackTrace();
}
initial.add(currentSet);
numOfdataSet--;
} while (numOfdataSet != 0);
} catch (IOException e) {
}
;
print();
}
// ***************************************************
void getArrays(ArrayList<String> a) {
// read the file and put the words into a temporary array
String[] temp = new String[a.size()];
for (int i = 0; i < a.size(); i++) {
temp[i] = a.get(i);
// System.out.println("temp "+i+" is "+temp[i]);
}
// extract the vocabulary counter from the temp array
int vocaCounter;
int shift;
if (!temp[0].equals("")) {
shift = 2;
vocaCounter = Integer.parseInt(temp[1]);
} else {
shift = 2;
vocaCounter = Integer.parseInt(temp[1]);
}
// System.out.println("there are "+vocaCounter);
// store the vocabulary into the array named as init
init = new String[vocaCounter];
for (int i = shift; i < vocaCounter + shift; i++) {
init[i - shift] = temp[i];
// System.out.println(i - shift + " voca is " + init[i - shift]);
}
// store the test words into the array named as test
test = new String[temp.length - vocaCounter - shift - 1];
for (int j = 0; j < temp.length - vocaCounter - shift - 1; j++) {
test[j] = temp[j + vocaCounter + shift];
// System.out.println("test "+j+" is "+test[j]);
}
sorted = init;
}
/**
* sort the two strings
*/
void arraySorter() {
x = x.toLowerCase();
initSort(x);
sort(0, x.length());
get();
// java.util.Arrays.sort(FirstArray);
y = y.toLowerCase();
initSort(y);
sort(0, y.length());
get();
}
String getEle(String in) {
initSort(in);
sort(0, in.length());
return new String(get());
}
void print() {
Iterator<ArrayList> iterator = initial.iterator();
while (iterator.hasNext()) {
getArrays((ArrayList<String>) iterator.next());
// ****************
/**
* sort the test array and store it as the testSort array
*/
String[] testSort = new String[test.length];
for (int i = 0; i < test.length; i++) {
testSort[i] = test[i];
}
for (int i = 0; i < test.length; i++) {
testSort[i] = getEle(testSort[i]);
}
// for(int i=0;i<test.length;i++)
// {
// System.out.println("test is "+test[i]+" and test sorted is "+testSort[i]);
// }
/**
* sort the vocabulary array and store the sorted array as vocaSort
*/
String[] vocaSort = new String[init.length];
for (int i = 0; i < init.length; i++) {
vocaSort[i] = init[i];
}
for (int i = 0; i < init.length; i++) {
vocaSort[i] = getEle(vocaSort[i]);
}
// start the testing process
for (int i = 0; i < test.length; i++) {
int counter = 1;
System.out.println("Anagrams for: " + test[i]);
for (int j = 0; j < sorted.length; j++) {
// anagramTester(test[i], init[j]);
boolean result = testSort[i].equals(vocaSort[j]);// //AnagramTester();
if (result == true && counter < 10) {
System.out.println(" " + counter + ") " + init[j]);
counter++;
} else if (result == true && counter < 100) {
System.out.println(" " + counter + ") " + init[j]);
counter++;
} else if (result == true && counter < 1000) {
System.out.println("" + counter + ") " + init[j]);
counter++;
}
}
if (counter == 1)
System.out.println("No anagrams for: " + test[i]);
}
System.out.println();
}
}
/**
* main function
*
* #param args
*/
public static void main(String[] args) {
Main myWork = new Main(); // create a dinamic instance
myWork.begin();
}
}
below is the input.txt file
1
4
atol
lato
rola
tara
kola
tola
END
2
24
uhgj
uhjg
ughj
ugjh
ujhg
ujgh
hujg
hugj
hgju
hguj
hjgu
hjug
guhj
gujh
ghuj
ghju
gjuh
gjhu
jugh
juhg
jhgu
jhug
jghu
jguh
jguh
END
it was a output format issue and problem solved

Categories

Resources