
//《连连看》小游戏 - (青春回忆版)
import win.ui;
import gdip;
import fonts.fontAwesome;
/*DSG{{*/
winform = win.form(text="连连看小游戏 (By: Mr_MAO)";right=583;bottom=639;bgcolor=0xFFFFFF;border="dialog frame";max=false)
winform.add(
btnReset={cls="button";text="重新开始";left=440;top=576;right=560;bottom=612;db=1;dr=1;z=2};
gameBoard={cls="plus";left=20;top=60;right=560;bottom=560;bgcolor=0xC0C0C0;db=1;dl=1;dr=1;dt=1;notify=1;z=1};
lblTime={cls="static";text="剩余时间: 60s";left=24;top=24;right=152;bottom=48;dl=1;dt=1;font=LOGFONT(h=-16;weight=700);z=3};
progressTime={cls="plus";left=160;top=28;right=560;bottom=44;bgcolor=0xEEEEEE;border={radius=8;width=1};dl=1;dr=1;dt=1;forecolor=0xFFAA44;z=4}
)
/*}}*/
var ROWS, COLS, TYPE_COUNT = 12, 12, 8;
var TOTAL_TIME = 100; // 游戏总时间(秒)
var timeLeft = TOTAL_TIME;
var timerId, map, firstSelect, activePath, isAnimating;
// 初始化地图
var initMap = function(){
var temp = {};
var total = (ROWS-2) * (COLS-2);
for(i=1;total;2){
var t = math.random(1, TYPE_COUNT);
table.push(temp, t, t);
}
for(i=#temp;1;-1){
var j = math.random(1, i);
temp[i], temp[j] = temp[j], temp[i];
}
map = {};
for(r=1;ROWS){
map[r] = {};
for(c=1;COLS){
if(r==1 || r==ROWS || c==1 || c==COLS) map[r][c] = 0;
else map[r][c] = table.remove(temp);
}
}
}
// 连通逻辑
var getDirectPath = function(r1, c1, r2, c2) {
if (r1 != r2 && c1 != c2) return null;
if (r1 == r2) {
var start, stop = math.min(c1, c2), math.max(c1, c2);
for (i = start + 1; stop - 1) if (map[r1][i] != 0) return null;
} else {
var start, stop = math.min(r1, r2), math.max(r1, r2);
for (i = start + 1; stop - 1) if (map[i][c1] != 0) return null;
}
return {{r=r1; c=c1}; {r=r2; c=c2}};
}
var getOneCornerPath = function(r1, c1, r2, c2) {
if (map[r1][c2] == 0) {
var p1 = getDirectPath(r1, c1, r1, c2);
var p2 = getDirectPath(r1, c2, r2, c2);
if(p1 && p2) return {{r=r1; c=c1}; {r=r1; c=c2}; {r=r2; c=c2}};
}
if (map[r2][c1] == 0) {
var p1 = getDirectPath(r1, c1, r2, c1);
var p2 = getDirectPath(r2, c1, r2, c2);
if(p1 && p2) return {{r=r1; c=c1}; {r=r2; c=c1}; {r=r2; c=c2}};
}
return null;
}
var getConnectPath = function(r1, c1, r2, c2) {
if (map[r1][c1] != map[r2][c2]) return null;
if (r1 == r2 && c1 == c2) return null;
var path = getDirectPath(r1, c1, r2, c2);
if(path) return path;
path = getOneCornerPath(r1, c1, r2, c2);
if(path) return path;
for (c = 1; COLS) {
if (map[r1][c] == 0) {
var p1 = getDirectPath(r1, c1, r1, c);
var p2 = getOneCornerPath(r1, c, r2, c2);
if(p1 && p2) return {{r=r1; c=c1}; {r=r1; c=c}; p2[2]; {r=r2; c=c2}};
}
}
for (r = 1; ROWS) {
if (map[r][c1] == 0) {
var p1 = getDirectPath(r1, c1, r, c1);
var p2 = getOneCornerPath(r, c1, r2, c2);
if(p1 && p2) return {{r=r1; c=c1}; {r=r; c=c1}; p2[2]; {r=r2; c=c2}};
}
}
return null;
}
// 检查是否游戏结束
var checkGameOver = function(){
for(r=1;ROWS){
for(c=1;COLS){
if(map[r][c] != 0) return false;
}
}
return true;
}
// 停止游戏
var stopGame = function(win){
if(timerId) winform.clearInterval(timerId);
isAnimating = true; // 锁定操作
if(win) winform.msgbox("恭喜你,挑战成功!","胜利");
else winform.msgbox("很遗憾,时间用完了!","游戏结束");
}
// 绘制立体小球函数
var drawGlassBall = function(graphics, rect, color, isSelected) {
// 1. 绘制主体阴影
var shadowBrush = gdip.solidBrush(0x30000000);
graphics.fillEllipse(shadowBrush, rect.x+2, rect.y+2, rect.width, rect.height);
shadowBrush.delete();
// 2. 绘制球体底色
var ballBrush = gdip.solidBrush(color);
graphics.fillEllipse(ballBrush, rect);
ballBrush.delete();
// 3. 绘制立体渐变蒙层
var highlightRect = ::RECTF(rect.x + rect.width*0.15, rect.y + rect.height*0.1, rect.width*0.5, rect.height*0.4);
var highlightBrush = gdip.solidBrush(0x80FFFFFF);
graphics.fillEllipse(highlightBrush, highlightRect);
highlightBrush.delete();
// 如果被选中,加一个外圈发光
if(isSelected){
var selectPen = gdip.pen(0xFFF00F00, 3);
graphics.drawEllipse(selectPen, rect);
selectPen.delete();
}
}
winform.gameBoard.onDrawContent = function(graphics, rc) {
var tileW = rc.width() / COLS;
var tileH = rc.height() / ROWS;
var colors = { 0xFFFF4444, 0xFF44FF44, 0xFF4444FF, 0xFFFFFF44, 0xFFFF44FF, 0xFF44FFFF, 0xFFFFA500, 0xFF800080 };
// 1. 绘制方块
for(r=1;ROWS){
for(c=1;COLS){
var val = map[r][c];
if(val == 0) continue;
var x = (c-1) * tileW;
var y = (r-1) * tileH;
var ballRect = ::RECTF(x+6, y+6, tileW-12, tileH-12);
var isSelected = (firstSelect && firstSelect.r == r && firstSelect.c == c);
drawGlassBall(graphics, ballRect, colors[val], isSelected);
}
}
// 2. 绘制连线动效
if(activePath){
var points = {};
for(i=1;#activePath){
var p = activePath[i];
table.push(points, (p.c - 0.5) * tileW, (p.r - 0.5) * tileH);
}
var linePen = gdip.pen(0xAAFF0000, 4);
linePen.dashStyle = 1/*_DashStyleDash*/;
linePen.lineJoin = 2/*_LineJoinRound*/;
graphics.drawCurve2(linePen, 0, points);
linePen.delete();
}
}
winform.gameBoard.onMouseDown = function(wParam, lParam){
if(isAnimating) return;
var x, y = win.getMessagePos(lParam);
var rc = owner.getClientRect();
var c = math.floor(x / (rc.width() / COLS)) + 1;
var r = math.floor(y / (rc.height() / ROWS)) + 1;
if(r < 1 || r > ROWS || c < 1 || c > COLS || map[r][c] == 0) return;
if(!firstSelect || (firstSelect.r == r && firstSelect.c == c)){
firstSelect = {r=r; c=c};
owner.redraw();
} else {
var path = getConnectPath(firstSelect.r, firstSelect.c, r, c);
if(path){
activePath = path;
isAnimating = true;
var r1, c1, r2, c2 = firstSelect.r, firstSelect.c, r, c;
firstSelect = null;
owner.redraw();
winform.setTimeout(function(){
map[r1][c1], map[r2][c2] = 0, 0;
activePath = null;
isAnimating = false;
winform.gameBoard.redraw();
if(checkGameOver()) stopGame(true);
}, 150);
} else {
firstSelect = {r=r; c=c};
owner.redraw();
}
}
}
// 开始/重置游戏
var startGame = function(){
if(timerId) winform.clearInterval(timerId);
timeLeft = TOTAL_TIME;
isAnimating = false;
firstSelect = null;
activePath = null;
initMap();
winform.progressTime.setProgressRange(1, TOTAL_TIME);
winform.progressTime.progressPos = TOTAL_TIME;
timerId = winform.setInterval(function(){
timeLeft--;
winform.lblTime.text = "剩余时间: " + timeLeft + "s";
winform.progressTime.progressPos = timeLeft;
if(timeLeft <= 0) stopGame(false);
}, 1000);
winform.gameBoard.redraw();
}
winform.btnReset.oncommand = function(id,event){
startGame();
}
startGame();
winform.show();
win.loopMessage();