Here's the question -
https://www.codechef.com/DEC17/problems/CPLAY
And here's my solution -
import java.util.Scanner;
class Penalty_Shoot_Out
{
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
//System.out.println("T: ");
int T = sc.nextInt();
sc.nextLine();
while(T-->0)
{
String s = sc.nextLine();
int l = s.length();
s = " " + s;
int A_score = 0, B_score = 0, A_shots = 0, B_shots = 0, flag = 0, A_shots_left = 5, B_shots_left = 5, shots_left = 0;
Outer:for(int i=1; i<=20; i++)
{
char c = s.charAt(i);
if(i%2==1)
{
flag = 0;
A_shots++;
A_shots_left--;
if(c=='1')
A_score++;
}
else
{
flag = 1;
B_shots++;
B_shots_left--;
if(c=='1')
B_score++;
}
if(i<=10)
{
if(A_score<B_score)
{
if(B_score-A_score>A_shots_left)
{
System.out.println("TEAM-B " + i);
break Outer;
}
}
else
{
if(A_score-B_score>B_shots_left)
{
System.out.println("TEAM-A " + i);
break Outer;
}
}
}
else if(i>10 && i<=20)
{
if(i%2==0)
{
if(A_score>B_score)
System.out.println("TEAM-A " + i);
else if(B_score>A_score)
System.out.println("TEAM-B " + i);
else
System.out.println("TIE");
break Outer;
}
}
}
}
}
}
These are the exceptions -
Exception
in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at Penalty_Shoot_Out.main(Main.java:8)
I'm getting the correct answer on my computer, but when I submit it online, I get the NZEC Runtime Error.
I tried Googling for solutions and most people said the error might have to do with the main function returning a wrong number or not returning a number. Some said it may be due to the use of a particular function or due to an exception that i am not handling during I/O. However, I haven't been able to figure it out.
I'd really appreciate it if someone could fix my code.
You should put your solution in a try catch.
public static void main(String args[])
{
try {
Scanner sc = new Scanner(System.in);
//System.out.println("T: ");
int T = sc.nextInt();
sc.nextLine();
while(T-->0)
{
String s = sc.nextLine();
int l = s.length();
s = " " + s;
int A_score = 0, B_score = 0, A_shots = 0, B_shots = 0, flag = 0,
A_shots_left = 5, B_shots_left = 5, shots_left = 0;
Outer:for(int i=1; i<=20; i++)
{
char c = s.charAt(i);
if(i%2==1)
{
flag = 0;
A_shots++;
A_shots_left--;
if(c=='1')
A_score++;
}
else
{
flag = 1;
B_shots++;
B_shots_left--;
if(c=='1')
B_score++;
}
if(i<=10)
{
if(A_score<B_score)
{
if(B_score-A_score>A_shots_left)
{
System.out.println("TEAM-B " + i);
break Outer;
}
}
else
{
if(A_score-B_score>B_shots_left)
{
System.out.println("TEAM-A " + i);
break Outer;
}
}
}
else if(i>10 && i<=20)
{
if(i%2==0)
{
if(A_score>B_score)
System.out.println("TEAM-A " + i);
else if(B_score>A_score)
System.out.println("TEAM-B " + i);
else
System.out.println("TIE");
break Outer;
}
}
}
}
} catch(Exception e) {
return;
}
}
}
Related
I am a somewhat intermediate-level Java programmer but I have had trouble with one of my recent programs. Basically the application is a Hangman game that allows the user to input letters in order to guess a word. Everything works okay except for the counter for how many lives the player has, in this case it is 5. The counter for some reason subtracts by 4 instead of 1, as well as this it takes away from the number of lives even if the letter is guessed correctly.
Any help would be widely appreciated, thank you in advance. The two classes are provided below. Also,
Instantiable Class
public class Hangman {
private char letterGuess;
private int numberLives;
private String outputWord;
private final String hiddenWord;
private final StringBuffer swapBuffer = new StringBuffer();
public Hangman() {
letterGuess = ' ';
numberLives = 5;
hiddenWord = "java";
outputWord = "";
for (int i = 0; i < hiddenWord.length(); i++) {
swapBuffer.append("*");
}
}
public void setLetterGuess(char letterGuess) {
this.letterGuess = letterGuess;
}
public void compute() {
for (int i = 0; i < hiddenWord.length(); i++) {
if (letterGuess == hiddenWord.charAt(i)) {
swapBuffer.setCharAt(i, letterGuess);
}
else {
numberLives--;
}
}
outputWord = swapBuffer.toString();
}
public int getNumberLives() {
return numberLives;
}
public String getHiddenWord() {
return hiddenWord;
}
public String getOutputWord() {
return outputWord;
}
}
Main Class
import javax.swing.*;
public class HangmanApp {
public static void main(String[] args) {
char letterGuess;
int numberLives;
String hiddenWord, outputWord, restartGame;
do {
Hangman myHangman = new Hangman();
JOptionPane.showMessageDialog(null, "Welcome to Java Hangman!");
JOptionPane.showMessageDialog(null, "In this game, a word will be printed to you in asterisks - each letter will be revealed upon a correct guess!");
JOptionPane.showMessageDialog(null, "You have 5 lives for the game, the game will end if you make too many incorrect guesses!");
for (int i = 0; i < 10; i++) {
hiddenWord = myHangman.getHiddenWord();
numberLives = myHangman.getNumberLives();
JOptionPane.showMessageDialog(null, "You currently have " +numberLives+ " lives!");
letterGuess = JOptionPane.showInputDialog(null, "Now, please enter a letter : ").charAt(0);
myHangman.setLetterGuess(letterGuess);
myHangman.compute();
outputWord = myHangman.getOutputWord();
JOptionPane.showMessageDialog(null, "The word so far is : " +outputWord);
}
numberLives = myHangman.getNumberLives();
JOptionPane.showMessageDialog(null, "You have finished the game with : " +numberLives+ " lives!");
restartGame = JOptionPane.showInputDialog(null, "Would you like to play again?");
}
while (restartGame.equalsIgnoreCase("Yes"));
}
}
Use a found boolean to check if the letter was found. If it wasn't, subtract a life.
var found = false;
for (int i = 0; i < hiddenWord.length(); i++) {
if (letterGuess == hiddenWord.charAt(i)) {
swapBuffer.setCharAt(i, letterGuess);
found = true;
}
}
if (!found) numberLives--;
If the guessed letter is wrong, in the compute function 1 life will be taken for each letter of the hidden word. You should try and use a switch(boolean) that will show you if the letter was found or not after parsing the whole word.
public void compute() {
// for (int i = 0; i < hiddenWord.length(); i++) {
// if (letterGuess == hiddenWord.charAt(i)) {
// swapBuffer.setCharAt(i, letterGuess);
// }
//
// else {
// numberLives--;
// }
// }
int letterNo = hiddenWord.length();
boolean found = false;
while (letterNo>0){
letterNo--;
if (letterGuess == hiddenWord.charAt(letterNo)){
swapBuffer.setCharAt(letterNo, letterGuess);
found = true;
}
}
if (!found){
numberLives--;
}
outputWord = swapBuffer.toString();
}
again. I keep getting an IllegalStateException when I try to attempt a task after one turn. Specifically, mentioning that a task is already scheduled or cancelled. Do you know how to fix this? Here is some relevant code.
public class Human_Agent implements GipfPlayable {
String[] edgeSpots;
String[] columns;
Random rng;
GipfGame mg;
//int turn = 0;
String str;
Timer t;
Integer val;
Integer myDir;
public Human_Agent(GipfGame g) {
this.edgeSpots = g.getEdgeSpots();
this.columns = g.getColumns();
rng = new Random(37);
//turn = 0;
}
TimerTask task1 = new TimerTask()
{
public void run()
{
if (str.equals(""))
{
System.out.println("You did not input a valid location.");
System.exit(0);
}
}
};
TimerTask task2 = new TimerTask()
{
public void run()
{
if (val == null)
{
System.out.println("You did not input a valid direction.");
System.exit(0);
}
}
};
public String getUserInput() throws Exception
{
t = new Timer();
t.schedule(task1, 5*1000);
Scanner scan = new Scanner(System.in);
System.out.print("Please provide a starting location: ");
String startLocation = "";
String x = scan.nextLine();
str = x;
int dirE = 0;
//t.cancel();
// Timer t2 = new Timer();
if (isItValidLocation(x))
{
startLocation = x;
t.cancel();
t = new Timer();
t.schedule(task2, 10*1000);
//t.scheduleAtFixedRate(task2, 5000, 5*1000);
System.out.print("\n Now, provide a number to move the piece");
dirE = scan.nextInt();
t.cancel();
}
else
{
System.out.println("Invalid Start location.");
t.cancel();
}
// scan.close();
// t.cancel();
return str + " " + Integer.toString(dirE);
}
#Override
public String makeGipfMove() {
String s;
try
{
s = getUserInput();
}
catch(Exception e)
{
String startLocation = edgeSpots[rng.nextInt(edgeSpots.length)];
Integer dir = rng.nextInt(6);
s = startLocation + " " + Integer.toString(dir);
e.printStackTrace();
}
// if ((mg.makeMove(x, dirE)) == false)
// {
// System.out.println("Can't move here.");
// }
//mg.makeMove(x, dirE);
// Integer dir = rng.nextInt(6);
//System.out.println("GIPHS REMAINING: " + )
return s;
}
public boolean isItValidLocation(String a)
{
boolean v = false;
System.out.println("YOU ENTERED: " + a);
for (int i = 0; i < edgeSpots.length; i++)
{
System.out.println(edgeSpots[i]);
if ((edgeSpots[i].equals(a)) && (v != true))
{
v = true;
}
}
System.out.println(v);
return v;
}
}
What this code does is play the game of Gipf with a human agent.
It looks like your post is mostly code; please add some more details. (Netbeans needs to get rid of this if you added details about your code!)
The same way you can't reuse a Timer after you cancel it, you cannot reuse a TimerTask.
You can create classes extending TimerTask and instantiate them whenever you need to schedule it.
I have this method which should output a toast at the end but it is coming up with the following error
Cannot resolve method Toast.makeText()
public Guess makeGuess() {
PegEnum[] data1 = new PegEnum[4];
PegEnum[] codeCpy = code.clone();
PegEnum[] guessCpy = guess.clone();
int correctCount = 0;
int correctColourCount =0;
for (int i = 0; i < codeCpy.length; i++) {
if(codeCpy[i]==guessCpy[i]) {
++correctCount;
codeCpy[i]=null;
guessCpy[i]=null;
}
}
for(int x =0; x<codeCpy.length; x++) {
if (codeCpy[x]!=null) {
for (int y = 0; y < guessCpy.length; y++) {
if (codeCpy[x]==guessCpy[y]) {
++correctColourCount;
guessCpy[y]=null;
}
}
}
}
return new Guess(guess.clone(), correctCount, correctColourCount);
Toast.makeText(this, "You have guessed: " + correctCount + " Correct Pegs" + " and "
+ correctColourCount + "Correct Colours", Toast.LENGTH_LONG).show();
}
There are some errors in your code -
1) Did you import Toast?2) Your toast is after the return statement, and that makes the code unreachable.
The for loop in the backEnd class - CompareGuess method is not working.
....................................................................................................................................................
public class frontEnd
{
public static void main (String args[])
{
int GetGuess = 0;
backEnd e1 = new backEnd();
e1.InitializeArray();
while(e1.chanceCounter<3)
{
System.out.println("Enter a number");
GetGuess = (int)(Math.random()*6);
System.out.println(GetGuess);
e1.UserGuess(GetGuess);
e1.CompareGuess();
if(e1.suc!=1)
{
System.out.println("It is a miss");
}
}
System.out.println("Sorry, no chances left");
}
}
class backEnd
{
int Guess;
int HitCounter=0;
int[] abc = new int[7] ;
int chanceCounter=0;
int suc = 0;
int x =0;
public void InitializeArray()
{
abc[1]= 3;
abc[2] = 5;
abc[4] = 1;
}
public void UserGuess(int guess)
{
Guess = guess;
}
public void CompareGuess()
{
for(x=0; x<=6; x++ )
{
if (abc[x] == Guess)
{
System.out.println("It is a hit");
chanceCounter = chanceCounter + 1;
suc = 1;
}
break;
}
}
}
The problems seems to be here:
for(x=0; x<=6; x++ )
{
if (abc[x] == Guess)
{
System.out.println("It is a hit");
chanceCounter = chanceCounter + 1;
suc = 1;
}
break; //Here
}
Look what your code does:
Your for loop makes the first iteration, taking x = 0
If abc[x] it's equals to Guess then your program executes the code inside the if statement. After, the break statement will be executed.
If not, it just execute the break statement
So, in both cases, the break statement it's going to be executed in the first iteration (therefore, your program will go out of the for loop).
Look that your program only will execute your first iteration but not the rest (x = 1, x = 2 [....] x =6).
If you want that your for loop go through all the iterations you have to remove your break statement from your code.
I expect it will be helpful for you!
Since your game is all about guessing. I took a guess at what it's supposed to do then I rewrote your code, because I couldn't bear to leave it as it was. I left it as similar to your as I can cope with:
public class FrontEnd
{
public static void main (String args[])
{
int getGuess = 0;
BackEnd e1 = new BackEnd();
e1.initializeArray();
int totalChances = 3;
while(e1.chanceCounter < totalChances)
{
System.out.println("Enter a number");
getGuess = (int)(Math.random()*6);
System.out.println(getGuess);
e1.userGuess(getGuess);
e1.compareGuess();
if(!e1.suc)
{
System.out.println("It is a miss");
}
e1.suc = false;
e1.chanceCounter++;
}
System.out.println("Sorry, no chances left");
System.out.println("you scored " + e1.hitCounter + " out of " + totalChances);
}
}
class BackEnd
{
int guess;
int hitCounter = 0;
int[] abc = new int[7] ;
int chanceCounter = 0;
boolean suc = false;
public void initializeArray()
{
abc[1] = 3;
abc[2] = 5;
abc[4] = 1;
}
public void userGuess(int guess)
{
this.guess = guess;
}
public void compareGuess()
{
for( int x = 0; x <= 6; x++ )
{
if (abc[x] == guess)
{
System.out.println("It is a hit");
hitCounter++;
suc = true;
break;
}
}
}
}
As others have said the break statement is supposed to be inside the conditional block. Also it looks like you were forgetting to reset the suc variable after each guess. Also you weren't using hitCounter at all. I assumed it's for counting correct guesses, which left me wondering when to update chanceCounter: either after each guess or after each wrong guess. I didn't know if the guesser was supposed to run out of chances after 3 guesses, or after 3 wrong guesses. I went with the former and update the chanceCounter after every guess.
guesses of 0 are considered correct because they match with all the entries in the abc array that are not initialised.
I'm stuck with a 'hold' function when developing a Yatzy bot. Everything else works, but the logic for this function seems to fail in some instances. Basically, the idea is to hold all the numbers given, and then roll the dice that don't match the numbers given.
[00:04] #Dessimat0r: .roll
[00:04] YatzyBot: #1: dice: [2, 5, 3, 4, 1], scores: [ 1 2 3 4 5 6 1P 2P 3K 4K SS LS H Y C ]
[00:04] #Dessimat0r: .hold 2 1
[00:04] YatzyBot: #2: dice: [2, 5, 3, 4, 1], scores: [ 1 2 3 4 5 6 1P 2P 3K 4K SS LS H Y C ]
[00:04] #Dessimat0r: .hold 2 1
[00:04] YatzyBot: #3: dice: [2, 5, 3, 4, 1], scores: [ 1 2 3 4 5 6 1P 2P 3K 4K SS LS H Y C ]
As can be seen, all numbers are being held instead of just the selected few (This is not coincidence from the dice rolls). The code is below:
} else if (event.getMessage().startsWith(".hold")) {
if (y.getTurn() != null && event.getUser().getNick().equals(y.getTurn().getPlayer().getName())) {
String[] tokens = event.getMessage().split(" ");
if (tokens[0].equals(".hold")) {
boolean failed = false;
try {
if (tokens.length == 1) {
bot.sendMessage(CHANNEL, "Must choose some dice to hold!");
return;
}
ArrayList<Integer> dice = new ArrayList<Integer>();
ArrayList<Integer> holdnums = new ArrayList<Integer>();
ArrayList<Integer> rollnums = new ArrayList<Integer>();
for (Die d : y.getDice()) {
dice.add(d.getFaceValue());
}
// parse other numbers
for (int i = 1; i < tokens.length; i++) {
int num = Integer.parseInt(tokens[i]);
holdnums.add(num);
}
ListIterator<Integer> diter = dice.listIterator();
dice: while (diter.hasNext()) {
Integer d = diter.next();
if (holdnums.isEmpty()) {
rollnums.add(d);
diter.remove();
continue;
}
ListIterator<Integer> iter = holdnums.listIterator();
while (iter.hasNext()) {
int holdnum = iter.next().intValue();
if (holdnum == d) {
iter.remove();
diter.remove();
continue dice;
}
}
}
if (!holdnums.isEmpty()) {
bot.sendMessage(CHANNEL, "Hold nums not found: " + holdnums);
failed = true;
}
if (!failed) {
y.getTurn().rollNumbers(convertIntegers(rollnums));
Map<Scoring, Integer> scores = y.getRollScores();
Map<Scoring, Integer> unchosen = new EnumMap<Scoring, Integer>(Scoring.class);
Map<Scoring, Integer> chosen = new EnumMap<Scoring, Integer>(Scoring.class);
for (Entry<Scoring, Integer> entry : scores.entrySet()) {
if (y.getTurn().getPlayer().getTotals().get(entry.getKey()) == -1) {
unchosen.put(entry.getKey(), entry.getValue());
} else {
chosen.put(entry.getKey(), entry.getValue());
}
}
bot.sendMessage(CHANNEL, "#" + y.getTurn().getRolls() + ": dice: " + y.getDiceStr() + ", scores: " + getDiceStr(y.getTurn().getPlayer().getTotals(), scores));
}
} catch (TurnException e1) {
bot.sendMessage(CHANNEL, e1.getMessage());
} catch (RollException e2) {
bot.sendMessage(CHANNEL, e2.getMessage());
} catch (YahtzyException e3) {
bot.sendMessage(CHANNEL, e3.getMessage());
} catch (NumberFormatException e4) {
bot.sendMessage(CHANNEL, e4.getMessage());
}
}
}
}
Edit: Fixed it all. Updated code:
} else if (event.getMessage().startsWith(".hold")) {
if (y.getTurn() != null && event.getUser().getNick().equals(y.getTurn().getPlayer().getName())) {
String[] tokens = event.getMessage().split(" ");
if (tokens[0].equals(".hold")) {
boolean failed = false;
try {
if (tokens.length == 1) {
bot.sendMessage(channel, "Must choose some dice to hold!");
return;
}
ArrayList<Integer> holdnums = new ArrayList<Integer>();
ArrayList<Integer> rollnums = new ArrayList<Integer>();
// parse other numbers
for (int i = 1; i < tokens.length; i++) {
int num = Integer.parseInt(tokens[i]);
holdnums.add(num);
}
for (int i = 0; i < y.getDice().length; i++) {
int d = y.getDice()[i].getFaceValue();
if (holdnums.isEmpty()) {
rollnums.add(d);
continue;
}
ListIterator<Integer> iter = holdnums.listIterator();
boolean found = false;
while (iter.hasNext()) {
int holdnum = iter.next().intValue();
if (holdnum == d) {
iter.remove();
found = true;
break;
}
}
if (!found) {
rollnums.add(d);
}
}
if (!holdnums.isEmpty()) {
bot.sendMessage(channel, "Hold nums not found: " + holdnums);
failed = true;
}
if (!failed) {
boolean[] rolled = y.getTurn().rollNumbers(convertIntegers(rollnums));
Map<Scoring, Integer> scores = y.getRollScores();
Map<Scoring, Integer> unchosen = new EnumMap<Scoring, Integer>(Scoring.class);
Map<Scoring, Integer> chosen = new EnumMap<Scoring, Integer>(Scoring.class);
for (Entry<Scoring, Integer> entry : scores.entrySet()) {
if (y.getTurn().getPlayer().getTotals().get(entry.getKey()) == -1) {
unchosen.put(entry.getKey(), entry.getValue());
} else {
chosen.put(entry.getKey(), entry.getValue());
}
}
bot.sendMessage(channel, "#" + y.getTurn().getRolls() + ": dice: " + diceToString(rolled) + ", scores: " + getDiceStr(y.getTurn().getPlayer().getTotals(), scores));
}
} catch (TurnException e1) {
bot.sendMessage(channel, e1.getMessage());
} catch (RollException e2) {
bot.sendMessage(channel, e2.getMessage());
} catch (YahtzyException e3) {
bot.sendMessage(channel, e3.getMessage());
} catch (NumberFormatException e4) {
bot.sendMessage(channel, e4.getMessage());
}
}
}
}
Everything looks OK, but this check for holdnum is not in the right place:
if (absent) {
bot.sendMessage(CHANNEL, "Hold num not found: " + holdnum);
failed = true;
break dice;
}
It is too early to say here if given hold number is right or wrong, so it is better to remove this piece of code. To check validity of holdnums you could look at this list after the "dice" loop finishes: if holdnums is not empty, it contains some items, that were not found.
For updated question:
I see one problem: rollnums.add(d) should not be called in nested while to avoid adding the same value several times. Instead, it should be called once, after this loop is completed.