Problems with while loops - java

I'm working on a project at the moment that's building a digitised version of a board game, and i'm having an issue with a while loop thats not doing as i expected.
Basically, if the player has 1 stone left in his/her hand, and the next pit is not empty, they pick up the next pits stones and continue doing so, until the next pit is empty.
Now, my code continues while the next pit is empty and while one stone is remaining in their hand, however, it doesn't pick up the next pits stones if it isn't empty, it just adds one until the next pit is empty.
So my code is almost there, just not quite. So i'm looking for some help to improve the current code (a big comment above the code that needs work).
Let me know if the explanation is poor, i'll do my best to re-write it.
Cheers
while(hand == 1 && pit.next.stones != 0 && pit.next.pit == false) {
int stones = pit.next.stones;
for(int i = stones; i >= 1; i--) {
hand++;
}
while(Hand >= 1 && pit.next.stones != 0) {
hand--;
addPieces(pit.next);
pit = pit.next;
}
}

Rather than having mutli-nested loops. You should probably just update the stones in hand and stones in the pit and let the main loop continue as normal since the main loop is just the main game logic loop: grab stones, drop in pits, grab more stones and repeat?, ???, profit!
Eg:
Instead of:
while(hand >= 1 && pit.next != null) {
// ...
while (hand == 1 && pit.next.stones != 0 && pit.next.pit == false) {
int stones = pit.next.stones;
for (int i = stones; i >= 1; i--) {
hand++;
}
while (hand >= 1 && pit.next.stones != 0) {
hand--;
addPieces(pit.next);
pit = pit.next;
}
}
do something like:
while(hand >= 1 && pit.next != null) {
// ...
if(hand == 1 && pit.next.stones > 0 && pit.next.pit == false) {
// update stones in hand
hand += pit.next;
// update stones in pit
pit.next.stones = 0;
}
// let main loop continue
}
(Note: I'm not 100% on the rules you are going for, just tried to follow what you said)

Related

Checking for Winner in Connect Four - Kotlin

I am creating a simple Connect Four program in Kotlin using a 2D array to print the board. Everything works fine except for my horizontal win-checker function. Because of the logic I am using, I get (index out of bounds) errors when trying to put your piece on the first column, because it is trying to check the next column in the array, but there is none. Is there a better way to handle checking for a winner? This is my function:
fun checkWinsHorizontal() {
for(row in 0 until gameBoard.size) {
for(col in 0 until gameBoard.size){
// if this spot is taken up by an "X", and the horizontally adjacent spaces are the same, declare winner
if (gameBoard[row][col] == "X" && (gameBoard[row][col] == gameBoard[row][col - 1] && gameBoard[row][col] == gameBoard[row][col - 2] && gameBoard[row][col] == gameBoard[row][col - 3]) ){
printBoard()
println("YOU WIN")
winner = true
return
}
// same thing as above but for a "computer" opponent
else if (gameBoard[row][col] == "O" && gameBoard[row][col] == gameBoard[row][col - 1] && gameBoard[row][col] == gameBoard[row][col - 2] && gameBoard[row][col] == gameBoard[row][col - 3]){
printBoard()
println("COMPUTER WINS")
winner = true
return
}
}
}
}
The comments above explain why you're getting the index out of bounds (you have hard coded values like gameBoard[row][col - 1] but col might be 0). I suggest a few fixes:
First, there's no need to check every cell on the board after each move. The only way a player can win is if the piece they just placed completes a row, column, or diagonal. So I suggest you check only potential wins involving that cell.
To do that for a row you could have something like:
fun completesRow(row: Int, col: Int) : Boolean {
var count: Int = 1
val symbol = gameBoard[row][col]
// First move left - now we check that the symbols (X or O) match
// AND that we're within bounds.
var curCol = col - 1
while (curCol >= 0 && gameBoard[row][curCol] == symbol) {
++count
if (count == 4) {
return true
}
--curCol
}
// same thing to the right; numColumns is assumed to be the number of
// columns in the board.
curCol = col + 1
while (curCol < numColumns && gameBoard[row][curCol] == symbol) {
++count
if (count == 4) {
return true
}
++curCol
}
// if you got here there weren't 4 in a row
return false
}
Note: the above is untested - I doubt it even compiles, but hopefully it's instructive.
You can also further generalize this if you want. Instead of having different functions that move left/right, up/down, and diagonally you could create Iterator instances for those movements and then have a single function that takes 2 iterators (one moving left and one right for example) and it can do the checks using that. That way you can use the same exact method to check a horizontal, vertical, or diagonal win.

Stuck at 958 combinations

I am trying to design a Tic-Tac-Toe game in Java. I must point out that I am a complete beginner in Java. So I am trying to generate all possible combinations of the game, then store it in a file. We know that there are 255168 possible combinations. Anyway here is my code:
import java.io.*;
import java.util.Random;
import java.util.Arrays;
public class generator2 {
public static void main(String[] args) {
Random r=new Random();
String s;
String store[] = new String[255168];
int count=0;
int i=0;
int a[][]=new int[3][3];
int wf;
int flag=0;
char b;
while(count<255168)
{
s="";
b='X';
flag=0;
for(int[] row : a)Arrays.fill(row, 0);
wf=0;
i=0;
while(wf==0)
{
int r1=r.nextInt(3)+0;
int r2=r.nextInt(3)+0;
if(a[r1][r2]==0)
{
i++;
if(flag==0) {a[r1][r2]=1;flag=1;}
else {a[r1][r2]=2;flag=0;}
if(a[0][0]==1 && a[0][1]==1 && a[0][2]==1 || a[1][0]==1 && a[1][1]==1 && a[1][2]==1 || a[2][0]==1 && a[2][1]==1 && a[2][2]==1 || a[0][0]==1 && a[1][0]==1 && a[2][0]==1 || a[0][1]==1 && a[1][1]==1 && a[2][1]==1 || a[0][2]==1 && a[1][2]==1 && a[2][2]==1 || a[0][0]==1 && a[1][1]==1 && a[2][2]==1 || a[0][2]==1 && a[1][1]==1 && a[2][0]==1)
{
b='W';
wf=1;
break;
}
else if(a[0][0]==2 && a[0][1]==2 && a[0][2]==2 || a[1][0]==2 && a[1][1]==2 && a[1][2]==2 || a[2][0]==2 && a[2][1]==2 && a[2][2]==2 || a[0][0]==2 && a[1][0]==2 && a[2][0]==2 || a[0][1]==2 && a[1][1]==2 && a[2][1]==2 || a[0][2]==2 && a[1][2]==2 && a[2][2]==2 || a[0][0]==2 && a[1][1]==2 && a[2][2]==2 || a[0][2]==2 && a[1][1]==2 && a[2][0]==2)
{
b='L';
wf=1;
break;
}
else if(i==9)
{
b='T';
wf=1;
break;
}
}
}
s+=b;
for(i=0;i<3;i++)
for(int j=0;j<3;j++)
s+=String.valueOf(a[i][j]);
if(repeat(s,store,count)) {store[count]=s;count++;s="";System.out.println(count);}
else {continue;}
}
// for(i=0;i<958;i++)
// {
// System.out.println(store[i]);
// }
}
public static boolean repeat(String s,String[] a,int count){
int flag=0;
for(int i=0;i<count;i++)
{
if(a[i].equals(s)) {flag=1;break;}
}
if(flag==1)return false;
else return true;
}
}
Format of stored string:
First Character: W-Player1 Win.. L-Player2 Win.. T-Tie
next 9 characters represent board layout:
211012012 represents
2 1 1
0 1 2
0 1 2
Note that 0 is for position still not filled by any player. As we can see Player1 wins in above game so the string is stored is W211012012.
Theoretically this method should generate all possible unique combinations(255168), but it is not. It generates 958 combinations and then the program is just stuck.
Actually I think you should be happy to know that 958 is the correct answer for the number of legal endgame states.
https://archive.ics.uci.edu/ml/machine-learning-databases/tic-tac-toe/tic-tac-toe.names
255168 is correct when you keep track of the order of each player's moves -- not just the final end state. You are computing the valid final end game states.
Take your example of W211012012. There are 108 ways to accomplish W211012012 when considering the order of each player's moves. Player 1's top right move can't be last and other 3 moves can be in any order for 3*3!. Player 2's three moves can be in any order for 3!. 108=3*3!*3!.
If instead you want to calculate all 255168 combinations when the order of the moves matters consider representing your state strings differently. Maybe [WLT](1,row,col)(2,row,col)(1,row,col)... or any other way that would encode the order of the moves.
You are simulating all possible games by having 2 players play randomly and keeping track of unique games. That's one way to do it, and a good exercise, but not particularly efficient. You could also use a searching algorithm like DFS https://en.m.wikipedia.org/wiki/Depth-first_search to explore the search space.

Why does my app crash at this point?

Whenever my game hits a score of 3, it crashes. After much reviewing, I noticed that it has to do with this code because I would remove it and then it wouldn't crash anymore. The weirdest part about it, is that it would only crash after playing for a while. I can play a new game, it would be more than 3 and not crash. I don't understand why it only happens once in a while The error code I then get is:
Assertion failed: (m_nodes[proxyId].IsLeaf()), function DestroyProxy, file /Users/badlogic/jenkins/workspace/libgdx-mac/gdx/jni/Box2D/Collision/b2DynamicTree.cpp, line 127.
Code:
int j = Asteroids.bodies.size;
if(j == 9 && p == 0) {
score ++;
p ++;
store.coins.putInteger("coins", (store.coins.getInteger("coins", 0) + 1));
}
if(j == 10 && p == 1) {
score ++;
p ++;
store.coins.putInteger("coins", (store.coins.getInteger("coins", 0) + 1));
}
if(j == 11 && p == 2) {
score ++;
p ++;
store.coins.putInteger("coins", (store.coins.getInteger("coins", 0) + 1));
}
try {
if(j > 11) {
for(int i = 0; i < Asteroids.bodies.size - 11; score ++) {
world.destroyBody(Asteroids.bodies.get(i));
Asteroids.bodies.removeIndex(i);
store.coins.putInteger("coins", (store.coins.getInteger("coins", 0) + 1));
}
}
}
catch(NullPointerException e) {
System.out.println("oops");
}
}
Why is it related to the score: because you only start running the code when asteroids.bodies.size>11 - this presumably only happens after you've shot something up.
In general it is not safe to remove items from a collection that are currently iterating over - without the declaration of asteroids.bodies it is difficult to see whether this is causing your problem. But something along the lines of:
while (there are more bodies than I want)
remove the first body in the list
is generally used for this situation.

Creating a binary truth "table"

First time posting on here! So ive searched and searched and cant find an answer. I dont really need a table, just to have that kind of output such as
0 and 0 = 0,
0 and 1 = 1,
and so on...
I need to read from a file that will extract the numbers and they are 0 0..0 1..1 0..1 1
I need to then make the AND, OR, NAND, and NOR "table" for them.
I created an arrayList for them, so i can access them easier. the method i was going to do doesnt work and will take very long lines of code and pretty much be duplicated stuff. Im trying to think of a way to use a loop, but have mental block. can anyone help me please?
heres what im talking about the code i have
int rec3a = Integer.parseInt(list1.get(2));
int rec3b = Integer.parseInt(list1.get(3));
System.out.println("AND:");
if(rec3a == 0 && rec3b == 0)
{
System.out.println("0");
}
if(rec3a == 0 && rec3b == 1)
{
System.out.println("0");
}
if(rec3a == 1 && rec3b == 0)
{
System.out.println("0");
}
if(rec3a == 1 && rec3b == 1)
{
System.out.println("1");
}
}
this doesnt really work for the OR statement either..its just a giant mess lol..any help would be appreciated
You could use the bitwise operators,
int rec3a = 1;
int rec3b = 0;
// AND
System.out.println(rec3a & rec3b);
// OR
System.out.println(rec3a | rec3b);
// NAND
System.out.println((rec3a & rec3b) == 1 ? 0 : 1);
// NOR
System.out.println((rec3a | rec3b) == 1 ? 0 : 1);
Which (in this example) outputs
0
1
1
0
You could simplify this to:
if (rec3a == 1 && rec3b == 1)
{
System.out.println("1");
}
else
{
System.out.println("0");
}
For the OR case it would be:
if (rec3a == 1 || rec3b == 1)
{
System.out.println("1");
}
else
{
System.out.println("0");
}
With Integers 0 and 1, you can use the built in bit-wise operators:
System.out.println(rec3a & rec3b); //AND
System.out.println(rec3A | rec3b); //OR

Checking if Element Exists in Boolean Array

I took a programming class, and I'm revisiting old programs that I did not quite get right. This one is a Game Of Life program, and I have a question about code cleanup.
I need to make sure that an array element is in bounds before checking whether its neighbor's boolean value is true or false. I have a statement to check if firstGen[0][0]'s top-left (up one row, left one column) is in bounds. Is there an easier or more elegant way to check if an element is in bounds or to restrict the element checks to the boundaries of a given array without using four && conditionals per if statement?
Note that I have only changed the first if statement thus far, so there may be errors elsewhere. I also excluded the boundary checks for the other neighbors.
public static boolean[][] generation(boolean[][] firstGen)
{
int length = firstGen.length;
boolean[][] newGen = new boolean[length][length];
for (int j = 0; j < firstGen[0].length; j++)
{ for (int i = 1; i < firstGen.length; i++)
{
int count = 0;
if ((i-1 >= 0) && (i-1 < length) && (j-1 >= 0) && (j-1 < length)) //top-left element exists
{ if (newGen[i-1][j-1] == true) count++; } //increment `count` if top-left element is true
if ((newGen[i][j] == false) && (count == 3)) newGen[i][j] = true;
else if ((newGen[i][j] == true) && (count == 1)) newGen[i][j] = false;
else if ((newGen[i][j] == true) && (count > 3)) newGen[i][j] = false;
else break;
}
}
return newGen;
}
If i and j are in bounds, then you know for sure that i - 1 < length and j - 1 < length are both true.
Also:
i - 1 >= 0 can be written i > 0
if (condition == true) can be rewritten if (cond)
So you could replace:
if ((i-1 >= 0) && (i-1 < length) && (j-1 >= 0) && (j-1 < length)) //top-left element exists
{ if (newGen[i-1][j-1] == true) count++; } //increment `count` if top-left element is true
by:
//increment `count` if top-left element is true
if (i > 0 && j > 0 && newGen[i-1][j-1]) count++;
That's the best way I can think of to check if its out of bounds, but an alternative method in general, and one that I think gives programs like the Game of Life more exciting outcomes, is adding periodic boundaries. Basically this means that if you walk off one edge, you end up on the other side (like in pac-man). It sounds complicated, but really all it takes is the % function, which returns the remainder of division between the two numbers given.
So:
27 % 5 = 2;
So for adding periodic boundries you would update x and y positions like this:
x = (x + xStep + horizontalSize) % horizontalSize;
y = (y + yStep + verticalSize) % verticalSize;
Where xStep and yStep are +1 or -1 depending on what direction you want to go. (this works nicely with a for loop) The addition of the size is to make sure you go below zero when you get close to borders.
Then you never have to worry about messy border conditions, everything simply overlaps. No need to check each and every border. I hope this makes sense. Please ask for clarification if not. I've used this more for random walker programs but the idea is the same.

Categories