A while I did an assignment creating a tictactoe program through eclipse. It works well enough, with me clicking empty boxes to place O's, and the program inputting X's afterward. However, I was using a pretty simple code for the placement of X's:
public int putX(){
for(int i=0; i<3;i++)
for(int j = 0;j<3;j++) {
if(position[i][j]==' ') {
position[i][j]='X';
return 0;
}
}
return -1; //some error occurred. This is odd. No cells were free.
}
Because of this, the X's are just placed in the row of each column, going down until the next column. Can someone show me a simple way to randomize this program?
What we want to do is generate an array of all the possible points, and pick one of those points at random. We use a for loop to iterate through all points in the 3x3 array, and add the valid ones to our temporary array, and then we choose a random index, and place an X there.
String[] list = new String[9]; // maximum 9 points
int size = 0;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(position[i][j] == ' ') {
list[size] = "" + i + j;
size++;
}
}
}
int index = (int) (Math.random() * (size+1));
position[Integer.parseInt(list[index].charAt(0))][Integer.parseInt(list[index].charAt(1))] = 'X';
Alternatively, instead of storing the x,y coordinates of the point in a String we could store them in a java.awt.Point like so:
Point[] list = new Point[9]; // maximum 9 points
int size = 0;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(position[i][j] == ' ') {
list[size] = new Point(i, j);
size++;
}
}
}
int index = (int) (Math.random() * (size+1));
position[list[index].getX()][list[index].getY()] = 'X';
As you can see, the code for using a Point is practically the same, but instead of parsing the coordinates out of the String, we can just access them directly from the Class.
You should also check to make sure that there are some elements left, by checking if size is still 0 after the for loop. If so, you should probably return -1 (what your existing code does). Otherwise, at the end of the whole code return 0.
Related
A brief explanation: With the code below it will make a randomly generated Square and some code below would make sure that it was a Magic Square, in which the sum of the elements in each row, column, and the two diagonals are the same value.
My teacher said at maximum it should take three minutes to generate a magic square. So all I ask is there anything that can be done to improve or fix this code, please?
import java.util.ArrayList;
import java.util.Random;
class Main {
public static void main(String[] args) {
int size = 9;
int N = 3;
boolean result = true;
ArrayList<Integer> list = new ArrayList<Integer>(size);
int[][] mat = new int[N][N];
while (result) {
for (int i = 1; i <= size; i++) {
list.add(i);
}
Random rand = new Random();
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int index = rand.nextInt(list.size());
System.out.print(list.remove(index)+" ");
}
System.out.println();
}
System.out.println();
// Checking process
// sumd1 and sumd2 are the sum of the two diagonals
int sumd1 = 0, sumd2 = 0;
for (int i = 0; i < N; i++) {
// (i, i) is the diagonal from top-left -> bottom-right
// (i, N - i - 1) is the diagonal from top-right -> bottom-left
sumd1 += mat[i][i];
sumd2 += mat[i][N - 1 - i];
}
// if the two diagonal sums are unequal then it is not a magic square
if (sumd1 != sumd2)
result = false;
// calculating sums of Rows and columns and checking if they are equal to each other,as well as equal to diagonal sum or not
for (int i = 0; i < N; i++) {
int rowSum = 0, colSum = 0;
for (int j = 0; j < N; j++) {
rowSum += mat[i][j];
colSum += mat[j][i];
}
if (rowSum != colSum || colSum != sumd1)
result=false;
}
result = true;
}
}
}
Trying with random numbers to coincidentally find a solution is deadly slow.
If you have the numbers 1 to 9, its entire sum 1+2+3+...+8+9 is 9*(1+9)/2 = 45.
As you have 3 rows and 3 colums, a row and column must sum upto 45/3 = 15.
Now that should restrict the number of possibilities.
So you must build in some intelligence in the code. Avoid random numbers as they do not even guarantee you'll find a solution in hundred years.
If you already treated recursion, that would be the easiest way to try all possibly valid combinations.
If you already treated Set, a BitSet maybe might be useful for a row, column or diagonal.
If you find it hard to code walking through all possibilities, you might hold the 2 dimensional matrix in a 1 dimensional array int[N*N], and have N (rows) + N (columns) + 2 (diagonals) arrays of N indices.
And of course I will not spoil your fun and satisfaction finding a smart solution.
Work it out on paper first.
I want to memory-efficient this (the game of life code of shiffman in the nature of code book). how can change the below code to have only two arrays and constantly swap them, writing the next set of states into whichever one isn’t the current array?
class GOL {
int w = 8;
int columns, rows;
int[][] board;
GOL() {
// Initialize rows, columns and set-up arrays
columns = width / w;
rows = height / w;
board = new int[columns][rows];
//next = new int[columns][rows];
// Call function to fill array with random values 0 or 1
init();
}
void init() {
for (int i = 1; i < columns - 1; i++) {
for (int j = 1; j < rows - 1; j++) {
board[i][j] = (int) random(2);
}
}
}
// The process of creating the new generation
void generate() {
int[][] next = new int[columns][rows];
// Loop through every spot in our 2D array and check spots neighbors
for (int x = 1; x < columns - 1; x++) {
for (int y = 1; y < rows - 1; y++) {
// Add up all the states in a 3x3 surrounding grid
int neighbors = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
neighbors += board[x + i][y + j];
}
}
// A little trick to subtract the current cell's state since
// we added it in the above loop
neighbors -= board[x][y];
// Rules of Life
if ((board[x][y] == 1) && (neighbors < 2)) next[x][y] = 0;
else if ((board[x][y] == 1) && (neighbors > 3)) next[x][y] = 0;
else if ((board[x][y] == 0) && (neighbors == 3)) next[x][y] = 1;
else next[x][y] = board[x][y];
}
}
// Next is now our board
board = next;
}
// This is the easy part, just draw the cells, fill 255 for '1', fill 0 for '0'
void display() {
for (int i = 0; i < columns; i++) {
for (int j = 0; j < rows; j++) {
if ((board[i][j] == 1)) fill(0);
else fill(255);
stroke(0);
rect(i * w, j * w, w, w);
}
}
}
}
You might not like this, but the honest answer is: don't bother.
how can change the below code to have only two arrays and constantly swap them, writing the next set of states into whichever one isn’t the current array
This is already exactly what the code does.
The Game of Life requires two arrays. If you're coming up against real performance issues, then look for other areas of improvement. Focusing on the array is a red herring.
There's an old saying: premature optimization is the root of all evil. In other words, you shouldn't waste time trying to fix code before it's broken.
One obvious thing you might improve is: why are you using an int[] array instead of a boolean[] array? You only need to store two states: alive or dead, so using int values seems unnecessary. You'll save a little bit of memory if you switch to a boolean[] array, but again, you probably won't even notice the improvement.
Please dont let the length of this post scare you! Okay so here is the prompt I am currently working on:
"Write a class named BucketSort containing a method called sort that:
a) Place each value of the one-dimensional array into a row of the bucket array, based on the value’s “ones” (rightmost) digit. For example, 97 is placed in row 7, 3 is placed in row 3 an 100 is placed in row 0. This procedure is called a distribution pass.
b) Loop through the bucket array row by row, and copy the values back to the original array. This procedure is called a gathering pass. The new order of the preceding values in the one-dimensional array is 100, 3 and 97.
c) Repeat this process for each subsequent digit position (tens, hundreds, thousands, etc.) On the second (tens digit) pass, 100 is placed in row 0, 3 is placed in row 0 (because 3 has no tens digit) and 97 is placed in row 9. After the gathering pass, the order of the values in the one-dimensional array is 100, 3 and 97. On the third (hundreds digit) pass, 100 is placed in row 1, 3 is placed in row 0 and 97 is placed in row 0 (after the 3) After this last gathering pass, the original array is in sorted order. being sorted.
This sorting technique provides better performance than a bubble sort,but requires much more memory—the bubble sort requires space for only one additional element of data. This comparison is an example of the space/time trade-off: The bucket sort uses more memory than the bubble sort, but performs better. This version of the bucket sort requires copying all the data back to the original array on each pass. Another possibility is to create a second two-dimensional bucket array and repeatedly swap the data between the two bucket arrays. The two-dimensional array of buckets is 10 times the length of the integer array"
A bit of a mouth full I know. Below is my code thus far, but I can't figure out why it will not print in the correct order and I think it is time for fresh eyes. Any ideas are appreciated, thanks!
import java.util.Arrays;
public class BucketSort_main {
public static void main(String[] args)
{
int[] numbers = new int [5];
int[] tnumbers = new int [500];
int [][] bucket = new int [10][numbers.length];
int [] a = new int [10];
int count = 0;
int divisor = 1;
int cnt = 1;
boolean moreDigits = true;
for (int s = 0; s < 10; s++)
{
a[s] = 0;
}
for (int b = 0; b < numbers.length; b++)
{
numbers [b] = (int)(Math.random()*2000);
tnumbers [b] = numbers [b];
}
int[] tmpSort = new int[10];
while (moreDigits)
{
moreDigits = false;
for (int i = 0; i < tmpSort.length; i++)
{
tmpSort[i]= -1; // hint hint
}
for (int i = 0; i < numbers.length; i++)
{
int tmp = tnumbers[i] / divisor;
if (tmp/10 != 0)
{
moreDigits = true;
}
int digit = tmp % 10;
tmpSort[digit] = tnumbers[i]; // hint hint
System.out.println("Number["+i+"], Digit "+cnt+" is "+digit + ". Full number = " + tnumbers[i]);
bucket [digit][a[digit]] = tnumbers[i];
System.out.println ("Digit " + digit + " going to slot " + a[digit] + ". " + bucket[digit][a[digit]]);
System.out.println (" ");
a[digit]++;
}
cnt++;
divisor *= 10;
for (int x = 0; x < 10; x++)
{
a [x] = 0;
for (int y = 0; y < numbers.length; y++)
{
if (bucket[x][y] != 0)
{
tnumbers [y] = 0;
tnumbers [y] = bucket[x][y];
bucket[x][y] = 0;
}
}
}
}
for (int o = 0; o < numbers.length; o++)
{
System.out.println (tnumbers[o]);
}
}
}
The Problem is here:
for (int x = 0; x < 10; x++)
{
a [x] = 0;
for (int y = 0; y < numbers.length; y++)
{
if (bucket[x][y] != 0)
{
tnumbers [y] = 0;
tnumbers [y] = bucket[x][y];
bucket[x][y] = 0;
}
}
}
You are using the same y to get values from the bucket and assign values to tnumbers. So, when you loop through y the second time you are starting over again at tnumbers[0], tnumbers[1], etc...
Fix this issue and your code works fine.
There are many symbol games working in this way so this should sound familiar to you.
Facts:
I have two arrays with same length of 4.
(A[4] and B[4])
I fill them with random integers from 1 to 6.
I can NOT sort them in any way (they must stay the same).
Problems:
I need to compare them and after that I need to have 3 values. FIRST one needs to count how many elements are the same and in the same place. I do it like this and it is working:
int first = 0;
int k = 0;
for (int j=1; j<=4; j++)
{
k++;
if (A[k] == B[j])
{
first++;
}
}
SECOND one needs to count how many elements are the same BUT not at the same place. THIRD one needs to count how many elements are not the same at all.
I need a solution to count either SECOND or THIRD number, because after that I can just subtract like 4-(first+second) or 4-(first+second).
Here's the logic you should use: loop over the first array; for each element, check if the corresponding element of the second array is the same - if yes, increment your first counter. If they are not the same, then check whether the second array contains the corresponding element of the first array. If it does, then it's definitely not in the same position (you just checked same positions) - increment your second count. Otherwise, increment your third count. The code can be as following:
int[] A = {...};
int[] B = {...};
List<Integer> lstB = new ArrayList<Integer>(B.length);
for (int index = 0; index < B.length; index++) {
lstB.add(B[index]);
}
int first = 0, second = 0, third = 0;
for(int i=0; i<4; i++) {
if(A[i] == B[i]) {
first++;
}
else if(lstB.contains(A[i]) {
second++;
}
else {
third++;
}
}
SOLUTION
Eventually I made the right algorithm. In general, the solution is to keep track of what fields you used when counting FIRST value. And here is the code:
int first = 0;
int second = 0;
int third = 0;
boolean[] codeUsed = new boolean[4];
boolean[] guessUsed = new boolean[4];
//same value and same place
for (int i = 0; i < 4; i++)
{
if (A[i] == B[i])
{
first++;
codeUsed[i] = guessUsed[i] = true;
}
}
//same value but not right place
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (!codeUsed[i] && !guessUsed[j] && A[i] == B[j])
{
second++;
codeUsed[i] = guessUsed[j] = true;
break;
}
}
}
//not the same value
third = 4 - first - second;
So im having a bit of problem with my code.. It's suppose to cross check rows and columns for same integers.
this is what i have so far.. but when i run it, it only seems to check the first integer only. (for example the first line of the sudoku board reads. 1 2 2 2 2 2 2 2 2 2) it wont detect the obvious multiple 2's but if i change the input to 1 1 2 2 2 2 2 2 2 the error will come up of multiple 1's in this case. the multiple any suggestions to tweak my loops to make it go through the columns?
public static void validate(final int[][] sudokuBoard) {
int width = sudokuBoard[0].length;
int depth = sudokuBoard.length;
for (int i = 0; i < width; i++) {
int j = i;
int reference = sudokuBoard[i][j];
while (true) {
if ((j >= width) || (j >= depth)) {
break;
}
else if (i == j){
// do nothing
}
else if (j < width) {
int current = sudokuBoard[i][j];
if (current == reference) {
System.out.print("Invalid entry found (width)" + "\n");
System.out.print(current + "\n");
// invalid entry found do something
}
} else if (j < depth) {
// note reversed indexes
int current = sudokuBoard[j][i];
if (current == reference) {
System.out.print("Invalid entry found (depth)" + "\n");
System.out.print(current + "\n");
// invalid entry found do something
}
}
j++;
}
Your code is more complex than it should be. Why put everything in one single function when you could split in several different functions?
public static void Validate(final int[][] sudokuBoard)
{
int width = sudokuBoard[0].length;
int depth = sudokuBoard.length;
for(int i = 0; i < width; i++)
if(!IsValidRow(sudokuBoard, i, width))
{
//Do something - The row has repetitions
}
for(int j = 0; j < height; j++)
if(!IsValidColumn(sudokuBoard, j, width))
{
//Do something - The columns has repetitions
}
}
static bool IsValidRow(int[][] sudokuBoard, int referenceRow, int width)
{
//Compare each value in the row to each other
for(int i = 0; i < width; i++)
{
for(int j = i + 1; j < width; j++)
{
if(sudokuBoard[referenceRow][i] == sudokuBoard[referenceRow][j])
return false
}
}
return true;
}
static bool IsValidColumn(int[][] sudokuBoard, int referenceColumn, int height)
{
//Compare each value in the column to each other
for(int i = 0; i < height; i++)
{
for(int j = i + 1; j < height; j++)
{
if(sudokuBoard[i][referenceColumn] == sudokuBoard[j][referenceColumn])
return false
}
}
return true;
}
That way, your code is much more easily maintainable/readable. This code above hasn't been tested, but it should be about right.
I suggest debugging this code step by step to really understand what's going on, if that's not clear for you.
Given the constraints of sudoku (a row of n cells must contain the numbers 1-n only) you don't need an order n^2 search (per row or column), you can do it order n by keeping a bit array indicating which numbers you've seen. Here's the pseudo-code for checking rows, do the same for columns:
for i in 0 to depth-1 // rows
boolean seen[] = new seen[width];
for j in 0 to width-1 // columns
if seen[board[i][j]-1] == true
duplicate number
else
seen[board[i][j]-1] = true
I would break the functionality into smaller boolean checks. This way, you can validate row by row, column by column, and square by square. For instance
private boolean isValidRow(int[] row) {
// Code here to check for valid row (ie, check for duplicate numbers)
}
private boolean isValidColumn(int[] column) {
// Code here to check for valid column
}
private boolean isValidSquare(int[][] square) {
// Code here to check for valid square
}
Note that rows and columns only need to be passed a 1 dimensional array. Squares are a 2 dimensional array as you need to check a 3x3 area. You can also treat these methods as static as their functionality is independent of the Sudoku board instance.
Edit: A suggestion on row/column/square validation is to use a HashSet. Sets can only have 1 element of a certain value, so you can add elements and look for a failure. For example:
HashSet<Integer> hs = new HashSet<Integer>();
for(int i = 0; i < 9; i++) {
if(!hs.add(integerArray[i])) // HashSet.add returns 'false' if the add fails
// (ie, if the element exists)
return false;
}
return true;