
import win.ui;
/*DSG{{*/
var winform = win.form(text="五子棋游戏 (By: Mr_MAO)";right=760;bottom=620;bgcolor=0xFFFFFF;border="dialog frame";max=false)
winform.add(
boardPlus={cls="plus";left=10;top=10;right=610;bottom=610;bgcolor=0xFFFFFF;edge=1;forecolor=0xFFFFFF;notify=1;z=1};
btnRestart={cls="button";text="重新开始";left=630;top=20;right=730;bottom=60;z=2};
staticInfo={cls="static";text="玩家执黑先行";left=630;top=80;right=730;bottom=200;transparent=1;z=3}
)
/*}}*/
// --- 游戏配置 ---
var boardSize = 15; // 棋盘 15x15
var cellSize = 40; // 格子变大一点,视觉更好
var margin = 20; // 棋盘边缘留白
var pieceRadius = 17; // 棋子半径
// --- 游戏状态 ---
var board = {}; // 存储棋盘数据 0:空, 1:黑(玩家), 2:白(电脑)
var isPlayerTurn = true;
var isGameOver = false;
// --- 初始化/重置游戏 ---
function initGame(){
for(r=1;boardSize){
board[r] = {};
for(c=1;boardSize){
board[r][c] = 0;
}
}
isPlayerTurn = true;
isGameOver = false;
winform.staticInfo.text = '当前回合:\n玩家 (黑棋)';
winform.boardPlus.redraw();
}
// --- Plus控件绘图逻辑 ---
winform.boardPlus.onDrawForegroundEnd = function(graphics,rc){
graphics.smoothingMode = 4; // 抗锯齿
// 1. 绘制棋盘底色 (在Plus区域内)
var brushBg = gdip.solidBrush(0xFFEEDD82);
graphics.fillRectangle(brushBg, 0, 0, rc.width, rc.height);
brushBg.delete();
// 2. 绘制网格线
var penLine = gdip.pen(0xFF000000, 1);
var boardWidth = (boardSize-1) * cellSize;
// 确保网格居中绘制
var offsetX = margin;
var offsetY = margin;
for(i=1;boardSize){
var pos = (i-1)*cellSize;
// 横线
graphics.drawLine(penLine, offsetX, offsetY + pos, offsetX + boardWidth, offsetY + pos);
// 竖线
graphics.drawLine(penLine, offsetX + pos, offsetY, offsetX + pos, offsetY + boardWidth);
}
// 3. 绘制天元和星位
var brushDot = gdip.solidBrush(0xFF000000);
var stars = {4;8;12};
for(i=1;3){
for(j=1;3){
var x = offsetX + (stars[i]-1)*cellSize;
var y = offsetY + (stars[j]-1)*cellSize;
graphics.fillEllipse(brushDot, x-4, y-4, 8, 8);
}
}
brushDot.delete();
// 4. 绘制棋子
var brushBlack = gdip.solidBrush(0xFF000000);
var brushWhite = gdip.solidBrush(0xFFFFFFFF);
var penBorder = gdip.pen(0xFFAAAAAA, 1);
for(r=1;boardSize){
for(c=1;boardSize){
if(board[r][c] != 0){
var px = offsetX + (c-1)*cellSize;
var py = offsetY + (r-1)*cellSize;
if(board[r][c] == 1){
// 黑棋 + 简单的反光效果
graphics.fillEllipse(brushBlack, px-pieceRadius, py-pieceRadius, pieceRadius*2, pieceRadius*2);
var brushShine = gdip.solidBrush(0x50FFFFFF);
graphics.fillEllipse(brushShine, px-pieceRadius+5, py-pieceRadius+5, 10, 10);
brushShine.delete();
} elseif(board[r][c] == 2){
// 白棋
graphics.fillEllipse(brushWhite, px-pieceRadius, py-pieceRadius, pieceRadius*2, pieceRadius*2);
graphics.drawEllipse(penBorder, px-pieceRadius, py-pieceRadius, pieceRadius*2, pieceRadius*2);
}
}
}
}
brushBlack.delete();
brushWhite.delete();
penLine.delete();
penBorder.delete();
}
// --- 胜负判定 ---
function checkWin(r, c, color){
var directions = {{1;0}; {0;1}; {1;1}; {1;-1}};
for(k=1;4){
var count = 1;
var dr = directions[k][1];
var dc = directions[k][2];
// 正向
var i = 1;
while(true){
var nr = r + dr*i;
var nc = c + dc*i;
if(nr<1 || nr>boardSize || nc<1 || nc>boardSize || board[nr][nc]!=color) break;
count++; i++;
}
// 反向
i = 1;
while(true){
var nr = r - dr*i;
var nc = c - dc*i;
if(nr<1 || nr>boardSize || nc<1 || nc>boardSize || board[nr][nc]!=color) break;
count++; i++;
}
if(count >= 5) return true;
}
return false;
}
// --- AI 逻辑 ---
function evaluatePoint(r, c, color){
var score = 0;
var directions = {{1;0}; {0;1}; {1;1}; {1;-1}};
for(k=1;4){
var dr = directions[k][1];
var dc = directions[k][2];
var count = 1;
var emptySides = 0;
// Check side 1
var i = 1;
while(true){
var nr = r + dr*i;
var nc = c + dc*i;
if(nr<1||nr>boardSize||nc<1||nc>boardSize) break;
if(board[nr][nc]==color) count++;
elseif(board[nr][nc]==0){ emptySides++; break;}
else break;
i++;
}
// Check side 2
i = 1;
while(true){
var nr = r - dr*i;
var nc = c - dc*i;
if(nr<1||nr>boardSize||nc<1||nc>boardSize) break;
if(board[nr][nc]==color) count++;
elseif(board[nr][nc]==0){ emptySides++; break;}
else break;
i++;
}
if(count >= 5) score += 100000;
elseif(count == 4 && emptySides == 2) score += 10000;
elseif(count == 4 && emptySides == 1) score += 1000;
elseif(count == 3 && emptySides == 2) score += 1000;
elseif(count == 3 && emptySides == 1) score += 100;
elseif(count == 2 && emptySides == 2) score += 100;
elseif(count == 2 && emptySides == 1) score += 10;
}
return score;
}
function computerMove(){
if(isGameOver) return;
var maxScore = -1;
var bestPoints = {};
for(r=1;boardSize){
for(c=1;boardSize){
if(board[r][c] == 0){
// 进攻(己方) + 防守(敌方)
var attack = evaluatePoint(r, c, 2);
var defend = evaluatePoint(r, c, 1);
var total = attack + defend;
if(attack >= 100000) total = 9999999; // 必胜
if(total > maxScore){
maxScore = total;
bestPoints = {{r;c}};
} elseif(total == maxScore){
table.push(bestPoints, {r;c});
}
}
}
}
if(#bestPoints == 0) return;
var move = bestPoints[math.random(1, #bestPoints)];
board[move[1]][move[2]] = 2;
winform.boardPlus.redraw();
if(checkWin(move[1], move[2], 2)){
isGameOver = true;
winform.msgbox("电脑获胜!","游戏结束");
return;
}
isPlayerTurn = true;
winform.staticInfo.text = '当前回合:\n玩家 (黑棋)';
}
// --- 交互事件绑定到 Plus 控件 ---
winform.boardPlus.onMouseDown = function(wParam,lParam){
if(isGameOver || !isPlayerTurn) return;
// 获取相对于 Plus 控件的坐标
var x,y = win.getMessagePos(lParam);
// 坐标换算为行列
var c = math.round((x - margin) / cellSize) + 1;
var r = math.round((y - margin) / cellSize) + 1;
// 边界检查
if(c < 1 || c > boardSize || r < 1 || r > boardSize) return;
// 模糊点击范围检查 (防止点在格子中间也落子)
var centerX = margin + (c-1)*cellSize;
var centerY = margin + (r-1)*cellSize;
var dist = math.sqrt( (x-centerX)**2 + (y-centerY)**2 );
if(dist > pieceRadius + 5) return; // 距离交叉点太远则无效
// 检查空位
if(board[r][c] != 0) return;
// 玩家落子
board[r][c] = 1;
winform.boardPlus.redraw(); // 触发 onDraw
if(checkWin(r, c, 1)){
isGameOver = true;
winform.msgbox("你赢了!","游戏结束");
return;
}
isPlayerTurn = false;
winform.staticInfo.text = '当前回合:\n电脑思考中...';
// 延时让电脑下棋,避免界面卡顿
winform.setTimeout(function(){
computerMove();
}, 50);
}
winform.btnRestart.oncommand = function(id,event){
initGame();
}
initGame(); //运行程序后,直接开始游戏
winform.enableDpiScaling(false);
winform.show();
win.loopMessage();