论坛首页 Java企业应用论坛

趣味编程:命令行版的扫雷游戏

浏览 3103 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-01-06   最后修改:2009-01-29
OO
今天很无聊,刚好有人问如何写一个扫雷程序。想了一下,写了一个命令行版的扫雷程序。等有时间再用Swing写个界面吧。贴在这里让大家玩玩,哈哈。
package fun.mine;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Random;

public class FunMine {
	int row,column; //行数、列数
	int mineNum;    //布雷数
	int marked;     //已标记雷数
	
	Cell[][] cells; //表示雷区的数组
	
	/**
	 * 布雷
	 */
	public void fill(int row,int column,int num){
		this.row=row;
		this.column=column;
		this.mineNum=num;
		this.marked=0;
		
		cells=new Cell[row][column];
		for(int i=0;i<row;i++){
			for(int j=0;j<column;j++){
				cells[i][j]=new Cell();
				cells[i][j].rowIndex=i;
				cells[i][j].colIndex=j;
			}
		}
		
		int nm=mineNum;
		Random rand=new Random(System.currentTimeMillis());
		while(nm>0){
			int r=rand.nextInt(row);
			int c=rand.nextInt(column);
			if (cells[r][c].mine==Cell.MINE_EMPTY){
				cells[r][c].mine=Cell.MINE_HAS;
				nm--;
			}
		}
		
		settingNumber();
	}
	/**
	 * 填数
	 */
	private void settingNumber(){
		for(int r=0;r<row;r++)
			for(int c=0;c<column;c++){
				if (cells[r][c].mine==Cell.MINE_EMPTY){
					List<Cell> adj=getAdjacentCells(cells[r][c], new CellFilter(){
						public boolean filter(Cell cell){
							return cell.mine==Cell.MINE_HAS;
						}
					});
					cells[r][c].mine=adj.size();
				}
			}
	}
	
	/**
	 * 取相邻单元格
	 * @param cell
	 * @param filter  一个实现了CellFilter接口的实例,用于过滤单元格
	 * @return
	 */
	private List<Cell> getAdjacentCells(Cell cell,CellFilter filter){
		List<Cell> rs=new java.util.ArrayList<Cell>();
		for(int roff=-1;roff<2;roff++)
			for(int coff=-1;coff<2;coff++){
				int cr=cell.rowIndex+roff;
				int cc=cell.colIndex+coff;
				if (cr>=0 && cr<row && cc >= 0 && cc < column ){
					if (cr==cell.rowIndex && cc==cell.colIndex) continue;
					if (filter.filter(cells[cr][cc]))
						rs.add(cells[cr][cc]);
				}
			}
		return rs;
	}
	
	/**
	 * 标记/取消标记
	 * @param r
	 * @param c
	 * @param mark
	 */
	public void mark(int r,int c,int mark){
		if (mark!=Cell.CELL_MARK && mark!=Cell.CELL_UNMARK) return;
		cells[r][c].mark=mark;
		if (mark==Cell.CELL_MARK) {
			marked++;
		}else{
			marked--;
		}
	}
	/**
	 * 打开指定的单元格
	 * 如果是空白,则打开其周围的单元格;
	 * 如果是雷,则 game over.
	 * 如果是数字,则只是置成打开的状态,不做进一步处理。
	 * 
	 * @param cell
	 */
	public int open(Cell cell){
		cell.status=Cell.STATUS_OPENED;
		if (cell.mine==Cell.MINE_HAS) return -1;
		if (cell.mine==Cell.MINE_EMPTY){
			List<Cell> adj=getAdjacentCells(cell, new CellFilter(){
				public boolean filter(Cell cell){
					return cell.status==Cell.STATUS_CLOSED;
				}
			});
			for(Cell a:adj) open(a);
		}
		return 0;
	}
	/**
	 * 打开指定的单元格
	 * 如果是空白,则打开其周围的单元格;
	 * 如果是雷,则 game over.
	 * 如果是数字,则只是置成打开的状态,不做进一步处理。
	 * 
	 * @param r
	 * @param c
	 */
	public int open(int r,int c){
		return open(cells[r][c]);
	}
	/**
	 * 单元格描述类
	 * 表示有雷或无雷、打开或关闭、标记或未标记。
	 */
	public static class Cell {
		public static int MINE_HAS=-1;
		public static int MINE_EMPTY=0;
		public static int CELL_UNMARK=0;
		public static int CELL_MARK=1;
		public static int STATUS_CLOSED=0;
		public static int STATUS_OPENED=1;
		
		public Cell(){
			mark=CELL_UNMARK;
			mine=MINE_EMPTY;
			status=STATUS_CLOSED;
		}
		
		int rowIndex;
		int colIndex;
		
		int mark;
		int mine;
		int status;
	}
	
	public static interface CellFilter{
		public boolean filter(Cell cell);
	}

	/**
	 * 打印雷区实际情况
	 */
	protected void debug(){
		System.out.println("Debug: ");
		for(int r=0;r<row;r++){
			for(int c=0;c<column;c++){
				System.out.print(String.format("%1$8s", cells[r][c].mine));
			}
			System.out.println();
		}
	}
	
	/**
	 * 打印游戏状态
	 */
	protected void print(){
		System.out.println("Status:");
		for(int r=0;r<row;r++){
			for(int c=0;c<column;c++){
				if (cells[r][c].status==Cell.STATUS_OPENED){
					System.out.print(String.format("%1$8s", cells[r][c].mine));
				}else if (cells[r][c].mark==Cell.CELL_MARK){
					System.out.print(String.format("%1$8s", "P"));
				}else{
					System.out.print(String.format("%1$8s", "I"));
				}
			}
			System.out.println();
		}
		System.out.println(String.format("总雷数:%1$d   已标记:%2$d ",mineNum,marked));
	}
	
	public static void main(String[] args){
		FunMine cm=new FunMine();
		cm.fill(8,8,15);
		System.out.println("准备好了吗?开始扫雷吧。");
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String line;
		try{
			while((line=br.readLine())!=null){
				try{
						if ("exit".equals(line)){
							break;
						}
						String[] argv=line.split("\\s");
						if ("open".equals(argv[0])){
							int r=Integer.parseInt(argv[1]);
							int c=Integer.parseInt(argv[2]);
							cm.open(r, c);
						}else if ("mark".equals(argv[0])){
							int r=Integer.parseInt(argv[1]);
							int c=Integer.parseInt(argv[2]);
							cm.mark(r, c, Cell.CELL_MARK);
						}else if ("umark".equals(argv[0])){
							int r=Integer.parseInt(argv[1]);
							int c=Integer.parseInt(argv[2]);
							cm.mark(r, c, Cell.CELL_UNMARK);
						}else if ("debug".equals(argv[0])){
							cm.debug();
						}else if ("print".equals(argv[0])){
							cm.print();
						}else if ("fill".equals(argv[0])){
							int r=Integer.parseInt(argv[1]);
							int c=Integer.parseInt(argv[2]);
							int n=Integer.parseInt(argv[3]);
							cm.fill(r,c,n);
						}else if ("help".equals(argv[0])){
							showUseage();
						}else{
							throw new Exception("input error.");
						}
					}catch(Exception ex){
						System.out.println("input error.");
					}
				}
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
	public static void showUseage(){
		System.out.println("exit           Quit this program.");
		System.out.println("fill r c num   Fill mines.");
		System.out.println("mark r c       Mark a unit as mine.");
		System.out.println("umark r c      Cancel a marking of the unit.");
		System.out.println("open r c       open the unit, be careful.");
		System.out.println("print          Print game status.");
		System.out.println("debug          Print all mines of the game, for debug.");
		System.out.println("help           Show this help screen.");
		
	}
}
   发表时间:2009-01-06  
好玩
0 请登录后投票
   发表时间:2009-01-06  
不行,有创意,在 mark 后直接 print 一下,多数人都要看的
0 请登录后投票
   发表时间:2009-01-07  
有创意,这个要比谁敲键盘快了
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics