免费 o3 mini high写的AI中国象棋网站,佬们可以测试其它模型的效果

  • 主题发起人 主题发起人 Scare
  • 开始时间 开始时间

Scare

0xFF|主权幽灵
07
908
172
奇源币
0
管理成员
工作人员
版主
VIP



PixPin_2025-02-25_22-33-02
PixPin_2025-02-25_22-33-021920×949 73.9 KB



<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>中国象棋</title>
<style>
body {
background: linear-gradient(135deg, #E0E0E0, #FFFFFF);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 20px;
text-align: center;
}
h1 {
color: #333;
}
#controls {
margin-bottom: 15px;
}
#status {
font-size: 18px;
margin-bottom: 10px;
color: #444;
}
#board {
background-color: #e6d8b3;
border: 2px solid #333;
box-shadow: 4px 4px 10px rgba(0,0,0,0.2);
cursor: pointer;
}
select, button {
padding: 5px 10px;
margin: 0 5px;
font-size: 16px;
}
</style>
</head>
<body>
<h1>中国象棋</h1>
<div id="controls">
<label for="difficulty">机器人难度:</label>
<!-- 提供更高搜索深度,数字越大 AI 计算量越高 -->
<select id="difficulty">
<option value="3">简单</option>
<option value="5" selected>中等</option>
<option value="7">困难</option>
<option value="9">专家</option>
</select>
<button id="restart">重新开始</button>
</div>
<div id="status">红方走棋</div>
<canvas id="board" width="450" height="500"></canvas>
<script>
(function(){
// 常量定义
const COLS = 9;
const ROWS = 10;
const CELL_SIZE = 50;

// 全局状态
let board = [];
let currentTurn = 'red'; // 红方玩家,黑方由 AI 操作
let selectedPiece = null;
let selectedPos = null;

// 获取页面元素
const canvas = document.getElementById('board');
const ctx = canvas.getContext('2d');
const statusEl = document.getElementById('status');

// 棋子估值(用于简单评估函数)
const pieceValues = {
king: 10000,
advisor: 110,
elephant: 110,
horse: 300,
chariot: 600,
cannon: 300,
soldier: 70
};

// 初始化棋盘状态
function initBoard(){
board = Array.from({length: ROWS}, () => Array(COLS).fill(null));
// 黑方(上方)
board[0][0] = {type: 'chariot', color: 'black'};
board[0][1] = {type: 'horse', color: 'black'};
board[0][2] = {type: 'elephant', color: 'black'};
board[0][3] = {type: 'advisor', color: 'black'};
board[0][4] = {type: 'king', color: 'black'};
board[0][5] = {type: 'advisor', color: 'black'};
board[0][6] = {type: 'elephant', color: 'black'};
board[0][7] = {type: 'horse', color: 'black'};
board[0][8] = {type: 'chariot', color: 'black'};
board[2][1] = {type: 'cannon', color: 'black'};
board[2][7] = {type: 'cannon', color: 'black'};
board[3][0] = {type: 'soldier', color: 'black'};
board[3][2] = {type: 'soldier', color: 'black'};
board[3][4] = {type: 'soldier', color: 'black'};
board[3][6] = {type: 'soldier', color: 'black'};
board[3][8] = {type: 'soldier', color: 'black'};
// 红方(下方)
board[9][0] = {type: 'chariot', color: 'red'};
board[9][1] = {type: 'horse', color: 'red'};
board[9][2] = {type: 'elephant', color: 'red'};
board[9][3] = {type: 'advisor', color: 'red'};
board[9][4] = {type: 'king', color: 'red'};
board[9][5] = {type: 'advisor', color: 'red'};
board[9][6] = {type: 'elephant', color: 'red'};
board[9][7] = {type: 'horse', color: 'red'};
board[9][8] = {type: 'chariot', color: 'red'};
board[7][1] = {type: 'cannon', color: 'red'};
board[7][7] = {type: 'cannon', color: 'red'};
board[6][0] = {type: 'soldier', color: 'red'};
board[6][2] = {type: 'soldier', color: 'red'};
board[6][4] = {type: 'soldier', color: 'red'};
board[6][6] = {type: 'soldier', color: 'red'};
board[6][8] = {type: 'soldier', color: 'red'};

currentTurn = 'red';
selectedPiece = null;
selectedPos = null;
updateStatus("红方走棋");
}

// 根据棋子类型和颜色返回显示字符
function getPieceChar(piece){
if(!piece) return "";
switch(piece.type){
case 'king': return piece.color === 'red' ? '帅' : '将';
case 'advisor': return piece.color === 'red' ? '仕' : '士';
case 'elephant': return piece.color === 'red' ? '相' : '象';
case 'horse': return '马';
case 'chariot': return '车';
case 'cannon': return '炮';
case 'soldier': return piece.color === 'red' ? '兵' : '卒';
default: return "";
}
}

// 绘制棋盘和棋子
function draw(){
ctx.clearRect(0,0, canvas.width, canvas.height);
// 绘制棋盘网格
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
for(let i = 0; i < COLS; i++){
ctx.beginPath();
ctx.moveTo(i * CELL_SIZE + CELL_SIZE/2, CELL_SIZE/2);
ctx.lineTo(i * CELL_SIZE + CELL_SIZE/2, (ROWS-1)*CELL_SIZE + CELL_SIZE/2);
ctx.stroke();
}
for(let j = 0; j < ROWS; j++){
ctx.beginPath();
ctx.moveTo(CELL_SIZE/2, j * CELL_SIZE + CELL_SIZE/2);
ctx.lineTo((COLS-1)*CELL_SIZE + CELL_SIZE/2, j * CELL_SIZE + CELL_SIZE/2);
ctx.stroke();
}
// 绘制宫内斜线
ctx.beginPath();
// 黑宫:3~5列,0~2行
ctx.moveTo(3*CELL_SIZE + CELL_SIZE/2, 0*CELL_SIZE + CELL_SIZE/2);
ctx.lineTo(5*CELL_SIZE + CELL_SIZE/2, 2*CELL_SIZE + CELL_SIZE/2);
ctx.moveTo(5*CELL_SIZE + CELL_SIZE/2, 0*CELL_SIZE + CELL_SIZE/2);
ctx.lineTo(3*CELL_SIZE + CELL_SIZE/2, 2*CELL_SIZE + CELL_SIZE/2);
ctx.stroke();
ctx.beginPath();
// 红宫:3~5列,7~9行
ctx.moveTo(3*CELL_SIZE + CELL_SIZE/2, 7*CELL_SIZE + CELL_SIZE/2);
ctx.lineTo(5*CELL_SIZE + CELL_SIZE/2, 9*CELL_SIZE + CELL_SIZE/2);
ctx.moveTo(5*CELL_SIZE + CELL_SIZE/2, 7*CELL_SIZE + CELL_SIZE/2);
ctx.lineTo(3*CELL_SIZE + CELL_SIZE/2, 9*CELL_SIZE + CELL_SIZE/2);
ctx.stroke();

// 高亮显示已选中的格子
if(selectedPos){
ctx.fillStyle = "rgba(0,255,0,0.3)";
ctx.fillRect(selectedPos.x * CELL_SIZE, selectedPos.y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
}

// 绘制棋子
for(let y = 0; y < ROWS; y++){
for(let x = 0; x < COLS; x++){
const piece = board[y][x];
if(piece){
ctx.beginPath();
ctx.arc(x * CELL_SIZE + CELL_SIZE/2, y * CELL_SIZE + CELL_SIZE/2, CELL_SIZE/2 - 5, 0, Math.PI*2);
ctx.fillStyle = piece.color === 'red' ? "#f88" : "#aaa";
ctx.fill();
ctx.stroke();
ctx.fillStyle = "#000";
ctx.font = "24px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(getPieceChar(piece), x * CELL_SIZE + CELL_SIZE/2, y * CELL_SIZE + CELL_SIZE/2);
}
}
}
}

// 更新状态提示信息
function updateStatus(msg){
statusEl.textContent = msg;
}

// 判断坐标是否在棋盘内
function inBounds(x, y){
return x >= 0 && x < COLS && y >= 0 && y < ROWS;
}

// 为指定颜色生成所有合法走法
function generateMoves(boardState, color){
let moves = [];
for(let y = 0; y < ROWS; y++){
for(let x = 0; x < COLS; x++){
const piece = boardState[y][x];
if(piece && piece.color === color){
moves.push(...generatePieceMoves(boardState, x, y, piece));
}
}
}
return moves;
}

// 根据棋子类型生成走法(覆盖基本走法规则,不穷尽所有特殊规则)
function generatePieceMoves(boardState, x, y, piece){
let moves = [];
function addMove(nx, ny){
if(!inBounds(nx, ny)) return;
const target = boardState[ny][nx];
if(!target || target.color !== piece.color){
moves.push({from: {x, y}, to: {x: nx, y: ny}});
}
}
if(piece.type === 'king'){
const deltas = [[1,0],[-1,0],[0,1],[0,-1]];
for(let d of deltas){
let nx = x + d[0], ny = y + d[1];
if(piece.color === 'red'){
if(nx < 3 || nx > 5 || ny < 7 || ny > 9) continue;
} else {
if(nx < 3 || nx > 5 || ny < 0 || ny > 2) continue;
}
addMove(nx, ny);
}
// “将帅见面”规则实际对局中会直接判负,此处不作为合法走法添加
} else if(piece.type === 'advisor'){
const deltas = [[1,1],[1,-1],[-1,1],[-1,-1]];
for(let d of deltas){
let nx = x + d[0], ny = y + d[1];
if(piece.color === 'red'){
if(nx < 3 || nx > 5 || ny < 7 || ny > 9) continue;
} else {
if(nx < 3 || nx > 5 || ny < 0 || ny > 2) continue;
}
addMove(nx, ny);
}
} else if(piece.type === 'elephant'){
const deltas = [[2,2],[2,-2],[-2,2],[-2,-2]];
for(let d of deltas){
let nx = x + d[0], ny = y + d[1];
if(piece.color === 'red' && ny < 5) continue;
if(piece.color === 'black' && ny > 4) continue;
let mx = x + d[0] / 2, my = y + d[1] / 2;
if(!inBounds(nx, ny)) continue;
if(boardState[my][mx]) continue;
addMove(nx, ny);
}
} else if(piece.type === 'horse'){
const horseMoves = [
{dx:2, dy:1, blockX:1, blockY:0},
{dx:2, dy:-1, blockX:1, blockY:0},
{dx:-2, dy:1, blockX:-1, blockY:0},
{dx:-2, dy:-1, blockX:-1, blockY:0},
{dx:1, dy:2, blockX:0, blockY:1},
{dx:-1, dy:2, blockX:0, blockY:1},
{dx:1, dy:-2, blockX:0, blockY:-1},
{dx:-1, dy:-2, blockX:0, blockY:-1}
];
for(let move of horseMoves){
let bx = x + move.blockX, by = y + move.blockY;
let nx = x + move.dx, ny = y + move.dy;
if(!inBounds(nx, ny)) continue;
if(boardState[by][bx]) continue;
addMove(nx, ny);
}
} else if(piece.type === 'chariot'){
const directions = [[1,0],[-1,0],[0,1],[0,-1]];
for(let d of directions){
let nx = x, ny = y;
while(true){
nx += d[0]; ny += d[1];
if(!inBounds(nx, ny)) break;
if(boardState[ny][nx]){
if(boardState[ny][nx].color !== piece.color)
moves.push({from: {x, y}, to: {x: nx, y: ny}});
break;
} else {
moves.push({from: {x, y}, to: {x: nx, y: ny}});
}
}
}
} else if(piece.type === 'cannon'){
const directions = [[1,0],[-1,0],[0,1],[0,-1]];
for(let d of directions){
let nx = x, ny = y;
// 不吃子走法
while(true){
nx += d[0]; ny += d[1];
if(!inBounds(nx, ny)) break;
if(boardState[ny][nx]) break;
moves.push({from: {x, y}, to: {x: nx, y: ny}});
}
// 吃子走法:需先隔一个障碍
nx = x; ny = y;
let jumped = false;
while(true){
nx += d[0]; ny += d[1];
if(!inBounds(nx, ny)) break;
if(!jumped){
if(boardState[ny][nx]) jumped = true;
} else {
if(boardState[ny][nx]){
if(boardState[ny][nx].color !== piece.color)
moves.push({from: {x, y}, to: {x: nx, y: ny}});
break;
}
}
}
}
} else if(piece.type === 'soldier'){
let forward = piece.color === 'red' ? -1 : 1;
addMove(x, y + forward);
// 过河后可左右走
if((piece.color === 'red' && y + forward < 5) ||
(piece.color === 'black' && y + forward > 4)){
addMove(x + 1, y);
addMove(x - 1, y);
}
}
return moves;
}

// 查找指定颜色的帅/将位置
function findKing(boardState, color){
for(let y = 0; y < ROWS; y++){
for(let x = 0; x < COLS; x++){
const piece = boardState[y][x];
if(piece && piece.type === 'king' && piece.color === color){
return {x, y};
}
}
}
return null;
}

// 应用走法,返回新棋盘状态(复制各行数组)
function applyMove(boardState, move){
let newBoard = boardState.map(row => row.slice());
newBoard[move.to.y][move.to.x] = newBoard[move.from.y][move.from.x];
newBoard[move.from.y][move.from.x] = null;
return newBoard;
}

// 简单评估函数:从黑方视角计算局面分数
function evaluateBoard(boardState){
let score = 0;
for(let y = 0; y < ROWS; y++){
for(let x = 0; x < COLS; x++){
const piece = boardState[y][x];
if(piece){
let val = pieceValues[piece.type] || 0;
score += (piece.color === 'black' ? val : -val);
}
}
}
return score;
}

// 判断是否结束(某方帅/将不存在)
function gameOver(boardState){
return !findKing(boardState, 'red') || !findKing(boardState, 'black');
}

// minimax 搜索(带 α–β 剪枝)
function minimax(boardState, depth, alpha, beta, maximizingPlayer){
if(depth === 0 || gameOver(boardState)){
return evaluateBoard(boardState);
}
if(maximizingPlayer){
let maxEval = -Infinity;
let moves = generateMoves(boardState, 'black');
for(let move of moves){
let newBoard = applyMove(boardState, move);
let evalVal = minimax(newBoard, depth - 1, alpha, beta, false);
maxEval = Math.max(maxEval, evalVal);
alpha = Math.max(alpha, evalVal);
if(beta <= alpha) break;
}
return maxEval;
} else {
let minEval = Infinity;
let moves = generateMoves(boardState, 'red');
for(let move of moves){
let newBoard = applyMove(boardState, move);
let evalVal = minimax(newBoard, depth - 1, alpha, beta, true);
minEval = Math.min(minEval, evalVal);
beta = Math.min(beta, evalVal);
if(beta <= alpha) break;
}
return minEval;
}
}

// AI 走棋:根据下拉框选择的搜索深度
function aiMove(){
const depth = parseInt(document.getElementById("difficulty").value);
let moves = generateMoves(board, 'black');
if(moves.length === 0) return;
let bestMove = null;
let bestEval = -Infinity;
for(let move of moves){
let newBoard = applyMove(board, move);
let evalVal = minimax(newBoard, depth, -Infinity, Infinity, false);
if(evalVal > bestEval){
bestEval = evalVal;
bestMove = move;
}
}
if(bestMove){
board = applyMove(board, bestMove);
currentTurn = 'red';
updateStatus("红方走棋");
draw();
if(gameOver(board)){
updateStatus("游戏结束!");
alert("游戏结束!");
}
}
}

// 处理玩家点击(红方走棋)
function handleClick(event){
if(currentTurn !== 'red') return;
const rect = canvas.getBoundingClientRect();
const x = Math.floor((event.clientX - rect.left) / CELL_SIZE);
const y = Math.floor((event.clientY - rect.top) / CELL_SIZE);
if(!inBounds(x, y)) return;
const clickedPiece = board[y][x];
// 若已有选中棋子,尝试走到目标位置
if(selectedPiece){
let valid = false;
let moves = generatePieceMoves(board, selectedPos.x, selectedPos.y, selectedPiece);
for(let move of moves){
if(move.to.x === x && move.to.y === y){
valid = true;
break;
}
}
if(valid){
board = applyMove(board, {from: selectedPos, to: {x, y}});
selectedPiece = null;
selectedPos = null;
currentTurn = 'black';
updateStatus("电脑思考中...");
draw();
if(gameOver(board)){
updateStatus("游戏结束!");
alert("游戏结束!");
return;
}
// 稍作延时后 AI 落子
setTimeout(aiMove, 500);
return;
} else {
// 如果再次点击自己的棋子,则切换选中;否则取消选中
if(clickedPiece && clickedPiece.color === 'red'){
selectedPiece = clickedPiece;
selectedPos = {x, y};
draw();
return;
}
selectedPiece = null;
selectedPos = null;
draw();
return;
}
}
// 选中红方棋子
if(clickedPiece && clickedPiece.color === 'red'){
selectedPiece = clickedPiece;
selectedPos = {x, y};
draw();
}
}

canvas.addEventListener("click", handleClick);
document.getElementById("restart").addEventListener("click", function(){
initBoard();
draw();
});

// 初始化并绘制棋盘
initBoard();
draw();
})();
</script>
</body>
</html>
 
后退
顶部