要制作JS五子棋的话我们可以一开始来理清一下思路,这样对我们后来的编程是有好处的

1、棋盘使用canvas制作。canvas用来做这种不用太过复杂的图形的时候是很有用处的,下图是我制作的一个五子棋棋盘

2、确定你是想做PC端的还是做移动端的

3、点击的棋子是放在棋盘上,还是另建一个canvas画布

对于这个问题,我选择了新建一个canvas画布,如果不新建的话,如果想有撤回按钮(我这边没放上去),不太好操作,因为使用API删除会不干净,所以我使用的是存下棋子数组,每一次下棋子,存入数组后,清空棋盘,重新绘制,那每次还要重新绘制一个棋盘,所以我把棋盘作为了一个固定的canvas。还有一点,棋盘的绘制,如果棋盘和canvas画布一样大小的话,下在最旁边的棋子是会有一部分看不见的,所以要么这个canvas大一部分,要么另起一个只放置棋子的画布。

HTML:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
  7. <meta name="viewport" content="target-densitydpi=320,width=640,user-scalable=no">
  8. <link rel="stylesheet" href="./CSS/reset.css">
  9. <link rel="stylesheet" href="./CSS/index.css">
  10. <script type="text/javascript">
  11. window.onresize = function () {
  12. resetPage();
  13. }
  14. function resetPage() {
  15. var deviceWidth = document.documentElement.clientWidth || document.body.clientWidth;
  16. var deviceHeight = document.documentElement.clientHeight || document.body.clientHeight;
  17. var scale = deviceWidth / 480;
  18. deviceHeight = deviceHeight / scale;
  19. document.body.style.zoom = scale;
  20. document.body.style.height = deviceHeight + 'px';
  21. }
  22.  
  23. </script>
  24. <title>Document</title>
  25. </head>
  26.  
  27. <body>
  28. <canvas id="canvas_0" width="560px" height="560px"></canvas>
  29. <canvas id="canvas_1" width="600px" height="600px"></canvas>
  30. <div id="shadowBox"></div>
  31. <div id="back1">后退</div>
  32. <div id="back2">后退</div>
  33. <script type="text/javascript" src="./JS/index.js"></script>
  34. </body>
  35.  
  36. </html>

canvas_0是棋盘canvas

canvas_1是棋子canvas

shadowBox是外面的边框(可以优化到canvas_0里面去)

后退按钮做了,不过没有放上去,在JS中功能有做出来。

CSS

  1. #canvas_0 {
  2. box-sizing: border-box;
  3. position: fixed;
  4. top: 50%;
  5. left: 50%;
  6. transform: translate(-50%, -50%);
  7. border: 1px solid black;
  8. background-color: #FFD75B;
  9. z-index:;
  10. }
  11.  
  12. #canvas_1 {
  13. position: fixed;
  14. top: 50%;
  15. left: 50%;
  16. transform: translate(-50%, -50%);
  17. z-index:;
  18. }
  19. #shadowBox{
  20. position: fixed;
  21. top: 50%;
  22. left: 50%;
  23. transform: translate(-50%, -50%);
  24. border: 20px solid #FFD75B;
  25. }
  26. #back1{
  27. position: absolute;
  28. top: 10%;
  29. left: 50%;
  30. transform: translateX(-50%);
  31. width: 50px;
  32. height: 50px;
  33. line-height: 50px;
  34. border-radius: 50%;
  35. font-size: 20px;
  36. background-color: red;
  37. color: white;
  38. }
  39. #back2{
  40. position: absolute;
  41. bottom: 10%;
  42. left: 50%;
  43. transform: translateX(-50%);
  44. width: 50px;
  45. height: 50px;
  46. line-height: 50px;
  47. border-radius: 50%;
  48. font-size: 20px;
  49. background-color: red;
  50. color: white;
  51. }

这里面没有什么需要注意的,因为本身canvas里面的东西和CSS就没多大关系

JavaScript代码有很多,我分开讲

JS => 起始部分

  1. var Board = document.getElementById('canvas_0');
  2. var BoardToGraw = document.getElementById('canvas_1');
  3. var shadowBox = document.getElementById('shadowBox');
  4. var back = document.getElementById('back1');
  5. var back = document.getElementById('back2');
  6. var windowWidth = document.documentElement.clientWidth || document.body.clientWidth;//拿到当前浏览器可视宽度
  7. var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;//拿到当前浏览器可视高度
  8. Board.style.width = windowWidth * 0.9 + "px";//棋盘宽度为当前浏览器可视宽度的90%
  9. Board.style.height = windowWidth * 0.9 + "px";//棋盘高度为当前浏览器可视宽度的90%
  10. BoardToGraw.style.width = windowWidth * 0.9 + 40 + "px";//棋子canvas宽度为当前浏览器可视宽度的90% + 左右各20px
  11. BoardToGraw.style.height = windowWidth * 0.9 + 40 + "px";//棋子canvas高度为当前浏览器可视宽度的90% + 上下各20px
  12. shadowBox.style.width = windowWidth * 0.9 + "px";//边框宽度为当前浏览器可视宽度的90%
  13. shadowBox.style.height = windowWidth * 0.9 + "px";//边框高度为当前浏览器可视宽度的90%

JS => 棋盘部分

  1. var piecesList = [];//棋子数组
  2. // 15×15
  3. if (Board.getContext) {
  4. var ctx0 = Board.getContext('2d'); /*获取上下文,或者说绘制工具箱ctx*/
  5. /*1、构造函数*/
  6. var LineChart = function (ctx0) {
  7. /*获取绘图工具*/
  8. this.ctx0 = ctx0 || document.getElementById('canvas_0').getContext('2d');
  9. /*画布的大小*/
  10. this.canvasWidth = 560;//这里是算过了,560/14 = 20 , 每个格子20
  11. this.canvasHeight = 560;
  12. }
  13. /*2、行为方法 */
  14. LineChart.prototype.init = function () {
  15. this.drawGrid();
  16. // 画四个点
  17. let LineTotal = 13;
  18. let EmptyWidth = this.canvasWidth / (LineTotal + 1);
  19. this.DrawCircle(EmptyWidth * 3, EmptyWidth * 3, 5, "#000");
  20. this.DrawCircle(this.canvasWidth - EmptyWidth * 3, EmptyWidth * 3, 5, "#000");
  21. this.DrawCircle(EmptyWidth * 3, this.canvasHeight - EmptyWidth * 3, 5, "#000");
  22. this.DrawCircle(this.canvasWidth - EmptyWidth * 3, this.canvasHeight - EmptyWidth * 3, 5, "#000");
  23. }
  24. /*绘制网格*/
  25. LineChart.prototype.drawGrid = function () {
  26. /*x方向的线*/
  27. let LineTotal = 13;
  28. let EmptyWidth = this.canvasWidth / (LineTotal + 1);
  29. //画X轴方向
  30. for (let i = 0; i < LineTotal; i++) {
  31. this.ctx0.beginPath();
  32. this.ctx0.moveTo(0, EmptyWidth * (i + 1));
  33. this.ctx0.lineTo(this.canvasWidth, EmptyWidth * (i + 1));
  34. this.ctx0.strokeStyle = '#000';
  35. this.ctx0.closePath();
  36. this.ctx0.stroke();
  37. }
  38. /*y方向的线*/
  39. for (let i = 0; i < LineTotal; i++) {
  40. this.ctx0.beginPath();
  41. this.ctx0.moveTo(EmptyWidth * (i + 1), 0);
  42. this.ctx0.lineTo(EmptyWidth * (i + 1), this.canvasHeight);
  43. this.ctx0.strokeStyle = '#000';
  44. this.ctx0.closePath();
  45. this.ctx0.stroke();
  46. }
  47. }
  48. LineChart.prototype.DrawCircle = function (start, end, r, color) {
  49. this.ctx0.beginPath();
  50. this.ctx0.moveTo(start - r, end);
  51. this.ctx0.arc(start, end, r, 2 * Math.PI, 0, true);
  52. this.ctx0.strokeStyle = color;
  53. this.ctx0.closePath();
  54. this.ctx0.fillStyle = color;
  55. this.ctx0.fill();
  56. }
  57. var lineChart = new LineChart();
  58. lineChart.init();
  59. } else {
  60. console.log("error!!!");
  61. }

由于棋盘是14 × 14的,所以一共要画13条宽,13条高,其中棋盘宽高的1/14就是一个格子的宽度,我这边设置成了20

LineChart.prototype.DrawCircle是我用来画五子棋的四个小黑点的,原理和画棋子差不多。
JS => 棋子部分
  1. if (BoardToGraw.getContext) {
  2. var ctx0 = BoardToGraw.getContext('2d'); /*获取上下文,或者说绘制工具箱ctx*/
  3. /*1、构造函数*/
  4. var LineChart2 = function (ctx0) {
  5. /*获取绘图工具*/
  6. this.ctx0 = ctx0 || document.getElementById('canvas_1').getContext('2d');
  7. /*画布的大小*/
  8. this.canvasWidth = 600;
  9. this.canvasHeight = 600;
  10. }
  11. //绘制整个棋子数组的函数
  12. LineChart2.prototype.DrawCircleList = function (circleList) {
  13. let r = 18;
  14. for(circle of circleList){
  15. this.ctx0.beginPath();
  16. this.ctx0.moveTo(circle.X * 40 + 20 - r, circle.Y);
  17. this.ctx0.arc(circle.X * 40 + 20, circle.Y * 40 + 20, r, 2 * Math.PI, 0, true);
  18. this.ctx0.strokeStyle = circle.color;
  19. this.ctx0.closePath();
  20. this.ctx0.fillStyle = circle.color;
  21. this.ctx0.fill();
  22. }
  23. }
  24. var LineChart2 = new LineChart2();
  25. } else {
  26. console.log("error!!!");
  27. }

棋子部分的canvas代码就很简单了,因为只需要获取棋子数组,然后画出来就OK,所以只有一个绘制函数

JS => 触摸事件部分,以左上角小黑点为例,写了很详细的注释

  1. BoardToGraw.addEventListener('click', (event) => {
  2. //每click一次,清除一次canvas,数组中添加当前棋子,重绘
  3. let x = event.offsetX;
  4. let y = event.offsetY;
  5. //棋子排位位置
  6. let rankingX, rankingY;
  7. //最终画出的位置
  8. let endX, endY;
  9. var data = {};//用于储存单个棋子信息
  10. var color = (piecesList.length % 2) == 1 ? "white" : "black";//从黑开始交替下子
  11. rankingX = Math.round((x - 20) / 40);//比如如果是左上角的小黑点位置的棋子,rankingX = 3
  12. rankingY = Math.round((y - 20) / 40);//比如如果是左上角的小黑点位置的棋子,rankingY = 3
  13. //rankingX,rankingY可能为-0
  14. rankingX == -0 ? rankingX = 0 : rankingX = rankingX;//如果是-0,转化为0
  15. rankingY == -0 ? rankingY = 0 : rankingY = rankingY;//如果是-0,转化为0
  16. endX = rankingX * 40 + 20;//真正应该画在的地方,endX = 140
  17. endY = rankingY * 40 + 20;//真正应该画在的地方,endY = 140
  18. //封装进piecesList的棋子排位对象
  19. data.X = rankingX;
  20. data.Y = rankingY;
  21. data.color = color;
  22. //data = {X:3,Y:3,color:"black"}
  23. for (pieces of piecesList) {//如果此次下的棋子位置与之前的棋子数组中的发生重复,那么退出这个函数
  24. if (pieces.X == data.X && pieces.Y == data.Y) {
  25. return;
  26. }
  27. }
  28. clearCanvas();//清除整个棋子canvas
  29. piecesList.push(data);//下棋成功,push进棋子数组
  30. LineChart2.DrawCircleList(piecesList);//将push后的棋子数组传入绘制函数
  31. checkFiveLink(piecesList);//重绘后,判断是否有胜利者。
  32. })

JS => 判断是否有胜利者

这里每次下棋只会判断当前棋子color的所有者会不会胜利,因为只有最后一个棋子,才有可能胜利,之前的棋子都是已经判断过的。

由于水平,垂直,倾斜的都可能成功连成五子,所以其实一共有8个方向 => 左、右、上、下、左下、左上、右下、右上。

而有可能我会下在两个棋子的中间,所以每次应该同时判断两个方向 => 左右、上下、左上及右下、左下及右上。

  1. //用于判断是否有五子相连的函数
  2. var checkFiveLink = function (piecesList) {
  3. let nowPrices = piecesList[piecesList.length - 1];
  4. let bolleanLr = lrCheck(piecesList, nowPrices);
  5. let bolleanTb = tbCheck(piecesList, nowPrices);
  6. let bolleanRtLb = rtLbCheck(piecesList, nowPrices);
  7. let bolleanLtRb = ltRbCheck(piecesList, nowPrices);
  8. if (bolleanLr || bolleanTb || bolleanRtLb || bolleanLtRb) {
  9. alert(`${nowPrices.color} : success !!!`);
  10. clearCanvas();
  11. }
  12. }
  13. //水平
  14. var lrCheck = function (piecesList, nowPrices) {
  15. var count = 1;
  16. var count2 = 1;
  17. //右
  18. for (let i = 0; i < 4; i++) {
  19. let obj = {};
  20. obj.X = nowPrices.X + i + 1;
  21. obj.Y = nowPrices.Y;
  22. obj.color = nowPrices.color;
  23. let staticNum = count;
  24. for (piece of piecesList) {
  25. if (piece.X == obj.X && piece.Y == obj.Y && piece.color == obj.color) {
  26. count++;
  27. }
  28. }
  29. if (staticNum == count) {
  30. break;
  31. }
  32. }
  33. for (let i = 0; i < 4; i++) {
  34. let obj = {};
  35. obj.X = nowPrices.X - i - 1;
  36. obj.Y = nowPrices.Y;
  37. obj.color = nowPrices.color;
  38. let staticNum = count2;
  39. for (piece of piecesList) {
  40. if (piece.X == obj.X && piece.Y == obj.Y && piece.color == obj.color) {
  41. count2++;
  42. }
  43. }
  44. if (staticNum == count2) {
  45. break;
  46. }
  47. }
  48. let Link = count + count2 - 1;
  49. if (Link >= 5) {
  50. return true;
  51. }
  52. else {
  53. return false;
  54. }
  55. }
  56. //竖直
  57. var tbCheck = function (piecesList, nowPrices) {
  58. var count = 1;
  59. var count2 = 1;
  60. //上
  61. for (let i = 0; i < 4; i++) {
  62. let obj = {};
  63. obj.X = nowPrices.X;
  64. obj.Y = nowPrices.Y + i + 1;
  65. obj.color = nowPrices.color;
  66. let staticNum = count;
  67. for (piece of piecesList) {
  68. if (piece.X == obj.X && piece.Y == obj.Y && piece.color == obj.color) {
  69. count++;
  70. }
  71. }
  72. if (staticNum == count) {
  73. break;
  74. }
  75. }
  76. for (let i = 0; i < 4; i++) {
  77. let obj = {};
  78. obj.X = nowPrices.X;
  79. obj.Y = nowPrices.Y - i - 1;
  80. obj.color = nowPrices.color;
  81. let staticNum = count2;
  82. for (piece of piecesList) {
  83. if (piece.X == obj.X && piece.Y == obj.Y && piece.color == obj.color) {
  84. count2++;
  85. }
  86. }
  87. if (staticNum == count2) {
  88. break;
  89. }
  90. }
  91. let Link = count + count2 - 1;
  92. if (Link >= 5) {
  93. return true;
  94. }
  95. else {
  96. return false;
  97. }
  98. }
  99. //右上至左下
  100. var rtLbCheck = function (piecesList, nowPrices) {
  101. var count = 1;
  102. var count2 = 1;
  103. //右上
  104. for (let i = 0; i < 4; i++) {
  105. let obj = {};
  106. obj.X = nowPrices.X + i + 1;
  107. obj.Y = nowPrices.Y + i + 1;
  108. obj.color = nowPrices.color;
  109. let staticNum = count;
  110. for (piece of piecesList) {
  111. if (piece.X == obj.X && piece.Y == obj.Y && piece.color == obj.color) {
  112. count++;
  113. }
  114. }
  115. if (staticNum == count) {
  116. break;
  117. }
  118. }
  119. for (let i = 0; i < 4; i++) {
  120. let obj = {};
  121. obj.X = nowPrices.X - i - 1;
  122. obj.Y = nowPrices.Y - i - 1;
  123. obj.color = nowPrices.color;
  124. let staticNum = count2;
  125. for (piece of piecesList) {
  126. if (piece.X == obj.X && piece.Y == obj.Y && piece.color == obj.color) {
  127. count2++;
  128. }
  129. }
  130. if (staticNum == count2) {
  131. break;
  132. }
  133. }
  134. let Link = count + count2 - 1;
  135. if (Link >= 5) {
  136. return true;
  137. }
  138. else {
  139. return false;
  140. }
  141. }
  142. //左上至右下
  143. var ltRbCheck = function (piecesList, nowPrices) {
  144. var count = 1;
  145. var count2 = 1;
  146. //左上
  147. for (let i = 0; i < 4; i++) {
  148. let obj = {};
  149. obj.X = nowPrices.X - i - 1;
  150. obj.Y = nowPrices.Y + i + 1;
  151. obj.color = nowPrices.color;
  152. let staticNum = count;
  153. for (piece of piecesList) {
  154. if (piece.X == obj.X && piece.Y == obj.Y && piece.color == obj.color) {
  155. count++;
  156. }
  157. }
  158. if (staticNum == count) {
  159. break;
  160. }
  161. }
  162. for (let i = 0; i < 4; i++) {
  163. let obj = {};
  164. obj.X = nowPrices.X + i + 1;
  165. obj.Y = nowPrices.Y - i - 1;
  166. obj.color = nowPrices.color;
  167. let staticNum = count2;
  168. for (piece of piecesList) {
  169. if (piece.X == obj.X && piece.Y == obj.Y && piece.color == obj.color) {
  170. count2++;
  171. }
  172. }
  173. if (staticNum == count2) {
  174. break;
  175. }
  176. }
  177. let Link = count + count2 - 1;
  178. if (Link >= 5) {
  179. return true;
  180. }
  181. else {
  182. return false;
  183. }
  184. }

JS = > 其他部分

  1. back1.addEventListener('click',(event)=>{
  2. backStep();
  3. })
  4. back2.addEventListener('click',(event)=>{
  5. backStep();
  6. })
  7. //清除canvas画布
  8. function clearCanvas() {
  9. var c = document.getElementById("canvas_1");
  10. c.height = c.height;
  11. }
  12. //后退一步
  13. function backStep() {
  14. var c = document.getElementById("canvas_1");
  15. c.height = c.height;
  16. piecesList.pop();
  17. LineChart2.DrawCircleList(piecesList);
  18. }

这个小网页我放在了我的服务器上,大家可以通过链接http://www.jobsofferings.cn/五子棋/index.html进行访问,谢谢大家

使用canvas制作五子棋游戏的更多相关文章

  1. 原生JS+Canvas实现五子棋游戏

    一.功能模块 先看下现在做完的效果: 线上体验:https://wj704.github.io/five_game.html 主要功能模块为: 1.人机对战功能 2.悔棋功能 3.撤销悔棋功能 二.代 ...

  2. 用Canvas制作小游戏——贪吃蛇

    今天呢,主要和小伙伴们分享一下一个贪吃蛇游戏从构思到实现的过程~因为我不是很喜欢直接PO代码,所以只copy代码的童鞋们请出门左转不谢. 按理说canvas与其应用是老生常谈了,可我在准备阶段却搜索不 ...

  3. 怎样用HTML5 Canvas制作一个简单的游戏

    原文连接: How To Make A Simple HTML5 Canvas Game 自从我制作了一些HTML5游戏(例如Crypt Run)后,我收到了很多建议,要求我写一篇关于怎样利用HTML ...

  4. Vue+WebSocket+ES6+Canvas 制作「你画我猜」小游戏

    Vue+WebSocket+ES6+Canvas 制作「你画我猜」小游戏 转载 来源:jrainlau 链接:https://segmentfault.com/a/1190000005804860 项 ...

  5. [译]怎样用HTML5 Canvas制作一个简单的游戏

    这是我翻译自LostDecadeGames主页的一篇文章,原文地址:How To Make A Simple HTML5 Canvas Game. 下面是正文: 自从我制作了一些HTML5游戏(例如C ...

  6. 自定义View实现五子棋游戏

    成功的路上一点也不拥挤,因为坚持的人太少了. ---简书上看到的一句话 未来请假三天顺带加上十一回家结婚,不得不说真是太坑了,去年婚假还有10天,今年一下子缩水到了3天,只能赶着十一办事了. 最近还在 ...

  7. Android实训案例(八)——单机五子棋游戏,自定义棋盘,线条,棋子,游戏逻辑,游戏状态存储,再来一局

    Android实训案例(八)--单机五子棋游戏,自定义棋盘,线条,棋子,游戏逻辑,游戏状态存储,再来一局 阿法狗让围棋突然就被热议了,鸿洋大神也顺势出了篇五子棋单机游戏的视频,我看到了就像膜拜膜拜,就 ...

  8. 使用CocosSharp制作一个游戏 - CocosSharp中文教程

    注:本教程翻译自官方<Walkthrough - Building a game with CocosSharp>,官方教程有很多地方说的不够详细,或者代码不全,导致无法继续,本人在看了G ...

  9. 用Canvas制作简单的画图工具

    今天用Canvas制作了一个画图工具,非常简单,功能也不是很多,主要有背景网格,画线,画圆,画矩形和画圆角矩形,也用到了canvas的一些基本知识,在这里一一列举. 1.线段的绘制: 如何绘制真正的1 ...

随机推荐

  1. 鼠标右键新建Markdown文档

    首先放一张github某项目中.md文件中的内容图片 Windows系统下,使用 Typora 软件来进入Markdown文档的编写非常容易,而且入门门槛非常的低 存在的问题: 习惯了使用Markdo ...

  2. OAuth2.0概念以及实现思路简介

    一.什么是OAuth? OAuth是一个授权规范,可以使A应用在受限的情况下访问B应用中用户的资源(前提是经过了该用户的授权,而A应用并不需要也无法知道用户在B应用中的账号和密码),资源通常以REST ...

  3. Windows安装EMQ服务器(mqtt)

    先去EMQ官网下载安装包 https://www.emqx.io/downloads#broker 注意:此处一定不能下错成企业版的,不然EMQ会由于缺少企业license无法启动服务 解压到任意路径 ...

  4. docker启动报错 (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport

    今天修改完docker宿主机的防火墙文件 vim /etc/sysconfig/iptables 停止容器再启动时 报如下错误 (iptables failed: iptables --wait -t ...

  5. SparkStreaming-Kafka集成

    SparkStreaming-Kafka集成 参考链接: Spark Streaming + Kafka Integration Guide 文章基本是官方的翻译, 最多再加入了一小部分自己的思考在内 ...

  6. 数字任意组合 - gcd

    链接:https://www.nowcoder.com/acm/contest/160/A来源:牛客网 题目描述有一个计数器,计数器的初始值为0,每次操作你可以把计数器的值加上a1,a2,...,an ...

  7. Windows10内嵌Ubuntu子系统初始化设置

    第一次启动 重启ubuntu Since Windows 10 version 1803, closing all WSL terminal windows won't kill background ...

  8. python 找到项目使用的所有组件和版本

    1.下载模块 pip3 install -i https://pypi.douban.com/simple pipreqs 2.生成文件 pipreqs ./ --encoding=utf-8

  9. Egret学习-TiledMap使用

    环境说明: 引擎版本:5.2.4 Egret Wing 4.1.6 1.下载依赖,下载地址https://github.com/egret-labs/egret-game-library/tree/m ...

  10. [洛谷P4178] Tree (点分治模板)

    题目略了吧,就是一棵树上有多少个点对之间的距离 \(\leq k\) \(n \leq 40000\) 算法 首先有一个 \(O(n^2)\) 的做法,枚举每一个点为起点,\(dfs\) 一遍可知其它 ...