在好例子网,分享、交流、成长!
您当前所在位置:首页Java 开发实例Android平台开发 → android 九宫格数独游戏

android 九宫格数独游戏

Android平台开发

下载此实例
  • 开发语言:Java
  • 实例大小:0.62M
  • 下载次数:36
  • 浏览次数:363
  • 发布时间:2015-09-11
  • 实例类别:Android平台开发
  • 发 布 人:crazycode
  • 文件格式:.zip
  • 所需积分:2
 相关标签: 游戏 九宫格 OpenSudoku

实例介绍

【实例简介】

【实例截图】

【核心代码】


/* 
 * Copyright (C) 2009 Roman Masek
 * 
 * This file is part of OpenSudoku.
 * 
 * OpenSudoku is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * OpenSudoku is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with OpenSudoku.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package cz.romario.opensudoku.game;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Collection of sudoku cells. This class in fact represents one sudoku board (9x9).
 * 
 * @author romario
 *
 */
public class CellCollection {
	
	public static final int SUDOKU_SIZE = 9;
	
    /**
     * String is expected to be in format "00002343243202...", where each number represents
	 * cell value, no other information can be set using this method.
     */
    public static int DATA_VERSION_PLAIN = 0;
    
    /**
     * See {@link #DATA_PATTERN_VERSION_1} and {@link #serialize()}.
     */
    public static int DATA_VERSION_1 = 1;
	
	// TODO: An array of ints is a much better than an array of Integers, but this also generalizes to the fact that two parallel arrays of ints are also a lot more efficient than an array of (int,int) objects
	// Cell's data.
	private Cell[][] mCells;
	
	// Helper arrays, contains references to the groups of cells, which should contain unique
	// numbers.
	private CellGroup[] mSectors;
	private CellGroup[] mRows;
	private CellGroup[] mColumns;
	
	private boolean mOnChangeEnabled = true;

	private final List<OnChangeListener> mChangeListeners = new ArrayList<OnChangeListener>();
	
	/**
	 * Creates empty sudoku.
	 * @return
	 */
	public static CellCollection createEmpty()
	{
		Cell[][] cells = new Cell[SUDOKU_SIZE][SUDOKU_SIZE];
		
		for (int r=0; r<SUDOKU_SIZE; r  )
		{
			
			for (int c=0; c<SUDOKU_SIZE; c  )
			{
				cells[r][c] = new Cell();
			}
		}
		
		return new CellCollection(cells);
	}
	
	/**
	 * Return true, if no value is entered in any of cells.
	 * 
	 * @return
	 */
	public boolean isEmpty() {
		for (int r=0; r<SUDOKU_SIZE; r  ) {
			for (int c=0; c<SUDOKU_SIZE; c  ){
				Cell cell = mCells[r][c];
				if (cell.getValue() != 0)
					return false;
			}
		}
		return true;
	}
	
	
	/**
	 * Generates debug game.
	 * 
	 * @return
	 */
	public static CellCollection createDebugGame() {
		CellCollection debugGame = new CellCollection(new Cell[][] {
                { new Cell(), new Cell(), new Cell(), new Cell(4), new Cell(5), new Cell(6), new Cell(7), new Cell(8), new Cell(9),},
                { new Cell(), new Cell(), new Cell(), new Cell(7), new Cell(8), new Cell(9), new Cell(1), new Cell(2), new Cell(3),},
                { new Cell(), new Cell(), new Cell(), new Cell(1), new Cell(2), new Cell(3), new Cell(4), new Cell(5), new Cell(6),},
                { new Cell(2), new Cell(3), new Cell(4), new Cell(), new Cell(), new Cell(), new Cell(8), new Cell(9), new Cell(1),},
                { new Cell(5), new Cell(6), new Cell(7), new Cell(), new Cell(), new Cell(), new Cell(2), new Cell(3), new Cell(4),},
                { new Cell(8), new Cell(9), new Cell(1), new Cell(), new Cell(), new Cell(), new Cell(5), new Cell(6), new Cell(7),},
                { new Cell(3), new Cell(4), new Cell(5), new Cell(6), new Cell(7), new Cell(8), new Cell(9), new Cell(1), new Cell(2),},
                { new Cell(6), new Cell(7), new Cell(8), new Cell(9), new Cell(1), new Cell(2), new Cell(3), new Cell(4), new Cell(5),},
                { new Cell(9), new Cell(1), new Cell(2), new Cell(3), new Cell(4), new Cell(5), new Cell(6), new Cell(7), new Cell(8),},
        });
		debugGame.markFilledCellsAsNotEditable();
		return debugGame;
	}
	
	public Cell[][] getCells() {
		return mCells;
	}
	
	/**
	 * Wraps given array in this object.
	 * @param cells
	 */
	private CellCollection(Cell[][] cells)
	{
		
		mCells = cells;
		initCollection();
	}
	
	/**
	 * Gets cell at given position.
	 * @param rowIndex
	 * @param colIndex
	 * @return
	 */
	public Cell getCell(int rowIndex, int colIndex) {
		return mCells[rowIndex][colIndex];
	}
	
	public void markAllCellsAsValid() {
		mOnChangeEnabled = false;
		for (int r=0; r<SUDOKU_SIZE; r  )
		{
			for (int c=0; c<SUDOKU_SIZE; c  )
			{
				mCells[r][c].setValid(true);
			}
		}
		mOnChangeEnabled = true;
		onChange();
	}
	
	/**
	 * Validates numbers in collection according to the sudoku rules. Cells with invalid
	 * values are marked - you can use getInvalid method of cell to find out whether cell
	 * contains valid value.
	 * 
	 * @return True if validation is successful. 
	 */
	public boolean validate() {
		
		boolean valid = true;
		
		// first set all cells as valid
		markAllCellsAsValid();

		mOnChangeEnabled = false;
		// run validation in groups
		for (CellGroup row : mRows) {
			if (!row.validate()) {
				valid = false;
			}
		}
		for (CellGroup column : mColumns) {
			if (!column.validate()) {
				valid = false;
			}
		}
		for (CellGroup sector : mSectors) {
			if (!sector.validate()) {
				valid = false;
			}
		}
		
		mOnChangeEnabled = true;
		onChange();

		return valid;
	}
	
	public boolean isCompleted() {
		for (int r=0; r<SUDOKU_SIZE; r  )
		{
			for (int c=0; c<SUDOKU_SIZE; c  )
			{
				Cell cell = mCells[r][c]; 
				if (cell.getValue() == 0 || !cell.isValid()) {
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * Marks all cells as editable.
	 */
	public void markAllCellsAsEditable() {
		for (int r=0; r<SUDOKU_SIZE; r  ) {
			for (int c=0; c<SUDOKU_SIZE; c  ){
				Cell cell = mCells[r][c];
				cell.setEditable(true);
			}
		}
	}
	
	/**
	 * Marks all filled cells (cells with value other than 0) as not editable.
	 */
	public void markFilledCellsAsNotEditable() {
		for (int r=0; r<SUDOKU_SIZE; r  ) {
			for (int c=0; c<SUDOKU_SIZE; c  ){
				Cell cell = mCells[r][c];
				cell.setEditable(cell.getValue() == 0);
			}
		}
	}
	
	
	/**
	 * Returns how many times each value is used in <code>CellCollection</code>.
	 * Returns map with entry for each value.
	 * 
	 * @return
	 */
	public Map<Integer, Integer> getValuesUseCount() {
		Map<Integer, Integer> valuesUseCount = new HashMap<Integer, Integer>();
		for (int value = 1; value <= CellCollection.SUDOKU_SIZE; value  ) {
			valuesUseCount.put(value, 0);
		}

		for (int r = 0; r < CellCollection.SUDOKU_SIZE; r  ) {
			for (int c = 0; c < CellCollection.SUDOKU_SIZE; c  ) {
				int value = getCell(r, c).getValue();
				if (value != 0) {
					valuesUseCount.put(value, valuesUseCount.get(value)   1);
				}
			}
		}
		
		return valuesUseCount; 
	}
	
	/**
	 * Initializes collection, initialization has two steps:
	 * 1) Groups of cells which must contain unique numbers are created.
	 * 2) Row and column index for each cell is set.
	 */
	private void initCollection() {
		mRows = new CellGroup[SUDOKU_SIZE];
		mColumns = new CellGroup[SUDOKU_SIZE];
		mSectors = new CellGroup[SUDOKU_SIZE];

		for (int i=0; i<SUDOKU_SIZE; i  ) {
			mRows[i] = new CellGroup();
			mColumns[i] = new CellGroup();
			mSectors[i] = new CellGroup();
		}
		
		for (int r=0; r<SUDOKU_SIZE; r  )
		{
			for (int c=0; c<SUDOKU_SIZE; c  )
			{
				Cell cell = mCells[r][c];
				
				cell.initCollection(this, r, c,
						mSectors[((c/3) * 3)   (r/3)],
						mRows[c],
						mColumns[r]
						);
			}
		}
	}

	/**
	 * Creates instance from given <code>StringTokenizer</code>.
	 * 
	 * @param data
	 * @return
	 */
	public static CellCollection deserialize(StringTokenizer data) {
		Cell[][] cells = new Cell[SUDOKU_SIZE][SUDOKU_SIZE];
		
		int r = 0, c = 0;
        while (data.hasMoreTokens() && r < 9) {
            cells[r][c] = Cell.deserialize(data);
            c  ;
            
            if (c == 9) {
            	r  ;
            	c = 0;
            }
        }
        
        return new CellCollection(cells);
	}
	
	/**
	 * Creates instance from given string (string which has been 
	 * created by {@link #serialize(StringBuilder)} or {@link #serialize()} method).
	 * earlier.
	 * 
	 * @param note
	 */
	public static CellCollection deserialize(String data) {
		// TODO: use DATA_PATTERN_VERSION_1 to validate and extract puzzle data
		String[] lines = data.split("\n");
        if (lines.length == 0) {
            throw new IllegalArgumentException("Cannot deserialize Sudoku, data corrupted.");
        }
        
        if (lines[0].equals("version: 1")) {
            StringTokenizer st = new StringTokenizer(lines[1], "|");
            return deserialize(st);	
        } else {
        	return fromString(data);
        }
    }
	
	/**
	 * Creates collection instance from given string. String is expected
	 * to be in format "00002343243202...", where each number represents
	 * cell value, no other information can be set using this method.
	 * 
	 * @param data
	 * @return
	 */
	public static CellCollection fromString(String data) {
		// TODO: validate
		
		Cell[][] cells = new Cell[SUDOKU_SIZE][SUDOKU_SIZE];

		int pos = 0;
		for (int r = 0; r < CellCollection.SUDOKU_SIZE; r  ) {
			for (int c = 0; c < CellCollection.SUDOKU_SIZE; c  ) {
				int value = 0;
				while (pos < data.length()) {
					pos  ;
					if (data.charAt(pos - 1) >= '0'
							&& data.charAt(pos - 1) <= '9') {
						// value=Integer.parseInt(data.substring(pos-1, pos));
						value = data.charAt(pos - 1) - '0';
						break;
					}
				}
				Cell cell = new Cell();
				cell.setValue(value);
				cell.setEditable(value == 0);
				cells[r][c] = cell;
			}
		}

		return new CellCollection(cells);
	}
	
	public String serialize() {
		StringBuilder sb = new StringBuilder();
		serialize(sb);
		return sb.toString();
	}
	
	/**
	 * Writes collection to given StringBuilder. You can later recreate the object instance
	 * by calling {@link #deserialize(String)} method.
	 * @return
	 */
	public void serialize(StringBuilder data) {
		data.append("version: 1\n");
        
        for (int r=0; r<SUDOKU_SIZE; r  )
        {
                for (int c=0; c<SUDOKU_SIZE; c  )
                {
                        Cell cell = mCells[r][c];
                        cell.serialize(data);
                }
        }
	}
	
    private static Pattern DATA_PATTERN_VERSION_PLAIN = Pattern.compile("^\\d{81}$");
    private static Pattern DATA_PATTERN_VERSION_1 = Pattern.compile("^version: 1\\n((?#value)\\d\\|(?#note)((\\d,) |-)\\|(?#editable)[01]\\|){0,81}$");

    /**
	 * Returns true, if given <code>data</code> conform to format of given data version.
	 * 
	 * @param data
	 * @param dataVersion
	 * @return
	 */
	public static boolean isValid(String data, int dataVersion) {
		if (dataVersion == DATA_VERSION_PLAIN) {
			return DATA_PATTERN_VERSION_PLAIN.matcher(data).matches();
		} else if (dataVersion == DATA_VERSION_1) {
			return DATA_PATTERN_VERSION_1.matcher(data).matches();
		} else {
			throw new IllegalArgumentException("Unknown version: "   dataVersion);
		}
	}
	
	public void addOnChangeListener(OnChangeListener listener) {
		if (listener == null) {
			throw new IllegalArgumentException("The listener is null.");
		}
		synchronized (mChangeListeners) {
			if (mChangeListeners.contains(listener)) {
				throw new IllegalStateException("Listener "   listener   "is already registered.");
			}
			mChangeListeners.add(listener);
		}
	}
	
	public void removeOnChangeListener(OnChangeListener listener) {
		if (listener == null) {
			throw new IllegalArgumentException("The listener is null.");
		}
		synchronized (mChangeListeners) {
			if (!mChangeListeners.contains(listener)) {
				throw new IllegalStateException("Listener "   listener   " was not registered.");
			}
			mChangeListeners.remove(listener);
		}
	}
	
	/**
	 * Returns whether change notification is enabled.
	 * 
	 * If true, change notifications are distributed to the listeners
	 * registered by {@link #addOnChangeListener(OnChangeListener)}.
	 * 
	 * @return
	 */
//	public boolean isOnChangeEnabled() {
//		return mOnChangeEnabled;
//	}
//	
//	/**
//	 * Enables or disables change notifications, that are distributed to the listeners
//	 * registered by {@link #addOnChangeListener(OnChangeListener)}.
//	 * 
//	 * @param onChangeEnabled
//	 */
//	public void setOnChangeEnabled(boolean onChangeEnabled) {
//		mOnChangeEnabled = onChangeEnabled;
//	}
	
	/** 
	 * Notify all registered listeners that something has changed.
	 */
	protected void onChange() {
		if (mOnChangeEnabled) {
			synchronized (mChangeListeners) {
				for (OnChangeListener l : mChangeListeners) {
					l.onChange();
				}
			}
		}
	}
	
	public interface OnChangeListener {
		/**
		 * Called when anything in the collection changes (cell's value, note, etc.)
		 */
		void onChange();
	}
}


实例下载地址

android 九宫格数独游戏

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警