SudCell suds[][] = new SudCell[NUM_VALS][NUM_VALS];
that creates a two-dimensional array of nulls. That's an important point to remember with Java. When you try to work with one of those values, you instantly get a NullPointerException. You need to instantiate each element of the array using "new SudCell()" before you reference it.
Because that calls suds[x][y].SetToBlank(); for each array element, but these are still all null as Greg said. In your constructor you need to add a block to initialize the array elements: suds[x][y] = new SudCell();
Java naming conventions: Standard Java naming conventions include starting method and variable names with a lower-case letter. Doing otherwise makes code more difficult to read than necessary.
Simplify logic expressions:Code organization: Put separate classes in separate files. To do otherwise obfuscates the logical separation of functionality, and makes navigation more difficult than necessary on both editing and cognitive levels.
Simplify flow: Consider your boolean RuleOut(int) method: first, every single path returns false. You only need one return, outside of any conditional. Second, pay attention to what you're doing: do you see any relationship between the val being passed in and the array index you're setting? This is a two-line method, unless the logic is completely wrong--which is possible, because a boolean method that always returns false doesn't need to return *anything*.
Particularly when trying to get help from people it's really important to keep things as simple, clear, and concise as possible. For your *own* benefit as well--code that's easy to read is easier to debug, understand, explain, extend, etc.
You're going to get a lot more errors--you're trying to test things that are going to throw runtime exceptions.
Right now it seems to me like you wrote everything at once without running *anything* -- the main method isn't going to get passed the forcedSet(-1) line before crashing.
Start small. Test as you go. Look for ways to simplify what you're doing--don't just blindly throw code at a problem without taking the time to reflect on what you've just written. Be consistent in conventions. Localize functionality. Make sure you're not doing more work than necessary; simple example:Here you're both not being consistent and doing more work than necessary--if the valuePresent(1) call is going to print correctly, why bother with the Boolean.toString(...) wrapping of the others? (And consider printf :)
I'm finding the code very difficult to follow as I bang on it, it's not clear to me what the intent of many things are. These things are fixable without a huge amount of effort.
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.