AS写的简单的扫雷

/*

10*10平铺网格,10个雷,未作扩展

可用上下左右键移动,F键标识,空格扫雷

扫雷结束后,未实现开始新游戏的功能

*/

package

{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.ui.Keyboard;

public class MineSweeper extends Sprite
{
private var w:uint;//横向节点数
private var h:uint;//纵向节点数
private var wh:uint;//节点的宽与高
private var c:uint;//控制地图中地雷的数量
private var sweepCount:uint;//已扫出雷的数量
private var sum:uint;//扫雷过程中,开启的节点总数
private var dx:uint;//当前操作格x坐标
private var dy:uint;//当前操作格y坐标
private var map:Sprite;//地图容器
private var mapArr:Array = new Array;//地图数组 
private var curr:MovieClip = new MovieClip;
private var old:MovieClip = new MovieClip;
private var res:TextField;

//构造函数
public function MineSweeper()
{
init();
}

//初始化
private function init():void
{
w = 10;
h = 10;
wh = 30;
c = (w+h)/2;
sweepCount = 0;
sum = 0;
createMap();
createTip();
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);//键盘事件
}

//生成地图
private function makeMap():void 
{
if (null != map)
{
removeChild(map);
mapArr = [];
createMap();
}
}

//创建地图
private function createMap():void
{
map = new Sprite;
map.x = wh;
map.y = wh;
addChild(map);
map.addEventListener(MouseEvent.MOUSE_DOWN, mapMouseDown);//鼠标点击地图事件
for (var x:uint=0; x<w; x++) {
mapArr.push(new Array);//建立二维数组保存地图信息
for (var y:uint=0; y<h; y++) {
var mapPoint:uint = 0/*Math.round(Math.random() - goo)*/;
var point:MovieClip=drawRect(mapPoint);//画出节点
point.name = "p"+x+"_"+y;
mapArr[x].push(point);//将节点加入地图数组中
mapArr[x][y].px=x;//当前节点横向索引位置
mapArr[x][y].py=y;//当前节点纵向索引位置
mapArr[x][y].mine=0;//标识雷 0:无雷 1:有雷
mapArr[x][y].status=0;//标识是否已经扫雷 0:未扫 1:已扫
mapArr[x][y].flag=0;//标识是否为雷 0:为标识 1:已标识
mapArr[x][y].x=x * wh;//当前节点的x位置
mapArr[x][y].y=y * wh;//当前节点的y位置
map.addChild(point);//将节点显示到地图容器中

//显示地图编号
var txt:TextField = new TextField;
var tf:TextFormat = new TextFormat;
tf.color = 0x0000ff;
txt.setTextFormat(tf);
txt.name = "t" + x + "_" + y;
txt.width = 30;
txt.height = 30;
txt.x=x * wh;
txt.y=y * wh;
// txt.text = "("+x+","+y+")";
txt.mouseEnabled = false;
map.addChild(txt);
}
}
createMine();
setFocus();//当前操作格
}

//创建提示信息
private function createTip():void {
res = new TextField;
res.x = wh;
res.y = (h+1)*wh + 10;
res.width = 200;
res.height = 30;
// res.text = "just do it ";
addChild(res);
}

//创建地雷
private function createMine():void
{
var count:uint = c;
//埋雷
while (count > 0) {
var x:uint = uint(Math.random()*w);
var y:uint = uint(Math.random()*h);
//防止埋重复的地雷
if (mapArr[x][y].mine == 0) {
mapArr[x][y].mine = 1;
count--;
(map.getChildByName("t" + x + "_" + y) as TextField).text = "*";
}
}
}

//点击地图事件处理
private function mapMouseDown(event:MouseEvent):void 
{
var point:MovieClip = event.target as MovieClip;
start(point);
}

//开始扫雷
private function start(point:MovieClip):void {
if (point.status == 1) return;//如果已扫雷,则返回
var count:uint = 0;//统计周边雷的数量
if (point.mine == 0) {
openMap(point);
// trace("无雷");
} else {
drawRect(3, point);//标识为已扫雷状态
point.status = 1;
showResult(0);//扫雷失败
}
}

//设置焦点
private function setFocus():void {
dx = 0;
dy = 0;
curr = map.getChildByName("p"+dx+"_"+dy) as MovieClip;
old = curr;
drawRect(4,curr);
}


//清除焦点
private function clearFocus(point:MovieClip):void {
if (point.status == 0) {
drawRect(0,point);
} else {
drawRect(2,point);
}
}

//改变焦点
private function changeFocus():void {
clearFocus(old);
curr = map.getChildByName("p"+dx+"_"+dy) as MovieClip;
old = curr;
drawRect(4,curr);
}


//监听键盘事件
private function keyDown(event:KeyboardEvent):void {
/*
backspace 8
tab 9
enter 13
esc 27
space 32
left   37
  up     38
right 39
down   40
*/
switch (event.keyCode) {
case Keyboard.SPACE:
start(curr);
break;
case Keyboard.LEFT:
if (dx>0) dx--;
changeFocus();
break;
case Keyboard.RIGHT:
if (dx<w-1) dx++;
changeFocus();
break;
case Keyboard.UP:
if (dy>0) dy--;
changeFocus();
break;
case Keyboard.DOWN:
if (dy<h-1) dy++;
changeFocus();
break;
case 70://'F'
case 102://'f'
var p:MovieClip = map.getChildByName("p" + dx + "_" + dy) as MovieClip;
if (p.status == 1) return;//如果已扫雷,则返回
//如果未标识,则标识为雷;否则清除
var t:TextField = map.getChildByName("t" + dx + "_" + dy) as TextField;
t.textColor = 0xff0000;
if (p.flag == 0) {
t.text = "F";
p.flag = 1;
if (p.mine == 1) {
sweepCount++;
if (sweepCount == c) showResult(1);//扫雷成功
}
} else {
t.text = "";
p.flag = 0;
}

break;
}
}

//扫雷,显示无雷节点的周边节点雷的数量
private function openMap(mc:MovieClip):void
{
var count:uint = 0;//统计周边雷的数量
//显示周边雷的情况
for (var x:int=mc.px-1; x<=mc.px+1; x++) {
for (var y:int=mc.py-1; y<=mc.py+1; y++) {
//边界处理
if (x>=0 && x<=w-1 && y>=0 && y<=h-1) {
if (x==mc.px && y==mc.py) continue;
if (mapArr[x][y].mine == 1) {
count++;
}
}
}
}
mc.status = 1;
sum++;
if (sum == w*h) showResult(1);
drawRect(2, mc);//标识为已扫雷状态
if (count > 0) {
(map.getChildByName("t" + mc.px + "_" + mc.py) as TextField).text = "" + count;
} else {
//显示节点周边雷的数量
for (x=mc.px-1; x<=mc.px+1; x++) {
for (y=mc.py-1; y<=mc.py+1; y++) {
if (x>=0 && x<=w-1 && y>=0 && y<=h-1) {
if (x==mc.px && y==mc.py) continue;
var tmp:MovieClip = map.getChildByName("p" + x + "_" + y) as MovieClip;
if (tmp.status == 0) openMap(tmp);
}
}
}
}
}

//显示结果
private function showResult(win:uint = 1):void {
if (win == 1) {
res.text = "You win!";
} else {
res.text = "You lose.";
}
}

//根据传入的数值,生成不同的节点
private function drawRect(mapPoint:uint, mc:MovieClip = null):MovieClip
{
if (null == mc) {
mc = new MovieClip;
} else {
mc.graphics.clear();
}
var color:uint;
switch (mapPoint) {
case 0 :
color=0x999999;//可通过为灰色
break;
case 1 :
color=0x000000;//不可通过为黑色
break;
case 2:
color=0xa4cec8;
break;
case 3:
color=0xff0000;
break;
case 4:
color=0x9bafb9;
break;
default :
color=0xff0000;
}//End switch
mc.graphics.beginFill(color);
mc.graphics.lineStyle(0.2,0xFFFFFF);
mc.graphics.drawRect(0,0,wh,wh);
mc.graphics.endFill();
return mc;
}
}
}
### 使用 Python 实现简单扫雷游戏 #### 创建基本框架 为了构建一个简单扫雷游戏,首先需要导入必要的库并设置全局变量。这里主要依赖于 `tkinter` 库用于图形界面开发。 ```python import tkinter as tk from tkinter import messagebox import random ``` 定义一些常量来控制游戏板大小以及地雷数量: ```python BOARD_WIDTH = 8 # 游戏区域宽度 BOARD_HEIGHT = 8 # 游戏区域高度 MINE_COUNT = 10 # 地雷总数目 ``` #### 初始化游戏面板 创建类 `GameBoard` 来管理整个游戏逻辑和UI组件。初始化方法负责建立窗口、按钮矩阵,并调用函数布置地雷位置[^1]。 ```python class GameBoard: def __init__(self, master): self.master = master self.buttons = [] self.mine_positions = set() # 设置主窗体属性 self.frame = tk.Frame(master) self.frame.pack() # 构建按钮网格布局 for row in range(BOARD_HEIGHT): button_row = [] for col in range(BOARD_WIDTH): btn = tk.Button(self.frame, width=2, height=1, command=lambda r=row, c=col: self.on_click(r, c)) btn.grid(row=row, column=col) button_row.append(btn) self.buttons.append(button_row) # 随机放置地雷 self.place_mines(MINE_COUNT) ``` #### 安置地雷 在上述代码片段中提到的方法 `place_mines()` 将会按照指定的数量随机分配地雷的位置到二维列表里保存起来以便后续判断玩家点击时是否触发爆炸事件[^3]。 ```python def place_mines(self, count): positions = list(range(BOARD_WIDTH * BOARD_HEIGHT)) selected = random.sample(positions, count) for pos in selected: self.mine_positions.add((pos // BOARD_WIDTH, pos % BOARD_WIDTH)) ``` #### 处理用户交互 当玩家点击某个方格时,则执行相应的动作&mdash;&mdash;如果踩到了地雷则结束游戏;如果没有碰到地雷,则计算周围八个方向上的地雷数目并显示出来[^2]。 ```python def on_click(self, row, col): if (row, col) in self.mine_positions: messagebox.showinfo("Game Over", "You hit a mine!") self.reset_game() # 结束当前局游戏重开新一局 else: neighbor_count = sum( ((r, c) in self.mine_positions and not ( r == row and c == col)) for r in range(max(0, row - 1), min(BOARD_HEIGHT, row + 2)) for c in range(max(0, col - 1), min(BOARD_WIDTH, col + 2))) self.update_button_text(row, col, str(neighbor_count or '')) ``` #### 更新界面上的文字信息 每当成功翻开一块安全区之后就要更新该处的文本标签为邻近的地雷计数值或者是空白字符表示此区域内无任何危险物存在。 ```python def update_button_text(self, row, col, text): self.buttons[row][col]['text'] = text self.buttons[row][col]['state'] = 'disabled' ``` #### 开始新的回合 提供给玩家重新开始的机会,在每次失败后能够立刻开启下一盘游戏而无需关闭应用程序退出再进入。 ```python def reset_game(self): for row in self.buttons: for b in row: b['text'] = '' b['state'] = 'normal' self.mine_positions.clear() self.place_mines(MINE_COUNT) ``` 最后一步是在脚本底部实例化 `tk.Tk()` 对象作为根容器启动消息循环等待接收用户的输入指令完成整个程序流程的设计。 ```python if __name__ == '__main__': root = tk.Tk() game_board = GameBoard(root) root.mainloop() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值