HTML5 Game Development Practice| Reversi

 Reversi, also known as Reversi, Othello, Apple Chess, and Reverse Chess. Reversi is very popular in the West and Japan. The game is played by flipping each other's pieces, and the winner is judged by who has more pieces on the board. The board of Reversi is a board with 8×8 squares. At the beginning, there are two white and two black four chess pieces crossed in the middle of the chessboard, and the black chess pieces are always played first.

(1) Sub-rules.

Put the chess pieces of one's own color on the blank space of the chessboard, and when the chess pieces put down by oneself have one of their own chess pieces in 8 directions of horizontal, vertical and oblique, all the chess pieces sandwiched in the middle are turned over to become their own chess pieces. And you can play only where you can flip the pieces. If a player has no place on the board to play, the player's opponent can make a double play.

(2) Conditions for winning or losing.

When both sides have no chess pieces to play, the game is over. The number of chess pieces is used to calculate the outcome, and the side with more chess pieces wins.

When the chessboard is not full, if one side's pieces have been eaten up by the other side, then the game is over. The side that eats all the opponent's pieces wins.

This article develops the Reversi game program, and the operation interface of the Reversi game is shown in the figure above. The game has the function of prompting the position of the player who can place the pieces and judging the outcome. During the game, click the "Help" button to display the position where the chess player can place ( 

Indicates the available position, as shown in Figure 1).

■ Diagram 1 shows the position where the chess player (black) can place a piece 

01. Reversi game design ideas

Chess pieces and board

When developing a game, black and white chess pieces and board pictures (as shown in Figure 2) need to be prepared in advance. When the game is initially displayed, 4 pieces are drawn on the board. Here, for the convenience of processing, a qizi two-dimensional array is used to store the pieces on the chessboard.

■ Figure 2 black and white chess pieces and board

Flip the opponent's pieces

You need to judge whether you need to flip the other side's pieces from the horizontal, vertical, and oblique directions centered on your own piece (x1, y1). The program is implemented by the mousedown event of the mouse. In the mousedown event, the parameter event object contains the pixel coordinates of the clicked position (event.pageX, event.pageY), which becomes the pixel coordinates (x, y) in the Canvas object after processing. Then it is converted by the following formula:

x1 = Math.round((x- 40) / 80);//Math.round 四舍五入y1 = Math.round((x- 40) / 80);

Converted to chessboard coordinates (x1, y1) after conversion.

Call procedure DirectReverse (x1, y1, dx, dy) at last from 8 directions of left, upper left, upper, upper right, right, lower right, lower, lower left to flip the other side's pieces. And the flipping of specific chess pieces is realized by FanQi(x, y). FanQi (x, y) modifies (x, y) of the array qizi to save information of pieces on the chessboard.

function FanQi(x,y)
if(qizi[x][y]== BLACK)qizi[x][y]= WHITE;
else
qizi[x][y]= BLACK,

Display the position where the chess player can place a piece

Can_go(x1, y1) calls the function CheckDirect(x1, y1, dx, dy) from 8 directions of left, upper left, upper, upper right, right, lower right, lower and lower left to judge whether a pinching trend is formed in a certain direction, if If it is formed and there is no hole in the middle, it will return True, indicating that (x1, y1) can be placed, and if (x1, y1) can be placed, it will be displayed in a picture.

The function of judging the outcome

qizi[][]The two-dimensional array stores the chess piece information on the board, and the element stores 1, indicating that this place is a black piece; the element stores 2, indicating that this place is a white piece; the element stores 0, indicating that there is no chess piece here. By counting the number of chess pieces of each party in the qizi array, when there is no place to play on the chessboard, the winner or loser can be judged according to the number of chess pieces of each party.

 

02. Key technologies

JavaScript mouse events supported by the Canvas object

The Canvas object supports all JavaScript mouse events, including mouse click (Mouse Click), mouse down (Mouse Down), mouse lift (Mouse Up) and mouse move (Mouse Move). There are two ways to add mouse events to Canvas, one way is as follows:

//鼠标事件 mouse event
canvas.addEventListener( "mousedown",doMouseDown,false);canvas.addEventListener( 'mousemove',doMouseMove,false);canvas.addEventListener('mouseup',doMouseUp,false);

Another way is called an anti-pattern in JavaScript.

canvas.onmousedown = function(e)canvas.onmouseup = function(e)canvas.onmousemove = function(e)

Get the coordinates of the mouse on the Canvas object

Because the coordinates of the mouse on the Canvas cannot be directly obtained in the mouse event on the Canvas, all obtained coordinates are based on the entire screen. So through the mouse event e. clientX and e. clientY to get the mouse position, and then through Canvas. The getBoundingClientRect() method is used to obtain the position of the Canvas object relative to the browser window (the method returns a rectangular object, which contains four attributes: left, top, right, and bottom. Representing the distance between each side of the Canvas object and the top and left sides of the page), through Calculate the coordinates of the mouse in the Canvas.

The code for converting event coordinates to Canvas coordinates is as follows:

function getPointOnCanvas(canvas,x,y)var bbox = canvas.getBoundingClientRect()return(x: x - bbox.left,
y:y - bbox.top);

If considering the CSS setting width and height at the same time, the code is as follows.

function getPointOnCanvas(canvas,x,y)
var bbox = canvas.getBoundingClientRect();
return(x: x- bbox.left *(canvas.width / bbox.width)y:y- bbox.top *(canvas.height/bbox.height)

03. The steps of Reversi game design

Game page index.html

<html >
< head >
< title>黑白棋</title>
<meta http - equiv= content - type content = "text/html; charset = utf - 8">< meta name="Generator" content ="EditPlus">
<meta name ="Author" content = "
n<meta name ="Keywords” content =
<meta name ="Description" content = "</head >
<body onload="init()”onkeydown ="DoKeyDown(event)"><canvas id="myCanvas”width="720”height ="720"你的浏览器还不支持</canvas>< img id= "whitestone"src = "img/whitestone.png"style= "display:none;">< img id= "blackstone"src = "img/blackstone.ng" style= "display:none;">< img id="gi pan1"src = "img/qi panl.jpg"style= "display:none;"><img id="Info2"src ="img/Info2.ng”style = "display:none;">
<div id= "message txt" style= "text - align:center;border:lpx solid red; width:720px;height20px;font- size:20px;"></div>
< input type ="button”value="走棋提示”onclick ="DoHelp()">< script type ="text/javascript"src ="Main.js"></script></body>
</html>

Design script (Main.js)

1. constant definition

Constant definition in the game, where BLACK is 1, WHITE is 2, and no chess is 0.

//常量
var BLACK = 1;
var WHITE = 2;
var KONG = 0;
var w= 80;
var h= 80:

Get the Canvas object, as well as the chess pieces, chessboard pictures, and prompt pictures used in the following.

//构造一个 gizi[][]二维数组用来存储棋子//当前走棋方var mycanvas = document.getElementById('myCanvas');var context = mycanvas.getContext(2d'):
var gizi=new Array();
var curQizi= BLACK;
var whitestone= document.getElementById("whitestone");var blackstone = document.getElementById("blackstone");var qipan = document.getElementById("qi pan1");var info = document.getElementById("Info2");var message txt = document.getElementById("message txt");
//白棋图片//黑棋图片//棋盘//提示图形//提醒文字

2. Initialize the game interface

When the game starts, the init() function is called to initialize the qizi array storing the information of the chess pieces on the chessboard, and at the same time, the initial 4 chess pieces are displayed on the chessboard.

function init()f
initLevel();
showMoveInfo();
//棋盘上初始 4个棋子
//当前走棋方信息
mycanvas.addEventListener( "mousedown,doMouseDown,false);
function initLevel()var i,j;for(i=0;i<8;i++){
   qizi[i]= new Array();for(j=0;j<8;j++)qizi[i][j]= KONG;
//棋盘上初始 4 个棋子
//1 为黑,2为白,0为无棋子qizi[3][3]= WHITE;qizi[4][ 4]= WHITEqizi[3][4] = BLACKqizi[4][3]= BLACK;DrawMap();
//初始化界面
//画棋盘和所有棋子
message txt.innerHTML="该黑棋走子”
//画棋盘和所有棋子
function DrawMap()
context.clearRect (0,0,720,720);context.drawImage(qipan,0,0,qipan.width,gipan.height);for(i= 0;i<gizi.length;i++)
//行号
//列号for(j= 0;j< gizi[i].length;j++)
var pic;
switch(qizi[i][j])
case KONG:
break;
case BLACK:
//0
//1
pic =blackstone:context.drawImage(pic,w * j,h *,pic.width,pic.height);break;
//2
case WHITE:
pic = whitestone;context.drawImage(pic,w * j,h *i,pic.width,pic.height);break;
}
}
}
}

Call the showMoveInfo() function to display which player's turn it is to move.

function showMoveInfo(
// 当前走棋方是黑棋message_txt.innerHTML ="该黑棋走子”
if(curOizi== BLACK)
else
message_txt.innerHTML="该白棋走子”

The init() function also adds a mouse click event listener to the canvas, and if the canvas is clicked, it will execute the doMouseDown function to complete the chess move function.

3. Chess process

If the chessboard is clicked, the position pixel information (event.clientX, event.clientY) can be converted into chessboard coordinates (x1, y1), and then judge whether the current position (x1, y1) can place a chess piece (conforming to the angle between potential), if possible, display your own chess piece graphics at this position, and call the FanALLQi(i, j) function to flip the opponent's chess from 8 directions such as left, upper left, upper, and upper right. Finally, judge whether the opponent has chess to move, and if the opponent can move, exchange the chess player. If the opponent cannot play chess, then he can continue to play chess until both sides can not play chess, and the winning and losing information is displayed.

function doMouseDown(event)
var x = event.clientX
var y = event.clientY:
var canvas = event.target;
var loc = getPointOnCanvas(canvas,x,y);console.log("mouse down at point( x:"+ loc.x+",y:"+ loc.y+")");clickQi(loc);
function getPointOnCanvas(canvas,x,y)
var bbox = canvas.getBoundingClientRect();return( x: x-bbox.left * (canvas.width/ bbox.width)y:y- bbox.top * (canvas.height / bbox.height)};
function clickQi(thisQi){
   
var x1,yl;xl = parseInt((thisQi.y- 20)/ 80);yl= parseInt((thisQi.x- 20)/ 80);if(Can_go(x1,y1)){
   //trace("can");qizi[x1][yl]= curQizi;//从左、左上、上、右上、右、右下、下、左下方向翻转对方的棋FanALLO(x1,yl);DrawMap();
//parseInt()函数丢弃小数部分,保留整数
// 判断当前位置是否可以放棋子
//判断对方是否有棋可走,如有交换走棋方
&&checkNext(WHITE))if(curQizi== WHITE &&checkNext(BLACK) curQizi== BLACK
if(curQizi== WHITE) [
curQizi= BLACK;
message txt.innerHTML ="该黑棋走子”;else
curQizi= WHITE;
message txt.innerHTML=“该白棋走子“
else if(checkNext(curQizi)) 
//判断自己是否有棋可走,如有,给出提示
message txt.innerHTML ="对方无棋可走请继续
//双方都无棋可走,游戏结束,显示输赢信息elseisLoseWin();
//统计双方的棋子数量,显示输赢信息
else {
   
message txt.innerHTML="不能落子!";

4. whether the move can be judged

Can_go(x1, y1) judges from 8 directions: left, upper left, upper, upper right, right, lower right, lower, lower left, whether the position (x1, y1) can be placed.

function Can go( x1,yl)//从左、左上、上、右上、右、右下、下、左下 8 个方向判断if(CheckDirect(x1,y1,- 1,0)== true)[return true;
if(CheckDirect(x1,y1,- 1,-1)== true){
   return true;
if(CheckDirect(x1,yl,0,- 1) == true) (return true;
if(CheckDirect(x1,y1,1,- 1)== true) {
   return true;
if(CheckDirect(x1,y1,1,0)== true) {
   return true;
if(CheckDirect(x1,y1,1,1)== true) {
   return true;
if(CheckDirect(x1,y1,0,1)== true) {
   return true;
if(CheckDirect(x1,y1,- 1,1)== true) {
   return true;
return false;

Call the CheckDirect() function to judge whether a flanking trend is formed in a certain direction. Returns True if formed with no gaps in between.

function CheckDirect(x1,yl,dx,dy)l
var x,Y;
var flag = false;
x=x1 + dx;
y=yl + dy;while(InBoard(x,y) && !Ismychess(x,y) && qizi[x][y] != 0){
   x+= dx;
y += dy;
flag = true;
//构成夹击之势
if(InBoard(x,y) && Ismychess(x,y) && flag == true) {
   //该方向落子有效return true;
return false;

Call the checkNext(i) function to verify whether the mover represented by the parameter still has moves to move.

验证参数代表的走棋方是否还有棋可走¥@param i代表走棋方,1为黑方,2为白方
@return true/false¥
function checkNext(i)!
old= curQizi;
curOizi=i;
if(Can Num()> 0){
   
curQizi=old;
return true;
else
curQizi=old;
return false;
}
}

Call the Can_Num() function to count the number of positions that can be placed.

function Can Num()var i,j,n=0;for(i=1;i<=8;i++) (for(j=1;j<=8;j++){
   if(Can go(i,j)){
   
//统计可以落子的位置数
n=n+1;
return n;
//可以落子的位置数

5. Flip the opponent's pieces

FanALLQi(int x1, int y1) flips the opponent's pieces from 8 directions: left, upper left, upper, upper right, right, lower right, lower, lower left.

function FanALLQi(x1,yl)//从左、左上、上、右上、右、右下、下、左下 8 个方向翻转if(CheckDirect(x1,y1,- 1,0)== true){DirectReverse(xl,y1,- 1,0);
if(CheckDirect(x1,yl,- 1,- 1) == true) {
   DirectReverse(x1,y1,- 1,-1);
if(CheckDirect(x1,yl,0,- 1)== true) {
   
DirectReverse(x1,y1,0,- 1);
if(CheckDirect(x1,y1,1,- 1) == true) (DirectReverse(x1,yl,1,- 1);
if(CheckDirect(x1,yl,1,0) == true) {
   DirectReverse(x1,yl,1,0);
if(CheckDirect(x1,y1,1,1) == true) {
   DirectReverse(x1,yl,1,1);
if(CheckDirect(x1,y1,0,1)== true) {
   DirectReverse(x1,y1,0,1);
if(CheckDirect(x1,y1,- 1,1)== true) {
   DirectReverse(x1,yl,- 1,1);
}

Call the DirectReverse() function to reverse the opponent's chess pieces that have formed a flanking trend in a certain direction.

function DirectReverse(x1,yl,dx,dy)
var x,Y;
var flag = false;
x= x1 + dx;
y= yl + dy;while(InBoard(x,y) && !Ismychess(x,y) && qizi[x][y] != 0)x+= dx;
y += dy;flag = true;
//构成夹击之势
if(InBoard(x,y) && Ismychess(x,y) && flag == true)do !
x-= dx;y-=dy;if((x!= xl y! y1)){
   FanQi(x,y);
) while((x != xl  y!= y1));

Calling the FanQi(int x, int y) function will store the chess piece information qizi[x][y] at (x, y) for inverse color processing.

function FanQi(x,y)
if(qizi[x][y]== BLACK)qizi[x][y]= WHITE;
else(
qizi[x][y]= BLACK;

Call the InBoard() function to determine whether (x, y) is within the boundaries of the board. Return True if in bounds, False otherwise.

//InBoard()函数判断(x,y)是否在棋盘界内function InBoard(x,yif(x>=0&& x<=7 && y>=0 && y<=7){return true;
else 
return false;

6. Display the position where the chess player can place a piece

The click event function of the "Chess Hint" button is the DoHelp() function, which displays the prompt of the position where the chess can be placed. Call the Show_Can_Position() function with pictures


Shows where the ball can be placed.

function DoHelp)
showCanPosition();
//显示可以落子的位置
function showCanPosition()
//显示可以落子的位置
var i,j;
var n=0;
for(i=0;i<=7;i++)[
//可以落子的位置统计
for(j=0;j<=7; j++)[
if(gizi[i][j]==0 && Can_go(i,j)){
   n=n+1;pic = info;//显示提示图形
context.drawImage(pic,w*i+ 20,h*i+20,pic.width,pic.height);

7. Judgment function

Call the isLoseWin() function to count the number of chess pieces on both sides, and display the winning and losing information.

//显示输赢信息
function isLoseWin() 
var whitenum = 0;
var blacknum = 0;
var n=0,x,Y;
for(x=0;x<= 8;x++)(for(y=0;y<=8;y++){
   if(qizi[x][y] != 0)[{
   n=n+1;if(qizi[x][y]== 2) {
   whitenum += 1;
if(qizi[x][y]== 1){
   blacknum += 1;
if(blacknum > whitenum) f
message txt.innerHTML ="游戏结束黑方胜利,黑方:"+ String(blacknum)"白方+String(whitenum);
elsemessage txt.innerHTML="游戏结束白方胜利,黑方:"+ String(blacknum)+"白方:
+String(whitenum);
}
}

So far, the Reversi game design has been completed.

 

Guess you like

Origin blog.csdn.net/qq_41640218/article/details/131547608