贴片的贴片的三年 - - §2023年2月26日...
我将与之处理 hó°°°°Cels nau na nha nha nha nha nha nha nha nha nha nha nha nha nho u°a
我有很多花
trä或ngcaìgoìcwood yourniìubear ing aark cché¢n qua
lu°在花中使用很多花。
khã´ngSäìcaìcaìutiìmbijªìcCaìnhBäìngLäng
不与花一样相同
mi nhe nhe nhe nh nh nh nh nh nh nh nh°°a d i thu th ...
1.介绍
1.1。概述
caro是一个简单的游戏,我们都在小时候玩过。我们可以以两种模式玩游戏:人与人类或更先进的人类与计算机。 Howerver,我们很喜欢它,我们可以创建两台计算机,它们可以与它们一起玩。在文章中,我将以三种模式开发游戏:
-
人与人类
-
人与计算机
-
计算机与计算机
1.2。介绍Caro游戏
gomoku以来在梅吉修复之前就在日本存在。[7] “ gomoku”这个名字来自日语,其中称为gomokunarabe(äºç®äply¦)。 GO表示五,Moku是碎片的反词,Narabe表示阵容。该游戏在中国很受欢迎,在中国被称为wuziqi(äº了£)。[8] Wu(äºWç)是指五,Zi(ÅZç)的意思是片段,而Qi(£Qã)是指中文的棋盘游戏类别。该游戏在韩国也很受欢迎,在韩国被称为Omok(QQ。[äºC®]),其结构和起源与日本名称相同。在十九世纪,该游戏被介绍给英国,在那里被称为Go Bang,据说是日语单词Goban的腐败,该单词本身是从中国k'i Pan(Qãpân)改编的。董事会。”
1.3。游戏规则
自由泳gomoku对任何一个玩家都没有限制,并且允许玩家通过创建五个或更多的石头来获胜,每个玩家交替一次将一块石头放置。
Black(首次移动的球员)长期以来一直在具有优势,甚至在L. Victor Allis证明Black可以强迫胜利之前(见下文)。 Renju试图通过额外的规则来减轻这种失衡,旨在降低黑人的第一名优势。它是在15ã15板上播放的,规则为三,四,四和四,并且仅适用于黑色。
-
三和三禁止行动的规则同时形成了两条敞开的三个石头(在任一端都不会被对手的石头阻塞)。
-
四个禁令的规则同时形成了两行的四个石头(开放与否)。
-
如果玩家形成一条6或更多的石头,则可以防止玩家获胜。 Renju还利用各种锦标赛开放规则,例如SOOSãµRV-8,当前的国际标准。
在Caro(也称为Gomoku+,在越南人中很受欢迎),获胜者必须具有一条上线或一排未经破坏的五块石头,这两端都没有被阻止(覆盖范围不受此规则的影响)。这使游戏更加平衡,并为怀特提供了更大的力量。
2.游戏项目结构
-
css :这是所有CSS文件都保存的文件夹:style.html,使页面变得漂亮,等等。
-
图像:这是保存游戏的所有图像的文件夹:背景,x,o,...
-
JS :这是保存所有JavaScript文件的文件夹:处理和处理游戏的所有功能。
-
caro.html,home.html :游戏接口。
3.开发游戏
3.1。游戏界面
- home.html :Caro Game的主页。
<!DOCTYPE html>
<html lang="en">
<link rel="stylesheet" href="../common/css/home.css">
<link rel="stylesheet" href="css/caro.css">
<head>
<meta charset="UTF-8">
<title>Home game tic tac toe</title>
</head>
<body>
<div>
<div class="options">
<label for="list-type-play"></label><select id="list-type-play" class="hide-option option">
<option selected="selected" disabled="disabled" value="">Select type play</option>
<option value="2-players">2 players</option>
<option value="player-computer">Player and computer</option>
<option value="computer-computer">Computer and computer</option>
</select>
</div>
<div class="options" style="margin-top: 30px">
<label for="list-row"></label><select id="list-row" class="hide-option option">
<option selected="selected" disabled="disabled" value="">Select amount of rows</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
<option value="50">50</option>
<option value="60">60</option>
</select>
</div>
<div class="options" style="margin-top: 30px">
<label for="list-column"></label><select id="list-column" class="hide-option option">
<option selected="selected" disabled="disabled" value="">Select amount of columns</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
<option value="50">50</option>
<option value="60">60</option>
</select>
</div>
</div>
<div class="button" id="button" onclick="handleLetGo()">Let's go!</div>
</body>
</html>
<script type="text/javascript" src="js/caro-home.js"></script>
- caro.html :主游戏接口
<!DOCTYPE html>
<html lang="en">
<link rel="stylesheet" href="css/caro.css">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Game caro</title>
<link href="https://fonts.googleapis.com/css?family=Indie+Flower" rel="stylesheet">
</head>
<body>
<h1>Game caro X-O</h1>
<table id="table_game">
</table>
</body>
</html>
<script type="text/javascript" src="js/constants.js"></script>
<script type="text/javascript" src="js/caro-main.js"></script>
- caro.css :我们可以为所有HTML元素添加样式:颜色页,背景,字体和尺寸单词。
body {
background-color: rgb(32, 32, 32);
background-image: url("https://janschreiber.github.io/img2/black-chalk.jpg");
color: rgb(230, 230, 230);
text-align: center;
font-family: 'Indie Flower', 'Comic Sans', cursive;
font-size: 0.7em;
}
h1 {
line-height: 1em;
margin-bottom: 0;
padding-bottom: 5px;
font-size: 2.8em;
font-weight: bold;
}
h2 {
font-size: 1.3em;
font-weight: bold;
padding: 0;
margin: 0;
}
h3 {
font-size: 1.1em;
text-decoration: underline;
text-decoration-style: dashed;
padding: 0;
margin: 10px 0 2px 0;
}
table {
margin: 2% auto;
border-collapse: collapse;
}
#table_game {
position: relative;
font-size: 120px;
margin: 1% auto;
border-collapse: collapse;
}
.td_game {
border: 4px solid rgb(230, 230, 230);
width: 90px;
height: 90px;
padding: 0;
vertical-align: middle;
text-align: center;
}
.fixed {
width: 90px;
height: 90px;
line-height: 90px;
display: block;
overflow: hidden;
cursor: pointer;
}
.td_list {
text-align: center;
font-size: 1.3em;
font-weight: bold;
}
.th_list {
font-size: 1.3em;
font-weight: bold;
text-align: center;
text-decoration: underline;
}
#restart {
font-size: 3em;
width: 1em;
height: 0.9em;
cursor: pointer;
margin: 0 auto;
overflow: hidden;
}
.x {
color: darksalmon;
position: relative;
top: -8px;
font-size: 1.2em;
cursor: default;
}
.o {
color: aquamarine;
position: relative;
top: -7px;
font-size: 1.0em;
cursor: default;
}
/* modal background */
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto; /* enable scroll if needed */
background-color: black; /* fallback color */
background-color: rgba(0, 0, 0, 0.6);
}
/* modal content */
.modal-content {
background-color: rgb(240, 240, 240);
color: rgb(32, 32, 32);
font-size: 2em;
font-weight: bold;
/* 16 % from the top and centered */
margin: 16% auto;
padding: 20px;
border: 2px solid black;
border-radius: 10px;
width: 380px;
max-width: 80%;
}
.modal-content p {
margin: 0;
padding: 0;
}
/* close button for modal dialog */
.close {
color: rgb(170, 170, 170);
float: right;
position: relative;
top: -25px;
right: -10px;
font-size: 34px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
.win-color {
background-color: rgb(240, 240, 240);
}
因为游戏接口仅具有HTML和CSS。它并不复杂或困难,所以让我们阅读和理解它!下面是结果
3.2。处理游戏的所有功能
caro-home.js :这是处理主页上所有功能和事件的文件。在主页上,我们将仅处理玩家单击按钮时发生的事件,让我们去。我们将添加三个参数:游戏模式,行总和和列的总和。
function handleLetGo() {
let typePlay = document.getElementById("list-type-play").value;
let rows = document.getElementById("list-row").value;
let columns = document.getElementById("list-column").value;
if (typePlay === "" || rows === "" || columns === "") {
alert("Vui lòng chọn kiểu chơi");
return
}
window.location.href = "/game-development/games/caro/caro.html?type=" + typePlay + "&rows=" + rows + "&columns=" + columns;
}
caro-main.js :这是处理游戏中所有主要事件的文件。在这一点上,我们将开发许多事件和功能。让我们和我一起发展游戏! ð7
当然!游戏将首次启动变量,事件,音乐和图像,... 函数init 将检索游戏模式的主页值,行总和和列的总和。基于该信息,我们将创建一个游戏矩阵,其中 x的 x 的总和。游戏矩阵将保存游戏的状态并按表标签绘制它。
let tableXO = document.getElementById("table_game");
tableXO.innerHTML = tableContent
完整的源代码功能init
function init() {
player = X;
matrixGame = [];
typeGame = TWO_PLAYER;
const urlParams = new URLSearchParams(window.location.search);
let rows = urlParams.get("rows");
let columns = urlParams.get("columns");
if (rows === "" || columns === "" || (urlParams.get("type") !== TWO_PLAYER && urlParams.get("type") !== COMPUTER && urlParams.get("type") !== COMPUTER_COMPUTER)) {
window.location.href = "/game-development/games/caro/home.html";
}
typeGame = urlParams.get("type")
// Data table
let tableXO = document.getElementById("table_game");
let tableContent = "";
for (let row = 0; row < rows; row++) {
let arr = [];
let rowHTML = "<tr>";
for (let col = 0; col < columns; col++) {
arr.push("");
rowHTML += `<td class="td_game"><div id="` + row.toString() + "-" + col.toString() + `" onclick="handleClick(this.id)" class="fixed"></div></td>`
}
rowHTML += "</tr>";
tableContent += rowHTML;
matrixGame.push(arr);
}
tableXO.innerHTML = tableContent
}
window.addEventListener("load", (event) => {
init();
});
处理游戏中的抽奖和获胜状态的检查非常简单:
-
绘制状态游戏:我们将循环浏览游戏矩阵中的所有元素(行X列)。如果所有元素都用“”表示,那么此位置就没有轮回播放了。和所有元素! =“” =>绘制游戏。
-
赢得状态游戏:我们将检查水平,垂直,右角和左对角线。如果在同一回合中具有超过5个,则玩家或计算机将赢得游戏。
源代码:
draw
function checkDraw() {
for (let i = 0; i < matrixGame.length; i++) {
for (let j = 0; j < matrixGame[0].length; j++) {
if (matrixGame[i][j] === "") {
return false
}
}
}
return true
}
win
function getHorizontal(x, y, player) {
let count = 1;
for (let i = 1; i < 5; i++) {
if (y + i < matrixGame[0].length && matrixGame[x][y + i] === player) {
count++;
} else {
break
}
}
for (let i = 1; i < 5; i++) {
if (y - i >= 0 && y - i < matrixGame[0].length && matrixGame[x][y - i] === player) {
count++;
} else {
break
}
}
return count;
}
function getVertical(x, y, player) {
let count = 1;
for (let i = 1; i < 5; i++) {
if (x + i < matrixGame.length && matrixGame[x + i][y] === player) {
count++;
} else {
break
}
}
for (let i = 1; i < 5; i++) {
if (x - i >= 0 && x - i < matrixGame.length && matrixGame[x - i][y] === player) {
count++;
} else {
break
}
}
return count;
}
function getRightDiagonal(x, y, player) {
let count = 1;
for (let i = 1; i < 5; i++) {
if (x - i >= 0 && x - i < matrixGame.length && y + i < matrixGame[0].length && matrixGame[x - i][y + i] === player) {
count++;
} else {
break
}
}
for (let i = 1; i < 5; i++) {
if (x + i < matrixGame.length && y - i >= 0 && y - i < matrixGame[0].length && matrixGame[x + i][y - i] === player) {
count++;
} else {
break
}
}
return count;
}
function getLeftDiagonal(x, y, player) {
let count = 1;
for (let i = 1; i < 5; i++) {
if (x - i >= 0 && x - i < matrixGame.length && y - i >= 0 && y - i < matrixGame[0].length && matrixGame[x - i][y - i] === player) {
count++;
} else {
break
}
}
for (let i = 1; i < 5; i++) {
if (x + i < matrixGame.length && y + i < matrixGame[0].length && matrixGame[x + i][y + i] === player) {
count++;
} else {
break
}
}
return count;
}
function checkWin(points) {
return getHorizontal(Number(points[0]), Number(points[1]), player) >= 5
|| getVertical(Number(points[0]), Number(points[1]), player) >= 5
|| getRightDiagonal(Number(points[0]), Number(points[1]), player) >= 5
|| getLeftDiagonal(Number(points[0]), Number(points[1]), player) >= 5
}
3.3。游戏模式人类和人类
我们在3.2中处理了所有游戏功能,包括初始化游戏,检查抽奖并赢得游戏。在3.3中,我们将在玩家或计算机打开游戏矩阵时处理活动。
-
如果函数 processClick 返回值“ win”,那么我们将通知带有内容“ x/o是获胜者”的消息,然后再次启动游戏。
-
如果函数 processClick 返回值“绘制”母鸡,我们将通知带有内容“绘制”的消息并再次启动游戏。
function handleClick(id) {
switch (processClick(id)) {
case WIN:
setTimeout(function () {
alert("Player: " + player + " is winner");
// reset game
init();
}, 100);
break;
case DRAW:
setTimeout(function () {
alert("Draw");
// reset game
init();
}, 100);
break;
}
}
函数流程:当玩家或计算机在“人与人类”游戏模式中播放时,处理事件。我们将遵循以下步骤:
-
步骤1:如果游戏矩阵中的此位置的值为“ x”或“ o”,那么我们将返回void。
-
步骤2:如果播放器是X
-
步骤3:如果播放器是o,则将游戏矩阵中位置的值设置为“ O”,然后在游戏界面上绘制X
html document.getElementById(id).innerHTML = OText;
-
步骤4:检查游戏是平局还是胜利。如果是绘制的,请返回“绘制”,如果是赢,则返回“赢”。
-
步骤5:交换转弯
javascript player = player === X ? O : X;
function processClick(id) {
let points = id.split("-");
switch (typeGame) {
case TWO_PLAYER:
if (matrixGame[Number(points[0])][Number(points[1])] === X || matrixGame[Number(points[0])][Number(points[1])] === O) {
return
}
if (player === X) {
matrixGame[Number(points[0])][Number(points[1])] = X;
document.getElementById(id).innerHTML = XText;
}
if (player === O) {
matrixGame[Number(points[0])][Number(points[1])] = O;
document.getElementById(id).innerHTML = OText;
}
if (checkWin(points)) {
return WIN;
}
// check draw
if (checkDraw()) {
return DRAW;
}
player = player === X ? O : X;
break;
case COMPUTER:
// source code to process play with computer
}
}
3.4。游戏模式人类和计算机
有很多算法:minimax,爬山,...它们被用来选择一些最佳转弯。 Minimax算法的示例:
minimax是人工智能,决策理论,游戏理论,统计和哲学中使用的决策规则,用于最大程度地减少最坏情况(最大损失)场景的损失。在处理收益时,它被称为“最大值”,以最大化最低收益。最初是针对多个玩家零和游戏理论制定的,涵盖了玩家采取替代动作的情况以及同时动作的案例,它也已扩展到更复杂的游戏,并在不确定性的情况下进行了一般决策。
在这里,我们将简化游戏,并根据玩家以前在游戏中的经验,确定玩家获胜的策略。
参考论文:
请参阅本文:L. Victor Allis, H. J. van den Herik, M. P. H. Huntjens, 1993. Go-Moku and Threat-Space Search
让我们去GOððð
我们将创建2个常数: map_score_computer , map_point_human
-
map_score_computer :我们将检查它在相同的转弯=> win =>中是否具有5个回合的分数是无穷大。如果它在相同的转弯中具有4个=>分数=为2000点。如果在同一转弯中具有3个=>分数=为500点。如果在相同的转弯中具有2个=>分数= 300点。如果它在相同的转弯中具有1个=>分数= 100点。此分数代表攻击。
-
map_point_human :如果它在相同的转弯中=>得分= 999999点。如果在相同的转弯中具有3个=>分数= 1000点。如果在相同的转弯中具有2个=>分数= 400点。如果在同一转弯中具有1个,则分数= 10分。如果它在相同的转弯中为零=>分数= 0点。此分数代表辩护。
const MAP_SCORE_COMPUTER = new Map([
[5, Infinity], [4, 2000], [3, 500], [2, 300], [1, 100]
])
const MAP_POINT_HUMAN = new Map([
[4, 999999], [3, 1000], [2, 400], [1, 10], [0, 0]
])
函数getpointscomputer :该功能将获得位置,这是计算机的转。
-
步骤1: maxScore 是计算机可以达到的最高分数。 ListScorePoint 是计算机的滴答位置的数组, PointsComputer 是计算机最高得分的数组。
-
步骤2:我们将循环浏览游戏矩阵并进行检查。如果位置的值为“”,那么我们将在水平,垂直,右角和左对角线之后获得最高的相同转弯。转弯的得分= map_score_computer [sá»næ°°»cliá»nká»lá»nnhất] + map_point_human [最高的相同转弯] p>
-
步骤3:我们将循环遍历具有得分等于MAXSCORE => push元素的游戏矩阵 pointscomputer
-
步骤4:因为每个游戏状态都会以相同的maxScore具有许多转弯:为了使其更公平,我们将随机分配点。
function getPointsComputer() {
let maxScore = -Infinity
let pointsComputer = []
let listScorePoint = []
for (let i = 0; i < matrixGame.length; i++) {
for (let j = 0; j < matrixGame[0].length; j++) {
if (matrixGame[i][j] === "") {
let score = MAP_SCORE_COMPUTER.get(Math.max(getHorizontal(i, j, O),getVertical(i, j, O),getRightDiagonal(i, j, O),getLeftDiagonal(i, j, O))) +
MAP_POINT_HUMAN.get(Math.max(getHorizontal(i, j, X),getVertical(i, j, X),getRightDiagonal(i, j, X),getLeftDiagonal(i, j, X)) - 1)
if (maxScore <= score) {
maxScore = score
listScorePoint.push({
"score": score,
"point": [i,j],
})
}
}
}
}
// get list max score
for (const element of listScorePoint) {
if (element.score === maxScore) {
pointsComputer.push(element.point)
}
}
return pointsComputer[Math.floor(Math.random()*pointsComputer.length)]
}
3.5。游戏模式计算机和计算机
游戏模式是在游戏模式下的fancyððð的,我们将用另一台计算机替换人类的转弯。我们仍然使用函数getpointscomputer获取转弯位置。
async function ComputerAndComputer(sumPoints) {
for (let i = 0; i < sumPoints; i++) {
await delay(100);
// computer A
let pointsComputerA = getPointsComputer()
matrixGame[pointsComputerA[0]][pointsComputerA[1]] = X;
document.getElementById(pointsComputerA[0].toString() + "-" + pointsComputerA[1].toString()).innerHTML = XText;
// check win
if (checkWin(pointsComputerA)) {
return WIN;
}
// check draw
if (checkDraw()) {
return DRAW;
}
player = player === X ? O : X;
await delay(100);
// computer B
let pointsComputerB = getPointsComputer()
matrixGame[pointsComputerB[0]][pointsComputerB[1]] = O;
document.getElementById(pointsComputerB[0].toString() + "-" + pointsComputerB[1].toString()).innerHTML = OText;
// check win
if (checkWin(pointsComputerB)) {
return WIN;
}
// check draw
if (checkDraw()) {
return DRAW;
}
player = player === X ? O : X;
}
}
我们将在加载事件中检查游戏模式是否为“计算机和计算机”,然后调用功能“计算机和计算机”以使两台计算机与它们一起播放。
注意:令sumpoints = matrixgame.length x matrixgame [0] .length 是最大转弯的总和。如果达到最大转弯,则绘制游戏状态。
window.addEventListener("load", (event) => {
init();
if(typeGame === COMPUTER_COMPUTER) {
let sumPoints = matrixGame.length * matrixGame[0].length
ComputerAndComputer(sumPoints).then(state => {
switch (state) {
case WIN:
setTimeout(function () {
alert("Player: " + player + " is winner");
// reset game
init();
location.reload();
}, 100);
break;
case DRAW:
setTimeout(function () {
alert("Draw");
// reset game
init();
location.reload();
}, 100);
break;
}
})
}
});
4。结论
这是产生的一些图像和视频。 ^^