Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
I am making a Connect 4 app for Android and right now I am using a minimax algorithm coupled with alpha-beta prunning and heuristic evaluation function for leaf nodes. I also ordered the moves to further maximize the pruning process. Unfortunately with that strategy the algorithm takes too much time in depth 7, leading me to abandon it in favor of using a transposition table.
Now, I've read information about transposition tables and have got a general idea of how they work, but I am unsure how to proceed with the actual implementation in code. I am not a Java expert so I need any help you can give me.
In my game I am using a int[42] array for the board positions. I thought of using a hash map and storing some kind of data structure objects, where every one of these object will include the board position(array) and an int "score"variable (which would in fact be the score given to this position by the evaluation function). But, that means that every time I want to put a new board position in the table I need to perform some kind of check to see if this position does not exist already(??). And if not, only then insert into the table?
I will be glad for any technical help you guys can give me on this subject. I can put some code examples if needed, but this is a general question and I don't think they are really necessary at this point.
Thanks in advance.
You can use a technique from chess transposition tables: Zobrist hashing. Basically instead of storing the entire board, you compute a long that serves as a hash key for the position, and store that along with the relevant data. It has the additional benefit of being able to be incrementally updated. Instead of generating the key from scratch when making moves, you can update the key with a single bitwise XOR operation (very fast).
Basically, generate some random numbers for each square (slot?). You need one for each side. I assume that black = 0 and red = 1 for easy indexing. Initialization looks like
long[][] zobrist = new long[42][2];
for (int square = 0; square < zobrist.length; square++)
for (int side = 0; side < zobrist[i].length; side++)
zobrist[square][side] = RandomLong();
You will need to find a PRNG that generates a random long for RandomLong(). Make sure it has good randomness when looking at the bits. I recommend against using LCGs.
To compute the hash key for a position from scratch, you just need to XOR together all the zobrist values.
long computeKey(int[] board) {
long hashKey = 0;
for (int square = 0; square < board.length; square++)
if (hasPiece(board[square])) {
int side = getColour(board[square]);
hashKey ^= zobrist[square][side];
}
}
To incrementally update, just XOR the effect of the move. This is when you want to make a move and just update the key.
long updateKey(long oldKey, int moveSquare, int moveSide) {
return oldKey ^ zobrist[moveSquare][moveSide];
}
To unmake the move and get the old key, the above function works too! XOR behaves like negation in logic, so applying it twice gets you back your original key.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
So I have been working on a game that utilizes procedural terrain & structure generation. Right now, I am tackling structure generation - which I used Poisson-Disc sampling, which I plan to implement on chunks in my world. However, my sampling relies on one single seed. Is there a way to accept 3 or more numbers to output a random number somehow related to those numbers?
On another note, the random number doesn't have to be within the possible ranges of the inputs.
If it is not possible, are there any other paradigms to implement Poisson Disc sampling (or alternatives thereof) on an infinite procedurally-generated world to create structures? I am kinda stuck.
Example:
Random x = new Random(138013, 28282, 37920)
x.nextInt() = 38309
Random y = new Random(138012, 28282, 37920)
y.nextInt() = 28323
Random z = new Random(138013, 28282, 37920)
z.nextInt() = 38309
//new Random(a,b,c).nextInt() does not have to be within ranges [a,b], [a,c], [b,c]
You could create the seed by joining these three values:
new Random(138013, 28282, 37920) => new Random("138013" + "28282" + "37920")
It's not valid code, but I hope you get the principle. The string should be then converted to long. If the number is too large for long, maybe you could apply a ceratain modulo. Like 138013 % 10000 and do that for every value. Or you could sum these three values.
Using a cryptographic hash of some values is often used to cause the result to be less deterministic. In your case, something like:
public Random fromCoords(long x, long y, long z) throws Exception {
var buf = ByteBuffer.allocate(4 * 8);
buf.putLong(world_seed);
buf.putLong(x);
buf.putLong(y);
buf.putLong(z);
buf.flip();
var md = MessageDigest.getInstance("SHA-256");
md.update(buf);
var seed = ByteBuffer.wrap(md.digest()).getLong();
return new Random(seed);
}
might be enough, but isn't particularly efficient. You could use some bit twiddling inplace of the ByteBuffer to avoid most of the unnecessary heap allocations if this is a problem.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 2 years ago.
Improve this question
so I was wondering if any of you can give me tips regarding this. I've been doing some challenges like (the classical) making a method to calculate the nth number of a Fibonacci sequence using a single recursive call (aka. avoid return fibo(n-1) + fibo(n-2);).
I really scratched my head on that one and ended up looking at the solution that made use of a helper method -
public static int fibonacci(int n) {
if (n < 2) {
return n;
}
return fibonacci_helper(n, 1, 0);
}
public static int fibonacci_helper(int n, int previous, int current) {
if (n < 1) {
return current;
}
return fibonacci_helper(n - 1, current, previous + current);
}
I'm not really sure what approach one takes to solve questions like that quickly (without first solving it iteratively and translating that to a tail recursion, which takes a lot of time).
Would really appreciate some tips, thanks in advance.
You need to first decide if the question needs a recursive solution.Typically a recursion is needed when a present solution is dependent on some previous (already calculated) solution.
To start with , first check on small inputs(call them corner/base cases) . Then build on it (manually by dry running) on small inputs.Once you have done this, you can , in most cases , figure out the recurrence relation(like here in fibonacci).Test its validity , and then using base cases and current recurrence relation , write a recursion.
For example , the given code searches for a node with particular value in a binary tree(check out if you don't know what binary tree is: https://en.wikipedia.org/wiki/Binary_tree)
bool search(Node root,int val){
if(root==null)//base case 1
return false;
if(root.value==val)//base case 2
return true;
return(search(root.left,val)||search(root.right,val));//recursing left and right subtrees for looking out for the value
}
Play with it on paper, and try discover hidden computations that are redone needlessly. Then try to avoid them.
Here you have f(n) = f(n-1) + f(n-2); obviously f(n-1) = f(n-2) + f(n-3) redoes f(n-2) needlessly, etc. etc. etc.. What if you could do the two at once?
Have f2(n) return two values, for n and for (n-1); then you do (in pseudocode)
f(n) = let { (a,b) := f2(n-1) } in (a+b)
Now you have two functions, none is yet defined, what good does it do? Turn this f into f2 as well, so it returns two values, not one, just as we expect it to do:
f2(n) = let { (a,b) := f2(n-1) } in (a+b,a)
And voila, a recursive definition where a is reused.
All that's left is to add some corner/edge/base case(s), and check for the off-by-1 errors.
Or even better, reverse the time arrow, start from the base case, and get your iterative version for free.
Recursion is a tool which is there to help us, to make problem solving easier.
The area you're thinking of is called Dynamic Programming. The way it works is that the solution to the larger problem you're trying to solve is composed of solutions to smaller problems, and the time complexity can be reduced dramatically if you keep those solutions and reuse them, instead of calculating them multiple times. The general approach to take is to consider how the problem can be broken down, and which solutions to the smaller problems you'll need to remember in order to solve it. In this case, you could do it in linear time and linear space by keeping all the results in an array, which should be pretty easy to think of if you're looking for a DP solution. Of course that can be simplified because you don't need to keep all those numbers, but that's a separate problem.
Typically, DP solutions will be iterative rather than recursive, because you need to keep a large number of solutions available to calculate the next larger one. To change it to use recursion, you just need to figure out which solutions you need to pass on, and include those as the parameters.
I am currently making a game. I have multiple users and for each user I have a id (UUID). I was hoping to use this id as like a key to generate a random pattern then to a image for that player.
boolean[] booleanPlayerID = BSUtility.bytesToBooleans(playerID.getBytes(UTF_8));
WritableImage image = new WritableImage(50, 50);
PixelWriter writer = image.getPixelWriter();
int booleanIndex = 0;
for(int y = 0; 50 > y; y++){
for(int x = 0; 50 > x; x++){
if(booleanIndex >= booleanPlayerID.length){
booleanIndex = 0;
}
if(booleanPlayerID[booleanIndex]){
writer.setColor(x, y, Color.BLACK);
}
booleanIndex++;
}
}
Assuming the image is going to be 50x50... What I have been doing is I take the player's id, convert to boolean array, cycle through image pixels, also cycle through boolean array, if the boolean value is true then set the pixel color to black. The if statement is to avoid indexing out of bounds (I know I should probably convert the boolean array to be the same length as how many pixels are in the image)...
This does produce some what of a pattern, but to be honest it is a really shitty pattern. The patterns generally tend to be very similar to one another. I was wondering if someone could provide tips/example of how to do this better. With my little research I really couldn't find much. I did however find patterns that I am hoping to somewhat obtain, I believe they are called tangle patterns. I would really hope to have each user have their own unique image/pattern but obvious it is fine if they are somewhat similar but not same. I don't know if this is possible to be honest.
If you need a complete example I can replace the code above. Although the code above should be pretty straight forward to making it a full example (only things missing is generating the userID and converting it to boolean array from bytes).
What you are talking about is known as IDENTICON.
I actually don't know how they work but i know that they use some sort of hashing with the UNIQUE TEXT and generate image with that hash.
Here are two website i found who do provide source code so if you are interested you can look into the code and extract any useful information from there.
http://identicon.net/
https://jdenticon.com/
PS. Code are in JavaScript and on one website its in .NET and PHP too.
I'm still trying to improve on my coding skills, and this question has got me spinning in my tracks a little bit, so any help is greatly appreciated. I know how to create the random array very easily, no problem with that. However, the logic of finding the chain is proving very difficult for me. I believe the proper approach is some sort of depth first searching algorithm, but I'm not entirely sure of how to implement that in this scenario, or whether that is even correct.
My basic question is, should I be using depth first search, and if so, should I be doing it recursively? Any tips or hints on implementation are also welcome!
Make a program that creates a 3x3 grid of random
positive numbers where 0 <= n <= 9. The program should
find all possible combinations of numbers that add up to the area of
the grid, or 9, using these rules (similar to Boggle):
a. The numbers must be "chained" in sequentially adjacent cells, where
"adjacent" cells are those horizontally, vertically, and diagonally
neighboring
b. The chain does not have to be in a line. For example, it could go
horizontally once, then vertically once, and finally diagonally once
c. At least the “grid width - 1” cells must be used in the chain (a
3x3 grid means that at least two cells must be used)
d. A chain cannot repeat a grid cell that it has already used
e. Chains that use the exact same cells as a previous chain are
considered repeats and should not be counted
I know that for each element, when you are searching through each adjacent element, you must check and keep track of whether it's been visited before, so you don't repeat numbers.
public class GridSolver {
int[][] workingGrid;
public GridSolver(int[][] workingGrid){
this.workingGrid = workingGrid;
}
public String solve(){
int length = this.workingGrid.length;
boolean[][] visited = new boolean[length][length];
for(int rows=0; rows<length; rows++){
for(int columns=0; columns<length; columns++){
if(visited[rows][columns] == false){
dfs(workingGrid[rows][columns]);
}
}
}
return null;
}
public HashSet<ArrayList<Integer>> dfs(int element){
HashSet<ArrayList<Integer>> chains = new HashSet<>();
checkLeft();
checkTopLeft();
checkTopMiddle();
checkTopRight();
checkRight();
checkBottomRight();
checkBottomMiddle();
checkBottomLeft();
return null;
}}
This is what I have so far and I realize that it is pretty sloppy and not the best thought out scheme, but that's why I'm here I guess :P.
Also just to explain some of my thinking in the code, the dfs()method has a return type of HashSet because I know that you can't have duplicate chains, and it is a set of a list of the chains. Also the "check" methods are not implemented, I just wrote them down because I know that you will need to process each of these adjacent blocks for each number.
Once again, any help is greatly appreciated, and thank you for humoring me as a beginner here!
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I've made a Tic-Tac-Toe game, and yes some of you probably think my program is not very good. I am a new programmer and have never used swing or anything related to a JAVA GUI before this game. The program works, MOSTLY. When you compile and run it, and click player vs computer, the game gets stuck after 3-4 turns. I've been trying to figure out what the problem is for hours and can't seem to figure it out. The code is quite long... Any help is appreciated!
Here is the code: http://txt.do/6dvm
your computers logic is a bit... flawed:
int row = (int)(2*Math.random())+1;
int column = (int)(2*Math.random())+1;
while (button[row][column].isEnabled()==false)
{
row = (int)(2*Math.random())+1;
column = (int)(2*Math.random())+1;
}
in an array of size 3x3 do you see any problem with the numbers its generating? What I see here is numbers 1<=x<=2 being generated. What that means is nothing in column 1 (or array index of 0) ever being chosen. What this means is when all locations other than the first row and column are taken you get stuck in an endless loop. The logic should read:
int row = (int)(3*Math.random());
int column = (int)(3*Math.random());
while (button[row][column].isEnabled()==false)
{
row = (int)(3*Math.random());
column = (int)(3*Math.random());
}
or better:
int row, column;
do
{
row = (int)(3*Math.random());
column = (int)(3*Math.random());
} while (!button[row][column].isEnabled()); // stop with the == boolean
this still leaves you with and infinite loop if no rows are enabled and a very bad implementation of a random selection that could take a while, heres a better way:
// list containing available locations for the computer to choose
java.util.List<int[]> availableIndexes = new java.util.ArrayList<int[]>();
// go through all our buttons and make a list of ones that are enabled
for(int r=0;r<button.length;r++) {
for(int c=0;c<button[r].length;c++) {
if(button[r][c].isEnabled()) {
availableIndexes.add(new int[]{r, c});
}
}
}
// see if we can even do anything
if(availableIndexes.isEmpty()) {
// cats game, i dont know what you want to do there....
} else {
// choose one of our avaible buttons at random
int [] randomButtonIndex = availableIndexes.get((int)(Math.random()*availableIndexes.size()));
int row = randomButtonIndex[0];
int column = randomButtonIndex[1];
// .... continue what you were doing
}
Some other stuff from comments I saw:
Learn to use an IDE, Netbeans, IntelliJ or Eclipse are good ones to look at.
Use data structures, loops and methods to your advantage. Things like button[0][0].addActionListener(new playerVSComputer()); button[0][1].addActionListener(new playerVSComputer());.... can be done with a loop and will help your code become more clear.
For further help try posting a question on the code review section of stack exchange.