html,body{ margin: 0; padding: 0; }
#canvas{ display: block; width: 100%; height:100%; margin: 5px auto 0; }
class Gobang{
constructor(options){
this.initElement(options);
this.initScale(options);
this.initStyle(options);
this.initPlayer(options);
this.viewChoose();
}
// 初始化绘制元素
initElement({element}){
if(!element){ throw new Error("初始化元素不能为空"); }
this.canvas = element;
this._2d = this.canvas.getContext("2d");
}
// 初始化规格
initScale({width,height,widthLength,heightLength}){
this.width = width;
this.height = height;
this.widthLength = widthLength;
this.heightLength = heightLength;
this.widthEvery = this.width/this.widthLength;
this.heightEvery = this.height/this.heightLength;
this.xLength = this.widthLength-1;
this.yLength = this.heightLength-1;
this.initDrawSize();
}
// 初始化绘制大小
initDrawSize(){
const width = this.width;
const height = this.height;
const canvas = this.canvas;
canvas.width = width;
canvas.height = height;
canvas.style.width = width;
canvas.style.height = height;
}
//初始化样式
initStyle({lineColor,backgroundColor}){
this.lineColor = lineColor;
this.backgroundColor = backgroundColor;
}
// 初始化播放列表
initPlayer({playerList}){
this.playerList = playerList;
}
// 添加事件
addEvent(type,fn,useCapture){
const canvas = this.canvas;
canvas.addEventListener(type,fn,useCapture);
this.EventList.push(()=>{
canvas.removeEventListener(type,fn,useCapture);
});
}
// 移除事件
removeEvent(){
if(this.EventList){
this.EventList.forEach(removeEvent=>{
removeEvent();
});
}
this.EventList = [];
}
// 重置游戏棋盘
resetPlayBoard(){
const xLength = this.xLength;
const yLength = this.yLength;
this.playerIndex = 0;
this.pieceHover = null;
this.chessBoard = new Array(xLength).fill(null).map(_=>
new Array(yLength).fill(null)
);
}
// 添加游戏玩家
appendPlayer(player){
this.playerList.push(player);
}
// 绘制游戏背景
drawPlayBackground = function(){
const _2d = this._2d;
const width = this.width;
const height = this.height;
const lineColor = this.lineColor;
const backgroundColor = this.backgroundColor;
_2d.save();
_2d.fillStyle = backgroundColor;
_2d.fillRect(0, 0, width, height);
_2d.strokeStyle = lineColor;
_2d.strokeRect(0, 0, width, height);
_2d.restore();
}
// 绘制游戏X轴
drawPlayXLine(){
const _2d = this._2d;
const width = this.width;
const length = this.heightLength;
const every = this.widthEvery;
_2d.save();
_2d.strokeStyle = this.lineColor;
for(let i=0; i
const y = every*i;
_2d.beginPath();
_2d.moveTo(0,y);
_2d.lineTo(width,y);
_2d.stroke();
}
_2d.restore();
}
// 绘制游戏Y轴
drawPlayYLine(){
const _2d = this._2d;
const height = this.height;
const length = this.widthLength;
const every = this.heightEvery;
_2d.save();
_2d.strokeStyle = this.lineColor;
for(let i=0; i
const x = every*i;
_2d.beginPath();
_2d.moveTo(x,0);
_2d.lineTo(x,height);
_2d.stroke();
}
_2d.restore();
}
// 绘制游戏棋子
drawPlayPiece(){
const _2d = this._2d;
const widthEvery = this.widthEvery;
const heightEvery = this.heightEvery;
const min = Math.min(widthEvery,heightEvery);
const lineColor = this.lineColor;
const chessBoard = this.chessBoard;
const playerList = this.playerList;
const playerLength = this.playerList.length;
_2d.save();
chessBoard.forEach((xData,xIndex)=>xData.forEach((playerIndex,yIndex)=>{
if(playerIndex!=null && playerIndex
const x = (xIndex+1)*widthEvery;
const y = (yIndex+1)*heightEvery;
const playInfo = playerList[playerIndex];
_2d.strokeStyle = lineColor;
_2d.fillStyle = playInfo.color;
_2d.beginPath();
_2d.arc(x,y,min/2*.8,0,Math.PI*2);
_2d.fill();
_2d.stroke();
}
}));
const pieceHover = this.pieceHover;
if(pieceHover){
const playerIndex = this.playerIndex;
const [xIndex,yIndex] = pieceHover;
const value = chessBoard[xIndex][yIndex];
if(value == null){
const x = (xIndex+1)*widthEvery;
const y = (yIndex+1)*heightEvery;
const playInfo = playerList[playerIndex];
_2d.globalAlpha = 0.3;
_2d.strokeStyle = lineColor;
_2d.fillStyle = playInfo.color;
_2d.beginPath();
_2d.arc(x,y,min/2*.8,0,Math.PI*2);
_2d.fill();
_2d.stroke();
_2d.globalAlpha = 1;
}
}
_2d.restore();
}
// 绘制游戏棋局
drawPlay(){
this.drawPlayBackground();
this.drawPlayXLine();
this.drawPlayYLine();
this.drawPlayPiece();
}
// 检查一个棋盘棋子
checkPlayOne(xIndex,yIndex,playerIndex){
const col = this.chessBoard[xIndex];
return col && col[yIndex] == playerIndex;
}
// 检查X轴棋盘棋子
checkPlayX(xIndex,yIndex,playerIndex){
let count = 1;
for(let i=1; i<5; i++){
if(this.checkPlayOne(xIndex-i,yIndex,playerIndex)){
count++;
}else{
break;
}
}
for(let i=1; i<5; i++){
if(this.checkPlayOne(xIndex+i,yIndex,playerIndex)){
count++;
}else{
break;
}
}
return count>=5;
}
// 检查Y轴棋盘棋子
checkPlayY(xIndex,yIndex,playerIndex){
let count = 1;
for(let i=1; i<5; i++){
if(this.checkPlayOne(xIndex,yIndex-i,playerIndex)){
count++;
}else{
break;
}
}
for(let i=1; i<5; i++){
if(this.checkPlayOne(xIndex,yIndex+i,playerIndex)){
count++;
}else{
break;
}
}
return count>=5;
}
// 检查左上到右下棋盘棋子
checkPlayLeftTop(xIndex,yIndex,playerIndex){
let count = 1;
for(let i=1; i<5; i++){
if(this.checkPlayOne(xIndex-i,yIndex-i,playerIndex)){
count++;
}else{
break;
}
}
for(let i=1; i<5; i++){
if(this.checkPlayOne(xIndex+i,yIndex+i,playerIndex)){
count++;
}else{
break;
}
}
return count>=5;
}
// 检查左下到右上棋盘棋子
checkLeftButton(xIndex,yIndex,playerIndex){
let count = 1;
for(let i=1; i<5; i++){
if(this.checkPlayOne(xIndex-i,yIndex+i,playerIndex)){
count++;
}else{
break;
}
}
for(let i=1; i<5; i++){
if(this.checkPlayOne(xIndex+i,yIndex-i,playerIndex)){
count++;
}else{
break;
}
}
return count>=5;
}
// 检查游戏是否结束
checkPlayGameOver(xIndex,yIndex,playerIndex){
return this.checkPlayX(xIndex,yIndex,playerIndex)||
this.checkPlayY(xIndex,yIndex,playerIndex)||
this.checkPlayLeftTop(xIndex,yIndex,playerIndex)||
this.checkLeftButton(xIndex,yIndex,playerIndex);
}
// 落下棋子点
nextPlayChess(position){
if(position == null){ return; }
const [xIndex,yIndex] = position;
const xLength = this.xLength;
const yLength = this.yLength;
const chessBoard = this.chessBoard;
const playerIndex = this.playerIndex;
const playerLength = this.playerList.length;
if(xIndex>xLength){ throw new Error("下棋横向位置超出范围"); }
if(yIndex>yLength){ throw new Error("下棋横向位置超出范围"); }
const value = chessBoard[xIndex][yIndex];
if(value != null){ return; }
chessBoard[xIndex][yIndex] = playerIndex;
const isGameOver = this.checkPlayGameOver(xIndex,yIndex,playerIndex);
if(isGameOver){
this.playGameOver();
return;
}else{
if(++this.playerIndex>=playerLength){
this.playerIndex=0;
}
}
this.drawPlay();
}
// 落下棋子坐标
nexPlayPointtChess(x,y){
this.nextPlayChess(this.getPlayPieceIndex(x,y));
}
// 鼠标悬停点
setPlayPieceHover(position){
this.pieceHover = position;
this.drawPlay();
}
// 鼠标悬停坐标
setPointHover(x,y){
this.setPlayPieceHover(this.getPlayPieceIndex(x,y));
}
// 取坐标的点位置
getPlayPieceIndex(left,top){
const xLength = this.xLength;
const yLength = this.yLength;
const widthEvery = this.widthEvery;
const heightEvery = this.heightEvery;
const widthEveryHalf = widthEvery/2;
const heightEveryHalf = heightEvery/2;
const x=left-widthEveryHalf;
const y=top-heightEveryHalf;
if(x<0 || y<0){ return null; }
const xIndex = Math.ceil(x/widthEvery)-1;
const yIndex = Math.ceil(y/heightEvery)-1;
if(xIndex>xLength-1 || yIndex>yLength-1){ return null; }
return [xIndex, yIndex];
};
// 添加游戏事件
addPlayEvent(){
this.removeEvent();
this.addEvent("click",e=>{
this.nexPlayPointtChess(e.offsetX,e.offsetY);
});
this.addEvent("mousemove",e=>{
this.setPointHover(e.offsetX,e.offsetY);
});
this.addEvent("mouseleave",e=>{
this.setPlayPieceHover(null);
});
}
// 游戏结束
playGameOver(){
const playInfo = this.playerList[this.playerIndex];
alert(`${playInfo.name}获得游戏的胜利`);
this.resetPlayBoard();
}
// 进入游戏界面
viewPlay(){
this.resetPlayBoard();
this.addPlayEvent();
this.drawPlay();
}
// 初始化选择界面元素
resetChooseElement(){
const width = this.width;
const height = this.height;
const widthSize = 85;
const heightSize = 20;
const context = "开始游戏";
this.chooseButton={
left:(width-widthSize)/2,
top:(height-heightSize)/2,
width: widthSize,
height: heightSize,
};
this.chooseContext={
string:context,
size:heightSize*.8,
left:width/2,
top:height/2+1,
};
}
// 绘制游戏棋局
drawChoose(){
const _2d = this._2d;
const width = this.width;
const height = this.height;
const lineColor = this.lineColor;
const backgroundColor = this.backgroundColor;
const btn = this.chooseButton;
const text = this.chooseContext;
_2d.save();
_2d.fillStyle = backgroundColor;
_2d.fillRect(0, 0, width, height);
_2d.strokeStyle = lineColor;
_2d.strokeRect(0, 0, width, height);
_2d.strokeRect(btn.left, btn.top, btn.width, btn.height);
_2d.font = `${text.size}px 微软雅黑`;
_2d.textAlign = "center";
_2d.textBaseline = "middle";
_2d.fillStyle = lineColor;
_2d.fillText(text.string, text.left, text.top);
_2d.restore();
}
// 添加游戏事件
addChooseEvent(){
const btn = this.chooseButton;
this.removeEvent();
this.addEvent("click",e=>{
const x = e.offsetX;
const y = e.offsetY;
const {left,top,width,height} = btn;
if(x>=left && x<=left+width && y>=top && y<=top+height){
this.viewPlay();
}
});
this.addEvent("mousemove",e=>{
this.drawChoose();
});
this.addEvent("mouseleave",e=>{
this.drawChoose();
});
}
// 进入选择界面
viewChoose(){
this.resetChooseElement();
this.addChooseEvent();
this.drawChoose();
}
}
new Gobang({
element: document.querySelector("#canvas"),
width: 600,
height: 600,
widthLength: 20,
heightLength: 20,
lineColor: "#010",
backgroundColor: "#999",
playerList: [
{ name: "玩家1", color: "#0f0" },
{ name: "玩家2", color: "#f00" },
],
});
一键复制
编辑
Web IDE
原始数据
按行查看
历史