【五子棋实战】第5章 开发五子棋前端页面

简介: 页面设计原则  1、可配置性。比如棋盘的大小可配置,棋盘边长可配置,黑白空期的值可配置;  2、响应式。各种屏幕大小下棋盘的布局要合理;  3、面向对象。棋子、棋盘的定义都用类来封装,代码要写的好看。

页面设计原则


  1、可配置性。比如棋盘的大小可配置,棋盘边长可配置,黑白空期的值可配置;


  2、响应式。各种屏幕大小下棋盘的布局要合理;


  3、面向对象。棋子、棋盘的定义都用类来封装,代码要写的好看。


开发页面


## 基础HTML骨架


  代码如下:


<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>三黄工作室 - 五子棋</title>
  <style>
    *
    {
      margin: 0;
    }
    body{
      background-image: url("img/bg.png");
    }
    #canvas_line {
      box-shadow: 0 0 5px 0px rgba(0, 0, 0, .8);
      border-radius: 5px;
      box-sizing: border-box;
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      border: 1px solid black;
      background-color: #ffbd5b;
      z-index: 5;
    }
    #canvas_chess {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      z-index: 10;
    }
    .loading-message {
      /* background-color: #f5f5f5; */
      padding: 5px;
      text-align: center;
      font-size: 18px;
      font-weight: bold;
      color:white;
    }
    .logo{
      background-color: #FCFCFD;
      padding: 5px;
      text-align: center;
      bottom: 0px;
      position: fixed;
      width: 100%;
    }
    .button-30 {
              align-items: center;
              appearance: none;
              background-color: #FCFCFD;
              border-radius: 4px;
              border-width: 0;
              box-shadow: rgba(45, 35, 66, 0.4) 0 2px 4px,rgba(45, 35, 66, 0.3) 0 7px 13px -3px,#D6D6E7 0 -3px 0 inset;
              box-sizing: border-box;
              color: #36395A;
              cursor: pointer;
              display: inline-flex;
              font-family: "JetBrains Mono",monospace;
              height: 40px;
              justify-content: center;
              line-height: 1;
              list-style: none;
              overflow: hidden;
              padding-left: 16px;
              padding-right: 16px;
              position: relative;
              text-align: left;
              text-decoration: none;
              transition: box-shadow .15s,transform .15s;
              user-select: none;
              -webkit-user-select: none;
              touch-action: manipulation;
              white-space: nowrap;
              will-change: box-shadow,transform;
              font-size: 18px;
            }
            .button-30:focus {
              box-shadow: #D6D6E7 0 0 0 1.5px inset, rgba(45, 35, 66, 0.4) 0 2px 4px, rgba(45, 35, 66, 0.3) 0 7px 13px -3px, #D6D6E7 0 -3px 0 inset;
            }
            .button-30:hover {
              box-shadow: rgba(45, 35, 66, 0.4) 0 4px 8px, rgba(45, 35, 66, 0.3) 0 7px 13px -3px, #D6D6E7 0 -3px 0 inset;
              transform: translateY(-2px);
            }
            .button-30:active {
              box-shadow: #D6D6E7 0 3px 7px inset;
              transform: translateY(2px);
            }
  </style>
</head>
<body> 
  <canvas id="canvas_line" width="600px" height="600px"></canvas>
    <canvas id="canvas_chess"></canvas>
  <div class="loading-message"><span style="display: none;">正在计算中...</span></div>
  <div class="loading-message"><button onclick="regreat()" class="button-30">悔棋</button></div>
  <div class="logo"><img src="img/logo.png" style="height: 30px;"/></div>
</body>
</html>


  目前的页面样式如下:


image.png


## 添加页面响应式功能


  现在的手机版页面如下,可以发现手机版的棋盘太小、按钮太小、下方的logo太小。


image.png


  于是我们添加响应式功能,在<head>里面添加<meta>头,在<style>里面追加手机页面下的css样式:

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
/* 在设备宽度小于600像素时,调整div的大小 */
@media (max-width: 600px) {
  #canvas_line{
    width: 100%;
  }
  #canvas_chess{
    width: 100%;
  }
}

  添加之后,手机版页面就刚好了:





编写JS


## 获取画布对象与DOM对象



  代码如下:

// 画布
var canvas_chess = document.getElementById("canvas_chess");
var context_chess = canvas_chess.getContext('2d');
var canvas_line = document.getElementById("canvas_line");
var context_line = canvas_line.getContext('2d');


  这段代码主要是获取两个画布元素,并分别创建了两个2D绘图上下文对象。这些上下文对象可以用于在画布上进行绘制和操作,例如绘制图形、文本等。


  获取Dom元素是为了得到元素的长宽、偏移量等;获取画布元素是为了绘制图形;获取2个一个是线条容器、一个是棋子容器。



## 定义棋子、棋盘对象.


  代码如下:


// 落子状态 'z'为空 'b'为黑 'w'为白
const white_flag = '1';
const black_flag = '-1';
const blank_flag = '0';
// 棋盘边长
const len = 15;
class Chess {
  constructor(x, y, z) {
    // 横坐标
    this.x = x;
    // 纵坐标
    this.y = y;
    // 落子状态 '0'为空 '-1'为黑 '1'为白
    this.z = z;
  }
}
class Board {
  constructor() {
    // 棋盘边长
    this.len = len;
    // 棋盘棋局状态值 value[len][len]
    this.value = Array.from(Array(this.len), () => new Array(this.len).fill(blank_flag));
    // 棋盘棋局状态值 value[len][len]
    this.chessList = [];
  }
}


 上述代码定义了两个类,Chess 和 Board。


 Chess 类表示一个棋子,具有横坐标 x、纵坐标 y 和落子状态 z 的属性。


 Board 类表示一个棋盘,具有棋盘边长 len、棋局状态值 value 和棋子列表 chessList 的属性。value 是一个二维数组,用于存储棋盘上每个位置的落子状态。chessList 则是用于存储已下的棋子对象。


 此外,代码中还定义了常量 white_flag、black_flag 和 blank_flag,分别表示白棋、黑棋和空白位置的落子状态。



## 定义绘画对象(重要!!)


  代码如下:


class Draw {
  constructor(canvas_line, context_line, canvas_chess, context_chess) {
    // 样式
    this.style = {
      // 棋盘边长
      len : len,
      // 棋盘线条颜色
      lineColor : "#555",
      // 棋盘线条间隔
      lineWidth : 40,
    }
    // 棋盘线条居中时,需要的偏移量
    this.style['offSet'] = (canvas_line.width - this.style.len * this.style.lineWidth) / 2;
    // dom对象
    this.dom = {
      l : canvas_line,
      c : canvas_chess
    }
    // context对象
    this.context ={
      l : context_line,
      c : context_chess
    }
    // 根据线条数、间隔大小 设置棋盘宽、高
    canvas_chess.height = this.style.len * this.style.lineWidth;
    canvas_chess.width = this.style.len * this.style.lineWidth; 
  }
  // 绘制棋盘线条
  drawChessBoard(){
    let style = this.style;
    let color = style.lineColor;
    let w = style.lineWidth;
    let o = style.offSet;
    let len = style.len;
    let h = w / 2;
    let c = this.context.l;
    for(var i=0; i < len; i++){
      c.strokeStyle = color;
      c.moveTo(h + i*w + o, h + o);//垂直方向画线
      c.lineTo(h + i*w + o, h * (2 * len - 1) + o);
      c.stroke();
      c.moveTo(h + o, h + i*w + o);//水平方向画线
      c.lineTo(h * (2 * len - 1) + o , h + i*w + o);
      c.stroke();
    }
  }
  /**
   * 绘制单个棋子
   * @param {*} j 横坐标
   * @param {*} i 纵坐标
   * @param {*} k 颜色 黑or白
   * @param {*} first 是否需要绘制小红点
   */
  drawChess(Chess, first = false){
    let j = Chess.x;
    let i = Chess.y;
    let k = Chess.z;
    let style = this.style;
    let w = style.lineWidth;
    let h = w / 2;
    let c = this.context.c;
    c.beginPath();
    c.arc(h + i*w, h+j*w, h-2, 0, 2 * Math.PI);//绘制棋子
    var g=c.createRadialGradient(h+i*w,h+j*w,13,h+i*w,h+j*w,0);//设置渐变
    if(k == black_flag){
      g.addColorStop(0,'#0A0A0A');//黑棋
      g.addColorStop(1,'#636766');  
    }else if(k == white_flag){
      g.addColorStop(0,'#D1D1D1');//白棋
      g.addColorStop(1,'#F9F9F9');
    }
    c.fillStyle=g;
    c.fill();
    c.closePath();
    if(first){
      c.fillStyle = 'red';
      c.fillRect(h*0.75 + i*w, h*0.75+j*w, h/2, h/2)
    }
  }
  // 绘制现有棋子
  drawChessAll(list) {
    // 清空棋子canvas
    let dom_c = this.dom.c;
    dom_c.height = dom_c.height;
    // 依次绘制棋子
    for(let i in list){
      if(i == list.length - 1)
        this.drawChess(list[i], true);
      else
        this.drawChess(list[i]);
    }
  }
}


 上述代码定义了一个名为 Draw 的类。


 Draw 类具有以下属性和方法:


 - 属性:


  - style:包含样式信息的对象,包括棋盘边长 (len)、棋盘线条颜色 (lineColor) 和棋盘线条间隔 (lineWidth)。


  - dom:包含存储 Canvas DOM 对象的属性 l 和 c。


  - context:包含存储 Canvas 上下文对象的属性 l 和 c。



 - 构造函数:


  - 接受两个 Canvas DOM 对象和对应的上下文对象作为参数,用于初始化 Draw 对象。


  - 在构造函数中,根据传入的参数设置样式、计算偏移量,并设置棋盘 Canvas 的宽度和高度。


 - 方法:


  - drawChessBoard():绘制棋盘线条的方法。这里有好多数学计算,再结合canvas线条绘制的api。


  - drawChess(Chess, first = false):绘制单个棋子的方法。接受 Chess 对象作为参数,包含棋子的横坐标 x、纵坐标 y 和落子状态 z。可选择是否绘制小红点。


  - drawChessAll(list):绘制现有棋子的方法。接受一个棋子对象列表作为参数,依次绘制列表中的棋子。


## 初始化绘制棋盘


  代码如下:



// 棋盘
let board = new Board();
// 绘画器
let draw = new Draw(canvas_line, context_line, canvas_chess, context_chess);
// 玩家
let currentPlayer = 1;
//绘制棋盘
   draw.drawChessBoard();


  目前的页面样式如下:



## 添加点击事件 能够下棋落子


  代码如下:


function clk (e){
    $("span").css("display","block");
    canvas_chess.onclick= null;
    var x = e.offsetY;//相对于棋盘左上角的x坐标
    var y = e.offsetX;//相对于棋盘左上角的y坐标
    // var i = Math.floor(x / draw.style.lineWidth);
    // var j = Math.floor(y / draw.style.lineWidth);
    var i = Math.floor(x * canvas_chess.width / canvas_chess.offsetWidth / draw.style.lineWidth);
    var j = Math.floor(y * canvas_chess.width / canvas_chess.offsetWidth / draw.style.lineWidth);
    if( board.value[i][j] == blank_flag ) {
      if(currentPlayer == 1){
        var c = new Chess(i,j,black_flag);
        board.value[i][j]=black_flag;
      }else{
        var c = new Chess(i,j,white_flag);
        board.value[i][j]=white_flag;
      }
      board.chessList.push(c);
      draw.drawChessAll(board.chessList);
      if(checkWin(board.chessList, currentPlayer) === true){
        alert((currentPlayer == 1? "black" : "white") + "win !!");
        return;
      }
      // 切换玩家
      currentPlayer = (currentPlayer === 1) ? 2 : 1;
    }else{
      $("span").css("display","none");
      canvas_chess.onclick= clk;
    }
  }

  这样我们就可以自己交替着下黑子和白子了。于是前端页面基本结束。




相关文章
|
14天前
|
前端开发 Java 开发工具
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
|
8天前
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
105 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
6天前
|
Dart 前端开发 容器
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
11天前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
14天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
16天前
|
Dart 前端开发 架构师
【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升
【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升
|
11天前
|
JavaScript 前端开发 jenkins
抛弃node和vscode,如何用记事本开发出一个完整的vue前端项目
本文探讨了在不依赖Node和VSCode的情况下,仅使用记事本和浏览器开发一个完整的Vue3前端项目的方法。通过CDN引入Vue、Vue Router、Element-UI等库,直接编写HTML文件实现页面功能,展示了前端开发的本质是生成HTML。虽然日常开发离不开现代工具,但掌握这种基础方法有助于快速实现想法或应对特殊环境限制。文章还介绍了如何用Node简单部署HTML文件到服务器,提供了一种高效、轻量的开发思路。
42 10
|
7天前
|
缓存 前端开发 IDE
【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
3月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
272 14
|
3月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
76 0

热门文章

最新文章