JavaScript写的一个带AI的井字棋
最近有一门课结束了,需要做一个井字棋的游戏,我用JavaScript写了一个。首先界面应该问题不大,用html稍微写一下就可以。主要是人机对弈时的ai算法,如何使电脑方聪明起来,是值得思考一下的。开始游戏后,由玩家先行。那么站在计算机的角度,可以对多种情况进行分析,并按照重要程度赋予权值。
情况如下:
1、同一排(行。列。对角线)有且只有两个棋子,并且都是自己的,只要再进一步就能获胜,那么剩下的那个位置权值最高,优先级最大。赋予一级权值。
2、同一排(行。列。对角线)有且只有两个棋子,并且都是对方的(也就是玩家的),只要再进一步,玩家就会成功,所以“我”要堵住,剩下的那个位置赋予二级权值。
3、因为电脑方后行,如果聪明点,需要一直堵玩家方,所以当一排只有一个棋,且是玩家的棋子,那么该排其他位置的权值设为三级。
4、四级权值:一排只有己方(电脑方)的棋子。
5、五级权限:同排没有棋子,包括对方和己方。
实现的时候,每个位置的棋子,可以用二维数组full表示,每个位置的权值大小也用一个二维数组val来表示。玩家方下完后,调用AI方的函数,AI方行棋前,先更新一下权值,然后选出权值最大的位置落子(最优解)。无论是ai还是玩家方,每次落子后都要判断有没有产生输赢。用alert()函数输出结果。
为了表示权值的大小,规定按照一级到五级顺序,依次加 10000、1000、10、5、3
注:由于可能要提交源码,我没有分离出css样式和js文件,不过最好还是分开写更规范。如有不足之处,欢迎批评指正。
源码如下:
- <html>
- <head>
- <meta charset="utf-8">
- <title>井字棋</title>
- <script>
- //定义全局变量
- var full=[[0,0,0],[0,0,0],[0,0,0]];//0表示null,1表示我下的,2表示电脑下的
- var val=[[1,1,1],[1,1,1],[1,1,1]];//表示每个位置的权值
- function judge(){
- //检测是否有人赢
- //行
- for(var i=0;i<3;i++){
- if(full[i][0]==full[i][1]&&full[i][1]==full[i][2]&&full[i][0]!=0){
- if(full[i][0]==1){
- window.alert("you win!");
- return true;
- }
- else {
- window.alert("you lose");
- return true;
- }
- }
- }
- //列
- for(var i=0;i<3;i++){
- if(full[0][i]==full[1][i]&&full[1][i]==full[2][i]&&full[0][i]!=0){
- if(full[0][i]==1){
- window.alert("you win!");
- return true;
- }
- else {
- window.alert("you lose");
- return true;
- }
- }
- }
- //主对角线
- if(full[0][0]==full[1][1]&&full[1][1]==full[2][2]&&full[0][0]!=0){
- if(full[0][0]==1){
- window.alert("you win!");
- return true;
- }
- else {
- window.alert("you lose");
- return true;
- }
- }
- if(full[0][2]==full[1][1]&&full[2][0]==full[1][1]&&full[0][2]!=0){
- if(full[0][2]==1){
- window.alert("you win!");
- return true;
- }
- else {
- window.alert("you lose");
- return true;
- }
- }
- for(var i=0;i<3;i++){
- for(var j=0;j<3;j++){
- if(full[i][j]==0)
- return false;//说明还没结束
- if(i==2&&j==2)
- {window.alert("平局!");
- return true;
- }
- }
- }
- return false;//无结果
- }
- function bn(i,j){
- //如果已经下过,则无效
- if(full[i][j]!=0){
- return 0;
- }else{
- //没下过
- full[i][j]=1;
- num1=(i*3+j+1)+"";
- document.getElementById(num1).value="X";
- if(judge()==true){
- return;
- }
- ai();//切换
- }
- }
- //重置权值:
- function resetValue(){
- for(var i=0;i<3;i++){
- for(var j=0;j<3;j++){
- if(full[i][j]!=0)
- val[i][j]=0;
- else{
- //看行和列:
- //最高权值
- if(((full[0][j]+full[1][j]+full[2][j])==4)&&(full[0][j]*full[1][j]*full[2][j])==0
- &&((full[0][j]-1)*(full[1][j]-1)*(full[2][j]-1))==-1)
- val[i][j]=val[i][j]+10000;
- if(((full[i][0]+full[i][1]+full[i][2])==4)&&(full[i][0]*full[i][1]*full[i][2])==0
- &&((full[i][0]-1)*(full[i][1]-1)*(full[i][2]-1))==-1)
- val[i][j]=val[i][j]+10000;
- //次级权值
- if(((full[0][j]+full[1][j]+full[2][j])==2)&&(full[0][j]*full[1][j]*full[2][j])==0
- &&((full[0][j]-1)*(full[1][j]-1)*(full[2][j]-1))==0)
- val[i][j]=val[i][j]+1000;
- if(((full[i][0]+full[i][1]+full[i][2])==2)&&(full[i][0]*full[i][1]*full[i][2])==0
- &&((full[i][0]-1)*(full[i][1]-1)*(full[i][2]-1))==0)
- val[i][j]=val[i][j]+1000;
- //三级权值(一排只有一个X)
- if(((full[0][j]+full[1][j]+full[2][j])==1)&&(full[0][j]*full[1][j]*full[2][j])==0
- &&((full[0][j]-1)*(full[1][j]-1)*(full[2][j]-1))==0)
- val[i][j]=val[i][j]+10;
- if(((full[i][0]+full[i][1]+full[i][2])==1)&&(full[i][0]*full[i][1]*full[i][2])==0
- &&((full[i][0]-1)*(full[i][1]-1)*(full[i][2]-1))==0)
- val[i][j]=val[i][j]+10;
- //四级权值(一排只有一个O)
- if(((full[0][j]+full[1][j]+full[2][j])==2)&&(full[0][j]*full[1][j]*full[2][j])==0
- &&((full[0][j]-1)*(full[1][j]-1)*(full[2][j]-1))==1)
- val[i][j]=val[i][j]+5;
- if(((full[i][0]+full[i][1]+full[i][2])==2)&&(full[i][0]*full[i][1]*full[i][2])==0
- &&((full[i][0]-1)*(full[i][1]-1)*(full[i][2]-1))==1)
- val[i][j]=val[i][j]+5;
- //五级权限(该行没有X或O)
- if(((full[0][j]+full[1][j]+full[2][j])==0)&&(full[0][j]*full[1][j]*full[2][j])==0
- &&((full[0][j]-1)*(full[1][j]-1)*(full[2][j]-1))==-1)
- val[i][j]=val[i][j]+2;
- if(((full[i][0]+full[i][1]+full[i][2])==0)&&(full[i][0]*full[i][1]*full[i][2])==0
- &&((full[i][0]-1)*(full[i][1]-1)*(full[i][2]-1))==-1)
- val[i][j]=val[i][j]+2;
- //主对角线:同上
- if((i==0&&j==0)||(i==2&&j==2)||(i==1&&j==1)){
- if(((full[0][0]+full[1][1]+full[2][2])==4)&&(full[0][0]*full[1][1]*full[2][2])==0
- &&((full[0][0]-1)*(full[1][1]-1)*(full[2][2]-1))==-1)
- val[i][j]=val[i][j]+10000;
- //次级权值
- if(((full[0][0]+full[1][1]+full[2][2])==2)&&(full[0][0]*full[1][1]*full[2][2])==0
- &&((full[0][0]-1)*(full[1][1]-1)*(full[2][2]-1))==0)
- val[i][j]=val[i][j]+1000;
- //三级权值(一排只有一个X)
- if(((full[0][0]+full[1][1]+full[2][2])==1)&&(full[0][0]*full[1][1]*full[2][2])==0
- &&((full[0][0]-1)*(full[1][1]-1)*(full[2][2]-1))==0)
- val[i][j]=val[i][j]+10;
- //四级权值(一排只有一个O)
- if(((full[0][0]+full[1][1]+full[2][2])==2)&&(full[0][0]*full[1][1]*full[2][2])==0
- &&((full[0][0]-1)*(full[1][1]-1)*(full[2][2]-1))==1)
- val[i][j]=val[i][j]+5;
- //五级权值(该行没有X或O)
- if(((full[0][0]+full[1][1]+full[2][2])==0)&&(full[0][0]*full[1][1]*full[2][2])==0
- &&((full[0][0]-1)*(full[1][1]-1)*(full[2][2]-1))==-1)
- val[i][j]=val[i][j]+2;
- }
- //副对角线(同上)
- if((i==0&&j==2)||(i==2&&j==0)||(i==1&&j==1)){
- //一级
- if(((full[0][2]+full[1][1]+full[2][0])==4)&&(full[0][2]*full[1][1]*full[2][0])==0
- &&((full[0][2]-1)*(full[1][1]-1)*(full[2][0]-1))==-1)
- val[i][j]=val[i][j]+10000;
- //二级
- if(((full[0][2]+full[1][1]+full[2][0])==2)&&(full[0][2]*full[1][1]*full[2][0])==0
- &&((full[0][2]-1)*(full[1][1]-1)*(full[2][0]-1))==0)
- val[i][j]=val[i][j]+1000;
- //三级权值(一排只有一个X)
- if(((full[0][2]+full[1][1]+full[2][0])==1)&&(full[0][2]*full[1][1]*full[2][0])==0
- &&((full[0][2]-1)*(full[1][1]-1)*(full[2][0]-1))==0)
- val[i][j]=val[i][j]+10;
- //四级权值(一排只有一个O)
- if(((full[0][2]+full[1][1]+full[2][0])==2)&&(full[0][2]*full[1][1]*full[2][0])==0
- &&((full[0][2]-1)*(full[1][1]-1)*(full[2][0]-1))==1)
- val[i][j]=val[i][j]+5;
- //五级权值(该行没有X或O)
- if(((full[0][2]+full[1][1]+full[2][0])==0)&&(full[0][2]*full[1][1]*full[2][0])==0
- &&((full[0][2]-1)*(full[1][1]-1)*(full[2][0]-1))==-1)
- val[i][j]=val[i][j]+2;
- }
- }
- }
- }
- }
- function ai(){
- if(judge()==true){
- return;
- }
- //挑选权值最大的
- resetValue();
- var mi=0,mj=0,temp=0;
- for(var i=0;i<3;i++)
- for(var j=0;j<3;j++){
- if(val[i][j]>temp){
- temp=val[i][j];
- mi=i;
- mj=j;
- }
- }
- full[mi][mj]=2;
- num1=(mi*3+mj+1)+"";
- document.getElementById(num1).value="O";
- if(judge()==true){
- return;
- }
- }
- function lose(){
- window.alert("you lose");
- location.reload();
- }
- </script>
- </head>
- <body>
- <h1 align=center> 井字棋</h1>
- <table border=2px bordercolor="blue"width="300"height="300" style="font-size:50 " align=center>
- <tr>
- <td><input type="button" id="1" Style="width:100px;height:100px;" value=" " onclick="bn(0,0)"/></td>
- <td><input type="button" id="2" Style="width:100px;height:100px;" value=" " onclick="bn(0,1)"/></td>
- <td><input type="button" id="3" Style="width:100px;height:100px;" value=" " onclick="bn(0,2)"/></td>
- </tr>
- <tr>
- <td><input type="button" id="4" Style="width:100px;height:100px;" value=" " onclick="bn(1,0)"/></td>
- <td><input type="button" id="5" Style="width:100px;height:100px;" value=" " onclick="bn(1,1)"/></td>
- <td><input type="button" id="6" Style="width:100px;height:100px;" value=" " onclick="bn(1,2)"/></td>
- </tr>
- <tr >
- <td><input type="button" id="7" Style="width:100px;height:100px;" value=" " onclick="bn(2,0)"/></td>
- <td><input type="button" id="8" Style="width:100px;height:100px;" value=" " onclick="bn(2,1)"/></td>
- <td><input type="button" id="9" Style="width:100px;height:100px;" value=" " onclick="bn(2,2)"/></td>
- </tr>
- </table>
- <div ><input type="button" style="position:relative;left:500px;top:5px;width:100px;height:50px;" value="重新开始" onclick="location.reload() "/>
- <input type="button" style="position:relative;left:550px;top:5px;width:100px;height:50px;" value="认 输" onclick="lose()"/>
- </div>
- <body>
- </html>
JavaScript写的一个带AI的井字棋的更多相关文章
- 井字棋小游戏(C语言)
最近沉迷于<NetHack>.<DCSS>等字符游戏,对其很感兴趣,于是用C语言写了个字符界面的井字棋小游戏.欢迎大家指教. 编写时遇到了一些问题,我原先准备用循环,直到读取到 ...
- Pascal小游戏 井字棋
一个很经典的井字棋游戏 Pascal源码Chaobs奉上 注意:1.有的FP版本不支持汉语,将会出现乱码.2.别想赢电脑了,平手不错了. 井字过三关: program TicTacToe; uses ...
- 用C语言实现井字棋(人人/AI人机)--完结版
目录 用C语言实现井字棋(人人/AI人机)--完结版 BUG与优化3: 1. 修改了step的计算方法,每个玩家玩完就加一次step 2. 改变了电脑下棋的逻辑,每个玩家玩完之后都跳过这次循环 源码: ...
- quick cocos2d-x 入门---井字棋
学习quick cocos2d-x 第二天 ,使用quick-x 做了一个井字棋游戏 . 我假设读者已经 http://wiki.quick-x.com/doku.php?id=zh_cn阅读了这个链 ...
- 井字棋(Tic-Tac-Toe)
井字棋介绍:https://en.wikipedia.org/wiki/Tic-tac-toe 井字棋简单,但是获胜策略却和直觉不同,四角比中间重要性要高,而且先手有很大的获胜概率获胜(先手胜:91, ...
- python 井字棋(Tic Tac Toe)
说明 用python实现了井字棋,整个框架是本人自己构思的,自认为比较满意.另外,90%+的代码也是本人逐字逐句敲的. minimax算法还没完全理解,所以参考了这里的代码,并作了修改. 特点 可以选 ...
- 使用 Vue.js 改写 React 的官方教程井字棋
React 的官方教程井字棋很好的引导初学者一步步走进 React 的世界,我想类似的教程对 Vue.js 的初学者应该也会有启发,于是使用 Vue.js 进行了改写 可以先查看最终的结果,尝试点击体 ...
- [游戏学习22] MFC 井字棋 双人对战
>_<:太多啦,感觉用英语说的太慢啦,没想到一年做的东西竟然这么多.....接下来要加速啦! >_<:注意这里必须用MFC和前面的Win32不一样啦! >_<:这也 ...
- TicTacToe井字棋 by reinforcement learning
对于初学强化学习的同学,数学公式也看不太懂, 一定希望有一些简单明了的代码实现加强对入门强化学习的直觉认识,这是一篇初级入门代码, 希望能对你们开始学习强化学习起到基本的作用. 井字棋具体玩法参考百度 ...
随机推荐
- HDU 1275 两车追及或相遇问题(相遇和追及公式)
传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1275 两车追及或相遇问题 Time Limit: 2000/1000 MS (Java/Others) ...
- 流Stream 文件File 流IO
Java 流(Stream).文件(File)和IO Java.io 包几乎包含了所有操作输入.输出需要的类.所有这些流类代表了输入源和输出目标. Java.io 包中的流支持很多种格式,比如:基本类 ...
- Oracle 11gR2 RAC 11.2.0.4 全自动打11.2.0.4.20170418 psu 步骤
说明:此次环境的patch p6880880_112000_Linux-x86-64.zip 和 p25476126_112040_Linux-x86-64.zip均放在/soft目录, 且grid和 ...
- Oracle模糊查询
通配符 % 匹配零个或更多的任意字符 _ 匹配一个任意字符 [ ] 匹配指定范围中的一个字符([a-z],[0-9]) [^ ] 不属于指定范围,不包含其中的字符 escape转义 --查询 ...
- 05 oracle中lock和latch的用途
oracle中lock和latch的用途 本文向各位阐述Oracle的Latch机制,Latch,用金山词霸翻译是门插栓,闭锁,专业术语叫锁存器,我开始接触时就不大明白为什么不写Lock,不都是锁 ...
- jQuery 遍历 - children() 方法 获取指定id下子元素的值
<a id="Aobj_2_2" class="" specid="2" specvid="2" href=&qu ...
- Linux下抓取登陆用户密码神器mimipenguin
windows下有Mimikatz,现在linux下有了mimipenguin,国外安全研究员huntergregal发布了工具mimipenguin,一款Linux下的密码抓取神器,弥补了Linux ...
- margin中的bug解决方法
margin bug问题 : 当做子元素中使用margin-top: 50px;父子元素都会跑出50px, 解决方法: 在父元素中使用下面三种任意一种都可以. 方法一:给父元素加边框 border: ...
- JZOJ 4273. 【NOIP2015模拟10.28B组】圣章-精灵使的魔法语
4273. [NOIP2015模拟10.28B组]圣章-精灵使的魔法语 (File IO): input:elf.in output:elf.out Time Limits: 1000 ms Mem ...
- SRM32(8)——ADC和DAC
1.ADC简介 STM32 拥有 1~3 个 ADC(STM32F101/102 系列只有 1 个 ADC)STM32F103至少拥有2个ADC,STM32F103ZE包含3个ADC,这些 ADC 可 ...