How would I move a blank space in a 2d array? - java

I'm working on a Slider puzzle game and I'm not sure how I would go about moving a "blank" around the array. The puzzle would something like this but randomized. Each method has a prerequisite indicating if it can move a certain direction or not.
- 2 3
4 5 6
7 8 9
// Modifies the puzzle by moving the blank up
// pre: canMoveUp()
public void up() {
}
// Modifies the puzzle by moving the blank down
// pre: canMoveDown()
public void down() {
}
// Modifies the puzzle by moving the blank left
// pre: canMoveLeft()
public void left() {
}
// Modifies the puzzle by moving the blank right
// pre: canMoveRight()
public void right() {
}

Here is an example of how you could implement right(), the rest of the methods would follow very similarly. I am assuming, as your comments imply, that the legality of the move has already been verified.
/*
represent the board in a 2-dimensional array with the following coordinate system
x --->
y
|
\/
*/
int x, y = 0; // keeping track of the blank position
int[][] board = ... // initialize the board as needed (sequentially? randomly?), assume -1 represents the blank space
public void right() { // move the blank in the positive x direction
// get the value currently in the position that the blank must move to, as it will need to be swapped
int tmp = board[x + 1][y];
board[x + 1][y] = -1; // move the blank here
board[x][y] = tmp; // complete the swap
x = x + 1; // the new x position of the blank needs to be updated
}

Related

Why does algorithm in Tic Tac Toe game doesn't block my moves?

I have a working TicTacToe game, where I am trying to implement an Ai to act as player "O". The issue I'm having is that it won't block my moves. I have read through the code many times using breakpoints, but I still can't find the issue. Do any of you know what the issue could be?
This is the main minimax function:
public int miniMax(String player, int currentDepth, String[] board) {
if(checkWin("O",board)){ //Checks if O wins. Returns 10-currentDepth to give value to terminal state (Ai wins)
return 10-currentDepth;
}
if(checkWin("X",board)){ //checks if X wins. Returns -10-currentDepth to give value to terminal state (Ai loses)
return -10-currentDepth;
}
if(checkTie(board)){ //Checks for tie. Returns 0-currentDepth
return 0-currentDepth;
}
currentDepth++;//Increases depth
if(player.equals("O")){ //If the player turn is O, I.E. the AI's turn/Max function of minimax
bestVal=Integer.MIN_VALUE;
bestSpot=0;
for(int i=0;i<board.length;i++){ //For loop that iterates through each possible move for O.
if(board[i].equals(" ")){ //Checks if the spot is empty before modifying it
board[i] = "O"; //When spot is empty, sets equal to O
int value = miniMax("X",currentDepth,board); //Recursive part of function. Recalls function changing the current player. Once it hits an end spot, gives it terminal value
if((value)>bestVal){ //Checks if value is better then the best, to determine best possible move.
bestVal = value; //If value is better, then sets new best to it.
bestSpot = i;// The location of the next best move
}
board[i]=" ";//sets the original location to empty to prevent board from being permanently changed
}
else{}//When the spot isn't empty, just skips that check.
}
return bestSpot;//Returns the best spot to allow program to make a move. This is what gets sent to gamelogic
}
else{ //If the player turn is X, I.E. the players turn/Mini function of minimax
minVal=Integer.MAX_VALUE;
bestSpot=0;
for(int i =0;i<board.length;i++){ //For loop that iterates through each possible move for X.
if(board[i].equals(" ")){ //Checks if the spot is empty before modifying it
board[i] = "X"; //When spot is empty, sets equal to X
int value = miniMax("O",currentDepth,board); //Recursive part of function. Recalls function changing the current player. Once it hits an end spot, gives it terminal value
if((value)<minVal){ //Checks if value is worse then the worst, to determine best possible move.
minVal = value; //If value is better, then sets new best to it.
bestSpot = i; //The location of the next best move
}
board[i] = " "; //Sets the original location to empty to prevent board from being permanently changed
}
else{} //When the spot isn't empty, just skips that check.
}
return bestSpot; //Returns the best move for X.
}
}
This is my checkwin and check tie function:
private boolean checkWin(String player, String[] board){
if(
(board[0].equals(player) && board[1].equals(player) && board[2].equals(player)) ||//first col
(board[3].equals(player) && board[4].equals(player) && board[5].equals(player)) ||//sec col
(board[6].equals(player) && board[7].equals(player) && board[8].equals(player)) ||//third col
(board[0].equals(player) && board[3].equals(player) && board[6].equals(player)) ||//first row
(board[1].equals(player) && board[4].equals(player) && board[7].equals(player)) ||//second row
(board[2].equals(player) && board[5].equals(player) && board[8].equals(player)) ||//third row
(board[0].equals(player) && board[4].equals(player) && board[8].equals(player)) ||//diag \
(board[2].equals(player) && board[4].equals(player) && board[6].equals(player)) //diag /
){
return true;
}
else{
return false;
}
}
private boolean checkTie(String[] board){
int inter=0;
for (String s : board) {
if(!s.trim().isEmpty()){
inter++;
}
}
return inter == 9;
}
Let me know if you need any more code from the program.
Have you tried using a more sophisticated reward function given a game state? I see that you only check for terminal states and there is no extra reward for "blocking" the opponent. The AI needs an incentive to perform certain moves, i.e. you need to reward it for certain actions such as blocking.

How can I save all the coordinates on which a person has moved to a two-dimensional array?

Heading
There is a man which is trying to move inside a square board. The board is a grid of size where the point is in its upper-left corner and the point is in its bottom-right corner. The man will move only by following some rules:
It will always move according to the current direction of the wind (possible directions are North, South, West, East, North-East, North-West, South-East, South-West).
It can visit a specific cell of the board only once.
It can not go out of the borders of the board.
If it reaches at a point where it can not move according to the rules, it will stay at the current position.
It can move only to the neighbouring cells (8 possible moves according to the above directions).
It will always start its journey from the point (the upper-left corner of the board).
It can only make one movement per second.
In order to make things more difficult for him, the wind will change its direction multiple times during the man's journey. You will always be given the direction of the wind before the man starts to move (0-th second) and then you will be given the specific time in seconds when the wind is going to change its direction (in a strictly increasing sequence).
After following all the journey of the man, you will have to specify how many positions inside the board were not visited by the man.
Input Format
In the first line you will be given two integers 'n' and 'k' where 'n' represents the dimension of the board. Then in the following 'k' lines you will be given an integer 'ti' and a string 'w'. The 'ti' represents the time in seconds in which on the board a wind of direction 'w' will be applied.The 'w' might take a value of N, S, W, E, NE, NW, SE, or SW (representing North, South, West, East, North-East, North-West, South-East or South-West, respectively).
Constraints
3 <= n <= 100000
2 <= k <= 100000
0 <= ti <=100000
t0 = 0 < t1 <...< tk-1
Output Format
Output the number of positions inside the board that were not visited by the man.
Sample Input 0
5 6
0 SE
1 NE
2 E
6 SW
15 N
20 W
Sample Output 0
13
public class Solution {
public static void main (String args []) {
//Table
int [][] board = new int [7][7];
// Seconds available for moving
int seconds = 43;
// Initial Man Coordinate
int Man = board [0][0];
// Two dimensional array to save the coordinates visited by the man
int [][] isVisited = new int [7][7];
// Formula to calculate the cells that are not visited by the man ( i know is wrong )
int notVisited = isVisited.isEmpty(true) - isVisited.isEmpty(false);
for (int i=0;i<=board.length;i++) {
for(int j=0;j<=board.length;j--) {
while (seconds < 4 ) {
i++;
j++;
Man = board [i][j];
//Here should be the code to save the coordinates visited by the man -->
I would first create a new call called Board:
public class Board {
private boolean[][] visited;
private int boardSize;
private int numVisited;
public Board(int boardSize) {
this.boardSize = boardSize;
visited = new boolean[boardSize][boardSize];
}
public void setVisited(int x, int y) {
if (!visited[x][y]) {
visited[x][y] = true;
numVisited++;
}
}
public int getBoardSize() {
return boardSize;
}
public int getNumVisited() {
return numVisited;
}
public int getNumNotVisited() {
return boardSize * boardSize - numVisited;
}
}
Afterwards you can create an instance of Board
Board myBoard = new Board(7);
And then in your logic, you can set a cell to visited by calling setVisited:
myBoard.setVisited(3, 3);
And you can count the number of visited cells by calling countVisited
int numberOfVisitedCells = myBoard.getNumVisited();
Or, if you want the number of cells that have not been visited:
int numberofCellsNotVisited = myBoard.getNumNotVisited();
EDIT: Thanks #Matthew for the improvement!

Sudoku backtracking algorithm (Java)

I've created a Sudoku solver that will solve a Sudoku as a human might- by checking possibilities + definite values in squares corresponding to the square being checked.
(Source: http://pastebin.com/KVrXUDBF)
However, I would like to create a random Sudoku generator (from a blank grid), and so have decided to use a backtracking algorithm. I understand the concept of backtracking, but am confused about one thing:
How do I know which previous node to return to (and change) once I know a certain solution is not allowed?
Should I simply return to the previous node and cycle through all possibilities? (And then if this yields no correct answers, return to the value before, etc.). This seems like a viable method, but also quite inefficient. Is this the correct way of implementing a backtracking method or is there a better way to go about it?
Thanks in advance.
More can be found about backtracking here: http://en.wikipedia.org/wiki/Backtracking
Sudoku Puzzle can be reduced to graph coloring problem which can be solved using simple backtracking like assigning colors to node (1-9) till the there is no violation that all directly connected nodes have no same color.
Constructing Graph from Sudoku : -
There is an direct edge between two grid points if they are in same
row or column or square.
Backtracking :-
Assign one color (1-9) to node
Check if there is no other directly connected node with same color
If valid color move to next node.
else change the color and recheck.
If all color exhausted backtrack to previous node.
Do recursion till all nodes are color.
Once You are done with it you can start removing numbers from the grid at random till you think the problem is unsolvable if any more numbers are removed.
A simple way to generate random Sudoku is that
1) generate a random completing Sudoku, that is, generate random Sudoku no square is blank.
2) Remove numbers from squares of 1).
3) Solve Sudoku of 2). If there are many solutions, then add a number removed at 2).
If there are still many solutions, then repeat 3).
1) sample source code:
public int[][] generateRandomCompleteSudoku() {
int[][] sudoku = new int[10];
for(int i = 1; i <= 9; i++) {
sudoku[i] = new int[10];
Arrays.fill(sudoku[i], 0);
}
generateRandomCompleteSudoku(sudoku, 1, 1);
return sudoku;
}
private boolean generateRandomCompleteSudoku(int[][] sudoku, int x, int y) {
if(x > 9) {
x = 1;
y++;
}
//sudoku of the argument is completing sudoku.
//so return true
if(y > 9) {
return true;
}
// enumerate the possible numbers of the pos(x,y).
List<Integer> possibleNumbers = new ArrayList<Integer>();
for(int i = 1; i <= 9; i++) {
boolean possible = true;
//check i is a possible number.
//check there isn't i in the raw of y .
for(int j = 1; j <= x - 1; j++) {
if(sudoku[j][y] == i) {
possible = false;
break;
}
}
//check there isn't i in the column of x(omitted).
//check there isn't i in the group of x,y(omitted).
if(possible) {
possibleNumbers.add(i);
}
}
//sudoku is wrong so return false.(There is no solution of sudoku)
if(possibleNumbers.size() <= 0) {
return false;
}
Collections.shuffle(possibleNumbers);// This gives sudoku randomness.
for(Integer possibleNumber : possibleNumbers) {
sudoku[x][y] = possibleNumber;
// a sudoku is generated, so return true
if(generateRandomCompleteSudoku(sudoku, x + 1, y)) {
return true;
}
}
// No sudoku is generated, so return false
return false;
}
For a backtracking solution, the first step is to define the state. So for this problem, I think the most straightforward way is (x,y, blank , num) with x , y is the position of the current state, blank is the number of blank position left, and num is the value you want to fill in that position (from 0 to 9 and 0 means blank).
And the return type should be boolean, which determine whether the move is valid or not (which means is there any valid solution for this move).
So, the state transition is column by column, row by row: x, y to x , (y + 1) or x , y to (x + 1), 0.
Similarly, the blank will be from a -> a - 1-> ... 0.
We have a draft solution here:
public boolean move(int x, int y, int blank, int num, int[][]sudoku){
sudoku[x][y] = num;
//checking condition and return if x,y is the last position, code omitted
if(y == sudoku[x].length){
x++;
y = 0;
}else{
y++;
}
for(int i = 1; i < 10; i++){
if(move(x,y,blank,i,sudoku){//Backtrack here
return true;
}
}
if(blank > 0){
if(move(x,y,blank - 1, 0, sudoku){//Backtrack here
return true;
}
}
return false;
}
So when ever there is a false return from the current state, it will backtrack to the last state , and the last state will continue to check for the next num until it find a correct solution (or return false).

Java game - run code sequentially in the game loop

I am creating a Java game within which the user can enter the commands of up, left, right, or down to move the character in that location for a certain amount of pixels. Within the Player class I am receiveing the commands from the user in an ArrayList of JTextFields after they have pressed the start button. I then use a for loop to go through all the inputs from the user and create x and y targets within a multi-dimensional array for the x and y amount of distance that the player needs to move. Finally I have a function called updatePosition() which is called within the main game loop. Within this function I loop through the multi-dimensional array of targets and have an if statement to check if the target has been reached or not. However when this method is executed and the user has input the commands of up and right for example, then the character moves diagonally up. I want a way which will move the character in the direction that the user has specified, executing them one after another.
Here is the code:
moveSpeed = 1;
private double moveAmt = 20;
private Double[][] targetCoordinates = null;
private ArrayList<JTextField> userInputTextFields = new ArrayList<JTextField>();
With method below I acquire the ArrayList of JTextFields within which the user has entered the commands and store it in a local ArrayList. I also instatiate an Array in the size of the amount of JTextFields that the user has entered the commands in. This array will be used to store the x and y targets for the character. I then lastly call the moveChar(); method which will set the target x and y.
public void getInputText(ArrayList<JTextField> textFields){
this.userInputTextFields = textFields;
targetCoordinates = new Double[userInputTextFields.size()][2];
moveChar();
}
This method will check if the commands that the user has enetered and set the x and y targets within the targetCoordinates array.
private void moveChar(){
for (int i = 0; i < userInputTextFields.size(); i++) {
if(userInputTextFields.get(i).getText().equals("up")){
targetCoordinates[i][0] = x;
targetCoordinates[i][1] = y - moveAmt;
} else if(userInputTextFields.get(i).getText().equals("down")){
targetCoordinates[i][0] = x;
targetCoordinates[i][1] = y + moveAmt;
} else if(userInputTextFields.get(i).getText().equals("left")){
targetCoordinates[i][0] = x - moveAmt;
targetCoordinates[i][1] = y;
} else if(userInputTextFields.get(i).getText().equals("right")){
targetCoordinates[i][0] = x + moveAmt;
targetCoordinates[i][1] = y;
}
}
}
Finally, this is the method which gets called within the main game loop. It goes through the targetCoordinates array and checks if the targets have been met. If not then incriment or decrement the character's x and y position accordingly.
public void updatePosition(){
if(targetCoordinates != null){
for (int i = 0; i < targetCoordinates.length; i++) {
if(y >= targetCoordinates[i][1]) {
moveCharacter(x, y - moveSpeed);
} else if(y < targetCoordinates[i][1]) {
moveCharacter(x, y + moveSpeed);
} else if(x > targetCoordinates[i][0]) {
moveCharacter(x - moveSpeed, y);
} else if(x <= targetCoordinates[i][0]) {
moveCharacter(x + moveSpeed, y);
}
}
}
}
At present you use all the available commands to create a single target position and use that to direct your motion (or possibly move towards all target positions simultaneously).
Instead you want a "hopper" of commands that survive beyond a specific game loop and a new command is only fetched after the current one is completed. New commands go in the top and out the bottom to be excecuted.
This would most likely look something like this
public class Player {
//holding commands as strings is a little bug prone, consider creating a custom class or enum
ArrayList<String> commandsHopper=new ArrayList<String>();
//replace with some sort of Vector2i as improvement
double[] targetCoOrdinates=new double[2];
public void addCommand(String command){
commandsHopper.add(command); //commands added at the top of arraylist
}
public void update(double timeSlice){
//Called once, every game loop
if (isAtTarget()){
getNextTarget();
}
moveTowardsTarget(timeSlice);
}
public void getNextTarget(){
if (commandsHopper.isEmpty()==false){
//commands used from bottom of the arraylist
targetCoOrdinates=determineTargetFromCommand(commandsHopper.get(0));
commandsHopper.remove(0); //inefficient with arraylist, consider other collections
}
}
}

Moving an object to another on a random path

I have a program which creates multiple randomly placed objects(balls) at the beginning, now im trying to move the player ball towards the closest object automatically until their centres are the same. I have determined the distance of the closest object stored in an array called distance with index of 'closest', and set the speed as variable delta initialised somewhere else, how do i get the direction right? Right now
It moves just diagonally but not towards the closest ball
coordinatex[closest] and coordinatey[closest] are the x and y coordinates of the closest object.
playerObject.getX and playerObjectgetY gives me the coordinates of the player onject
public void move(int delta) {
for(int i=0; i<distance[closest]; i++) {
if (x<coordinatex[closest] && y<coordinatey[closest]) {
playerObject.setX(playerObject.getX() + 0.1*delta);
playerObject.setY(playerObject.getY() + 0.1*delta);
} else if(x>coordinatex[closest] && y>coordinatey[closest]) {
playerObject.setX(playerObject.getX() - 0.1*delta);
playerObject.setY(playerObject.getY() - 0.1*delta);
} else if(x>coordinatex[closest] && y<coordinatey[closest]) {
playerObject.setX(playerObject.getX() - 0.1*delta);
playerObject.setY(playerObject.getY() + 0.1*delta);
} else if (x<coordinatex[closest] && y>coordinatey[closest]) {
playerObject.setX(playerObject.getX() + 0.1*delta);
playerObject.setY(playerObject.getY() - 0.1*delta);
}
}
}
Something very similar to this:
angle=atan2(ClosestBally-player_y,closestBallx-player_x);
dxperframe = cos(angle);
dyperframe = sin(-angle);
I see your handlers for the four semi-cardinal (diagonal) directions, but not the four cardinal directions. In this game, for example, enemies approach the player in a step-wise manner using the move(int row, int col) method, shown here, from any of eight directions.

Categories

Resources