I have an idea and it's kind of complicated and you must be familiar with assembly and multithreading to understand why I want to do this.
Did you ever notice that the cancel button never does anything when the program you are running is in a hot loop? But if you put an if statement in the hot loop you slow it down drastically.
In the Linux kernel, processes are scheduled by a timer onto the CPU by an interrupt when the timeslice has expired. See the schedule method in kernel/sched/core.c
Now in user space in Java and C programs, you have a thread in a hot loop unless you put an if statement inside the hot loop to check an aborted flag you cannot interrupt the hot loop from user space.
Only the kernel can preempt a thread.
But I have an idea on how we can preempt a thread in C programming from a userspace.
We can disassemble a function address to a RET to get its assembly. We can therefore identify the conditional jumps of the loop. We can introduce a go-to statement of __sched_yield() after the hot loop we can identify where in memory the relative address of the Sched yield from the disassembly.
From this, we can virtually interrupt a user thread from user space. Shall need to madvise/memprotect the executable code to update the conditional jump statement to jump to the goto statement.
What do you think? How easy is this?
How to learn the size of a function
How to disassemble a function with libopcodes
How to update memory of functions
In Java, C and Rust you can preempt a thread in a hot loop by directly changing the looped variable to go beyond the loop invariant. You can do this from any thread.
You can create cancellable APIs with this approach, your cancel token can represent all the loops indexes that the code is in. So you can create profoundly responsive code. Even if you are deep in encryption or compression or uploading data. As long as you're not in a syscall.
I also pasted a C version of this sourcecode below the Java version. The Rust version is below the C version
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
public class Scheduler {
public static class KernelThread extends Thread {
public Map<LightWeightThread, Boolean> scheduled = new HashMap<>();
public void preempt() {
for (LightWeightThread thread : scheduled.keySet()) {
scheduled.put(thread, false);
for (int loop = 0 ; loop < thread.getLoops(); loop++) {
thread.preempt(loop);
}
}
}
public void addLightWeightThread(LightWeightThread thread) {
scheduled.put(thread, false);
}
public boolean isScheduled(LightWeightThread lightWeightThread) {
return scheduled.get(lightWeightThread);
}
public void run() {
while (true) {
LightWeightThread previous = null;
for (LightWeightThread thread : scheduled.keySet()) {
scheduled.put(thread, false);
}
for (LightWeightThread thread : scheduled.keySet()) {
if (previous != null) {
scheduled.put(previous, false);
}
scheduled.put(thread, true);
thread.run();
previous = thread;
}
}
}
}
public interface Preemptible {
void registerLoop(int name, int defaultValue, int limit);
int increment(int name);
boolean isPreempted(int name);
int getLimit(int name);
int getValue(int name);
void preempt(int id);
int getLoops();
}
public static abstract class LightWeightThread implements Preemptible {
public int kernelThreadId;
public int threadId;
public KernelThread parent;
AtomicInteger[] values = new AtomicInteger[1];
int[] limits = new int[1];
boolean[] preempted = new boolean[1];
int[] remembered = new int[1];
public LightWeightThread(int kernelThreadId, int threadId, KernelThread parent) {
this.kernelThreadId = kernelThreadId;
this.threadId = threadId;
this.parent = parent;
for (int i = 0 ; i < values.length; i++) {
values[i] = new AtomicInteger();
}
}
public void run() {
}
public void registerLoop(int name, int defaultValue, int limit) {
if (preempted.length > name && remembered[name] < limit) {
values[name].set(remembered[name]);
limits[name] = limit;
} else {
values[name].set(defaultValue);
limits[name] = limit;
}
preempted[name] = false;
}
public int increment(int name) {
return values[name].incrementAndGet();
}
public boolean isPreempted(int name) {
return preempted[name];
}
public int getLimit(int name) {
return limits[name];
}
public int getValue(int name) {
return values[name].get();
}
public int initialVar(int name, int value) {
values[name].set(value);
return value;
}
public void preempt(int id) {
remembered[id] = values[id].get();
preempted[id] = true;
while (!values[id].compareAndSet(values[id].get(), limits[id])){};
}
public int getLoops() {
return values.length;
}
}
public static void main(String[] args) throws InterruptedException {
List<KernelThread> kernelThreads = new ArrayList<>();
for (int i = 0; i < 5; i++) {
KernelThread kt = new KernelThread();
for (int j = 0 ; j < 5; j++) {
LightWeightThread lightWeightThread = new LightWeightThread(i, j, kt) {
#Override
public void run() {
while (this.parent.isScheduled(this)) {
System.out.println(String.format("%d %d", this.kernelThreadId, this.threadId));
registerLoop(0, 0, 10000000);
for (initialVar(0, 0); getValue(0) < getLimit(0); increment(0)) {
Math.sqrt(getValue(0));
}
if (isPreempted(0)) {
System.out.println(String.format("%d %d: %d was preempted !%d < %d", this.kernelThreadId, this.threadId, 0, values[0].get(), limits[0]));
}
}
}
};
kt.addLightWeightThread(lightWeightThread);
}
kernelThreads.add(kt);
}
for (KernelThread kt : kernelThreads) {
kt.start();
}
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
for (KernelThread kt : kernelThreads) {
kt.preempt();
}
}
}, 10, 10);
for (KernelThread kt : kernelThreads) {
kt.join();
}
}
}
This is the C version of the same thing:
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <math.h>
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct lightweight_thread {
int thread_num;
volatile int preempted;
int num_loops;
int *limit;
volatile int *value;
int *remembered;
int kernel_thread_num;
struct lightweight_thread* (*user_function) (struct lightweight_thread*);
};
struct thread_info { /* Used as argument to thread_start() */
pthread_t thread_id; /* ID returned by pthread_create() */
int thread_num; /* Application-defined thread # */
char *argv_string; /* From command-line argument */
int lightweight_threads_num;
struct lightweight_thread *user_threads;
volatile int running;
};
struct timer_thread {
pthread_t thread_id;
struct thread_info *all_threads;
int num_threads;
int lightweight_threads_num;
int delay;
volatile int running;
};
static void *
timer_thread_start(void *arg) {
int iterations = 0;
struct timer_thread *timer_thread = arg;
int msec = 0, trigger = timer_thread->delay; /* 10ms */
clock_t before = clock();
while (timer_thread->running == 1 && iterations < 100000) {
do {
for (int i = 0 ; i < timer_thread->num_threads; i++) {
for (int j = 0 ; j < timer_thread->all_threads[i].lightweight_threads_num; j++) {
// printf("Preempting kernel thread %d user thread %d\n", i, j);
timer_thread->all_threads[i].user_threads[j].preempted = 0;
}
}
for (int i = 0 ; i < timer_thread->num_threads; i++) {
for (int j = 0 ; j < timer_thread->all_threads[i].lightweight_threads_num; j++) {
// printf("Preempting kernel thread %d user thread %d\n", i, j);
for (int loop = 0; loop < timer_thread->all_threads[i].user_threads[j].num_loops; loop++) {
timer_thread->all_threads[i].user_threads[j].remembered[loop] = timer_thread->all_threads[i].user_threads[j].value[loop];
timer_thread->all_threads[i].user_threads[j].value[loop] = timer_thread->all_threads[i].user_threads[j].limit[loop];
}
}
}
clock_t difference = clock() - before;
msec = difference * 1000 / CLOCKS_PER_SEC;
iterations++;
} while ( msec < trigger && iterations < 100000 );
// printf("Time taken %d seconds %d milliseconds (%d iterations)\n",
// msec/1000, msec%1000, iterations);
}
return 0;
}
/* Thread start function: display address near top of our stack,
and return upper-cased copy of argv_string. */
static void *
thread_start(void *arg)
{
struct thread_info *tinfo = arg;
char *uargv;
printf("Thread %d: top of stack near %p; argv_string=%s\n",
tinfo->thread_num, (void *) &tinfo, tinfo->argv_string);
uargv = strdup(tinfo->argv_string);
if (uargv == NULL)
handle_error("strdup");
for (char *p = uargv; *p != '\0'; p++) {
*p = toupper(*p);
}
while (tinfo->running == 1) {
for (int i = 0 ; i < tinfo->lightweight_threads_num; i++) {
tinfo->user_threads[i].preempted = 0;
}
int previous = -1;
for (int i = 0 ; i < tinfo->lightweight_threads_num; i++) {
if (previous != -1) {
tinfo->user_threads[previous].preempted = 0;
}
tinfo->user_threads[i].preempted = 1;
tinfo->user_threads[i].user_function(&tinfo->user_threads[i]);
previous = i;
}
}
return uargv;
}
void
register_loop(int index, int value, struct lightweight_thread* m, int limit) {
if (m->remembered[index] == -1) {
m->limit[index] = limit;
m->value[index] = value;
} else {
m->limit[index] = limit;
m->value[index] = m->remembered[index];
}
}
int
lightweight_thread_function(struct lightweight_thread* m)
{
while (m->preempted != 0) {
register_loop(0, 0, m, 100000000);
for (; m->value[0] < m->limit[0]; m->value[0]++) {
sqrt(m->value[0]);
}
printf("Kernel thread %d User thread %d ran\n", m->kernel_thread_num, m->thread_num);
}
return 0;
}
struct lightweight_thread*
create_lightweight_threads(int kernel_thread_num, int num_threads) {
struct lightweight_thread *lightweight_threads =
calloc(num_threads, sizeof(*lightweight_threads));
if (lightweight_threads == NULL)
handle_error("calloc lightweight threads");
for (int i = 0 ; i < num_threads ; i++) {
lightweight_threads[i].kernel_thread_num = kernel_thread_num;
lightweight_threads[i].thread_num = i;
lightweight_threads[i].num_loops = 1;
lightweight_threads[i].user_function = lightweight_thread_function;
int *remembered = calloc(lightweight_threads[i].num_loops, sizeof(*remembered));
int *value = calloc(lightweight_threads[i].num_loops, sizeof(*value));
int *limit = calloc(lightweight_threads[i].num_loops, sizeof(*limit));
lightweight_threads[i].remembered = remembered;
lightweight_threads[i].value = value;
lightweight_threads[i].limit = limit;
for (int j = 0 ; j < lightweight_threads[i].num_loops ; j++) {
lightweight_threads[i].remembered[j] = -1;
}
}
return lightweight_threads;
}
int
main(int argc, char *argv[])
{
int s, timer_s, opt, num_threads;
pthread_attr_t attr;
pthread_attr_t timer_attr;
ssize_t stack_size;
void *res;
int timer_result;
/* The "-s" option specifies a stack size for our threads. */
stack_size = 16384ul;
num_threads = 5;
while ((opt = getopt(argc, argv, "t:")) != -1) {
switch (opt) {
case 't':
num_threads = strtoul(optarg, NULL, 0);
break;
default:
fprintf(stderr, "Usage: %s [-t thread-size] arg...\n",
argv[0]);
exit(EXIT_FAILURE);
}
}
/* Initialize thread creation attributes. */
s = pthread_attr_init(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_init");
timer_s = pthread_attr_init(&timer_attr);
if (timer_s != 0)
handle_error_en(s, "pthread_attr_init timer_s");
if (stack_size > 0) {
s = pthread_attr_setstacksize(&attr, stack_size);
int t = pthread_attr_setstacksize(&timer_attr, stack_size);
if (t != 0)
handle_error_en(t, "pthread_attr_setstacksize timer");
if (s != 0)
handle_error_en(s, "pthread_attr_setstacksize");
}
/* Allocate memory for pthread_create() arguments. */
struct thread_info *tinfo = calloc(num_threads, sizeof(*tinfo));
if (tinfo == NULL)
handle_error("calloc");
for (int tnum = 0 ; tnum < num_threads; tnum++) {
tinfo[tnum].running = 1;
}
struct timer_thread *timer_info = calloc(1, sizeof(*timer_info));
timer_info->running = 1;
timer_info->delay = 10;
timer_info->num_threads = num_threads;
if (timer_info == NULL)
handle_error("calloc timer thread");
/* Create one thread for each command-line argument. */
timer_info->all_threads = tinfo;
for (int tnum = 0; tnum < num_threads; tnum++) {
tinfo[tnum].thread_num = tnum + 1;
tinfo[tnum].argv_string = argv[0];
struct lightweight_thread *lightweight_threads = create_lightweight_threads(tnum, num_threads);
tinfo[tnum].user_threads = lightweight_threads;
tinfo[tnum].lightweight_threads_num = num_threads;
/* The pthread_create() call stores the thread ID into
corresponding element of tinfo[]. */
s = pthread_create(&tinfo[tnum].thread_id, &attr,
&thread_start, &tinfo[tnum]);
if (s != 0)
handle_error_en(s, "pthread_create");
}
s = pthread_create(&timer_info[0].thread_id, &timer_attr,
&timer_thread_start, &timer_info[0]);
if (s != 0)
handle_error_en(s, "pthread_create");
/* Destroy the thread attributes object, since it is no
longer needed. */
s = pthread_attr_destroy(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_destroy");
s = pthread_attr_destroy(&timer_attr);
if (s != 0)
handle_error_en(s, "pthread_attr_destroy timer");
/* Now join with each thread, and display its returned value. */
s = pthread_join(timer_info->thread_id, &timer_result);
if (s != 0)
handle_error_en(s, "pthread_join");
printf("Joined timer thread");
for (int tnum = 0; tnum < num_threads; tnum++) {
tinfo[tnum].running = 0;
s = pthread_join(tinfo[tnum].thread_id, &res);
if (s != 0)
handle_error_en(s, "pthread_join");
printf("Joined with thread %d; returned value was %s\n",
tinfo[tnum].thread_num, (char *) res);
free(res); /* Free memory allocated by thread */
for (int user_thread_num = 0 ; user_thread_num < num_threads; user_thread_num++) {
free(tinfo[tnum].user_threads[user_thread_num].remembered);
free(tinfo[tnum].user_threads[user_thread_num].value);
free(tinfo[tnum].user_threads[user_thread_num].limit);
}
free(tinfo[tnum].user_threads);
}
free(timer_info);
free(tinfo);
exit(EXIT_SUCCESS);
}
The Rust version uses unsafe.
extern crate timer;
extern crate chrono;
use std::sync::Arc;
use std::thread;
use std::sync::atomic::{AtomicI32, Ordering};
use std::{time};
struct LightweightThread {
thread_num: i32,
preempted: AtomicI32,
num_loops: i32,
limit: Vec<AtomicI32>,
value: Vec<AtomicI32>,
remembered: Vec<AtomicI32>,
kernel_thread_num: i32,
lightweight_thread: fn(&mut LightweightThread)
}
fn register_loop(loopindex: usize, initialValue: i32, limit: i32, _thread: &mut LightweightThread) {
if _thread.remembered[loopindex].load(Ordering::Relaxed) < _thread.limit[loopindex].load(Ordering::Relaxed) {
_thread.value[loopindex].store( _thread.remembered[loopindex].load(Ordering::Relaxed), Ordering::Relaxed);
_thread.limit[loopindex].store(limit, Ordering::Relaxed);
} else {
_thread.value[loopindex].store(initialValue, Ordering::Relaxed);
_thread.limit[loopindex].store(limit, Ordering::Relaxed);
}
}
fn lightweight_thread(_thread: &mut LightweightThread) {
register_loop(0usize, 0, 1000000, _thread);
while _thread.preempted.load(Ordering::Relaxed) == 1 {
while _thread.value[0].load(Ordering::Relaxed) < _thread.limit[0].load(Ordering::Relaxed) {
let i = _thread.value[0].load(Ordering::Relaxed);
f64::sqrt(i.into());
_thread.value[0].fetch_add(1, Ordering::Relaxed);
}
}
println!("Kernel thread {} User thread {}", _thread.kernel_thread_num, _thread.thread_num)
}
fn main() {
println!("Hello, world!");
let timer = timer::Timer::new();
static mut threads:Vec<LightweightThread> = Vec::new();
let mut thread_handles = Vec::new();
for kernel_thread_num in 1..=5 {
let thread_join_handle = thread::spawn(move || {
for i in 1..=5 {
let mut lthread = LightweightThread {
thread_num: i,
preempted: AtomicI32::new(0),
num_loops: 1,
limit: Vec::new(),
value: Vec::new(),
remembered: Vec::new(),
kernel_thread_num: kernel_thread_num.clone(),
lightweight_thread: lightweight_thread
};
lthread.limit.push(AtomicI32::new(-1));
lthread.value.push(AtomicI32::new(-1));
lthread.remembered.push(AtomicI32::new(1));
unsafe {
threads.push(lthread);
}
}
loop {
let mut previous:Option<&mut LightweightThread> = None;
unsafe {
for (_pos, current_thread) in threads.iter_mut().enumerate() {
if current_thread.kernel_thread_num != kernel_thread_num {
continue;
}
if !previous.is_none() {
previous.unwrap().preempted.store(0, Ordering::Relaxed)
}
current_thread.preempted.store(1, Ordering::Relaxed);
(current_thread.lightweight_thread)(current_thread);
previous = Some(current_thread);
// println!("Running")
}
}
} // loop forever
}); // thread
thread_handles.push(thread_join_handle);
} // thread generation
let timer_handle = thread::spawn(move || {
unsafe {
loop {
for thread in threads.iter() {
thread.preempted.store(0, Ordering::Relaxed);
}
let mut previous:Option<usize> = None;
for (index, thread) in threads.iter_mut().enumerate() {
if !previous.is_none() {
threads[previous.unwrap()].preempted.store(0, Ordering::Relaxed);
}
previous = Some(index);
for loopindex in 0..thread.num_loops {
thread.remembered[loopindex as usize].store(thread.value[loopindex as usize].load(Ordering::Relaxed), Ordering::Relaxed);
thread.value[loopindex as usize].store(thread.limit[loopindex as usize].load(Ordering::Relaxed), Ordering::Relaxed);
}
thread.preempted.store(1, Ordering::Relaxed);
}
let ten_millis = time::Duration::from_millis(10);
thread::sleep(ten_millis);
} // loop
} // unsafe
}); // end of thread
timer_handle.join();
for thread in thread_handles {
thread.join();
}
}
Related
I am working on a prime number generator that is multi-threaded. My goal for this multi-threaded process is that each process will check a single number. I do have somewhat working code, but I am having some issues with the "locking" concept in where the schedular is running 2 process's very closely to each other.
Claimed Lock: 0; Claimed Number: 75827; isPrime: false
Claimed Lock: 1; Claimed Number: 75829; isPrime: false
Claimed Lock: 2; Claimed Number: 75831; isPrime: false
Claimed Lock: 4; Claimed Number: 75835; isPrime: false
Claimed Lock: 5; Claimed Number: 75837; isPrime: false
Claimed Lock: 5; Claimed Number: 75837; isPrime: false
Claimed Lock: 3; Claimed Number: 75833; isPrime: true
Claimed Lock: 6; Claimed Number: 75839; isPrime: false.
(you can see that 2 locks - i.e. 5 get called twice - they should be disctinct)
My main goal of this program is to have 1 thread calculate 1 based prime numbers. There will be n number of threads based on what Java JVM reports back to the int cores variable inside of the code.
Here is a quick explanation of my program:
The program starts out getting the number logical cpu cores of the given computer
Creates a 2d Array of [2] [Num of CPU Cores]
Array[0][i] = Gets filled with 2k+1 (odd numbers) of potential prime numbers (doing this since 2 is the only known prime number that is even)
Array[1][i] = Gets filled with "-1" = Meaning that number is ready to be picked up by a process/thread
The program then spins up n number of threads (based on cpu core count)
A new thread that has been created is supposed to look for the next available Array[1][i] == -1 and change it to the value of 2. (2 represents a process lock and/or the number is being checked if prime or not)
-6a. The n number of child processes check if prime, and will change the Array[1][i] to either 1 or 0 (1 meaning it is prime or 0 meaning its not prime)
-6b. Child Process Terminates
Parent process - Main will busy wait until all Array[1][i] is either 1 or 0
Repeat back to step 3
What am I a missing or doing wrong with this logic? I believe I am missing something with the JVM/OS Schedular. But, I feel like I could be incorrect in this assumption as well? What could I do to remedy this issue?
Here is my Code:
Multi-Threaded Class
class MultithreadCalculate extends Thread {
public void run() {
try {
int indexNum = -1;
for (int i = 0; i < MultiThreadPrimeNumGen.cores; i++) {
if (MultiThreadPrimeNumGen.primeArray[1][i] == -1) {
MultiThreadPrimeNumGen.primeArray[1][i] = 2;
indexNum = i;
break;
}
}
boolean isPrime = true;
for (int i = 2; i < MultiThreadPrimeNumGen.primeArray[0][indexNum]; i++) {
if (MultiThreadPrimeNumGen.primeArray[0][indexNum] % i == 0) {
isPrime = false;
MultiThreadPrimeNumGen.primeArray[1][indexNum] = 0;
break;
}
}
if (isPrime) {
MultiThreadPrimeNumGen.primeArray[1][indexNum] = 1;
}
System.out.println("Thread " + Thread.currentThread().getId() + "; Claimed Lock: " + indexNum + "; Claimed Number: " + MultiThreadPrimeNumGen.primeArray[0][indexNum] + "; isPrime: " + isPrime);
}
catch (Exception e) {
System.out.println("Exception is caught");
}
}
}
Here is the main class:
public class MultiThreadPrimeNumGen {
public static int[][] primeArray;
public static int primeBase = 1;
public static int cores;
private static void fillArray() {
for (int i = 0; i < cores; i++) {
primeBase += 2;
primeArray[0][i] = primeBase;
}
for (int i = 0; i < cores; i++) {
primeArray[1][i] = -1;
}
}
public static void main(String[] args) throws FileNotFoundException {
File file = new File(System.getProperty("user.home") + "/Desktop" + "/PrimeNumber.txt");
PrintWriter out = new PrintWriter(file);
//Gets number of CPU Cores
cores = Runtime.getRuntime().availableProcessors();
System.out.println("Number of Cores: " + cores);
while (true) {
primeArray = new int[2][cores];
fillArray();
for (int i = 0; i < cores; i++) {
MultithreadCalculate multithreadCalculate = new MultithreadCalculate();
multithreadCalculate.start();
}
while (true) {
boolean flag = false;
for (int i = 0; i < cores; i++) {
if ((primeArray[1][i] == 0) || (primeArray[1][i] == 1)) {
flag = true;
} else {
flag = false;
break;
}
}
if (flag) {
break;
}
}
for (int i = 0; i < cores; i++) {
if (primeArray[1][i] == 1) {
out.println("PrimeNum: " + primeArray[0][i]);
out.flush();
}
}
}
}
}
So you want thread at the loop while filling the array:
Runnable run1 = new Runnable(){
public void run()
{
// Code to fill array
}
};
Thread thread1 = new Thread(run1);
thread1.start();
Runnable run2 = new Runnable(){
public void run()
{
// Code to fill array
}
};
Thread thread2 = new Thread2(run2);
thread2.start();
Actually, I solved my own idea without using Locks. The Idea Came from another user who posted on here: Prime Balpreet. So thank you! What I did was create getters and setters inside of the code. Here is the Modified code:
Multithreaded Class:
class MultithreadCalculate extends Thread {
int PrimeNumCalculate = -1;
int indexNum = -1;
public int getPrimeNumCalculate() {
return PrimeNumCalculate;
}
public void setPrimeNumCalculate(int primeNumCalculate) {
PrimeNumCalculate = primeNumCalculate;
}
public int getIndexNum() {
return indexNum;
}
public void setIndexNum(int indexNum) {
this.indexNum = indexNum;
}
public void run() {
try {
boolean isPrime = true;
for (int i = 2; i < getPrimeNumCalculate(); i++) {
if (getPrimeNumCalculate() % i == 0) {
isPrime = false;
MultiThreadPrimeNumGen.primeArray[0][getIndexNum()] = getPrimeNumCalculate();
MultiThreadPrimeNumGen.primeArray[1][getIndexNum()] = 0;
break;
}
}
if (isPrime) {
MultiThreadPrimeNumGen.primeArray[0][getIndexNum()] = getPrimeNumCalculate();
MultiThreadPrimeNumGen.primeArray[1][getIndexNum()] = 1;
}
System.out.println("Thread " + Thread.currentThread().getId() + "; Index: " + getIndexNum() + "; Number: " + getPrimeNumCalculate() + "; isPrime: " + isPrime);
}
catch (Exception e) {
System.out.println("Exception is caught");
}
}
}
Here is my Main Class:
public class MultiThreadPrimeNumGen {
public static int [][] primeArray;
public static int primeBase = 1;
public static int cores;
private static void fillArray() {
for (int i = 0; i < cores; i++) {
primeArray[0][i] = -1;
}
for (int i = 0; i < cores; i++) {
primeArray[1][i] = -1;
}
}
public static void main(String[] args) throws FileNotFoundException {
File file = new File(System.getProperty("user.home") + "/Desktop" + "/PrimeNumber.txt");
PrintWriter out = new PrintWriter(file);
cores = Runtime.getRuntime().availableProcessors();
System.out.println("Number of Cores: " + cores);
out.println(2);
out.flush();
while (true) {
primeArray = new int[2][cores];
fillArray();
for (int i = 0; i < cores; i++) {
MultithreadCalculate multithreadCalculate = new MultithreadCalculate();
multithreadCalculate.setPrimeNumCalculate(primeBase += 2);
multithreadCalculate.setIndexNum(i);
multithreadCalculate.start();
}
while (true) {
boolean flag = false;
for (int i = 0; i < cores; i++) {
if ((primeArray[1][i] == 0) || (primeArray[1][i] == 1)) {
flag = true;
} else {
flag = false;
break;
}
}
if (flag) {
break;
}
}
printMatrix(primeArray);
for (int i = 0; i < cores; i++) {
if (primeArray[1][i] == 1) {
out.println(primeArray[0][i]);
}
}
out.flush();
}
}
public static void printMatrix(int[][] arr) {
if (null == arr || arr.length == 0) {
return;
}
int idx = -1;
StringBuilder[] sbArr = new StringBuilder[arr.length];
for (int[] row : arr) {
sbArr[++idx] = new StringBuilder("[\t");
for (int elem : row) {
sbArr[idx].append(elem).append("\t");
}
sbArr[idx].append("]");
}
for (StringBuilder stringBuilder : sbArr) {
System.out.println(stringBuilder);
}
}
}
I am making an android Hashikawekero puzzle game, I have implemented a algorithm to spawn nodes (Islands) at random positions using a 2-d array this works fine it creates the node at random position but most of the times the map cant be solved. The map nodes spawn at random.
BoardCreation.java Class - this generates the map.
package Island_and_Bridges.Hashi;
import android.annotation.TargetApi;
import android.os.Build;
import android.util.Log;
import java.util.Random;
import static junit.framework.Assert.*;
//This class Creates the map by random using a 2d array
public class BoardCreation {
// This class member is used for random initialization purposes.
static private final Random random = new Random();
// The difficulty levels.
private static final int EASY = 0;
static public final int MEDIUM = 1;
static public final int HARD = 2;
static public final int EMPTY = 0;
private static int ConnectionFingerprint(BoardElement start, BoardElement end) {
int x = start.row * 100 + start.col;
int y = end.row * 100 + end.col;
// Swap to get always the same fingerprint independent whether we are called
// start-end or end-start
if (x > y ) {
int temp = x;
x = y;
y = temp;
}
Log.d("", String.format("%d %d" , x ,y));
return x ^ y;
}
public class State {
// The elements of the board are stored in this array.
// A value defined by "EMPTY" means that its not set yet.
public BoardElement [][] board_elements = null;
public int [][] cell_occupied = null;
// The width of the board. We only assume squared boards.
public int board_width=0;
public State(int width) {
board_width = width;
board_elements = new BoardElement[width][width];
cell_occupied = new int[width][width];
}
public State CloneWithoutConnections() {
State newstate = new State(board_width);
if (board_elements != null) {
newstate.board_elements = new BoardElement[board_elements.length][board_elements.length];
for (int i = 0; i < board_elements.length; ++i) {
for (int j = 0; j < board_elements.length; ++j) {
if (board_elements[i][j] == null)
continue;
newstate.board_elements[i][j] = board_elements[i][j].clone();
}
}
}
if (cell_occupied != null) {
assert board_elements != null;
newstate.cell_occupied = new int[board_elements.length][board_elements.length];
for (int i = 0; i < board_elements.length; ++i) {
System.arraycopy(cell_occupied[i], 0, newstate.cell_occupied[i], 0, board_elements.length);
}
}
return newstate;
}
public void AddToBridgeCache(BoardElement first, BoardElement second) {
if (first == null || second == null) { return; }
final int fingerprint = ConnectionFingerprint(first, second);
Log.d(getClass().getName(),
String.format("Fingerprint of this bridge %d", fingerprint));
// mark the end points as occupied.
cell_occupied[first.row][first.col] = fingerprint;
cell_occupied[second.row][second.col] = fingerprint;
int dcol = second.col - first.col;
int drow = second.row - first.row;
if (first.row == second.row) {
for (int i = (int) (first.col + Math.signum(dcol)); i != second.col; i += Math.signum(dcol)) {
cell_occupied[first.row][i] = fingerprint;
String.format("deleting bridge");
}
} else {
assert first.col == second.col;
for (int i = (int) (first.row + Math.signum(drow)); i != second.row; i+= Math.signum(drow)) {
cell_occupied[i][first.col] = fingerprint;
}
}
}
} // end of state
private State current_state, old_state;
static private final int WIDTH_EASY = 7;
private void NewGame(int hardness) {
switch(hardness) {
case EASY:
Log.d(getClass().getName(), "Initializing new easy game");
InitializeEasy();
old_state = getCurrentState().CloneWithoutConnections();
break;
}
}
public void ResetGame() {
if (old_state != null) {
Log.d(getClass().getName(), "Setting board_elements to old_elements");
setCurrentState(old_state.CloneWithoutConnections());
} else {
Log.d(getClass().getName(), "old_lements are zero");
}
}
public BoardCreation(int hardness) {
NewGame(hardness);
}
public boolean TryAddNewBridge(BoardElement start, BoardElement end, int count) {
assertEquals(count, 1);
assert (start != null);
assert (end != null);
final int fingerprint = ConnectionFingerprint(start, end);
Log.d(getClass().getName(),
String.format("considering (%d,%d) and (%d,%d)", start.row,start.col, end.row,end.col));
if (start.row == end.row && start.col == end.col) {
Log.d(getClass().getName(), "Same nodes selected!");
return false;
}
assert count > 0;
int dcol = end.col - start.col;
int drow = end.row - start.row;
// It must be a vertical or horizontal bridge:
if (Math.abs(dcol) > 0 && Math.abs(drow) > 0) {
Log.d(getClass().getName(), "not a horizontal or vertical bridge.");
return false;
}
// First we check whether start and end elements can take the specified bridge counts.
int count_start = start.GetCurrentCount();
int count_end = end.GetCurrentCount();
if (count_start + count > start.max_connecting_bridges ||
count_end + count > end.max_connecting_bridges) {
Log.d(getClass().getName(), "This Bridge is not allowed");
return false;
}
Log.d(getClass().getName(),
String.format("Sums:%d # (%d,%d) and %d # (%d,%d)",
count_start, start.row, start.col,
count_end, end.row, end.col));
Connection start_connection = null;
Connection end_connection = null;
// Next we check whether we are crossing any lines.
if (start.row == end.row) {
for (int i = (int) (start.col + Math.signum(dcol)); i != end.col; i += Math.signum(dcol)) {
if (getCurrentState().cell_occupied[start.row][i] > 0 &&
getCurrentState().cell_occupied[start.row][i] != fingerprint) {
Log.d(getClass().getName(), "Crossing an occupied cell.");
return false;
}
}
assert start.col != end.col;
if (start.col > end.col) {
start.connecting_east = GetOrCreateConnection(end, start.connecting_east);
end.connecting_west = GetOrCreateConnection(start, end.connecting_west);
start_connection = start.connecting_east;
end_connection = end.connecting_west;
} else {
start.connecting_west = GetOrCreateConnection(end, start.connecting_west);
end.connecting_east = GetOrCreateConnection(start, end.connecting_east);
start_connection = start.connecting_west;
end_connection = end.connecting_east;
}
} else {
assert start.col == end.col;
for (int i = (int) (start.row + Math.signum(drow)); i != end.row ; i += Math.signum(drow)) {
if (getCurrentState().cell_occupied[i][start.col] > 0 &&
getCurrentState().cell_occupied[i][start.col] != fingerprint) {
Log.d(getClass().getName(), "Crossing an occupied cell.");
return false;
}
}
if (start.row > end.row ) {
start.connecting_north = GetOrCreateConnection(end, start.connecting_north);
end.connecting_south = GetOrCreateConnection(start, end.connecting_south);
start_connection = start.connecting_north;
end_connection = end.connecting_south;
} else {
start.connecting_south= GetOrCreateConnection(end, start.connecting_south);
end.connecting_north = GetOrCreateConnection(start, end.connecting_north);
start_connection = start.connecting_south;
end_connection = end.connecting_north;
}
}
start_connection.destination = end;
end_connection.destination = start;
start_connection.second += count;
end_connection.second += count;
getCurrentState().AddToBridgeCache(start, end);
Log.d(getClass().getName(),
String.format("New bridge added. Sums:%d # (%d,%d) and %d # (%d,%d)",
count_start, start.row,start.col,
count_end, end.row,end.col));
return true;
}
private Connection GetOrCreateConnection(
BoardElement end,
Connection connection) {
if (connection!= null) { return connection; }
return new Connection();
}
#TargetApi(Build.VERSION_CODES.N)
private void InitializeEasy() {
Random rand = new Random();
String[][] debug_board_state = new String[7][7];
setCurrentState(new State(WIDTH_EASY));
for (int row = 0; row < debug_board_state.length; row++) {
for (int column = 0; column < debug_board_state[row].length; column++) {
debug_board_state[row][column] = String.valueOf(rand.nextInt(5));
}
}
for (int row = 0; row < debug_board_state.length; row++) {
for (int column = 0; column < debug_board_state[row].length; column++) {
System.out.print(debug_board_state[row][column] + " ");
}
System.out.println();
}
for (int row = 0; row < WIDTH_EASY; ++row) {
for (int column = 0; column < WIDTH_EASY; ++column) {
getCurrentState().board_elements[row][column] = new BoardElement();
getCurrentState().board_elements[row][column].max_connecting_bridges = Integer.parseInt(debug_board_state[row][column]);
getCurrentState().board_elements[row][column].row = row;
getCurrentState().board_elements[row][column].col = column;
if (getCurrentState().board_elements[row][column].max_connecting_bridges > 0) {
getCurrentState().board_elements[row][column].is_island = true;
}
}
}
}
private void setCurrentState(State new_state) {
this.current_state = new_state;
}
public State getCurrentState() {
return current_state;
}
}
What algorithm could I use to make sure the Map can be Solved (Islands Connected with Bridges) before spawning the nodes.
This is what the map looks like (don't mind the design)
One thing to consider would be to start with a blank board. Place an island. Then place another island that can be connected to the first one (i.e. on one of the four cardinal directions). Connect the two with a bridge, and increment each island's count.
Now, pick one of the two islands and place another island that it can connect. Add the bridge and increment.
Continue in this way until you've placed the number of islands that you want to place.
The beauty here is that you start with an empty board, and during construction the board is always valid.
You'll have to ensure that you're not crossing bridges when you place new islands, but that's pretty easy to do, since you know where the existing bridges are.
The following is my Brute force code for Sudoku:
public abstract class SudokuBoard
{
protected int ROWS = 9;
protected int COLS = 9;
int solutionsCounter;
double startTime;
double endTime;
String[] data = new String[8];
int puzzleNum = countTotalRows();
// data accessors
public abstract int get(int r, int c);
public abstract void set(int r, int c, int v);
// specific constraints checker, returns true even if the values are not complete
abstract boolean isRowCompatible(int r, int c);
abstract boolean isColCompatible(int r, int c);
abstract boolean isBoxCompatible(int r, int c);
// returns true if element S[r,c] is compatible, even if some values arount it are not filled
public boolean isCompatible(int r, int c)
{
for (int i=0; i<ROWS; i++)
for (int j=0; j<COLS; j++)
if(! (isRowCompatible(r, c) && isColCompatible(r, c) && isBoxCompatible(r, c)))
return false;
return true;
}
// this is the one called to solve the sudoku
public void solve()
{
//convert to seconds
startTime = System.nanoTime() / 1000000000.0;
solve(1,1);
}
// function to incorporate clues
public void incorporateClues(int[] clues)
{
for (int i=0; i<clues.length; i++)
set(clues[i]/100, (clues[i]%100)/10, clues[i]%10);
}
// the recursive backtracking function that does the hardwork
void solve(int r, int c)
{
while (((System.nanoTime() / 1000000000.0) - startTime) < 10) {
System.out.println("Time: " + ((System.nanoTime() / 1000000000.0) - startTime));
if (r<=9 && c<=9)
{
if (get(r,c) == 0)
{
for (int v=1; v<=COLS; v++)
{
set(r,c,v);
if (isCompatible(r,c))
solve((c==9)?(r+1):r, (c==9)?1:(c+1));
}
set(r, c, 0);
}
else
solve((c==9)?(r+1):r, (c==9)?1:(c+1));
}
else
{
solutionsCounter = solutionsCounter + 1;
//convert to seconds
endTime = System.nanoTime() / 1000000000.0;
// print();
}
}
}
// sample display function
void print()
{
for(int i=1; i<=ROWS; i++)
{
for (int j=1; j<=COLS; j++)
System.out.print(get(i,j));
System.out.println();
}
System.out.println("count: " + solutionsCounter);
}
void saveData (String[] data) throws java.io.IOException
{
try
{
java.io.BufferedWriter outfile = new java.io.BufferedWriter(new java.io.FileWriter("15-clue_results.csv", true));
for (int i = 0; i < data.length; i++) {
outfile.write(String.valueOf(data[i]));
outfile.append(',');
}
outfile.append('\n');
outfile.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
static int countTotalRows () {
int count = 0;
try
{
java.io.BufferedReader bufferedReader = new java.io.BufferedReader(new java.io.FileReader("15-clue_results.csv"));
String input;
while((input = bufferedReader.readLine()) != null)
{
count = count + 1;
}
} catch (java.io.IOException e) {
e.printStackTrace();
}
return count;
}
public static void main(String []arg)
{
int numClues;
try {
java.io.BufferedReader csvFile = new java.io.BufferedReader(new java.io.FileReader("clue_set"));
String dataRow;
while ((dataRow = csvFile.readLine()) != null) {
SudokuBoard board = new SB_IntMatrix();
String[] stringSet = new String[15];
int[] PUZZLE1 = new int[15];
board.puzzleNum = board.puzzleNum + 1;
stringSet = dataRow.split(" ");
for (int i = 0; i < stringSet.length; i++) {
PUZZLE1[i] = Integer.parseInt(stringSet[i]);
}
board.incorporateClues(PUZZLE1);
for (int i = 0; i < 1; i++) {
board.solutionsCounter = 0;
board.solve();
board.data[0] = Integer.toString(board.puzzleNum);
board.data[1] = dataRow;
board.data[2] = Integer.toString(board.solutionsCounter);
board.data[3 + i] = Double.toString(board.endTime - board.startTime);
}
try
{
board.saveData(board.data);
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
csvFile.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
}
The requirement is to limit the solving time of solve(int r, int c) to only 1 hour.
To do this, I tried to put it inside a while loop while (((System.nanoTime() / 1000000000.0) - startTime) < 10) . The number 10 is to just test the code.
I understand that I looped it only 5 times in main method but, it resets back to 0 always and never stops and exceeds the limit of my loop in main.
You should use a Future:
final ExecutorService executor = Executors.newFixedThreadPool(4);
final Future<Boolean> future = executor.submit(() -> {
// Call solve here
return true;
});
future.get(60, TimeUnit.MINUTES); // Blocks
You can do something like:
Init the start date:
LocalDateTime startDateTime = LocalDateTime.now();
And check if 1 hour has elapsed:
LocalDateTime toDateTime = LocalDateTime.now();
if (Duration.between(startDateTime, toDateTime).toHours() > 0) {
// stop the execution
}
I need to implement a "round-robin" scheduler with a job class that I cannot modify. Round-robin scheduler should process the job that has been waiting the longest first, then reset timer to zero. If two jobs have same wait time, lower id is processed first. The job class only gives three values (job id, remaining duration, and priority(which is not needed for this). each job has a start time, so only a couple of jobs may be available during first cycle, few more next cycle, etc. Since the "job array" I am calling is different every time I call it, I'm not sure how to store the wait times.
This is the job class:
public class Jobs{
private int[] stas = new int[0];
private int[] durs = new int[0];
private int[] lefs = new int[0];
private int[] pris = new int[0];
private int[] fins = new int[0];
private int clock;
public Jobs()
{
this("joblist.csv");
}
public Jobs(String filename)
{
BufferedReader fp = null;
String line = "";
String[] b = null;
int[] tmp;
try
{
fp = new BufferedReader(new FileReader(filename));
while((line = fp.readLine()) != null)
{
b = line.split(",");
if(b.length == 3)
{
try
{
int sta = Integer.parseInt(b[0]);
//System.out.println("sta: " + b[0]);
int dur = Integer.parseInt(b[1]);
//System.out.println("dur: " + b[1]);
int pri = Integer.parseInt(b[2]);
//System.out.println("pri: " + b[2]);
stas = app(stas, sta);
//System.out.println("stas: " + Arrays.toString(stas));
durs = app(durs, dur);
//System.out.println("durs: " + Arrays.toString(durs));
lefs = app(lefs, dur);
//System.out.println("lefs: " + Arrays.toString(lefs));
pris = app(pris, pri);
//System.out.println("pris: " + Arrays.toString(pris));
fins = app(fins, -1);
//System.out.println("fins: " + Arrays.toString(fins));
}
catch(NumberFormatException e) {}
}
}
fp.close();
}
catch(FileNotFoundException e) { e.printStackTrace(); }
catch(IOException e) { e.printStackTrace(); }
clock = 0;
}
public boolean done()
{
boolean done = true;
for(int i=0; done && i<lefs.length; i++)
if(lefs[i]>0) done=false;
return done;
}
public int getClock() { return clock; }
public int[][] getJobs()
{
int count = 0;
for(int i=0; i<stas.length; i++)
if(stas[i]<=clock && lefs[i]>0)
count++;
int[][] jobs = new int[count][3];
count = 0;
for(int i=0; i<stas.length; i++)
if(stas[i]<=clock && lefs[i]>0)
{
jobs[count] = new int[]{i, lefs[i], pris[i]};
count++;
}
return jobs;
}
public int cycle() { return cycle(-1); }
public int cycle(int j)
{
if(j>=0 && j<lefs.length && clock>=stas[j] && lefs[j]>0)
{
lefs[j]--;
if(lefs[j] == 0) fins[j] = clock+1;
}
clock++;
return clock;
}
private int[] app(int[] a, int b)
{
int[] tmp = new int[a.length+1];
for(int i=0; i<a.length; i++) tmp[i] = a[i];
tmp[a.length] = b;
return tmp;
}
public String report()
{
String r = "JOB,PRIORITY,START,DURATION,FINISH,DELAY,PRI*DELAY\n";
float dn=0;
float pdn=0;
for(int i=0; i<stas.length; i++)
{
if(fins[i]>=0)
{
int delay = ((fins[i]-stas[i])-durs[i]);
r+= ""+i+","+pris[i]+","+stas[i]+","+durs[i]+","+fins[i]+","+delay+","+(pris[i]*delay)+"\n";
dn+= delay;
pdn+= pris[i]*delay;
}
else
{
int delay = ((clock*10-stas[i])-durs[i]);
r+= ""+i+","+pris[i]+","+stas[i]+","+durs[i]+","+fins[i]+","+delay+","+(pris[i]*delay)+"\n";
dn+= delay;
pdn+= pris[i]*delay;
}
}
if(stas.length>0)
{
r+= "Avg,,,,,"+(dn/stas.length)+","+pdn/stas.length+"\n";
}
return r;
}
public String toString()
{
String r = "There are "+stas.length+" jobs:\n";
for(int i=0; i<stas.length; i++)
{
r+= " JOB "+i+": START="+stas[i]+" DURATION="+durs[i]+" DURATION_LEFT="+lefs[i]+" PRIORITY="+pris[i]+"\n";
}
return r;
}
I don't need full code, just an idea of how to store wait times and cycle the correct job.
While a array based solution 'may' work, I would advocate a more object oriented approach. Create 'Job' class with the desire attributes (id, start_time, wait etc). Using the csv file, create Job objects and hold them in a list. Write a comparator to sort this jobs-list (in this case based on job wait/age would be the factor).
The job executor then has to do the following:
while(jobs exist) {
iterate on the list {
if job is executable // start_time > current sys_time
consume cycles/job for executable jobs
mark completed jobs (optional)
}
remove the completed jobs
}
//\ This loop will add +1 to each job
for(int i = 0; i < jobs.length; i++)
{
waitTime[jobs[i][0]] += 1;
}
int longestWait = 0;//\ This holds value for greatest wait time
int nextJob = 0; //\ This holds value for index of job with greatest wait time
//\ this loop will check for the greatest wait time and and set variables accordingly
for(int i = 0; i < waitTime.length; i++)
{
if(waitTime[i] > longestWait)
{
longestWait = waitTime[i];
nextJob = i;
}
}
//\ this cycles the job with the highest wait time
jobsource.cycle(nextJob);
//\ this resets the wait time for processed job
waitTime[nextJob] = 0;
I'm trying to make a 2d array of an object in java. This object in java has several private variables and methods in it, but won't work. Can someone tell me why and is there a way I can fix this?
This is the exeception I keep getting for each line of code where I try to initialize and iterate through my 2d object.
"Exception in thread "main" java.lang.NullPointerException
at wumpusworld.WumpusWorldGame.main(WumpusWorldGame.java:50)
Java Result: 1"
Here is my main class:
public class WumpusWorldGame {
class Agent {
private boolean safe;
private boolean stench;
private boolean breeze;
public Agent() {
safe = false;
stench = false;
breeze = false;
}
}
/**
* #param args
* the command line arguments
* #throws java.lang.Exception
*/
public static void main(String [] args) {
// WumpusFrame blah =new WumpusFrame();
// blah.setVisible(true);
Scanner input = new Scanner(System.in);
int agentpts = 0;
System.out.println("Welcome to Wumpus World!\n ******************************************** \n");
//ArrayList<ArrayList<WumpusWorld>> woah = new ArrayList<ArrayList<WumpusWorld>>();
for (int i = 0 ; i < 5 ; i++) {
WumpusWorldObject [] [] woah = new WumpusWorldObject [5] [5];
System.out.println( "*********************************\n Please enter the exact coordinates of the wumpus (r and c).");
int wumpusR = input.nextInt();
int wumpusC = input.nextInt();
woah[wumpusR][wumpusC].setPoints(-3000);
woah[wumpusR][wumpusC].setWumpus();
if ((wumpusR <= 5 || wumpusC <= 5) && (wumpusR >= 0 || wumpusC >= 0)) {
woah[wumpusR][wumpusC].setStench();
}
if (wumpusC != 0) {
woah[wumpusR][wumpusC - 1].getStench();
}
if (wumpusR != 0) {
woah[wumpusR - 1][wumpusC].setStench();
}
if (wumpusC != 4) {
woah[wumpusR][wumpusC + 1].setStench();
}
if (wumpusR != 4) {
woah[wumpusR + 1][wumpusC].setStench();
}
System.out.println( "**************************************\n Please enter the exact coordinates of the Gold(r and c).");
int goldR = input.nextInt();
int goldC = input.nextInt();
woah[goldR][goldC].setGold();
System.out.println("***************************************\n How many pits would you like in your wumpus world?");
int numPits = input.nextInt();
for (int k = 0 ; k < numPits ; k++) {
System.out.println("Enter the row location of the pit");
int r = input.nextInt();
System.out.println("Enter the column location of the pit");
int c = input.nextInt();
woah[r][c].setPit();
if ((r <= 4 || c <= 4) && (r >= 0 || c >= 0)) {
woah[r][c].setBreeze();
}
if (c != 0) {
woah[r][c - 1].setBreeze();
}
if (r != 0) {
woah[r - 1][c].setBreeze();
}
if (c != 4) {
woah[r][c + 1].setBreeze();
}
if (r != 4) {
woah[r + 1][c].setBreeze();
}
}
for (int x = 0 ; x < 4 ; x++) {
int j = 0;
while (j < 4) {
agentpts = agentpts + woah[x][j].getPoints();
Agent [] [] k = new Agent [4] [4];
if (woah[x][j].getWumpus() == true) {
agentpts = agentpts + woah[x][j].getPoints();
System.out.println("You just got ate by the wumpus!!! THE HORROR!! Your score is " + agentpts);
}
if (woah[x][j].getStench() == true) {
k[x][j].stench = true;
System.out.println("You smell something funny... smells like old person.");
}
if (woah[x][j].getBreeze() == true) {
k[x][j].breeze = true;
System.out.println("You hear a breeze. yeah");
}
if (woah[x][j].getPit() == true) {
agentpts = agentpts + woah[x][j].getPoints();
System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH! you dumb bith, your dead now.");
}
// if breeze or stench, if breeze and stench, if nothing, etc then move.
k[x][j].safe = true;
// if(k[i][j].isSafe()!=true){
// } else { }
}
}
}
}
}
Here is my class object that I'm trying to implement:
package wumpusworld;
/**
*
* #author Jacob
*/
public class WumpusWorldObject {
private boolean stench;
private boolean breeze;
private boolean pit;
private boolean wumpus;
private boolean gold;
private int points;
private boolean safe;
public WumpusWorldObject(){
}
public boolean getPit() {
return pit;
}
public void setPit() {
this.pit = true;
}
public boolean getWumpus() {
return wumpus;
}
public void setWumpus() {
this.wumpus = true;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
public boolean getStench() {
return stench;
}
public void setStench() {
this.stench = true;
}
public boolean getBreeze() {
return breeze;
}
public void setBreeze() {
this.breeze = true;
}
public boolean getSafe() {
return safe;
}
public void setSafe() {
this.safe = true;
}
public void setGold(){
this.gold=true;
}
}
Creating array doesn't mean it will be automatically filled with new instances of your class. There are many reasons for that, like
which constructor should be used
what data should be passed to this constructor.
This kind of decisions shouldn't be made by compiler, but by programmer, so you need to invoke constructor explicitly.
After creating array iterate over it and fill it with new instances of your class.
for (int i=0; i<yourArray.length; i++)
for (int j=0; j<yourArray[i].length; j++)
yourArray[i][j] = new ...//here you should use constructor
AClass[][] obj = new AClass[50][50];
is not enough, you have to create instances of them like
obj[i][j] = new AClass(...);
In your code the line
woah[wumpusR][wumpusC].setPoints(-3000);
must be after
woah[wumpusR][wumpusC] = new WumpusWorldObject();
.