I can't seem to get my min max AI to work. This is the code so far. I get an error saying my allScores array is empty so it won't set my move to the bestScored move. Any help would be appreciated.
int[] move;
public static int makeMove(Board board, int currentPlayerColor, int maxingPlayerColor){
int score = 0;
int[] moveIndex={};
if (Rules.gameOver(board)[0]==1){
if(Rules.gameOver(board)[1] == maxingPlayerColor){
System.out.println("1");
return score = 1;
} else if(Rules.gameOver(board)[1] == Math.abs(maxingPlayerColor-1)) {
System.out.println("-1");
return score = -1;
} else{
System.out.println("0");
return score = 0;
}
} else {
int[][] availableMoves = board.availableMoves(board, currentPlayerColor);
int[] allScores = {};
System.out.println("loop length: "+ availableMoves.length);
for(int x = 0; x<availableMoves.length; x++){
Board temp = board;
if(currentPlayerColor == maxingPlayerColor){
Board.doMove(availableMoves[x], temp, 7);
} else {
Board.doMove(availableMoves[x], temp, 0);
}
System.out.println(""+x);
allScores = add(makeMove(temp,Math.abs(maxingPlayerColor-1), maxingPlayerColor), allScores);
System.out.println("allscore len "+ allScores.length);
}
if(currentPlayerColor == maxingPlayerColor){
for(int x = 0; x<allScores.length; x++){
if(score < allScores[x]){
allScores = add(score, allScores);
}
}
for(int x = 0; x<allScores.length; x++){
if(score == allScores[x]){
moveIndex = add(x,moveIndex);
}
}
System.out.println("max "+moveIndex.length);
move = availableMoves[rand.nextInt(moveIndex.length)];
} else {
for(int x = 0; x<allScores.length; x++){
if(score > allScores[x]){
score = allScores[x];
}
}
for(int x = 0; x<allScores.length; x++){
if(score == allScores[x]){
moveIndex = add(x,moveIndex);
}
}
System.out.println("min "+moveIndex.length);
move = availableMoves[rand.nextInt(moveIndex.length)];
}
}
return 0;
}
You're trying to add elements onto an array with
allScores = add(...
But that isn't how it works. You can't actually add elements onto an array, you can only change existing elements.
So when you make the array, you have this:
int[] allScores = {};
But that creates an empty array and you can't do anything with that. Instead, declare it like this:
int[] allScores = new int[SIZE];
Replacing SIZE with the number of elements you want the array to hold.
Then you can access and change certain elements like this:
allScores[index] = someNumber;
There are also some formatting and syntax errors. Try using a text editor or IDE that includes syntax highlighting to find easy mistakes.
Also read over this guide to learn about arrays.
Related
my intend is to use simplest java (array and loops) to generate random numbers without duplicate...but the output turns out to be 10 repeating numbers, and I cannot figure out why.
Here is my code:
int[] number = new int[10];
int count = 0;
int num;
while (count < number.length) {
num = r.nextInt(21);
boolean repeat = false;
do {
for (int i=0; i<number.length; i++) {
if (num == number[i]) {
repeat = true;
} else if (num != number[i] && i == count) {
number[count] = num;
count++;
repeat = true;
}
}
} while (!repeat);
}
for (int j = 0; j < number.length; j++) {
System.out.print(number[j] + " ");
}
How about you use a Set instead? If you also want to keep track of the order of insertion you can use a LinkedHashSet.
Random r = new Random();
Set<Integer> uniqueNumbers = new HashSet<>();
while (uniqueNumbers.size()<10){
uniqueNumbers.add(r.nextInt(21));
}
for (Integer i : uniqueNumbers){
System.out.print(i+" ");
}
A Set in java is like an Array or an ArrayList except it handles duplicates for you. It will only add the Integer to the set if it doesn't already exist in the set. The class Set has similar methods to the Array that you can utilize. For example Set.size() is equivalent to the Array.length and Set.add(Integer) is semi-equivalent to Array[index] = value. Sets do not keep track of insertion order so they do not have an index. It is a very powerful tool in Java once you learn about it. ;)
Hope this helps!
You need to break out of the for loop if either of the conditions are met.
int[] number = new int[10];
int count=0;
int num;
Random r = new Random();
while(count<number.length){
num = r.nextInt(21);
boolean repeat=false;
do{
for(int i=0; i<number.length; i++){
if(num==number[i]){
repeat=true;
break;
}
else if(i==count){
number[count]=num;
count++;
repeat=true;
break;
}
}
}while(!repeat);
}
for(int j=0;j<number.length;j++){
System.out.print(number[j]+" ");
}
This will make YOUR code work but #gonzo proposed a better solution.
Your code will break the while loop under the condition: num == number[i].
This means that if the pseudo-generated number is equal to that positions value (the default int in java is 0), then the code will end execution.
On the second conditional, the expression num != number[i] is always true (otherwise the code would have entered the previous if), but, on the first run, when i == count (or i=0, and count=0) the repeat=true breaks the loop, and nothing else would happen, rendering the output something such as
0 0 0 0 0 0...
Try this:
int[] number = new int[10];
java.util.Random r = new java.util.Random();
for(int i=0; i<number.length; i++){
boolean repeat=false;
do{
repeat=false;
int num = r.nextInt(21);
for(int j=0; j<number.length; j++){
if(number[j]==num){
repeat=true;
}
}
if(!repeat) number[i]=num;
}while(repeat);
}
for (int k = 0; k < number.length; k++) {
System.out.print(number[k] + " ");
}
System.out.println();
Test it here.
I believe the problem is much easier to solve. You could use a List to check if the number has been generated or not (uniqueness). Here is a working block of code.
int count=0;
int num;
Random r = new Random();
List<Integer> numbers = new ArrayList<Integer>();
while (count<10) {
num = r.nextInt(21);
if(!numbers.contains(num) ) {
numbers.add(num);
count++;
}
}
for(int j=0;j<10;j++){
System.out.print(numbers.get(j)+" ");
}
}
Let's start with the most simple approach, putting 10 random - potentially duplicated - numbers into an array:
public class NonUniqueRandoms
{
public static void main(String[] args)
{
int[] number = new int[10];
int count = 0;
while (count < number.length) {
// Use ThreadLocalRandom so this is a contained compilable unit
number[count++] = ThreadLocalRandom.current().nextInt(21);
}
for (int j = 0; j < number.length; j++) {
System.out.println(number[j]);
}
}
}
So that gets you most of the way there, the only thing you know have to do is pick a number and check your array:
public class UniqueRandoms
{
public static void main(String[] args)
{
int[] number = new int[10];
int count = 0;
while (count < number.length) {
// Use ThreadLocalRandom so this is a contained compilable unit
int candidate = ThreadLocalRandom.current().nextInt(21);
// Is candidate in our array already?
boolean exists = false;
for (int i = 0; i < count; i++) {
if (number[i] == candidate) {
exists = true;
break;
}
}
// We didn't find it, so we're good to add it to the array
if (!exists) {
number[count++] = candidate;
}
}
for (int j = 0; j < number.length; j++) {
System.out.println(number[j]);
}
}
}
The problem is with your inner 'for' loop. Once the program finds a unique integer, it adds the integer to the array and then increments the count. On the next loop iteration, the new integer will be added again because (num != number[i] && i == count), eventually filling up the array with the same integer. The for loop needs to exit after adding the unique integer the first time.
But if we look at the construction more deeply, we see that the inner for loop is entirely unnecessary.
See the code below.
import java.util.*;
public class RandomDemo {
public static void main( String args[] ){
// create random object
Random r = new Random();
int[] number = new int[10];
int count = 0;
int num;
while (count < number.length) {
num = r.nextInt(21);
boolean repeat = false;
int i=0;
do {
if (num == number[i]) {
repeat = true;
} else if (num != number[i] && i == count) {
number[count] = num;
count++;
repeat = true;
}
i++;
} while (!repeat && i < number.length);
}
for (int j = 0; j < number.length; j++) {
System.out.print(number[j] + " ");
}
}
}
This would be my approach.
import java.util.Random;
public class uniquerandom {
public static void main(String[] args) {
Random rnd = new Random();
int qask[]=new int[10];
int it,i,t=0,in,flag;
for(it=0;;it++)
{
i=rnd.nextInt(11);
flag=0;
for(in=0;in<qask.length;in++)
{
if(i==qask[in])
{
flag=1;
break;
}
}
if(flag!=1)
{
qask[t++]=i;
}
if(t==10)
break;
}
for(it=0;it<qask.length;it++)
System.out.println(qask[it]);
}}
public String pickStringElement(ArrayList list, int... howMany) {
int counter = howMany.length > 0 ? howMany[0] : 1;
String returnString = "";
ArrayList previousVal = new ArrayList()
for (int i = 1; i <= counter; i++) {
Random rand = new Random()
for(int j=1; j <=list.size(); j++){
int newRand = rand.nextInt(list.size())
if (!previousVal.contains(newRand)){
previousVal.add(newRand)
returnString = returnString + (i>1 ? ", " + list.get(newRand) :list.get(newRand))
break
}
}
}
return returnString;
}
Create simple method and call it where you require-
private List<Integer> q_list = new ArrayList<>(); //declare list integer type
private void checkList(int size)
{
position = getRandom(list.size()); //generating random value less than size
if(q_list.contains(position)) { // check if list contains position
checkList(size); /// if it contains call checkList method again
}
else
{
q_list.add(position); // else add the position in the list
playAnimation(tv_questions, 0, list.get(position).getQuestion()); // task you want to perform after getting value
}
}
for getting random value this method is being called-
public static int getRandom(int max){
return (int) (Math.random()*max);
}
I'm still very new to Java and this is an assignment for school where I'm to create a ShellSort class and driver class. The ShellSort class should create and populate an array of n size, and contains a shell sort method using the following pseudo-code:
This is the code I have so far:
import java.util.*;
public class ShellArray {
int array[] = null;
int size=0;
Random random = new Random();
int gap = 0;
public ShellArray (int size) {
this.size = size;
array=new int[size];
for (int i = 0; i<size; i++) {
this.array[i]=random.nextInt(100);
}
System.out.println("Your array is: ");
for(int i=0; i<size;i++) {
System.out.print(" " +array[i] + " ");
}
}
public int[] shellSort(int size) {
gap = size/2;
do {
boolean swapflag = true;
do {
swapflag = false;
for (int s = 0; s<(size-gap);s++) {
if (array[s] > array[s+gap]) {
//swap array[s] with array[s+gap]
swapflag = true;
}
}
}
while (swapflag != false);
}while (gap>0);
gap = gap/2;
}
public String toString () {
//to output array results of each swap
}
}
I'm lost as to how to swap array[s] with array[s+gap] and how to use toString to output array at each swap.
I've tried using a "temp" variable to put array[s] in, so I can put array[s+gap] into array[s]'s index, but I received "ShellArray#7c53a9eb" error?
Any help will be much appreciated! Thank you.
To print your array, use System.out.println(Arrays.toString(array))
To swap array element,
if (array[s] > array[s + gap]) {
int temp = array[s];
array[s] = array[s + gap];
array[s + gap] = temp;
// swap array[s] with array[s+gap]
swapflag = true;
}
In addition, it seems gap = gap/2; is should be inside the first do while loop.
I have to make a 3 way merge sort of an array. the array length is a in a power of 3, i.e. 3,9,27 etc. So I can use only one split function and not "left","mid","right".
Would like to get an answer how to repair it and why does not it work.
I have written the code, however don't know how to get it to work.
Here it is:
EDITED THE CODE, STILL DOES NOT WORK
public class Ex3 {
public static void main(String[] args) { //main function
Scanner in = new Scanner(System.in); //scanner
int size = in.nextInt();
int[] arr = new int[size];
for (int i = 0; i<arr.length; i++){
arr[i] = in.nextInt();
}
in.close();
arr = merge3sort (arr); //send to the function to merge
for (int i = 0; i<arr.length; i++){ //printer
System.out.print(arr[i]+ " ");
}
}
static int[] split(int[] m, int thirdNum) { //split function that splits to 3 arrays
int third[] = new int[m.length/3];
int third1[]=new int[m.length/3];
int third2[]=new int[m.length/3];
for(int i = 0; i<=m.length/3; i++)
third[i]=m[i];
for(int i=0; i<=m.length/3;i++)
third1[i]=m[i+thirdNum];
for(int i=0; i<=m.length/3;i++)
third2[i]=m[i+2*thirdNum];
return merge(third,third1,third2);
//return null;
}
static int minOf3(int[] a3) { //function that finds out how what is the index of the smallest number
int num0 = a3[0];
int num1 = a3[1];
int num2 = a3[2];
int idx = 0;
if(num0<num1 && num1<num2)
idx=0;
if(num1<num0 && num0<num2)
idx=1;
else
idx=2;
return idx;
}
static int[] merge(int[] th0, int[] th1, int[] th2) { //function that sorts the numbers between 3 arrays
int len0=th0.length;
int len1=th1.length;
int len2=th2.length;
int[] united = new int[len0+len1+len2];
int ind = 0; int i0=0; int i1=0; int i2=0;
while(i0<len0 && i1<len1 && i2<len2){
if(th0[i0]<th1[i1]){
if(th0[i0]<th2[i2]){
united[ind]=th0[i0];
i0=i0+1;
}//end inner if
else{
united[ind]=th2[i2];
i2=i2+1;
}//end inner else
}//end outer if
else{
united[ind]=th1[i1];
i1=i1+1;
}//end outer else
ind=ind+1;
}//end while
for (int i = i0; i < len0; i = i + 1) {
united[ind] = th0[i];
ind = ind + 1;
}
for (int i = i1; i < len1; i = i + 1) {
united[ind] = th1[i];
ind = ind + 1;
}for (int i = i2; i < len2; i = i + 1) {
united[ind] = th2[i];
ind = ind + 1;
}
return united;
}
static int[] merge3sort(int[] m) { //function that glues all together
if (m.length == 1) {
return m;
}
else{
return merge(merge3sort(split(m,m.length/3)),merge3sort(split(m,m.length/3)),merge3sort(split(m,m.length/3))); }
}
I get the following exception:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at ololosh1.Ex3.split(Ex3.java:27)
at ololosh1.Ex3.merge3sort(Ex3.java:98)
at ololosh1.Ex3.main(Ex3.java:15)
Look at this part of your code:
for(int i = 0; i<=m.length/3; i++)
third[i]=m[i];
for(int i=0; i<=m.length/3;i++)
third1[i]=m[i+thirdNum];
for(int i=0; i<=m.length/3;i++)
third2[i]=m[i+2*thirdNum];
Arrays are indexed from 0 to length-1. Each third* array has length m.length/3. Therefore their index can only go up to m.length/3 - 1. Yet you are indexing up to and including m.length/3.
Once you get your application working correctly, you really should clean it up. There is a lot of redundancy. For example, you are using the expression m.length/3 multiple times in method split() but you are also passing that same value to it as an argument.
I made a program that makes an array of random ints and doubles in size if the user tries to add an int. Example: 1|2|3|4 if they were to add another int it would look like 1|2|3|4|5|0|0|0. I have made a method to add an int which works but now I am trying to make methods that remove one of a certain int and another that removes all of a certain int. for example removeInt(3) would give me 1|2|0|4|5|0|0|0. I have the first part working so that it shifts the zero to the end like this 1|2|4|5|0|0|0|0 but cannot get it to work for more than one of the same value. Any suggestions?
// ****************************************************************
// IntegerList.java
//
// Define an IntegerList class with methods to create & fill
// a list of integers.
//
// ****************************************************************
public class IntegerList
{
int[] list; //values in the list
//-------------------------------------------------------
//create a list of the given size
//-------------------------------------------------------
public IntegerList(int size)
{
list = new int[size];
}
//-------------------------------------------------------
//fill array with integers between 1 and 100, inclusive
//-------------------------------------------------------
public void randomize()
{
for (int i=0; i<list.length; i++)
list[i] = (int)(Math.random() * 100) + 1;
}
//-------------------------------------------==----------
//print array elements with indices
//-------------------------------------------------------
public void print()
{
for (int i=0; i<list.length; i++)
System.out.println(i + ":\t" + list[i]);
}
public void addElement(int newVal){
boolean full = true;
System.out.println(list.length);
int position = 0;
int place;
while(position < list.length){
System.out.println("HERE");
if(list[position]==0){
System.out.println("here");
full = false;
place = position;
System.out.println(place);
}
position = position+1;
}
if(full == true){
list = increaseSize(list);
System.out.println("L"+list.length);
full = false;
}
for(int i = 0;i<list.length;i++){
if(list[i]==0){
if(i<position){
position = i;
System.out.println(list.length);
}
}
}
list[position] = newVal;
}
public void removeFirst(int newVal){
int position = 0;
boolean removed = false;
for(int i = 0; i<list.length;i++){
if(list[i] == newVal){
list[i]=0;
position = i;
removed = true;
break;
}
}
if(removed==true){
for(int i = position;i<list.length;i++){
if(i!=list.length-1){
list[i]=list[i+1];
}
}
list[list.length-1]= 0;
}
}
public void removeAll(int newVal){
int position = 0;
boolean removed = false;
for(int i = 0; i<list.length;i++){
if(list[i] == newVal){
list[i]=0;
position = i;
removed = true;
}
}
if(removed==true){
for(int i = 0;i<list.length;i++){
if(i!=list.length-1 && list[i+1]==newVal){
list[i]=0;
}
if(list[i]==newVal){
list[i]=0;
}
}
}
}
public static int[] increaseSize(int[] x){
int newLength = x.length *2;
int[] newx = new int[newLength];
for(int i = 0; i<x.length; i++){
newx[i] = x[i];
}
return newx;
}
public static int[] halfSize(int[] x){
int[] newx = new int[x.length / 2];
for(int i = 0; i<x.length; i++){
newx[i] = x[i];
}
return newx;
}
}
I believe there's an easier way to implement your removeAll method. Move 2 (rather than 1) indices through your array constantly shifting the values over the items you are removing;
int dest = 0;
int source = 0;
while (source < array.length) {
if (array[dest] != valueToRemove)
dest++;
array[dest] = array[source++];
}
while (dest < array.length) {
array[dest++] = 0;
}
I executed your code and found out that the problem is in this piece, under removeAll()...
if(removed){
for(int i = 0;i<list.length;i++){
if(i!=list.length-1 && list[i+1]==newVal){
list[i]=0;
}
if(list[i]==newVal){
list[i]=0;
}
}
}
If you comment out and try once, you will see the removeAll() is working and your desired number is replaced with 0s. Now why you don't simply check your numbers and shift(sorting), if they are greater than 0 to the left?
The following is NOT a homework problem, it's just a set of problems that I've been working through for practice and I was wondering if anybody else could figure it out:
http://codingbat.com/prob/p159339
Return an array that contains exactly the same numbers as the given array, but rearranged so that every 3 is immediately followed by a 4. Do not move the 3's, but every other number may move. The array contains the same number of 3's and 4's, every 3 has a number after it that is not a 3 or 4, and a 3 appears in the array before any 4.
*SOLVED - here is my working code:
public int[] fix34(int...nums)
{
int[] returnArray = new int[nums.length];
//ASSIGN ARRAY
//We know that all 3's can't be moved, and after every 3 there
//will automatically be a 4
for(int i = 0; i<nums.length; i++)
{
if(nums[i] == 3)
{
returnArray[i] = 3;
returnArray[i+1] = 4;
}
}
//REBUILD ARRAY - UNMOVED INDEXES
//If a value was not moved/affected by the above, it will get placed into the array
//in the same position
for (int i = 0; i < nums.length; i++)
{
if (returnArray[i] != 3 && returnArray[i] != 4 && nums[i] != 3 && nums[i] != 4)
{
returnArray[i] = nums[i];
}
}
//REBUILD ARRAY - MOVED INDEXES
//changed values = 0 in returnArray, as a result, any time we hit a 0 we
//can simply assign the value that was in the 4's place in the nums array
OuterLoop: for (int i = 0; i < nums.length; i++)
{
if (returnArray[i] == 0)
{
for (int n = 0; n < returnArray.length; n++)
{
if (returnArray[n] == 4)
{
returnArray[i] = nums[n];
continue OuterLoop;
}
}
}
}
return returnArray;
}
I don't know java, but maybe I can help anyway. i dont want to give you the solution, but think of it like this:
you can move every number that isn't a 3. that's our only limit. that being said:
the only spots you need to change are the spots following 3s....so....every time you loop through, your program should be aware if it finds a spot after a 3 that isn't a 4....
it should also be aware if it finds any 4s not preceded by a 3......
during each loop, once it's found the location of each of those two things, you should know what to do.
Initialize all the variables
for(int i = 0; i<n-1; i++)
{
if(arr[i] == 3)
{
if(arr[i+1] == 4)
continue;
else
{
temp = 0;
while(arr[temp] != 4)
temp++;
//Write your own code here
}
//Complete the code
}
I have NOT provided the entire code. Try completing it as you said it was for your practice.
public int[] fix34(int[] nums) {
int[] arr = new int[nums.length];
int index = 0;
int tempVal= 0,j=0;
for(int i=0;i<nums.length;i++){
if(nums[i]==3){
arr[i] = nums[i];
index=i+1;
tempVal = nums[i+1];
j=index;
while(j<nums.length){
if(j<nums.length && nums[j]==4){
//System.out.println(j+"\t="+nums[j]);
nums[j]=tempVal;
nums[index] = 4;
break;
}
j++;
}
tempVal=0;
index=0;
}else{
arr[i] = nums[i];
}
}
index =0;
for(int i=0;i<nums.length;i++){
if(nums[i]==3 && nums[i+1]==4){
i+=1;
}else if(nums[i]==4){
index = i;
j=index;
while(j<nums.length){
if(nums[j]==3 && nums[j+1]!=4){
arr[index] = nums[j+1];
arr[j+1] = 4;
}
j++;
}
}
}
return arr;
}
Here's mine: A little overkill, but is always right, anyways i make 2 additional arrays and I make 2 passes in the loop putting the correct elements in the correct places. See Logic Below.
public int[] fix34(int[] nums) {
int index1 = 0;
int index2 = 0;
int index3 = 0;
int[] only4 = fours(nums); //holds all 4's in nums
int[] misc = new int[count4(nums)]; //will hold numbers after 3
for(int a = 0; a < nums.length - 1; a++){
if(nums[a] == 3){
misc[index1] = nums[a + 1]; //get it for later use
index1++;
nums[a + 1] = only4[index2]; //now the number after 3 is a 4, from the
index2++; //only4 array
}
}
for(int b = 1; b < nums.length; b++){
if(nums[b] == 4 && nums[b - 1] != 3){ //finds misplaced 4's
nums[b] = misc[index3]; //replaces lone 4's with the
index3++; //right hand side of each 3 original values.
}
}
return nums;
}
public int count4(int[] nums){
int cnt = 0;
for(int e : nums){
if(e == 4){
cnt++;
}
}
return cnt;
}
public int[] fours(int[] nums){
int index = 0;
int[] onlyFours = new int[count4(nums)]; //must set length
for(int e : nums){
if(e == 4){
onlyFours[index] = e;
index++;
}
}
return onlyFours;
}
I solved mine using two ArrayLists which contain the places of 3's and 4's.
I hope this helps.
public int[] fix34(int[] nums)
{
//Create a copy of nums to manipulate.
int[] ret = nums;
//Create two ArrayLists which carry corresponding places of 3 and 4;
ArrayList<Integer> threePositions = new ArrayList<Integer>();
ArrayList<Integer> fourPositions = new ArrayList<Integer>();
//Get the places of 3 and 4 and put them in the respective ArrayLists.
for (int i = 0; i < ret.length; i++)
{
if (ret[i] == 3)
{
threePositions.add(i);
}
if (ret[i] == 4)
{
fourPositions.add(i);
}
}
//Swap all ints right after the 3 with one of the 4s by using the referenced
//ArrayLists values.
for (int i = 0; i < threePositions.size(); i++)
{
int temp = ret[threePositions.get(i) + 1];
ret[threePositions.get(i) + 1] = ret[fourPositions.get(i)];
ret[fourPositions.get(i)] = temp;
}
//Return the ret array.
return ret;
}