/src/clarknova/software/sumdokusolver/AndroidSumdokuSolver.java

https://bitbucket.org/ClarkNovaSoftware/android-sumdoku-solver · Java · 1343 lines · 1028 code · 183 blank · 132 comment · 128 complexity · 8a4c1aa08e5499e55f6218793bc96c1c MD5 · raw file

  1. package clarknova.software.sumdokusolver;
  2. import java.util.Vector;
  3. import android.app.Activity;
  4. import android.app.AlertDialog;
  5. import android.app.Dialog;
  6. import android.content.Context;
  7. import android.content.DialogInterface;
  8. import android.content.Intent;
  9. import android.graphics.Color;
  10. import android.os.AsyncTask;
  11. import android.os.Bundle;
  12. import android.os.Handler;
  13. import android.util.Log;
  14. import android.view.Display;
  15. import android.view.Menu;
  16. import android.view.MenuInflater;
  17. import android.view.MenuItem;
  18. import android.view.View;
  19. import android.view.ViewGroup.LayoutParams;
  20. import android.view.Window;
  21. import android.widget.Button;
  22. import android.widget.RelativeLayout;
  23. import android.widget.SeekBar;
  24. import android.widget.TableLayout;
  25. import android.widget.TableRow;
  26. import android.widget.TextView;
  27. import android.widget.Toast;
  28. public class AndroidSumdokuSolver extends Activity {
  29. public final static String MODE = "clarknova.software.sumdokusolver.mode";
  30. private boolean isReleaseVersion = true;
  31. // private boolean isReleaseVersion = false;
  32. public final static int SAVE = 1;
  33. public final static int LOAD = 2;
  34. public static Activity activity;
  35. public final static String TAG = "sumdoku";
  36. public static final String NAME = "name";
  37. private static final String FIELDSTATE = "field state";
  38. public static final int NOTCOMPLETE = 0;
  39. public static final int SOLVED = 1;
  40. public static final int EMPTYCELL = -1;
  41. public static final int WRONGTOTALSUM = -2;
  42. private static final int OK = 1;
  43. public Calculate calculate = new Calculate();
  44. public Solve solve = new Solve(this);
  45. public Toast toast;
  46. public Button get_sum_button, remove_button, solve_button;
  47. private int sumdoku_size=Calculate.SUMDOKU_SIZE;
  48. private int fieldwidth;
  49. public TableLayout field;
  50. public RelativeLayout rLayout;
  51. private int current_sum;
  52. private Sum sum_back = new Sum(0, this);
  53. public Data data = new Data(this);
  54. public Vector<Integer> selected_cells = new Vector<Integer>();
  55. public Vector<CellView> cells = new Vector<CellView>();
  56. private View sumbuttonsLayout;
  57. private DBAdapter db = new DBAdapter(this);
  58. private SolveTask solution;
  59. private GetField getfield;
  60. private SaveField savefield;
  61. public Dialog waitdialog;
  62. private Data data_back = new Data(this);
  63. private boolean doubleBackToExitPressedOnce;
  64. /** Called when the activity is first created. */
  65. @Override
  66. public void onCreate(Bundle savedInstanceState) {
  67. super.onCreate(savedInstanceState);
  68. activity = this;
  69. toast = Toast.makeText(getApplicationContext(), "",Toast.LENGTH_SHORT);
  70. toast.setText("");
  71. toast.show();
  72. toast.cancel();
  73. setContentView(R.layout.main);
  74. presetScreen();
  75. loadsavedstate();
  76. }
  77. private void loadsavedstate() {
  78. loadfield(FIELDSTATE);
  79. }
  80. // @Override
  81. // public void onPause(){
  82. // super.onPause();
  83. // InputMethodManager imm = (InputMethodManager) getSystemService (Context.INPUT_METHOD_SERVICE);
  84. // imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
  85. // }
  86. //
  87. @Override
  88. public void onActivityResult(int requestCode,int resultCode,Intent data)
  89. {
  90. super.onActivityResult(requestCode, resultCode, data);
  91. if (data == null){
  92. Log.v(TAG, "No result data");
  93. return;
  94. }
  95. String save_name = data.getStringExtra(NAME);
  96. Log.d("myLogs", "requestCode = " + requestCode + ", resultCode = " + resultCode);
  97. if (resultCode == RESULT_OK) {
  98. switch (requestCode) {
  99. case SAVE:
  100. Log.v(TAG, "onActivityResult save "+save_name);
  101. savefield(save_name);
  102. break;
  103. case LOAD:
  104. Log.v(TAG, "onActivityResult load "+save_name);
  105. loadfield(save_name);
  106. break;
  107. default:
  108. Log.v(TAG, "Use requestCodes!");
  109. }
  110. } else {
  111. Log.v(TAG, "Wrong result");
  112. }
  113. }
  114. // @Override
  115. // public boolean onKeyDown(int keycode, KeyEvent e) {
  116. // switch(keycode) {
  117. // case KeyEvent.KEYCODE_BACK:
  118. // if (!selected_cells.isEmpty()){
  119. // cancel_selection();
  120. // }
  121. // else this.finish();
  122. // return true;
  123. // }
  124. //
  125. // return super.onKeyDown(keycode, e);
  126. // }
  127. @Override
  128. public void onBackPressed() {
  129. if (!selected_cells.isEmpty()){
  130. cancel_selection();
  131. return;
  132. }
  133. if (doubleBackToExitPressedOnce) {
  134. super.onBackPressed();
  135. return;
  136. }
  137. this.doubleBackToExitPressedOnce = true;
  138. Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
  139. new Handler().postDelayed(new Runnable() {
  140. @Override
  141. public void run() {
  142. doubleBackToExitPressedOnce=false;
  143. }
  144. }, 2000);
  145. }
  146. //----=== START FUNCTIONS ===----
  147. // @SuppressWarnings("deprecation")
  148. private void presetScreen() {
  149. Display display = getWindowManager().getDefaultDisplay();
  150. rLayout = (RelativeLayout) findViewById(R.id.mainLayout);
  151. /*if (android.os.Build.VERSION.SDK_INT >= 13){
  152. Point size = new Point();
  153. display.getSize(size);
  154. fieldwidth = Math.min(size.x,size.y);
  155. }*/
  156. //else {
  157. fieldwidth = Math.min(display.getHeight(), display.getWidth());
  158. //}
  159. createtable();
  160. sumbuttonsLayout=findViewById(R.id.sum_buttons);
  161. get_sum_button = (Button) findViewById(R.id.button_get_sum);
  162. remove_button = (Button) findViewById(R.id.button_remove);
  163. solve_button = (Button) findViewById(R.id.button_solve);
  164. get_sum_button.setOnClickListener(new View.OnClickListener() {
  165. public void onClick(View v) {
  166. Log.v(TAG, "USER ACTION: OkClick");
  167. okClick(v);}
  168. });
  169. remove_button.setOnClickListener(new View.OnClickListener() {
  170. public void onClick(View v) {
  171. Log.v(TAG, "USER ACTION: ClearClick");
  172. removeClick(v);}
  173. });
  174. solve_button.setOnClickListener(new View.OnClickListener() {
  175. public void onClick(View v) {
  176. Log.v(TAG, "USER ACTION: SolveClick");
  177. solveClick(v);
  178. }
  179. });
  180. }
  181. private void createtable() {
  182. int cellsize = (fieldwidth-sumdoku_size-1)/(sumdoku_size);
  183. int fieldsize = sumdoku_size*cellsize+sumdoku_size+1;
  184. Log.v(TAG, "fieldwidth: "+fieldwidth+", fieldsize:"+fieldsize+", cellsize:"+cellsize);
  185. field = new TableLayout(this);
  186. rLayout.addView(field);
  187. RelativeLayout.LayoutParams tParams = (RelativeLayout.LayoutParams)field.getLayoutParams();
  188. tParams.width=fieldsize;
  189. tParams.height=fieldwidth;
  190. field.setLayoutParams(tParams);
  191. cells.clear();
  192. View b = new View(this);
  193. field.addView(b,new TableLayout.LayoutParams
  194. (fieldsize,(fieldwidth-fieldsize)/2));
  195. b.setBackgroundColor(Color.WHITE);
  196. b = new View(this);
  197. field.addView(b,new TableLayout.LayoutParams
  198. (fieldsize,1));
  199. b.setBackgroundColor(Color.BLACK);
  200. for (int i=0;i<sumdoku_size;i++){
  201. TableRow row = new TableRow(this);
  202. b = new View(this);
  203. row.addView(b,new TableRow.LayoutParams
  204. (1,cellsize));
  205. b.setBackgroundColor(Color.BLACK);
  206. for(int k=0; k<sumdoku_size; k++){
  207. final CellView cell = new CellView(this);
  208. cell.setTag(""+i+""+k);
  209. cells.add(cell);
  210. row.addView(cell);
  211. TableRow.LayoutParams params =
  212. (TableRow.LayoutParams)cell.getLayoutParams();
  213. params.width = cellsize;
  214. params.height = cellsize;
  215. cell.setLayoutParams(params);
  216. b = new View(this);
  217. row.addView(b,new TableRow.LayoutParams
  218. (1,cellsize));
  219. if ((k+1)%3==0){
  220. b.setBackgroundColor(Color.BLACK);
  221. }
  222. else {b.setBackgroundColor(Color.LTGRAY);}
  223. }
  224. field.addView(row,
  225. new TableLayout.LayoutParams
  226. (LayoutParams.WRAP_CONTENT
  227. ,LayoutParams.WRAP_CONTENT));
  228. b = new View(this);
  229. field.addView(b,new TableLayout.LayoutParams
  230. (fieldsize, 1));
  231. if ((i+1)%3==0){
  232. b.setBackgroundColor(Color.BLACK);
  233. }
  234. // if (i==sumdoku_size/3-1 ||i==2*sumdoku_size/3-1){
  235. // b.setBackgroundColor(Color.BLACK);
  236. // }
  237. else {b.setBackgroundColor(Color.LTGRAY);}
  238. }
  239. b = new View(this);
  240. field.addView(b,new TableLayout.LayoutParams
  241. (fieldsize,(fieldwidth-fieldsize)/2));
  242. b.setBackgroundColor(Color.WHITE);
  243. RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) field.getLayoutParams();
  244. params.addRule(RelativeLayout.CENTER_HORIZONTAL);
  245. field.setLayoutParams(params);
  246. field.invalidate();
  247. //Log.v(TAG, "Table is set");
  248. }
  249. //----=== USER ACTIONS ===----
  250. public void removeClick(View v) {
  251. //TODO: do different things!
  252. AlertDialog.Builder builder = new AlertDialog.Builder(this);
  253. builder.setTitle(R.string.title_remove_sum)
  254. .setItems(R.array.array_remove_sum, new DialogInterface.OnClickListener() {
  255. public void onClick(DialogInterface dialog, int which) {
  256. switch (which) {
  257. case 0:
  258. //Remove Sum
  259. if (!selected_cells.isEmpty()){
  260. Sum sum = data.getsum(selected_cells.firstElement());
  261. data.getsums().removeElement(sum);
  262. disborder(selected_cells);
  263. //clearselection();
  264. }
  265. dialog.cancel();
  266. break;
  267. case 1:
  268. //Remove Values
  269. for (int cell_num : selected_cells) {
  270. data.setValue(0, cell_num);
  271. cells.elementAt(calculate.num_to_location(cell_num)).clearvalue();
  272. }
  273. // clearselection();
  274. dialog.cancel();
  275. break;
  276. case 2:
  277. //Remove all
  278. if (!selected_cells.isEmpty()){
  279. for (int cell_num : selected_cells) {
  280. data.setValue(0, cell_num);
  281. cells.elementAt(calculate.num_to_location(cell_num)).clearvalue();
  282. }
  283. Sum sum = data.getsum(selected_cells.firstElement());
  284. data.getsums().removeElement(sum);
  285. clearselection();
  286. }
  287. dialog.cancel();
  288. break;
  289. default:
  290. dialog.cancel();
  291. break;
  292. }
  293. }
  294. });
  295. AlertDialog clearField = builder.create();
  296. clearField.show();
  297. }
  298. void cancel_selection(){
  299. Log.v(TAG, "cancel_selection()");
  300. // Log.v(TAG, "last_sum: "+last_sum.sum+" ("+last_sum.cell_nums+"), selected_cells: "+selected_cells);
  301. // if (!data.sums.contains(last_sum)){
  302. // clearselection();
  303. // if (noneinsums(last_sum.cell_nums)){
  304. // setsum(last_sum);
  305. // }
  306. // }
  307. Log.v(TAG, "sum_back: "+sum_back.sum+" ("+sum_back.cell_nums+"), selected_cells: "+selected_cells);
  308. if (!data.sums.contains(sum_back)){
  309. clearselection();
  310. if (noneinsums(sum_back.cell_nums)){
  311. setsum(sum_back);
  312. }
  313. }
  314. get_sum_button.setEnabled(false);
  315. remove_button.setEnabled(false);
  316. }
  317. private boolean noneinsums(Vector<Integer> cell_nums){
  318. for (int cellnum : cell_nums) {
  319. if (data.getsum(cellnum)!=null){
  320. return false;
  321. }
  322. }
  323. return true;
  324. }
  325. private void clearselection() {
  326. for (int cellnum:selected_cells){
  327. int n=calculate.num_to_location(cellnum);
  328. CellView cell = cells.elementAt(n);
  329. cell.clear();
  330. }
  331. selected_cells.clear();
  332. get_sum_button.setEnabled(false);
  333. remove_button.setEnabled(false);
  334. }
  335. public void okClick(View v) {
  336. if (cells_connected(selected_cells)){
  337. Vector<Integer> alone_cells = alone_cells_near(selected_cells);
  338. if (alone_cells==null || alone_cells.size()==0){
  339. getsum();
  340. }
  341. else {
  342. //TODO: change toast by highlighting alone cells
  343. toast.setText("Alone cells: "+alone_cells);
  344. toast.show();
  345. }
  346. }
  347. else {
  348. //TODO: do not allow user to set a sum by interface
  349. toast.setText("Cells in selection should be connected");
  350. toast.show();
  351. }
  352. }
  353. /**
  354. * Shows user a dialog where they can select a value of sum in selected cells
  355. */
  356. private void getsum() {
  357. current_sum = 0;
  358. final int min_sum=calculate.minsum(selected_cells.size());
  359. int max_sum=calculate.maxsum(selected_cells.size());
  360. final Dialog dialog = new Dialog(this,R.style.myBackgroundStyle);
  361. dialog.setContentView(R.layout.dialog_pick_a_sum);
  362. dialog.setTitle(R.string.text_sum);
  363. // WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();
  364. // lp.dimAmount=0.1f;
  365. // lp.alpha=0.7f;
  366. //
  367. // dialog.getWindow().setAttributes(lp);
  368. // dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
  369. final TextView sum_text = (TextView) dialog.findViewById(R.id.editText_sum);
  370. TextView min_sumTextView = (TextView) dialog.findViewById(R.id.min_sum);
  371. TextView max_sumTextView = (TextView) dialog.findViewById(R.id.max_sum);
  372. min_sumTextView.setText(""+min_sum);
  373. max_sumTextView.setText(""+max_sum);
  374. Button done = (Button) dialog.findViewById(R.id.button_sum_done);
  375. done.setOnClickListener(new View.OnClickListener() {
  376. public void onClick(View v) {
  377. if (sum_text.getText().length()>0){
  378. current_sum = Integer.parseInt(sum_text.getText().toString());
  379. setsum(current_sum);
  380. Log.v(TAG, "sum="+current_sum);
  381. dialog.dismiss();
  382. }
  383. else {
  384. //TODO: check if it happens
  385. Log.e(TAG, "WTF? No sum?");
  386. toast.setText("Enter Sum!");
  387. toast.show();
  388. }
  389. }
  390. });
  391. //done.getBackground().setAlpha(100);
  392. SeekBar seek_sum = (SeekBar) dialog.findViewById(R.id.seekBar_sum);
  393. seek_sum.setMax(max_sum-min_sum);
  394. sum_text.setText(""+min_sum);
  395. // int lastsum =getLast_sum().sum;
  396. // if (lastsum!=0 && lastsum>=min_sum && lastsum<=max_sum){
  397. // sum_text.setText(""+lastsum);
  398. // seek_sum.setProgress(lastsum-min_sum);
  399. // }
  400. seek_sum.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
  401. //@Override
  402. public void onProgressChanged(SeekBar seekBar, int progress,
  403. boolean fromUser) {
  404. sum_text.setText(String.valueOf(progress+min_sum));
  405. }
  406. //@Override
  407. public void onStartTrackingTouch(SeekBar seekBar) { }
  408. //@Override
  409. public void onStopTrackingTouch(SeekBar seekBar) { }
  410. });
  411. //dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
  412. dialog.show();
  413. }
  414. private void setsum(int sum){
  415. Sum s = new Sum(sum, this);
  416. for (int cell_num : selected_cells) {
  417. s.cell_nums.add(cell_num);
  418. }
  419. data.addtosums(s);
  420. if (sum_back.sum!=0){
  421. disborder(sum_back.cell_nums);
  422. }
  423. border(sum);
  424. // setLast_sum(s);
  425. if (!selected_cells.isEmpty()){
  426. Log.v(TAG, "Sum: "+data.getsum(selected_cells.firstElement()).sum+", " +
  427. "cells:"+data.getsum(selected_cells.firstElement()).cell_nums+"\n");}
  428. selected_cells.clear();
  429. get_sum_button.setEnabled(false);
  430. remove_button.setEnabled(false);
  431. // Log.v(TAG,"new cells:"+new_cells);
  432. if (total_sums_size()==sumdoku_size*sumdoku_size){
  433. all_sums_filled();
  434. }
  435. }
  436. private int total_sums_size(){
  437. int size=0;
  438. for (Sum s : data.getsums()) {
  439. size+=s.cell_nums.size();
  440. }
  441. Log.v(TAG, "total sums size = "+size);
  442. return size;
  443. }
  444. private void setsum(Sum sum){
  445. while (!selected_cells.isEmpty()){
  446. int cellnum = selected_cells.remove(0);
  447. CellView cell = cells.elementAt(calculate.num_to_location(cellnum));
  448. View b = cell.findViewById(R.id.back);
  449. b.setBackgroundColor(Color.WHITE);
  450. b.invalidate();
  451. }
  452. selected_cells.addAll(sum.cell_nums);
  453. setsum(sum.sum);
  454. }
  455. public void editSum(int num) {
  456. Sum sum = data.getsum(num);
  457. if (sum.sum==0){return;}
  458. //setLast_sum(sum);
  459. set_sum_back(sum);
  460. hidesolvebutton();
  461. // Log.v(TAG,"Cell: num="+cell.num+", sum="+cell.sum+", sum_area="+cell.sum_area);
  462. for (int cell_num : sum.cell_nums) {
  463. int location = calculate.num_to_location(cell_num);
  464. CellView cellView = cells.elementAt(location);
  465. cellView.findViewById(R.id.back).setBackgroundColor(Color.GRAY);
  466. selected_cells.add(cell_num);
  467. }
  468. data.getsums().removeElement(sum);
  469. tempborder(selected_cells);
  470. get_sum_button.setEnabled(selected_cells.size()>1);
  471. remove_button.setEnabled(selected_cells.size()>0);
  472. }
  473. private void disborder(Vector<Integer> cell_nums) {
  474. sum_back = new Sum(0, this);
  475. for (int cellnum : cell_nums) {
  476. int n=calculate.num_to_location(cellnum);
  477. CellView cell = cells.elementAt(n);
  478. TextView sum_textview = (TextView) cell.findViewById(R.id.sum);
  479. sum_textview.setText("");
  480. cell.hideborders();
  481. }
  482. }
  483. private void tempborder(Vector<Integer> cell_nums){
  484. for (int cellnum:selected_cells){
  485. int n=calculate.num_to_location(cellnum);
  486. CellView cell = cells.elementAt(n);
  487. View t = cell.findViewById(R.id.tempback);
  488. t.setVisibility(View.VISIBLE);
  489. }
  490. }
  491. private void border(int sum) {
  492. // Log.v(TAG, "border()");
  493. int min = calculate.min(selected_cells);
  494. // Log.v(TAG, "Sum: "+sum+", selected_cells="+AndroidSumdokuSolver.selected_cells);
  495. for (int cellnum:selected_cells){
  496. int i=cellnum/10;
  497. int k=cellnum%10;
  498. int n=calculate.num_to_location(cellnum);
  499. // Log.v(TAG, " cellnum: "+cellnum+", n="+n);
  500. CellView cell = cells.elementAt(n);
  501. // Log.v(TAG, " cell.getTag().toString(): "+cell.getTag().toString());
  502. View b = cell.findViewById(R.id.back);
  503. b.setBackgroundColor(Color.WHITE);
  504. b.invalidate();
  505. if(cellnum==min){
  506. TextView t = (TextView) cell.findViewById(R.id.sum);
  507. t.setText(""+sum);
  508. }
  509. if (!selected_cells.contains(10*(i-1)+k)){
  510. cell.findViewById(R.id.border_top).setVisibility(View.VISIBLE);
  511. if (selected_cells.contains(10*i+k-1)){
  512. cell.findViewById(R.id.border_top_rl).setVisibility(View.VISIBLE);
  513. }
  514. if (selected_cells.contains(10*i+k+1)){
  515. cell.findViewById(R.id.border_top_lr).setVisibility(View.VISIBLE);
  516. }
  517. }
  518. else{
  519. if (!selected_cells.contains(10*(i-1)+k-1)){
  520. cell.findViewById(R.id.border_left_bt).setVisibility(View.VISIBLE);
  521. }
  522. if (!selected_cells.contains(10*(i-1)+k+1)){
  523. cell.findViewById(R.id.border_right_bt).setVisibility(View.VISIBLE);
  524. }
  525. }
  526. if (!selected_cells.contains(10*i+k-1)){
  527. cell.findViewById(R.id.border_left).setVisibility(View.VISIBLE);
  528. if (selected_cells.contains(10*(i+1)+k)){
  529. cell.findViewById(R.id.border_left_tb).setVisibility(View.VISIBLE);
  530. }
  531. if (selected_cells.contains(10*(i-1)+k)){
  532. cell.findViewById(R.id.border_left_bt).setVisibility(View.VISIBLE);
  533. }
  534. }
  535. else{
  536. if (!selected_cells.contains(10*(i-1)+k-1)){
  537. cell.findViewById(R.id.border_top_rl).setVisibility(View.VISIBLE);
  538. }
  539. if (!selected_cells.contains(10*(i+1)+k-1)){
  540. cell.findViewById(R.id.border_bottom_rl).setVisibility(View.VISIBLE);
  541. }
  542. }
  543. if (!selected_cells.contains(10*(i+1)+k)){
  544. cell.findViewById(R.id.border_bottom).setVisibility(View.VISIBLE);
  545. if (selected_cells.contains(10*i+k-1)){
  546. cell.findViewById(R.id.border_bottom_rl).setVisibility(View.VISIBLE);
  547. }
  548. if (selected_cells.contains(10*i+k+1)){
  549. cell.findViewById(R.id.border_bottom_lr).setVisibility(View.VISIBLE);
  550. }
  551. }
  552. else{
  553. if (!selected_cells.contains(10*(i+1)+k-1)){
  554. cell.findViewById(R.id.border_left_tb).setVisibility(View.VISIBLE);
  555. }
  556. if (!selected_cells.contains(10*(i+1)+k+1)){
  557. cell.findViewById(R.id.border_right_tb).setVisibility(View.VISIBLE);
  558. }
  559. }
  560. if (!selected_cells.contains(10*i+k+1)){
  561. cell.findViewById(R.id.border_right).setVisibility(View.VISIBLE);
  562. if (selected_cells.contains(10*(i+1)+k)){
  563. cell.findViewById(R.id.border_right_tb).setVisibility(View.VISIBLE);
  564. }
  565. if (selected_cells.contains(10*(i-1)+k)){
  566. cell.findViewById(R.id.border_right_bt).setVisibility(View.VISIBLE);
  567. }
  568. }
  569. else{
  570. if (!selected_cells.contains(10*(i-1)+k+1)){
  571. cell.findViewById(R.id.border_top_lr).setVisibility(View.VISIBLE);
  572. }
  573. if (!selected_cells.contains(10*(i+1)+k+1)){
  574. cell.findViewById(R.id.border_bottom_lr).setVisibility(View.VISIBLE);
  575. }
  576. }
  577. cell.invalidate();
  578. }
  579. field.invalidate();
  580. }
  581. // MENU
  582. @Override
  583. public boolean onCreateOptionsMenu(Menu menu) {
  584. MenuInflater inflater = getMenuInflater();
  585. inflater.inflate(R.menu.menu, menu);
  586. return true;
  587. }
  588. @Override
  589. public boolean onPrepareOptionsMenu(Menu menu) {
  590. if (isReleaseVersion){
  591. menu.findItem(R.id.printfield).setVisible(false);
  592. }
  593. else menu.findItem(R.id.helpscreen).setVisible(false);
  594. return true;
  595. }
  596. @Override
  597. public boolean onOptionsItemSelected(MenuItem item) {
  598. switch (item.getItemId()) {
  599. case R.id.menuclear:
  600. Log.v(TAG, "USER ACTION: Menu - ClearField");
  601. menuclear();
  602. return true;
  603. case R.id.printfield:
  604. Log.v(TAG, "USER ACTION: Menu - PrintField");
  605. data.printfield();
  606. return true;
  607. case R.id.helpscreen:
  608. Log.v(TAG, "USER ACTION: Menu - PrintField");
  609. helpscreen();
  610. return true;
  611. case R.id.getexample:
  612. Log.v(TAG, "USER ACTION: Menu - getExample");
  613. //clearfield();
  614. clearAll();
  615. example();
  616. return true;
  617. case R.id.savefield:
  618. Log.v(TAG, "USER ACTION: Menu - saveField");
  619. savefield();
  620. return true;
  621. case R.id.loadfield:
  622. Log.v(TAG, "USER ACTION: Menu - loadField");
  623. loadfield();
  624. return true;
  625. default:
  626. // return super.onOptionsItemSelected(item);
  627. return false;
  628. }
  629. }
  630. private void helpscreen() {
  631. Intent helpscreen = new Intent(this, HelpScreen.class);
  632. startActivity(helpscreen);
  633. }
  634. private void menuclear() {
  635. AlertDialog.Builder builder = new AlertDialog.Builder(this);
  636. builder.setTitle(R.string.title_clear_field)
  637. .setItems(R.array.array_clear_field, new DialogInterface.OnClickListener() {
  638. public void onClick(DialogInterface dialog, int which) {
  639. switch (which) {
  640. case 0:
  641. clearSums();
  642. dialog.cancel();
  643. break;
  644. case 1:
  645. clearValues();
  646. dialog.cancel();
  647. break;
  648. case 2:
  649. clearAll();
  650. dialog.cancel();
  651. break;
  652. default:
  653. dialog.cancel();
  654. break;
  655. }
  656. }
  657. });
  658. AlertDialog clearField = builder.create();
  659. clearField.show();
  660. }
  661. private void clearAll(){
  662. for (int cell_num : selected_cells) {
  663. int location = calculate.num_to_location(cell_num);
  664. CellView cellView = cells.elementAt(location);
  665. cellView.clear();
  666. }
  667. selected_cells.clear();
  668. clearSums();
  669. clearValues();
  670. hidesolvebutton();
  671. get_sum_button.setEnabled(false);
  672. remove_button.setEnabled(false);
  673. }
  674. private void clearValues() {
  675. for (int cell_num : selected_cells) {
  676. int location = calculate.num_to_location(cell_num);
  677. CellView cellView = cells.elementAt(location);
  678. cellView.clear();
  679. }
  680. selected_cells.clear();
  681. get_sum_button.setEnabled(false);
  682. remove_button.setEnabled(false);
  683. for (int i=0;i<sumdoku_size;i++) {
  684. for (int k=0;k<sumdoku_size;k++) {
  685. int cell_num=10*i+k;
  686. data.setValue(0, cell_num);
  687. cells.elementAt(calculate.num_to_location(cell_num)).clearvalue();
  688. }
  689. }
  690. }
  691. private void clearSums() {
  692. for (int cell_num : selected_cells) {
  693. int location = calculate.num_to_location(cell_num);
  694. CellView cellView = cells.elementAt(location);
  695. cellView.clear();
  696. }
  697. selected_cells.clear();
  698. get_sum_button.setEnabled(false);
  699. remove_button.setEnabled(false);
  700. while (!data.sums.isEmpty()){
  701. removesums();
  702. }
  703. sum_back = new Sum(0,this);
  704. hidesolvebutton();
  705. }
  706. private void suggsolve() {
  707. Data data_back = new Data(this);
  708. data_back.copy_from(data);
  709. data=data.solving_by_suggestions();
  710. Log.v(TAG, "");
  711. Log.v(TAG, "BEFORE SOLVING BY SUGESTIONS (data_back):");
  712. data_back.printfield();
  713. Log.v(TAG, "AFTER SOLVING BY SUGESTIONS (data):");
  714. data.printfield();
  715. // showresult();
  716. }
  717. private void removesums() {
  718. //TODO: Check if realization of this is not stupid
  719. if (!data.sums.isEmpty()){
  720. // Log.v(TAG,"sumnumber=="+sumnumber+", getsums.size=="+data.getsums().size());
  721. Log.v(TAG,"sums was: "+data.getsums().size());
  722. Sum sum = data.getsums().lastElement();
  723. if (sum.cell_nums.isEmpty()){
  724. data.getsums().removeElement(sum);
  725. removesums();
  726. return;
  727. }
  728. for (int cell_num : sum.cell_nums){
  729. int location = calculate.num_to_location(cell_num);
  730. CellView cellView = cells.elementAt(location);
  731. // Cell cell = data.getcell(location);
  732. cellView.findViewById(R.id.back).setBackgroundColor(Color.WHITE);
  733. TextView oldsum = (TextView) cellView.findViewById(R.id.sum);
  734. oldsum.setText("");
  735. cellView.hideborders();
  736. // Log.v(TAG,"cleared cell #"+cell.num+", cell.sum="+cell.sum+", cell.sum_area="+cell.sum_area);
  737. // done_cells.removeElement(cell_num);
  738. //new_cells.add(cell_num);
  739. }
  740. data.getsums().removeElement(sum);
  741. // last_sum.sum=0;
  742. // last_sum.cell_nums.clear();
  743. sum_back = new Sum (0,this);
  744. Log.v(TAG,"sums remains: "+data.getsums().size());
  745. // toast.setText("removed sum area : "+sum.sum_area);
  746. // toast.show();
  747. }
  748. }
  749. //----=== SOLVING ===----
  750. private void all_sums_filled() {
  751. Log.v(TAG, "All sums filled");
  752. findViewById(R.id.sum_buttons).setVisibility(View.INVISIBLE);
  753. solve_button.setVisibility(View.VISIBLE);
  754. }
  755. public void solveClick(View v) {
  756. int checkfield = fieldIsOk();
  757. switch (checkfield) {
  758. case OK:
  759. solution = new SolveTask();
  760. solution.execute(data);
  761. break;
  762. case WRONGTOTALSUM:
  763. somethingwrong(R.string.message_wrong_total_sum);
  764. break;
  765. default:
  766. somethingwrong(R.string.message_wrong_field);
  767. break;
  768. }
  769. }
  770. private int fieldIsOk(){
  771. int total_sum=0;
  772. for (Sum sum:data.sums){
  773. total_sum+=sum.sum;
  774. }
  775. if (total_sum!=calculate.totalsum()) {
  776. Log.v(TAG, "total_sum="+total_sum+", calculate.totalsum()="+calculate.totalsum());
  777. return WRONGTOTALSUM;}
  778. return OK;
  779. }
  780. //----=== SHOW RESULT ===----
  781. private void showresult() {
  782. //System.out.println(cells);
  783. int i=0;
  784. for (CellView cellview : cells) {
  785. //Log.v(TAG, "result: ");
  786. Cell cell = data.field[i];
  787. TextView value_textview = (TextView) cellview.findViewById(R.id.value);
  788. TextView vars_textview = (TextView) cellview.findViewById(R.id.vars);
  789. if (value_textview.getText()=="" || value_textview.getText()==null){
  790. if (cell.getValue()>0){
  791. vars_textview.setVisibility(View.INVISIBLE);
  792. value_textview.setTextAppearance(this, android.R.style.TextAppearance_Large);
  793. value_textview.setTextColor(Color.BLACK);
  794. value_textview.setText(""+cell.getValue());}
  795. else {
  796. vars_textview.setVisibility(View.VISIBLE);
  797. vars_textview.setTextAppearance(this, android.R.style.TextAppearance_Small_Inverse);
  798. vars_textview.setTextColor(Color.GREEN);
  799. String s="";
  800. for (int n = 0; n < sumdoku_size; n++) {
  801. if (((1 << n) & cell.var_value) == (1<<n)) {
  802. s += (n + 1);
  803. }
  804. }
  805. vars_textview.setText(""+s);
  806. }
  807. }
  808. i++;
  809. }
  810. }
  811. //----=== OTHER ===----
  812. private void hidesolvebutton() {
  813. sumbuttonsLayout.setVisibility(View.VISIBLE);
  814. solve_button.setVisibility(View.INVISIBLE);
  815. }
  816. private boolean cells_connected(Vector<Integer> cells) {
  817. boolean connection = (cells.size()>1);
  818. if (connection){
  819. Vector<Integer> nearfirst = new Vector<Integer>();
  820. Vector<Integer> checked = new Vector<Integer>();
  821. nearfirst.addAll(near(cells.firstElement(),checked,cells));
  822. connection=(nearfirst.size()==cells.size());
  823. }
  824. return connection;
  825. }
  826. private Vector <Integer> alone_cells_near(Vector<Integer> selected_cells){
  827. Vector<Integer> alone_cells = new Vector<Integer>();
  828. Vector<Integer> near_cells = new Vector<Integer>();
  829. for (int cell_num : selected_cells) {
  830. near_cells.addAll(near_cells(cell_num));
  831. }
  832. for (int cell_num : near_cells) {
  833. Vector<Integer> n_cells = near_cells(cell_num);
  834. if (((n_cells==null || n_cells.size()==0))&& !alone_cells.contains(cell_num)){
  835. alone_cells.add(cell_num);
  836. Log.v(TAG, "alone cell detected: "+cell_num);
  837. }
  838. else Log.v(TAG, cell_num+" is not alone: "+n_cells);
  839. }
  840. Log.v(TAG, "selected cells:"+selected_cells+
  841. ", near cells:"+near_cells+
  842. ", alone cells:"+alone_cells);
  843. return alone_cells;
  844. }
  845. private Vector<Integer> near_cells(int cell_num) {
  846. Vector<Integer> near_cells = new Vector<Integer>();
  847. if (cell_num/10>=1 && !selected_cells.contains(cell_num-10)
  848. && !near_cells.contains(cell_num-10) && data.getsum(cell_num-10)==null)
  849. {near_cells.add(cell_num-10);}
  850. if (cell_num/10<sumdoku_size-1 && !selected_cells.contains(cell_num+10)
  851. && !near_cells.contains(cell_num+10) && data.getsum(cell_num+10)==null)
  852. {near_cells.add(cell_num+10);}
  853. if (cell_num%10>=1 && !selected_cells.contains(cell_num-1)
  854. && !near_cells.contains(cell_num-1) && data.getsum(cell_num-1)==null)
  855. {near_cells.add(cell_num-1);}
  856. if (cell_num%10<sumdoku_size-1 && !selected_cells.contains(cell_num+1)
  857. && !near_cells.contains(cell_num+1) && data.getsum(cell_num+1)==null)
  858. {near_cells.add(cell_num+1);}
  859. return near_cells;
  860. }
  861. private Vector<Integer> near(Integer firstElement, Vector<Integer> checked, Vector<Integer> cells) {
  862. Vector<Integer> n = new Vector<Integer>();
  863. n.add(firstElement);
  864. int i=firstElement/10;
  865. int k=firstElement%10;
  866. checked.add(firstElement);
  867. if (i>=1){
  868. int num=(i-1)*10+k;
  869. if (!checked.contains(num)&&cells.contains(num)){
  870. n.addAll(near(num,checked,cells));
  871. }
  872. }
  873. if (i<sumdoku_size-1){
  874. int num=(i+1)*10+k;
  875. if (!checked.contains(num)&&cells.contains(num)){
  876. n.addAll(near(num,checked,cells));
  877. }
  878. }
  879. if (k>=1){
  880. int num=i*10+k-1;
  881. if (!checked.contains(num)&&cells.contains(num)){
  882. n.addAll(near(num,checked,cells));
  883. }
  884. }
  885. if (k<sumdoku_size-1){
  886. int num=i*10+k+1;
  887. if (!checked.contains(num)&&cells.contains(num)){
  888. n.addAll(near(num,checked,cells));
  889. }
  890. }
  891. return n;
  892. }
  893. // public Sum getLast_sum() {
  894. // return last_sum;
  895. // }
  896. // public void setLast_sum(Sum sum) {
  897. // last_sum = new Sum(sum.sum, this);
  898. // last_sum.cell_nums.addAll(sum.cell_nums);
  899. // }
  900. public void set_sum_back(Sum sum) {
  901. sum_back = new Sum(sum.sum, this);
  902. sum_back.cell_nums.addAll(sum.cell_nums);
  903. }
  904. // ---=== EXAMPLE ===---
  905. private void example() {
  906. exSaveValue(6, 4);
  907. exSaveValue(20, 4);
  908. //exSaveValue(68, 7);
  909. exSaveValue(82, 9);
  910. selected_cells.clear();
  911. get_sum_button.setEnabled(false);
  912. remove_button.setEnabled(false);
  913. exSaveSum(new int[] {0, 10,20,30}, 22);
  914. exSaveSum(new int[] {1, 2, 3, 11}, 26);
  915. exSaveSum(new int[] {4, 5, 6, 15}, 21);
  916. exSaveSum(new int[] {7, 8, 16, 17, 26}, 26);
  917. exSaveSum(new int[] {12, 13, 14}, 7);
  918. exSaveSum(new int[] {18, 27, 28}, 15);
  919. exSaveSum(new int[] {21, 31, 32}, 10);
  920. exSaveSum(new int[] {22, 23, 33}, 17);
  921. exSaveSum(new int[] {24, 25}, 9);
  922. exSaveSum(new int[] {34, 44, 54}, 9);
  923. exSaveSum(new int[] {35, 45}, 14);
  924. exSaveSum(new int[] {36, 37}, 13);
  925. exSaveSum(new int[] {38, 48}, 3);
  926. exSaveSum(new int[] {40, 50}, 9);
  927. exSaveSum(new int[] {41, 42}, 11);
  928. exSaveSum(new int[] {43, 53}, 14);
  929. exSaveSum(new int[] {46, 47}, 16);
  930. exSaveSum(new int[] {51, 52}, 14);
  931. exSaveSum(new int[] {55, 65, 66}, 11);
  932. exSaveSum(new int[] {56, 57, 67}, 19);
  933. exSaveSum(new int[] {58, 68, 78, 88}, 20);
  934. exSaveSum(new int[] {60, 61, 70}, 13);
  935. exSaveSum(new int[] {62, 71, 72, 80, 81}, 23);
  936. exSaveSum(new int[] {63, 64}, 8);
  937. exSaveSum(new int[] {73, 82, 83, 84}, 19);
  938. exSaveSum(new int[] {74, 75, 76}, 16);
  939. exSaveSum(new int[] {77, 85, 86, 87}, 20);
  940. }
  941. private void exSaveValue(int cell_num, int value){
  942. int location = calculate.num_to_location(cell_num);
  943. CellView cellView = cells.elementAt(location);
  944. cellView.setvalue(value);
  945. }
  946. private void exSaveSum(int[] cellnums, int sum){
  947. for (int cell_num : cellnums) {
  948. selected_cells.add(cell_num);
  949. }
  950. setsum(sum);
  951. }
  952. public void sumtofield(Sum sum){
  953. selected_cells.clear();
  954. selected_cells.addAll(sum.cell_nums);
  955. setsum(sum);
  956. }
  957. public void cellToField(Cell cell){
  958. int location = calculate.num_to_location(cell.num);
  959. CellView cellView = cells.elementAt(location);
  960. if (cell.getValue()!=0){cellView.setvalue(cell.getValue());}
  961. data.field[location]=cell;
  962. }
  963. //---===SAVE/LOAD field===---
  964. private void savefield() {
  965. Intent saveload = new Intent(this, SaveAndLoad.class);
  966. saveload.putExtra(MODE, SAVE);
  967. startActivityForResult(saveload,SAVE);
  968. }
  969. private void savefield(String save_name) {
  970. //Log.v(TAG, "SAving to "+save_name+"...");
  971. savefield = new SaveField();
  972. savefield.execute(save_name);
  973. }
  974. private void savefieldstate(){
  975. db.clearSaving(FIELDSTATE);
  976. db.savedata(data, FIELDSTATE);
  977. // db.savefield(data.field,FIELDSTATE);
  978. // db.saveSums(data.sums,FIELDSTATE);
  979. }
  980. private void loadfield() {
  981. selected_cells.clear();
  982. get_sum_button.setEnabled(selected_cells.size()>1);
  983. remove_button.setEnabled(selected_cells.size()>0);
  984. Intent saveload = new Intent(this, SaveAndLoad.class);
  985. saveload.putExtra(MODE, LOAD);
  986. startActivityForResult(saveload, LOAD);
  987. }
  988. class StringContext{
  989. String string;
  990. Context context;
  991. public StringContext(String s, Context c) {
  992. string=s;
  993. context=c;
  994. }
  995. }
  996. private void loadfield(String save_name) {
  997. getfield = new GetField();
  998. StringContext name_context = new StringContext(save_name,activity);
  999. getfield.execute(name_context);
  1000. }
  1001. public class SolveTask extends AsyncTask<Data,Void,Integer> {
  1002. Context context;
  1003. @Override
  1004. protected void onPreExecute() {
  1005. super.onPreExecute();
  1006. context = data.getcontext();
  1007. data_back.copy_from(data);
  1008. setWaitDialog("Solving");
  1009. waitdialog.show();
  1010. }
  1011. @Override
  1012. protected Integer doInBackground(Data... d) {
  1013. int result =NOTCOMPLETE;
  1014. try {
  1015. Data data = d[0];
  1016. result = data.solving();
  1017. Log.v(TAG, "solving() is "+ result);
  1018. if (result==NOTCOMPLETE){
  1019. suggsolve();
  1020. }
  1021. } catch (Exception e) {
  1022. Log.e(TAG, "Error: "+ e.getMessage());
  1023. }
  1024. return result;
  1025. }
  1026. @Override
  1027. protected void onPostExecute(Integer result) {
  1028. super.onPostExecute(result);
  1029. Log.v(TAG, "onPostExecute(result) : "+result);
  1030. if (result!=EMPTYCELL) {
  1031. showresult();
  1032. waitdialog.cancel();}
  1033. else{
  1034. waitdialog.cancel();
  1035. data.copy_from(data_back);
  1036. somethingwrong(R.string.message_empty_cell);
  1037. }
  1038. }
  1039. }
  1040. private void setWaitDialog(String message) {
  1041. waitdialog = new Dialog(this);
  1042. waitdialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
  1043. waitdialog.setContentView(R.layout.dialog_progress);
  1044. TextView dialogmessage = (TextView) waitdialog.findViewById(R.id.message);
  1045. dialogmessage.setText(message);
  1046. waitdialog.setCancelable(false);
  1047. }
  1048. public class GetField extends AsyncTask<StringContext,Void,Data> {
  1049. @Override
  1050. protected void onPreExecute() {
  1051. super.onPreExecute();
  1052. setWaitDialog("Loading");
  1053. waitdialog.show();
  1054. }
  1055. @Override
  1056. protected Data doInBackground(StringContext... sc) {
  1057. Vector<Sum> sums = new Vector<Sum>();
  1058. Cell[] field = null;
  1059. Data fromdb=null;
  1060. try {
  1061. String save_name = sc[0].string;
  1062. Context context = sc[0].context;
  1063. fromdb=new Data(context);
  1064. Log.v(TAG, "Loading from \""+save_name+"\"...");
  1065. // Log.i(TAG,"SUMS...");
  1066. sums = db.loadSums(save_name);
  1067. // Log.i(TAG,"CELLS...");
  1068. field = db .loadfield(save_name);
  1069. } catch (Exception e) {
  1070. Log.e(TAG, "Error: "+ e.getMessage());
  1071. }
  1072. if (sums!=null) fromdb.sums.addAll(sums);
  1073. fromdb.field = field;
  1074. return fromdb;
  1075. }
  1076. @Override
  1077. protected void onPostExecute(Data fromdb) {
  1078. super.onPostExecute(fromdb);
  1079. clearAll();
  1080. if ((fromdb.sums!=null) && (!fromdb.sums.isEmpty())){
  1081. for (Sum sum : fromdb.sums) {
  1082. sumtofield(sum);
  1083. // Log.i(TAG," "+sum.sum+"("+sum.cell_nums+")");
  1084. }
  1085. }
  1086. // else Log.v(TAG, "No sums in save");
  1087. if (fromdb.field!=null && fromdb.field.length!=0){
  1088. for (Cell cell : fromdb.field) {
  1089. cellToField(cell);
  1090. }
  1091. }
  1092. waitdialog.cancel();
  1093. // else {Log.v(TAG, "No cells in save");}
  1094. }
  1095. }
  1096. public class SaveField extends AsyncTask<String,Void,Integer> {
  1097. @Override
  1098. protected void onPreExecute() {
  1099. super.onPreExecute();
  1100. setWaitDialog("Saving");
  1101. waitdialog.show();
  1102. }
  1103. @Override
  1104. protected Integer doInBackground(String... s) {
  1105. String save_name="";
  1106. try {
  1107. save_name = s[0];
  1108. Log.v(TAG, "Saving to \""+save_name+"\"...");
  1109. // db.clearSaving(save_name);
  1110. // db.savefield(data.field,save_name);
  1111. // db.saveSums(data.sums,save_name);
  1112. db.savedata(data, save_name);
  1113. } catch (Exception e) {
  1114. Log.e(TAG, "Error: "+ e.getMessage());
  1115. }
  1116. return 1;
  1117. }
  1118. @Override
  1119. protected void onPostExecute(Integer result) {
  1120. super.onPostExecute(result);
  1121. waitdialog.cancel();
  1122. }
  1123. }
  1124. public void somethingwrong(int couse) {
  1125. // String message = "";
  1126. // switch (couse) {
  1127. // case EMPTYCELL:
  1128. // message="This field can not be solved. Check all values you set";
  1129. // break;
  1130. //
  1131. // default:
  1132. // message="Something wrong";
  1133. // break;
  1134. // }
  1135. AlertDialog.Builder builder = new AlertDialog.Builder(this);
  1136. builder.setMessage(couse)
  1137. .setTitle(R.string.title_somethingwrong);
  1138. builder.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
  1139. public void onClick(DialogInterface dialog, int id) {
  1140. dialog.dismiss();
  1141. }});
  1142. AlertDialog messagedialog = builder.create();
  1143. messagedialog.show();
  1144. }
  1145. @Override
  1146. protected void onStop() {
  1147. super.onStop();
  1148. Log.v(TAG, "onStop()");
  1149. //cancel_selection();
  1150. //solution.cancel(true);
  1151. }
  1152. @Override
  1153. protected void onDestroy() {
  1154. super.onDestroy();
  1155. Log.v(TAG, "onDestroy()");
  1156. //solution.cancel(true);
  1157. cancel_selection();
  1158. savefieldstate();
  1159. }
  1160. }