为童年复刻四连棋网页游戏,下一步AI人机对战
小学时曾在朋友家玩过这个游戏,还记得是五块一盒,最近因为想到小孩的玩具突然回忆起,遂买了几个大小不同版本。 顺路跑去送了好友一个,他人不在,给他妈妈了。后来感谢我 上一次在他家下棋还是十几年前了!!!回忆涌上心头,泪目( Ĭ ^ Ĭ ) 趁娃还没出生,今天必须复刻一个
游戏名:四子棋,小时候我记叫做扣子棋,我现在叫做 “四连棋”
〇、对战规则
- 1 棋盘6x7 42个格子,双方不同色
- 2 双方轮留下1子,从底部开始累加
- 3 先完成横、竖、斜任一方向四连获胜
一、HTML构建棋盘
HTML快速生成6行7列的棋盘,使用main>section*6>div*7
<div id="设置">
<button id="AI">AI未启用</button>
</div>
<div id="弹窗" class="隐藏"> 提示:提示内容 </div>
<section id="遮罩层" class="隐藏"></section>
<main id="棋盘">
<section>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</section>
<section>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</section>
。。。
<footer id="底座"></footer>
</main>
二、CSS棋盘样式
棋盘主要样式,布局广泛采用flex,考虑移动端(手机)的访问,单位主要使用vw、vh。为了便于直接理解,就用中文命名了
body{
margin: 0;
padding: 0;
display: flex;
justify-content: center; /* 水平居中*/
align-items: center; /* 垂直居中*/
height: 100vh;
}
#棋盘{
width: 80vw;
height: 80vh;
background-color: paleturquoise;
display: flex;
flex-direction: column; /* 主轴 按列 */
justify-content: flex-end; /* 主轴起点 靠下方 */
padding-bottom: 2vh;
position: relative;
}
#棋盘 section{
display: flex;
justify-content: space-evenly; /* 主轴 均分 */
}
#棋盘 section div{
width: 10vw;
height: 10vh;
background-color: pink;
border: 1px solid black;
background-color: white;
border-radius: 50%;
border: 1px solid gray;
cursor: pointer;
color: gray;
}
#棋盘 section div:hover{
box-shadow: 2px 2px 2px 2px black;
}
.红{
background-color: red !important;
}
#棋盘 section div.黄{
background-color: yellow;
}
不像真实棋盘,考虑到需要限制并提醒玩家,落子得叠叠乐,增加了弹窗、遮罩层。值得注意的是 body需要设置height:100vh,而不是height:100%,遮罩层才不会底部留白。
单独定义了一个class="隐藏"
,便于js的classList.add/move
来控制 弹窗 和遮罩层的 效果。
#弹窗 {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: gold;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0,0,0,0.3);
z-index: 20; /* 确保弹窗在最上层 */
width:96vw;
height: 3vh;
line-height: 3vh;
text-align: center;
}
#遮罩层{
width: 100vw;
height: 100vh;
background-color:black;
position: absolute;
z-index: 10;
opacity: 0.6;
}
.隐藏{
display: none !important;
}
三、原生JS,启动!棋盘交互
考虑使用二维数组来存放棋盘,或者动态生成棋盘。 这样做可以虚拟增加一行,每个落子都是1,每次落子都只用在数组位置判断正下方是否为1就行
下面采用的是一维数组
的方式,因为发现直接给 下标+7
就是正下方的棋子。
因为每个位置只能下一次。点击成功使用了 onclick= null
,所以JS判断能下子的逻辑就是:
棋子编号大于35,最后一排可以下。
或下方有子,可以下。
另外,双人对战,使用一个计数器N来判断,奇偶 = 双人轮流。
//获取所有的棋子
let divArr = document.querySelectorAll("#棋盘 div")
let n = 0 // 判断 双方
let 弹窗 = document.querySelector("#弹窗");
let 遮罩层 = document.querySelector("#遮罩层");
for(let i=0 ;i<divArr.length ; i++){
let 棋子 = divArr[i]
棋子.onclick = ()=>{
//已下的子判断,除了最下方一行 ,其他位置 下子前必须有子
if(i>=35 || divArr[i+7].classList.contains("红") || divArr[i+7].classList.contains("黄") ){
if(n%2==0){
棋子.classList.add("黄")
}else{
棋子.classList.add("红")
}
棋子.onclick = null //防止重复点击
n++ //点击增加计数
}else{
控制弹窗('开','请勿悬空落子')
}
}//
}
//AI启用
AI.onclick = ()=>{
AI.innerHTML = "AI对战中"
AI.classList.add("选中")
}
//控制弹窗
遮罩层.onclick = ()=>{
if( ! 遮罩层.classList.contains("隐藏") ){
控制弹窗('关')
}
}
function 控制弹窗(flag,msg=''){
switch(flag){
case '开':
弹窗.innerHTML = `提示:${msg}`
弹窗.classList.remove("隐藏")
遮罩层.classList.remove("隐藏")
break;
case '关':
弹窗.classList.add("隐藏")
遮罩层.classList.add("隐藏")
break;
}
}
四、一起来拓展
完整代码: 2020wa.com/四子棋v1.0.0/i… 因为六一只有一天,来不及写AI代码了。 最基础的AI ,配合玩家的演出,只有7列,每次随机0~6下一个。
棋盘+棋子 用canvas来做,后期可以带来更加炸裂的效果。 这其实属于2D棋子,3D 例题的 4X4X4, 这不是透视图用 three.js就更加酷炫了。
转载自:https://juejin.cn/post/7375183112835940362