新建
120
.gitignore
vendored
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
# ---> Node
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
.env.test
|
||||||
|
.env.production
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.*
|
||||||
|
|
@ -1,3 +1,8 @@
|
|||||||
# battleship
|
# 海战 Battleship
|
||||||
|
|
||||||
海战
|
## 参考
|
||||||
|
|
||||||
|
- [海战 (游戏)-维基百科](https://zh.m.wikipedia.org/wiki/%E6%B5%B7%E6%88%98_(%E6%B8%B8%E6%88%8F))
|
||||||
|
- [Battleship-维基百科](https://en.wikipedia.org/wiki/Battleship_(game))
|
||||||
|
- [一个单人游戏的例子](https://billmei.github.io/battleboat/)
|
||||||
|
- [一个多人游戏的例子](http://zh.battleship-game.org/)
|
||||||
|
3
参考项目/battleboat-gh-pages/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*.xlsx
|
||||||
|
*.xls
|
||||||
|
*.csv
|
20
参考项目/battleboat-gh-pages/LICENSE.txt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Bill Mei
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
10
参考项目/battleboat-gh-pages/README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
battleboat
|
||||||
|
==========
|
||||||
|
|
||||||
|
A JavaScript AI that beats humans at battleship.
|
||||||
|
|
||||||
|
Play the game here: [https://billmei.github.io/battleboat](https://billmei.github.io/battleboat)
|
||||||
|
|
||||||
|
If you've forked a copy of this repo or are playing around with the code on the `https://billmei.github.io/battleboat` page, please be nice and don't hack the `Stats` object. I'm using Google Analytics to collect info about the AI's win/loss percentage in order to improve the bot, so if you do look around, I kindly ask that you don't give it bad data. Thanks :)
|
||||||
|
|
||||||
|
If you want to try stuff out, run `setDebug(true);` in the console before doing anything. You'll also get access to some cool features.
|
319
参考项目/battleboat-gh-pages/css/styles.css
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700);
|
||||||
|
html, body {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
background-color: #ddd;
|
||||||
|
min-width: 860px;
|
||||||
|
}
|
||||||
|
h1, h2, h3, h4, h5, h6, p, li, span {
|
||||||
|
font-family: 'Open Sans', Helvetica, Arial, sans-serif;
|
||||||
|
color: #222222;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #222222;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
font-family: 'Open Sans', Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 1.2em;
|
||||||
|
color: #EEEEEE;
|
||||||
|
background-color: #25567B;
|
||||||
|
border: none;
|
||||||
|
margin: 1em auto 0 auto;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
button:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
button:active {
|
||||||
|
background-color: #99C2E1;
|
||||||
|
}
|
||||||
|
#start-game,
|
||||||
|
#place-randomly,
|
||||||
|
#restart-game {
|
||||||
|
position: relative;
|
||||||
|
color: #FFFFFF;
|
||||||
|
background-color: #FF9200;
|
||||||
|
}
|
||||||
|
#start-game:hover,
|
||||||
|
#place-randomly:hover,
|
||||||
|
#restart-game:hover {
|
||||||
|
background-color: #FFB655;
|
||||||
|
}
|
||||||
|
#start-game:active,
|
||||||
|
#place-randomly:active,
|
||||||
|
#restart-game:active {
|
||||||
|
background-color: #FFCE8E;
|
||||||
|
}
|
||||||
|
|
||||||
|
#prefetch1 {
|
||||||
|
background: url('../img/cross-icon.svg');
|
||||||
|
}
|
||||||
|
#prefetch2 {
|
||||||
|
background: url('../img/cross-icon.png');
|
||||||
|
}
|
||||||
|
#prefetch3 {
|
||||||
|
background: url('../img/crosshair.png');
|
||||||
|
}
|
||||||
|
.prefetch {
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: -9999px -9999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tagline {
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
.instructions {
|
||||||
|
width: auto;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: left;
|
||||||
|
margin: 0 auto 3em auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 870px;
|
||||||
|
text-align: center;
|
||||||
|
margin: 20px auto 100px auto;
|
||||||
|
}
|
||||||
|
.game-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
#roster-sidebar, #stats-sidebar, #restart-sidebar {
|
||||||
|
width: 150px;
|
||||||
|
padding: 20px;
|
||||||
|
margin: 0;
|
||||||
|
background-color: #EEEEEE;
|
||||||
|
position: absolute;
|
||||||
|
top: 4.5em;
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
-moz-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
#roster-sidebar, #restart-sidebar {
|
||||||
|
left: -200px;
|
||||||
|
}
|
||||||
|
#stats-sidebar {
|
||||||
|
right: -200px;
|
||||||
|
}
|
||||||
|
#roster-sidebar h2, #stats-sidebar h2, #restart-sidebar h2 {
|
||||||
|
margin: 0 0 1em 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fleet-roster {
|
||||||
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.fleet-roster, button {
|
||||||
|
opacity: 1;
|
||||||
|
-webkit-transition: opacity 0.5s ease-out;
|
||||||
|
-o-transition: opacity 0.5s ease-out;
|
||||||
|
transition: opacity 0.5s ease-out;
|
||||||
|
}
|
||||||
|
.fleet-roster li {
|
||||||
|
margin: 0.5em 0;
|
||||||
|
}
|
||||||
|
.fleet-roster li:hover {
|
||||||
|
color: #aaa;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.fleet-roster .placing {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.fleet-roster .placed {
|
||||||
|
visibility: hidden;
|
||||||
|
font-weight: bold;
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transition: all 0.2s ease-in;
|
||||||
|
-o-transition: all 0.2s ease-in;
|
||||||
|
transition: all 0.2s ease-in;
|
||||||
|
}
|
||||||
|
.invisible {
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transition: opacity 0.5s ease-in;
|
||||||
|
-o-transition: opacity 0.5s ease-in;
|
||||||
|
transition: opacity 0.5s ease-in;
|
||||||
|
z-index: -20;
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-container {
|
||||||
|
width: 430px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.grid-container h2 {
|
||||||
|
width: 430px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
position: relative;
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 5px;
|
||||||
|
height: 420px;
|
||||||
|
width: 420px;
|
||||||
|
background-color: #25567B;
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
-moz-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.grid-container:last-child {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.no-js {
|
||||||
|
width: 300px;
|
||||||
|
height: 300px;
|
||||||
|
margin: 100px auto;
|
||||||
|
display: inline-block;
|
||||||
|
color: #EEEEEE;
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
.grid-cell {
|
||||||
|
vertical-align: top; /*clears the vertical space between rows*/
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #99C2E1;
|
||||||
|
margin: 1px;
|
||||||
|
-webkit-border-radius: 2px;
|
||||||
|
-moz-border-radius: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.grid-cell:hover {
|
||||||
|
cursor: pointer; /* Fallback for IE */
|
||||||
|
background-color: #66A3D2;
|
||||||
|
}
|
||||||
|
.human-player .grid-cell:hover {
|
||||||
|
background-color: #99C2E1;
|
||||||
|
}
|
||||||
|
.computer-player .grid-cell:hover, .computer-player:hover {
|
||||||
|
cursor: url('../img/crosshair.png') 16 16, crosshair;
|
||||||
|
}
|
||||||
|
.grid-ship, .human-player .grid-ship:hover {
|
||||||
|
background-color: #808080;
|
||||||
|
}
|
||||||
|
.grid-miss, .grid-miss:hover, .human-player .grid-miss:hover {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
background-image: url('../img/cross-icon.png'); /* Fallback */
|
||||||
|
background-image: url('../img/cross-icon.svg');
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
.grid-hit, .grid-hit:hover, .human-player .grid-hit:hover {
|
||||||
|
background-color: #F60018;
|
||||||
|
background-image: url('../img/cross-icon.png'); /* Fallback */
|
||||||
|
background-image: url('../img/cross-icon.svg');
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
.grid-sunk, .grid-sunk:hover, .human-player .grid-sunk:hover {
|
||||||
|
background-color: #222222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
overflow: visible; /* Bugfix for IE */
|
||||||
|
}
|
||||||
|
.highlight:before {
|
||||||
|
content: "\2193";
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 75px;
|
||||||
|
color: #FF9200;
|
||||||
|
text-shadow: 0 0 5px #FF9200;
|
||||||
|
position: absolute;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
top: -100px;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -50px;
|
||||||
|
-webkit-animation: highlight 1.5s infinite;
|
||||||
|
-o-animation: highlight 1.5s infinite;
|
||||||
|
animation: highlight 1.5s infinite;
|
||||||
|
}
|
||||||
|
.current-step {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media(max-width: 1300px) {
|
||||||
|
.container {
|
||||||
|
width: 440px;
|
||||||
|
}
|
||||||
|
.grid-container:last-child {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@-webkit-keyframes highlight {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
-webkit-transform: translateY(-20px);
|
||||||
|
transform: translateY(-20px);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-moz-keyframes highlight {
|
||||||
|
0% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-20px);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-o-keyframes highlight {
|
||||||
|
0% {
|
||||||
|
-o-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
-o-transform: translateY(-20px);
|
||||||
|
transform: translateY(-20px);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-o-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes highlight {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: translateY(0);
|
||||||
|
-ms-transform: translateY(0);
|
||||||
|
-o-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
-webkit-transform: translateY(-20px);
|
||||||
|
-ms-transform: translateY(-20px);
|
||||||
|
-o-transform: translateY(-20px);
|
||||||
|
transform: translateY(-20px);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: translateY(0);
|
||||||
|
-ms-transform: translateY(0);
|
||||||
|
-o-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.6 KiB |
BIN
参考项目/battleboat-gh-pages/img/apple-touch-icon-precomposed.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
参考项目/battleboat-gh-pages/img/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
参考项目/battleboat-gh-pages/img/cross-icon.png
Normal file
After Width: | Height: | Size: 187 B |
8
参考项目/battleboat-gh-pages/img/cross-icon.svg
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||||
|
<line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" x1="0" y1="0" x2="16" y2="16"/>
|
||||||
|
<line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" x1="0" y1="16" x2="16" y2="0"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 685 B |
BIN
参考项目/battleboat-gh-pages/img/crosshair.png
Normal file
After Width: | Height: | Size: 639 B |
BIN
参考项目/battleboat-gh-pages/img/favicon.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
95
参考项目/battleboat-gh-pages/index.html
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width,maximum-scale=1">
|
||||||
|
<title>Battleboat.js - A JavaScript AI that beats humans at battleship.</title>
|
||||||
|
<meta name="description" content="Battleboat.js: A JavaScript AI that beats humans at battleship.">
|
||||||
|
<meta name="keywords" content="Battleboat.js, battleship, AI, robot, JavaScript">
|
||||||
|
<meta name="google" content="notranslate">
|
||||||
|
<link rel="icon" type="image/png" href="img/favicon.png" />
|
||||||
|
<link rel="image_src" href="img/apple-touch-icon-144x144-precomposed.png" />
|
||||||
|
<link rel="apple-touch-icon" href="img/apple-touch-icon.png" />
|
||||||
|
<link rel="apple-touch-icon-precomposed" href="img/apple-touch-icon-precomposed.png" />
|
||||||
|
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="img/apple-touch-icon-57x57-precomposed.png" />
|
||||||
|
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="img/apple-touch-icon-72x72-precomposed.png" />
|
||||||
|
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="img/apple-touch-icon-114x114-precomposed.png" />
|
||||||
|
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="img/apple-touch-icon-144x144-precomposed.png" />
|
||||||
|
|
||||||
|
<link rel="author" href="https://plus.google.com/+BillMei" />
|
||||||
|
<link rel="publisher" href="https://plus.google.com/+BillMei" />
|
||||||
|
|
||||||
|
<link href="css/styles.css" rel="stylesheet" media="all"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Battleboat.js</h1>
|
||||||
|
<p class="tagline">A JavaScript AI that beats humans at battleship.</p>
|
||||||
|
<p>How to play</p>
|
||||||
|
<ol class="instructions">
|
||||||
|
<li id="step1">Select your ships from the left-hand side</li>
|
||||||
|
<li id="step2">Place your ships on your map</li>
|
||||||
|
<li id="step3">Click on the cells of the enemy's map<br>
|
||||||
|
to find and destroy all five enemy ships</li>
|
||||||
|
<li id="step4">The computer will fire on your ships<br>
|
||||||
|
immediately after you fire on its ships.</li>
|
||||||
|
</ol>
|
||||||
|
<div class="game-container">
|
||||||
|
<div id="restart-sidebar" class="hidden">
|
||||||
|
<h2>Try Again</h2>
|
||||||
|
<button id="restart-game">Restart Game</button>
|
||||||
|
</div><div id="roster-sidebar">
|
||||||
|
<h2>Place Your Ships</h2>
|
||||||
|
<ul class="fleet-roster">
|
||||||
|
<li id="patrolboat">Patrol Boat</li>
|
||||||
|
<li id="submarine">Submarine</li>
|
||||||
|
<li id="destroyer">Destroyer</li>
|
||||||
|
<li id="battleship">Battleship</li>
|
||||||
|
<li id="carrier">Aircraft Carrier</li>
|
||||||
|
</ul>
|
||||||
|
<button id="rotate-button" data-direction="0">Rotate Ship</button>
|
||||||
|
<button id="start-game" class="hidden">Start Game</button>
|
||||||
|
<button id="place-randomly" class="hidden">Place Randomly and Start</button>
|
||||||
|
</div><div id="stats-sidebar">
|
||||||
|
<h2>Stats</h2>
|
||||||
|
<p><strong>Games Won</strong></p>
|
||||||
|
<p id="stats-wins">0 of 0</p>
|
||||||
|
<p><strong>Accuracy</strong></p>
|
||||||
|
<p id="stats-accuracy">0%</p>
|
||||||
|
<button id="reset-stats">Reset Stats</button>
|
||||||
|
<button id="prob-heatmap" class="hidden">Show Probability Heatmap</button>
|
||||||
|
</div><div class="grid-container">
|
||||||
|
<h2>Your Fleet</h2>
|
||||||
|
<div class="grid human-player"><span class="no-js">Please enable JavaScript to play this game</span></div>
|
||||||
|
</div><div class="grid-container">
|
||||||
|
<h2>Enemy Fleet</h2>
|
||||||
|
<div class="grid computer-player"><span class="no-js">Please enable JavaScript to play this game</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>Created by <a href="https://billmei.net">Bill Mei</a>.</p>
|
||||||
|
<p>This project is open source <a href="https://github.com/billmei/battleboat">on GitHub</a>.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a href="https://github.com/billmei/battleboat"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"></a>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Don't change this variable.
|
||||||
|
var DEBUG_MODE = localStorage.getItem('DEBUG_MODE') === 'true';
|
||||||
|
// To turn DEBUG_MODE on, run `setDebug(true);` in the console.
|
||||||
|
if (!DEBUG_MODE) {
|
||||||
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||||
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||||
|
ga('create', 'UA-10730961-10', 'auto');
|
||||||
|
ga('send', 'pageview');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="js/battleboat.js"></script>
|
||||||
|
<span class="prefetch" id="prefetch1"></span>
|
||||||
|
<span class="prefetch" id="prefetch2"></span>
|
||||||
|
<span class="prefetch" id="prefetch3"></span>
|
||||||
|
</body>
|
||||||
|
</html>
|
1371
参考项目/battleboat-gh-pages/js/battleboat.js
Normal file
176
参考项目/battleship-ui/battleship.css
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
* {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body,
|
||||||
|
html {
|
||||||
|
width: 1260px;
|
||||||
|
margin: auto;
|
||||||
|
color: darkslategray;
|
||||||
|
background-color: lightgrey;
|
||||||
|
font-family: Georgia, 'Times New Roman', Times, serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
margin: 2rem 0 0.5rem;
|
||||||
|
text-shadow: 1px 1px 2px white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#游戏区域 {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.棋盘 {
|
||||||
|
width: 600px;
|
||||||
|
height: 600px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#我方海域 {
|
||||||
|
background: url(images/sea.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
#敌方海域 {
|
||||||
|
background: url(images/grey.png);
|
||||||
|
cursor: url(images/crosshair.png) 16 16, crosshair;
|
||||||
|
}
|
||||||
|
|
||||||
|
.战舰 {
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
position: absolute;
|
||||||
|
left: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.甲板 {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#航空母舰 {
|
||||||
|
width: 60px;
|
||||||
|
height: 300px;
|
||||||
|
top: 60px;
|
||||||
|
}
|
||||||
|
#航空母舰.水平放置 {
|
||||||
|
height: 60px;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
#航空母舰0.甲板 {
|
||||||
|
background: url(images/ship1.png) -2px 0px no-repeat;
|
||||||
|
}
|
||||||
|
#航空母舰1.甲板 {
|
||||||
|
background: url(images/ship1.png) -2px -60px no-repeat;
|
||||||
|
}
|
||||||
|
#航空母舰2.甲板 {
|
||||||
|
background: url(images/ship1.png) -2px -120px no-repeat;
|
||||||
|
}
|
||||||
|
#航空母舰3.甲板 {
|
||||||
|
background: url(images/ship1.png) -2px -180px no-repeat;
|
||||||
|
}
|
||||||
|
#航空母舰4.甲板 {
|
||||||
|
background: url(images/ship1.png) -2px -240px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
#战列舰 {
|
||||||
|
width: 60px;
|
||||||
|
height: 240px;
|
||||||
|
top: 120px;
|
||||||
|
}
|
||||||
|
#战列舰.水平放置 {
|
||||||
|
width: 240px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
#战列舰0.甲板 {
|
||||||
|
background: url(images/ship2.png) -2px 0px no-repeat;
|
||||||
|
}
|
||||||
|
#战列舰1.甲板 {
|
||||||
|
background: url(images/ship2.png) -2px -60px no-repeat;
|
||||||
|
}
|
||||||
|
#战列舰2.甲板 {
|
||||||
|
background: url(images/ship2.png) -2px -120px no-repeat;
|
||||||
|
}
|
||||||
|
#战列舰3.甲板 {
|
||||||
|
background: url(images/ship2.png) -2px -180px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
#巡洋舰 {
|
||||||
|
width: 60px;
|
||||||
|
height: 180px;
|
||||||
|
top: 180px;
|
||||||
|
}
|
||||||
|
#驱逐舰 {
|
||||||
|
width: 60px;
|
||||||
|
height: 180px;
|
||||||
|
top: 240px;
|
||||||
|
}
|
||||||
|
#驱逐舰.水平放置,
|
||||||
|
#巡洋舰.水平放置 {
|
||||||
|
width: 180px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
#巡洋舰0.甲板 {
|
||||||
|
background: url(images/ship3.png) -2px 0px no-repeat;
|
||||||
|
}
|
||||||
|
#巡洋舰1.甲板 {
|
||||||
|
background: url(images/ship3.png) -2px -60px no-repeat;
|
||||||
|
}
|
||||||
|
#巡洋舰2.甲板 {
|
||||||
|
background: url(images/ship3.png) -2px -120px no-repeat;
|
||||||
|
}
|
||||||
|
#驱逐舰0.甲板 {
|
||||||
|
background: url(images/ship4.png) -2px 0px no-repeat;
|
||||||
|
}
|
||||||
|
#驱逐舰1.甲板 {
|
||||||
|
background: url(images/ship4.png) -2px -60px no-repeat;
|
||||||
|
}
|
||||||
|
#驱逐舰2.甲板 {
|
||||||
|
background: url(images/ship4.png) -2px -120px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
#巡逻艇 {
|
||||||
|
width: 60px;
|
||||||
|
height: 120px;
|
||||||
|
top: 300px;
|
||||||
|
}
|
||||||
|
#巡逻艇.水平放置 {
|
||||||
|
width: 120px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
#巡逻艇0.甲板 {
|
||||||
|
background: url(images/ship5.png) -2px 0px no-repeat;
|
||||||
|
}
|
||||||
|
#巡逻艇1.甲板 {
|
||||||
|
background: url(images/ship5.png) -2px -60px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.水平放置 .甲板 {
|
||||||
|
transform-origin: top left;
|
||||||
|
transform: scaleY(-1) rotate(-90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.拖拽中 {
|
||||||
|
z-index: -10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.平静海面 {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
position: absolute;
|
||||||
|
background: url(images/sea.png) no-repeat center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.爆炸海面 {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
position: absolute;
|
||||||
|
background: url(images/boom.png) no-repeat center, url(images/sea.png) no-repeat center;
|
||||||
|
}
|
101
参考项目/battleship-ui/battleship.js
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
let 游戏已开始 = false
|
||||||
|
|
||||||
|
const 我方舰队 = document.querySelectorAll('.战舰')
|
||||||
|
|
||||||
|
我方舰队.forEach((ship) => {
|
||||||
|
// 拖拽开始记录拖拽位置
|
||||||
|
ship.addEventListener('dragstart', (event) => {
|
||||||
|
ship.classList.add('拖拽中')
|
||||||
|
const rect = ship.getBoundingClientRect()
|
||||||
|
ship.dataset.drag_left = event.clientX - rect.left
|
||||||
|
ship.dataset.drag_top = event.clientY - rect.top
|
||||||
|
event.dataTransfer.setData('mouse_x', event.layerX)
|
||||||
|
event.dataTransfer.setData('mouse_y', event.layerY)
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
console.log(`拖动了${ship.id},拖动点位于船上(${ship.dataset.drag_left},${ship.dataset.drag_top})`)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 拖拽结束更新战舰位置
|
||||||
|
ship.addEventListener('dragend', (event) => {
|
||||||
|
// const 其它战舰 = [...我方海域.querySelectorAll('.战舰:not(.拖拽中)')]
|
||||||
|
|
||||||
|
// event.dataTransfer.setData('a', event.clientX)
|
||||||
|
// event.dataTransfer.setData('b', event.clientY)
|
||||||
|
|
||||||
|
let mouse_x = event.dataTransfer.getData('mouse_x')
|
||||||
|
let mouse_y = event.dataTransfer.getData('mouse_y')
|
||||||
|
let x = event.layerX
|
||||||
|
let y = event.layerY
|
||||||
|
console.log(parseInt(Math.ceil((x - mouse_x) / 60)), parseInt(Math.ceil((y - mouse_y) / 60)))
|
||||||
|
|
||||||
|
// 判断移动是否合法
|
||||||
|
|
||||||
|
// 更新战舰显示位置
|
||||||
|
ship.style.left = `${ship.dataset.drop_left}px`
|
||||||
|
ship.style.top = `${ship.dataset.drop_top}px`
|
||||||
|
|
||||||
|
ship.classList.remove('拖拽中')
|
||||||
|
delete ship.dataset.drag_left
|
||||||
|
delete ship.dataset.drag_top
|
||||||
|
delete ship.dataset.drop_left
|
||||||
|
delete ship.dataset.drop_top
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
// console.log(我方海域状态)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 左键点击旋转战舰
|
||||||
|
ship.addEventListener('click', (event) => {
|
||||||
|
// TODO: 检查旋转是否合法:1游戏未开始,2没有碰撞其它战舰,3没有出边界
|
||||||
|
if (游戏已开始) return
|
||||||
|
ship.classList.toggle('水平放置')
|
||||||
|
|
||||||
|
// DEGUB
|
||||||
|
console.log(`点击了[ ${ship.id} ]的[ ${event.target.id} ]甲板`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
我方海域.addEventListener('dragover', (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
const dragging_ship = document.querySelector('.拖拽中')
|
||||||
|
if (event.target === 我方海域) {
|
||||||
|
const 拖拽中的战舰 = document.querySelector('.拖拽中')
|
||||||
|
拖拽中的战舰.dataset.drop_left = parseInt(Math.ceil(event.layerX - 拖拽中的战舰.dataset.drag_left + 30) / 60) * 60
|
||||||
|
拖拽中的战舰.dataset.drop_top = parseInt(Math.ceil(event.layerY - 拖拽中的战舰.dataset.drag_top + 30) / 60) * 60
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
console.log(`拖拽到了(${拖拽中的战舰.dataset.drop_left}, ${拖拽中的战舰.dataset.drop_top})`)
|
||||||
|
}
|
||||||
|
// const 拖拽中的战舰 = document.querySelector('.拖拽中')
|
||||||
|
// const other_ships = [...我方海域.querySelectorAll('.ship:not(.拖拽中)')]
|
||||||
|
// let leading_ship = null
|
||||||
|
// for (let ship of other_ships) {
|
||||||
|
// const ship_rect = ship.getBoundingClientRect()
|
||||||
|
// const mouse_offset = mouse_x - ship_rect.left - ship_rect.width / 2
|
||||||
|
// if (mouse_offset > 0) leading_ship = ship
|
||||||
|
// }
|
||||||
|
// if (leading_ship) leading_ship.after(拖拽中的战舰)
|
||||||
|
// else 我方海域.prepend(拖拽中的战舰)
|
||||||
|
})
|
||||||
|
|
||||||
|
我方海域.addEventListener('dragend', (event) => {
|
||||||
|
// console.log(event)
|
||||||
|
})
|
||||||
|
|
||||||
|
敌方海域.addEventListener('click', (event) => {
|
||||||
|
if (event.target !== 敌方海域) return
|
||||||
|
|
||||||
|
// 展开迷雾
|
||||||
|
const area = document.createElement('div')
|
||||||
|
if (Math.random() > 0.5) area.classList.add('平静海面')
|
||||||
|
else area.classList.add('爆炸海面')
|
||||||
|
const col = parseInt(event.layerX / 60)
|
||||||
|
const row = parseInt(event.layerY / 60)
|
||||||
|
area.style.left = `${col * 60}px`
|
||||||
|
area.style.top = `${row * 60}px`
|
||||||
|
敌方海域.append(area)
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
console.log(`炮击地方海域(${col}, ${row})`)
|
||||||
|
})
|
BIN
参考项目/battleship-ui/favicon.ico
Normal file
After Width: | Height: | Size: 164 KiB |
BIN
参考项目/battleship-ui/images/boom.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
参考项目/battleship-ui/images/btn_play.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
参考项目/battleship-ui/images/btn_shuffle.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
参考项目/battleship-ui/images/btn_startwar.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
参考项目/battleship-ui/images/crosshair.png
Normal file
After Width: | Height: | Size: 639 B |
BIN
参考项目/battleship-ui/images/grey.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
参考项目/battleship-ui/images/port.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
参考项目/battleship-ui/images/sea.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
参考项目/battleship-ui/images/ship1.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
参考项目/battleship-ui/images/ship2.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
参考项目/battleship-ui/images/ship3.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
参考项目/battleship-ui/images/ship4.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
参考项目/battleship-ui/images/ship5.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
53
参考项目/battleship-ui/index.html
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="stylesheet" href="battleship.css" />
|
||||||
|
<title>海战 Battleship</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>海战 Battleship</h1>
|
||||||
|
<div id="游戏区域">
|
||||||
|
<div id="我方">
|
||||||
|
<h2>我方海域 Player Area</h2>
|
||||||
|
<div id="我方海域" class="棋盘">
|
||||||
|
<div id="航空母舰" class="战舰 水平放置" draggable="true" title="航空母舰 Carrier">
|
||||||
|
<div id="航空母舰0" class="甲板" data-location="11"></div>
|
||||||
|
<div id="航空母舰1" class="甲板" data-location="21"></div>
|
||||||
|
<div id="航空母舰2" class="甲板" data-location="31"></div>
|
||||||
|
<div id="航空母舰3" class="甲板" data-location="41"></div>
|
||||||
|
<div id="航空母舰4" class="甲板" data-location="51"></div>
|
||||||
|
</div>
|
||||||
|
<div id="战列舰" class="战舰 水平放置" draggable="true" title="战列舰 Battleship">
|
||||||
|
<div id="战列舰0" class="甲板" data-location="12"></div>
|
||||||
|
<div id="战列舰1" class="甲板" data-location="22"></div>
|
||||||
|
<div id="战列舰2" class="甲板" data-location="32"></div>
|
||||||
|
<div id="战列舰3" class="甲板" data-location="42"></div>
|
||||||
|
</div>
|
||||||
|
<div id="巡洋舰" class="战舰 水平放置" draggable="true" title="巡洋舰 Cruiser">
|
||||||
|
<div id="巡洋舰0" class="甲板" data-location="13"></div>
|
||||||
|
<div id="巡洋舰1" class="甲板" data-location="23"></div>
|
||||||
|
<div id="巡洋舰2" class="甲板" data-location="33"></div>
|
||||||
|
</div>
|
||||||
|
<div id="驱逐舰" class="战舰 水平放置 沉没" draggable="true" title="驱逐舰 Destroyer">
|
||||||
|
<div id="驱逐舰0" class="甲板" data-location="14"></div>
|
||||||
|
<div id="驱逐舰1" class="甲板" data-location="24"></div>
|
||||||
|
<div id="驱逐舰2" class="甲板" data-location="34"></div>
|
||||||
|
</div>
|
||||||
|
<div id="巡逻艇" class="战舰 水平放置" draggable="true" title="巡逻艇 Patrol Boat">
|
||||||
|
<div id="巡逻艇0" class="甲板" data-location="15"></div>
|
||||||
|
<div id="巡逻艇1" class="甲板" data-location="25"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="敌方">
|
||||||
|
<h2>敌方海域 Enemy Area</h2>
|
||||||
|
<div id="敌方海域" class="棋盘"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="battleship.js" defer></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
3553
参考项目/battleship.js/package-lock.json
generated
Normal file
24
参考项目/battleship.js/package.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "battleship.js",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "A multiplayer battleship game.",
|
||||||
|
"main": "server.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node server",
|
||||||
|
"dev": "nodemon server"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"multiplayer",
|
||||||
|
"battleship",
|
||||||
|
"game"
|
||||||
|
],
|
||||||
|
"author": "Zhao Xin <7176466@qq.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"nodemon": "^2.0.15"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.17.3",
|
||||||
|
"socket.io": "^4.4.1"
|
||||||
|
}
|
||||||
|
}
|
41
参考项目/battleship.js/public/battleship.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
const client = io()
|
||||||
|
|
||||||
|
client.on('connect', () => {
|
||||||
|
console.log('connected')
|
||||||
|
})
|
||||||
|
|
||||||
|
client.on('welcome', () => {
|
||||||
|
console.log('welcome')
|
||||||
|
})
|
||||||
|
|
||||||
|
const CARRIER = 1 // 航空母舰 5
|
||||||
|
const BATTLESHIP = 2 // 战列舰 4
|
||||||
|
const DESTROYER = 3 // 驱逐舰 3
|
||||||
|
const SUBMARINE = 4 // 潜艇 3
|
||||||
|
const PATROLBOAT = 5 // 巡逻艇 2
|
||||||
|
|
||||||
|
CONST.EMPTY = 0
|
||||||
|
CONST.SHIP = 1
|
||||||
|
CONST.MISS = 2
|
||||||
|
CONST.HIT = 3
|
||||||
|
CONST.SUNK = 4
|
||||||
|
|
||||||
|
function player_click(event) {
|
||||||
|
const x = event.target.dataset.x
|
||||||
|
const y = event.target.dataset.y
|
||||||
|
const player = event.target.dataset.player
|
||||||
|
const status = event.target.dataset.status
|
||||||
|
console.log(x, y, player, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
function enemy_click(event) {
|
||||||
|
const x = event.target.dataset.x
|
||||||
|
const y = event.target.dataset.y
|
||||||
|
const player = event.target.dataset.player
|
||||||
|
const status = event.target.dataset.status
|
||||||
|
console.log(x, y, player, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ship_rotate(event) {
|
||||||
|
event.target.classList.toggle('ship-horizontal')
|
||||||
|
}
|
BIN
参考项目/battleship.js/public/favicon.ico
Normal file
After Width: | Height: | Size: 164 KiB |
BIN
参考项目/battleship.js/public/images/Battleships_Paper_Game.svg.png
Normal file
After Width: | Height: | Size: 163 KiB |
BIN
参考项目/battleship.js/public/images/Sea Warfare Set.zip
Normal file
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 367 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 129 B |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 203 B |
BIN
参考项目/battleship.js/public/images/Sea Warfare Set/Display.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 382 B |
After Width: | Height: | Size: 118 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 999 B |
After Width: | Height: | Size: 958 B |
After Width: | Height: | Size: 166 B |
BIN
参考项目/battleship.js/public/images/aim.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
参考项目/battleship.js/public/images/bg_game.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
参考项目/battleship.js/public/images/boom.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
参考项目/battleship.js/public/images/boom60.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
参考项目/battleship.js/public/images/btn_close.png
Normal file
After Width: | Height: | Size: 994 B |
BIN
参考项目/battleship.js/public/images/btn_exit.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
参考项目/battleship.js/public/images/btn_home.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
参考项目/battleship.js/public/images/btn_play.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
参考项目/battleship.js/public/images/btn_restart.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
参考项目/battleship.js/public/images/btn_rotate.png
Normal file
After Width: | Height: | Size: 529 B |
BIN
参考项目/battleship.js/public/images/btn_shuffle.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
参考项目/battleship.js/public/images/btn_sound_off.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
参考项目/battleship.js/public/images/btn_sound_on.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
参考项目/battleship.js/public/images/btn_startwar.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
参考项目/battleship.js/public/images/crosshair.png
Normal file
After Width: | Height: | Size: 639 B |
BIN
参考项目/battleship.js/public/images/exp.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
参考项目/battleship.js/public/images/footer.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
参考项目/battleship.js/public/images/guide.png
Normal file
After Width: | Height: | Size: 765 KiB |
BIN
参考项目/battleship.js/public/images/missile1.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
参考项目/battleship.js/public/images/missile2.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
参考项目/battleship.js/public/images/ship1.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
参考项目/battleship.js/public/images/ship2.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
参考项目/battleship.js/public/images/ship3.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
参考项目/battleship.js/public/images/ship4.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
参考项目/battleship.js/public/images/ship5.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
参考项目/battleship.js/public/images/splash.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
参考项目/battleship.js/public/images/tile.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
参考项目/battleship.js/public/images/tile_green.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
参考项目/battleship.js/public/images/tile_red.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
参考项目/battleship.js/public/images/touch.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
参考项目/battleship.js/public/images/turn1.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
参考项目/battleship.js/public/images/turn2.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
参考项目/battleship.js/public/images/weapon1.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
参考项目/battleship.js/public/images/weapon2.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
参考项目/battleship.js/public/images/window.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
284
参考项目/battleship.js/public/index.html
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="stylesheet" href="style.css" />
|
||||||
|
<title>海战 Battleship</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>海战 Battleship</h1>
|
||||||
|
<div id="game">
|
||||||
|
<div class="row">
|
||||||
|
<table id="player1" class="gameboard">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>我方舰队 Your Fleet</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="0" data-x="0" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="0" data-x="1" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="0" data-x="2" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="0" data-x="3" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="0" data-x="4" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="0" data-x="5" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="0" data-x="6" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="0" data-x="7" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="0" data-x="8" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="0" data-x="9" onclick="player_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="1" data-x="0" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell ship11" data-player="0" data-status="0" data-y="1" data-x="1" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="1" data-x="2" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="1" data-x="3" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="1" data-x="4" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="1" data-x="5" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="1" data-x="6" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="1" data-x="7" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="1" data-x="8" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="1" data-x="9" onclick="player_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="2" data-x="0" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell ship12h" data-player="0" data-status="0" data-y="2" data-x="1" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="2" data-x="2" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="2" data-x="3" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="2" data-x="4" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="2" data-x="5" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="2" data-x="6" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="2" data-x="7" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="2" data-x="8" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="2" data-x="9" onclick="player_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="3" data-x="0" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="3" data-x="1" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="3" data-x="2" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="3" data-x="3" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="3" data-x="4" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="3" data-x="5" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="3" data-x="6" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="3" data-x="7" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="3" data-x="8" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="3" data-x="9" onclick="player_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="4" data-x="0" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="4" data-x="1" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="4" data-x="2" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="4" data-x="3" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="4" data-x="4" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="4" data-x="5" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="4" data-x="6" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="4" data-x="7" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="4" data-x="8" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="4" data-x="9" onclick="player_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="5" data-x="0" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="5" data-x="1" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="5" data-x="2" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="5" data-x="3" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="5" data-x="4" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="5" data-x="5" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="5" data-x="6" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="5" data-x="7" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="5" data-x="8" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="5" data-x="9" onclick="player_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="6" data-x="0" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="6" data-x="1" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="6" data-x="2" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="6" data-x="3" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="6" data-x="4" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="6" data-x="5" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="6" data-x="6" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="6" data-x="7" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="6" data-x="8" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="6" data-x="9" onclick="player_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="7" data-x="0" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="7" data-x="1" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="7" data-x="2" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="7" data-x="3" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="7" data-x="4" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="7" data-x="5" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="7" data-x="6" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="7" data-x="7" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="7" data-x="8" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="7" data-x="9" onclick="player_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="8" data-x="0" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="8" data-x="1" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="8" data-x="2" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="8" data-x="3" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="8" data-x="4" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="8" data-x="5" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="8" data-x="6" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="8" data-x="7" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="8" data-x="8" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="8" data-x="9" onclick="player_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="9" data-x="0" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="9" data-x="1" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="9" data-x="2" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="9" data-x="3" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="9" data-x="4" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="9" data-x="5" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="9" data-x="6" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="9" data-x="7" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="9" data-x="8" onclick="player_click(event)"></td>
|
||||||
|
<td class="cell" data-player="0" data-status="0" data-y="9" data-x="9" onclick="player_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table id="player2" class="gameboard">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>敌方舰队 Enemy Fleet</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="0" data-x="0" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="0" data-x="1" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="0" data-x="2" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="0" data-x="3" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="0" data-x="4" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="0" data-x="5" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="0" data-x="6" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="0" data-x="7" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="0" data-x="8" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="0" data-x="9" onclick="enemy_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="1" data-x="0" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="1" data-x="1" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="1" data-x="2" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="1" data-x="3" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="1" data-x="4" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="1" data-x="5" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="1" data-x="6" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="1" data-x="7" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="1" data-x="8" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="1" data-x="9" onclick="enemy_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="2" data-x="0" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="2" data-x="1" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="2" data-x="2" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="2" data-x="3" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="2" data-x="4" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="2" data-x="5" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="2" data-x="6" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="2" data-x="7" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="2" data-x="8" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="2" data-x="9" onclick="enemy_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="3" data-x="0" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="3" data-x="1" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="3" data-x="2" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="3" data-x="3" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="3" data-x="4" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="3" data-x="5" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="3" data-x="6" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="3" data-x="7" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="3" data-x="8" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="3" data-x="9" onclick="enemy_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="4" data-x="0" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="4" data-x="1" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="4" data-x="2" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="4" data-x="3" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="4" data-x="4" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="4" data-x="5" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="4" data-x="6" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="4" data-x="7" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="4" data-x="8" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="4" data-x="9" onclick="enemy_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="5" data-x="0" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="5" data-x="1" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="5" data-x="2" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="5" data-x="3" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="5" data-x="4" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="5" data-x="5" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="5" data-x="6" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="5" data-x="7" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="5" data-x="8" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="5" data-x="9" onclick="enemy_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="6" data-x="0" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="6" data-x="1" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="6" data-x="2" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="6" data-x="3" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="6" data-x="4" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="6" data-x="5" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="6" data-x="6" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="6" data-x="7" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="6" data-x="8" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="6" data-x="9" onclick="enemy_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="7" data-x="0" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="7" data-x="1" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="7" data-x="2" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="7" data-x="3" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="7" data-x="4" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="7" data-x="5" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="7" data-x="6" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="7" data-x="7" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="7" data-x="8" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="7" data-x="9" onclick="enemy_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="8" data-x="0" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="8" data-x="1" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="8" data-x="2" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="8" data-x="3" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="8" data-x="4" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="8" data-x="5" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="8" data-x="6" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="8" data-x="7" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="8" data-x="8" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="8" data-x="9" onclick="enemy_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="9" data-x="0" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="9" data-x="1" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="9" data-x="2" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="9" data-x="3" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="9" data-x="4" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="9" data-x="5" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="9" data-x="6" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="9" data-x="7" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="9" data-x="8" onclick="enemy_click(event)"></td>
|
||||||
|
<td class="cell" data-player="1" data-status="0" data-y="9" data-x="9" onclick="enemy_click(event)"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div id="ships" class="row">
|
||||||
|
<div class="ship ship-carrier" id="carrier" data-size="5" onclick="ship_rotate(event)" title="航空母舰 Carrier"></div>
|
||||||
|
<div class="ship ship-battleship" id="battleship" data-size="4" onclick="ship_rotate(event)" title="战列舰 Battleship"></div>
|
||||||
|
<div class="ship ship-destroyer" id="destroyer" data-size="3" onclick="ship_rotate(event)" title="战列舰 Battleship"></div>
|
||||||
|
<div class="ship ship-submarine" id="submarine" data-size="3" onclick="ship_rotate(event)" title="潜艇 Submarine"></div>
|
||||||
|
<div class="ship ship-patrolboat" id="patrolboat" data-size="2" onclick="ship_rotate(event)" title="护卫舰 Patrol Boat"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="/socket.io/socket.io.min.js"></script>
|
||||||
|
<script src="battleship.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
174
参考项目/battleship.js/public/style.css
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/* @import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); */
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
overflow-x: hidden;
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
margin: 40px auto;
|
||||||
|
color: darkblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
width: 1280px;
|
||||||
|
margin: auto;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
border: 1px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gameboard {
|
||||||
|
width: 600px;
|
||||||
|
height: 600px;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: darkblue;
|
||||||
|
color: aquamarine;
|
||||||
|
}
|
||||||
|
|
||||||
|
#player1 tbody {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#player2 tbody {
|
||||||
|
cursor: url(images/crosshair.png) 16 16, crosshair;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gameboard tbody tr {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell {
|
||||||
|
width: 58px;
|
||||||
|
height: 58px;
|
||||||
|
margin: 1px;
|
||||||
|
background: url(images/tile.png) no-repeat center;
|
||||||
|
border-radius: 3px;
|
||||||
|
z-index: 0;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship11 {
|
||||||
|
background: url(images/ship1.png) -2px 0px no-repeat, url(images/tile.png) no-repeat center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship12 {
|
||||||
|
background: url(images/ship1.png) -2px -60px no-repeat, url(images/tile.png) no-repeat center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship12h {
|
||||||
|
background: url(images/boom60.png) 0px 0px no-repeat, url(images/ship1.png) -2px -60px no-repeat, url(images/tile.png) no-repeat center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ships {
|
||||||
|
display: flex;
|
||||||
|
justify-content: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship {
|
||||||
|
width: 60px;
|
||||||
|
border: 1px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship-carrier {
|
||||||
|
height: 300px;
|
||||||
|
background: url(images/ship1.png) -2px -1px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship-battleship {
|
||||||
|
height: 240px;
|
||||||
|
background: url(images/ship2.png) -2px -1px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship-destroyer {
|
||||||
|
height: 180px;
|
||||||
|
background: url(images/ship3.png) -2px -1px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship-submarine {
|
||||||
|
height: 180px;
|
||||||
|
background: url(images/ship4.png) -2px -1px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship-patrolboat {
|
||||||
|
height: 120px;
|
||||||
|
background: url(images/ship5.png) -2px -1px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship-carrier.ship-horizontal {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
.ship-battleship.ship-horizontal {
|
||||||
|
width: 240px;
|
||||||
|
}
|
||||||
|
.ship-destroyer.ship-horizontal,
|
||||||
|
.ship-submarine.ship-horizontal {
|
||||||
|
width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship-patrolboat.ship-horizontal {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship-horizontal {
|
||||||
|
width: 60px !important;
|
||||||
|
transform-origin: top left;
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
margin-top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .ship1 {
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship1::after {
|
||||||
|
content: '';
|
||||||
|
z-index: 1000;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background-position: bottom;
|
||||||
|
background-size: cover;
|
||||||
|
width: 60px;
|
||||||
|
height: 300px;
|
||||||
|
background: url(images/ship1.png) -2px 0px no-repeat;
|
||||||
|
transform-origin: top left;
|
||||||
|
transform: scaleY(-1) rotate(-90deg);
|
||||||
|
} */
|
||||||
|
|
||||||
|
.gameboard tbody td:hover {
|
||||||
|
/* border: 2px dashed aqua; */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .container {
|
||||||
|
width: 100vw;
|
||||||
|
background-color: orange;
|
||||||
|
margin: 10px auto;
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gameboard {
|
||||||
|
width: 600px;
|
||||||
|
height: 600px;
|
||||||
|
margin: 10px;
|
||||||
|
background-color: aqua;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ship {
|
||||||
|
width: 100px;
|
||||||
|
height: 20px;
|
||||||
|
background-color: blue;
|
||||||
|
border: 1px black solid;
|
||||||
|
} */
|
11
参考项目/battleship.js/server.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
const express = require('express')
|
||||||
|
const app = express()
|
||||||
|
app.use(express.static(require('path').join(__dirname, 'public')))
|
||||||
|
const host = process.env.HOST || 'localhost'
|
||||||
|
const port = process.env.PORT || 3000
|
||||||
|
const server = require('http').createServer(app)
|
||||||
|
const io = require('socket.io')(server)
|
||||||
|
io.on('connection', (client) => {
|
||||||
|
client.emit('welcome')
|
||||||
|
})
|
||||||
|
server.listen(port, host, () => console.log(`battleship game server listening at http://${host}:${port}/`))
|
1
参考项目/battleship_frontend
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 05bbc36a563ee4ce2ab0b111450f77f2a3b6539a
|
1
参考项目/battleships
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit ed4a739219b343f6f6ae1781d5ea36beb58faea7
|