I am trying to develop a game in android that solves the boggle. At this stage i have hard-coded the 4x4 array values.
It has an activity and 2 java helper class. The problem is that when i run the java helper classes in console mode it solves the boggle perfectly. But, when i integrate in android environment it throws an error "Unfortunately, Wordgame has stopped" and stops.
The activity code is as follows:
package org.example.sudoku;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class GameActivity extends Activity {
public final static char matrix[][] =
{
{'s', 'h', 'g', 'n'},
{'u', 'e', 'o', 'o'},
{'s', 'l', 'o', 'h'},
{'k', 'l', 'd', 'p'}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
ListView list = (ListView) findViewById(R.id.list);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1);
Solver solver = null;
try {
solver = new Solver();
} catch (IOException e) {
e.printStackTrace();
}
HashSet<String> words;
words = solver.findWords(matrix, true); // The programs throws error in this line
//DO SOMETHING WITH THE VALUE OF "words"
}
}
Solver.java Class is as follow:
package org.example.sudoku;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
public class Solver {
private boolean q_is_qu_flag;
private Trie st_machine;
private HashSet<String> words_;
public Solver() throws IOException {
q_is_qu_flag = true;
st_machine = new Trie();
words_ = new HashSet<String>();
// insert dictionary words
FileInputStream fis = new FileInputStream("wordlist.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis, "UTF-8"));
String word;
while ((word = br.readLine()) != null) {
st_machine.insert(word);
}
br.close();
}
private void check(char matrix[][], boolean path[][], int i, int j) {
if (i < 0 || i >= matrix.length || j < 0 || j >= matrix[0].length)
return;
// check if it's gonna form a cycle
if (path[i][j] == true)
return;
if (!st_machine.transition_forward(matrix[i][j]))
return;
// special case 'q' becomes 'qu'
// additional transition forward
if (matrix[i][j] == 'q' && q_is_qu_flag) {
if (!st_machine.transition_forward('u'))
return;
}
// update path
path[i][j] = true;
if (st_machine.isWord())
words_.add(st_machine.path());
check(matrix, path, i-1, j-1);
check(matrix, path, i, j-1);
check(matrix, path, i+1, j-1);
check(matrix, path, i-1, j);
check(matrix, path, i+1, j);
check(matrix, path, i-1, j+1);
check(matrix, path, i, j+1);
check(matrix, path, i+1, j+1);
st_machine.transition_backward();
// pop 'q' after popping 'u'
if (matrix[i][j] == 'q' && q_is_qu_flag)
st_machine.transition_backward();
// pop off path
path[i][j] = false;
}
// Returns dictionary words found in the 2d array
// 'q' is treated as 'qu' by default
// call the overloaded method if you want 'q' to be treated as is
public HashSet<String> findWords(char matrix[][]) {
// path is used to determine cycles
boolean path[][] = new boolean[matrix.length][matrix[0].length];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
check(matrix, path, i, j);
}
}
return words_;
}
// First param: 2D array of characters
// Second param: Boolean value. If true, 'q' is treated as 'qu' else 'q' is treated as is.
// Returns dictionary words found in the 2d array
public HashSet<String> findWords(char matrix[][], boolean qIsQu) {
q_is_qu_flag = qIsQu;
return findWords(matrix);
}
}
Trie.java Class is as follow:
package org.example.sudoku;
import java.util.Stack;
public class Trie {
private class State {
boolean isWord;
State alphabet[];
private State() {
isWord = false;
alphabet = new State[26];
}
}
private State start_;
private Stack<State> state_stack;
private Stack<Character> path_;
public Trie() {
start_ = new State();
state_stack = new Stack<State>();
state_stack.push(start_);
path_ = new Stack<Character>();
}
private int charToInt(char c) {
return (int)Character.toUpperCase(c) - 65;
}
public void insert(State state, String word, int str_index) {
if (str_index == word.length()) {
state.isWord = true;
return;
}
int index = charToInt(word.charAt(str_index));
if (index < 0 || index > 25)
return;
if (state.alphabet[index] == null)
state.alphabet[index] = new State();
insert(state.alphabet[index], word, str_index+1);
}
public void insert(String word) {
word = word.toUpperCase();
this.insert(start_, word, 0);
}
public boolean transition_forward(char c) {
int transition_input = charToInt(c);
State curr_state = state_stack.peek();
if (curr_state.alphabet[transition_input] == null)
return false;
state_stack.push(curr_state.alphabet[transition_input]);
path_.push(c);
return true;
}
public boolean transition_backward() {
if (state_stack.size() > 1) {
state_stack.pop();
path_.pop();
return true;
}
return false;
}
public boolean isWord() {
return state_stack.peek().isWord;
}
public String path() {
char path[] = new char[path_.size()];
for (int i=0; i < path_.size(); i++)
path[i] = path_.get(i).charValue();
return new String(path);
}
}
AndroidManifest.xml file is as follow:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.example.sudoku"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="org.example.sudoku.GameActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
The logcat output is as follow:
11-14 02:09:54.511: D/gralloc_goldfish(1088): Emulator without GPU emulation detected.
11-14 02:11:57.461: I/Choreographer(1088): Skipped 33 frames! The application may be doing too much work on its main thread.
11-14 02:11:57.941: D/dalvikvm(1088): GC_FOR_ALLOC freed 67K, 7% free 2818K/3004K, paused 70ms, total 85ms
11-14 02:11:57.961: I/dalvikvm-heap(1088): Grow heap (frag case) to 3.471MB for 635812-byte allocation
11-14 02:11:58.081: D/dalvikvm(1088): GC_FOR_ALLOC freed 7K, 6% free 3432K/3628K, paused 112ms, total 112ms
11-14 02:11:58.251: W/System.err(1088): java.io.FileNotFoundException: /wordlist.txt: open failed: ENOENT (No such file or directory)
11-14 02:11:58.251: W/System.err(1088): at libcore.io.IoBridge.open(IoBridge.java:409)
11-14 02:11:58.251: W/System.err(1088): at java.io.FileInputStream.<init>(FileInputStream.java:78)
11-14 02:11:58.251: W/System.err(1088): at java.io.FileInputStream.<init>(FileInputStream.java:105)
11-14 02:11:58.281: W/System.err(1088): at org.example.sudoku.Solver.<init>(Solver.java:20)
11-14 02:11:58.281: W/System.err(1088): at org.example.sudoku.GameActivity.onCreate(GameActivity.java:36)
11-14 02:11:58.281: W/System.err(1088): at android.app.Activity.performCreate(Activity.java:5133)
11-14 02:11:58.301: W/System.err(1088): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
11-14 02:11:58.301: W/System.err(1088): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
11-14 02:11:58.301: W/System.err(1088): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
11-14 02:11:58.321: W/System.err(1088): at android.app.ActivityThread.access$600(ActivityThread.java:141)
11-14 02:11:58.331: W/System.err(1088): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
11-14 02:11:58.331: W/System.err(1088): at android.os.Handler.dispatchMessage(Handler.java:99)
11-14 02:11:58.341: W/System.err(1088): at android.os.Looper.loop(Looper.java:137)
11-14 02:11:58.341: W/System.err(1088): at android.app.ActivityThread.main(ActivityThread.java:5103)
11-14 02:11:58.351: W/System.err(1088): at java.lang.reflect.Method.invokeNative(Native Method)
11-14 02:11:58.351: W/System.err(1088): at java.lang.reflect.Method.invoke(Method.java:525)
11-14 02:11:58.351: W/System.err(1088): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
11-14 02:11:58.361: W/System.err(1088): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-14 02:11:58.371: W/System.err(1088): at dalvik.system.NativeStart.main(Native Method)
11-14 02:11:58.381: W/System.err(1088): Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory)
11-14 02:11:58.411: W/System.err(1088): at libcore.io.Posix.open(Native Method)
11-14 02:11:58.421: W/System.err(1088): at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
11-14 02:11:58.432: W/System.err(1088): at libcore.io.IoBridge.open(IoBridge.java:393)
11-14 02:11:58.432: W/System.err(1088): ... 18 more
11-14 02:11:58.451: D/AndroidRuntime(1088): Shutting down VM
11-14 02:11:58.451: W/dalvikvm(1088): threadid=1: thread exiting with uncaught exception (group=0x414c4700)
11-14 02:11:58.521: E/AndroidRuntime(1088): FATAL EXCEPTION: main
11-14 02:11:58.521: E/AndroidRuntime(1088): java.lang.RuntimeException: Unable to start activity ComponentInfo{org.example.sudoku/org.example.sudoku.GameActivity}: java.lang.NullPointerException
11-14 02:11:58.521: E/AndroidRuntime(1088): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
11-14 02:11:58.521: E/AndroidRuntime(1088): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
11-14 02:11:58.521: E/AndroidRuntime(1088): at android.app.ActivityThread.access$600(ActivityThread.java:141)
11-14 02:11:58.521: E/AndroidRuntime(1088): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
11-14 02:11:58.521: E/AndroidRuntime(1088): at android.os.Handler.dispatchMessage(Handler.java:99)
11-14 02:11:58.521: E/AndroidRuntime(1088): at android.os.Looper.loop(Looper.java:137)
11-14 02:11:58.521: E/AndroidRuntime(1088): at android.app.ActivityThread.main(ActivityThread.java:5103)
11-14 02:11:58.521: E/AndroidRuntime(1088): at java.lang.reflect.Method.invokeNative(Native Method)
11-14 02:11:58.521: E/AndroidRuntime(1088): at java.lang.reflect.Method.invoke(Method.java:525)
11-14 02:11:58.521: E/AndroidRuntime(1088): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
11-14 02:11:58.521: E/AndroidRuntime(1088): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-14 02:11:58.521: E/AndroidRuntime(1088): at dalvik.system.NativeStart.main(Native Method)
11-14 02:11:58.521: E/AndroidRuntime(1088): Caused by: java.lang.NullPointerException
11-14 02:11:58.521: E/AndroidRuntime(1088): at org.example.sudoku.GameActivity.onCreate(GameActivity.java:42)
11-14 02:11:58.521: E/AndroidRuntime(1088): at android.app.Activity.performCreate(Activity.java:5133)
11-14 02:11:58.521: E/AndroidRuntime(1088): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
11-14 02:11:58.521: E/AndroidRuntime(1088): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
11-14 02:11:58.521: E/AndroidRuntime(1088): ... 11 more
11-14 02:16:58.691: I/Process(1088): Sending signal. PID: 1088 SIG: 9
In the above circumstances, I would urge upon the experts to suggest me the solution to the above error.
You can't open files in Android like you can do it in the JVM on PC.
You should place your file to the your_project/res/raw
directory and then you can access it via R.raw.your_file.
Your code to open the file will look like following:
BufferedReader instream = new BufferedReader(new InputStreamReader(
context.getResources().openRawResource(R.raw.your_file)));