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

今天很无聊,刚好有人问如何写一个扫雷程序。想了一下,写了一个命令行版的扫雷程序。等有时间再用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.");

}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值