“Build And Play Reversi Online: Cheat Sheet”
Now, let’s create a simple Reversi game with HTML, CSS, and Python. Reversi, also known as Othello, is a strategy board game for two players. The objective is to have the majority of your colored discs on the board at the end of the game.
Step 1: HTML Structure
Create a new file named `reversi.html` and add the following content:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reversi Online</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<h1>Reversi Online</h1>
<div id="board">
<!-- The game board will be generated here -->
</div>
<button id="start-btn">Start Game</button>
</div>
<script src="script.js"></script>
</body>
</html>
```
Step 2: CSS Styling
Create a new file named `styles.css` and add the following CSS styles:
```css
body {
font-family: Arial, sans-serif;
text-align: center;
background-color: #f5f5f5;
}
.container {
margin-top: 50px;
}
h1 {
font-size: 36px;
margin-bottom: 20px;
}
#board {
display: grid;
grid-template-columns: repeat(8, 50px);
grid-template-rows: repeat(8, 50px);
gap: 2px;
background-color: #8BC34A;
border: 1px solid #333;
margin: 0 auto;
width: 400px;
}
.cell {
width: 50px;
height: 50px;
border: 1px solid #333;
background-color: #4CAF50;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
font-weight: bold;
cursor: pointer;
}
button {
padding: 8px 16px;
background-color: #4CAF50;
color: #fff;
border: none;
cursor: pointer;
}
```
Step 3: Python Backend
Create a new file named `reversi.py` for the Python backend. In this step, we’ll define the core functions for the Reversi game.
```python
import numpy as np
# Define the board size
BOARD_SIZE = 8
# Define player colors
BLACK = 'B'
WHITE = 'W'
EMPTY = 'E'
# Function to initialize the board
def initialize_board():
board = np.full((BOARD_SIZE, BOARD_SIZE), EMPTY, dtype=str)
board[3, 3] = WHITE
board[4, 4] = WHITE
board[3, 4] = BLACK
board[4, 3] = BLACK
return board
# Function to check if a move is valid
def is_valid_move(board, color, row, col):
if board[row, col] != EMPTY:
return False
directions = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
for dr, dc in directions:
r, c = row + dr, col + dc
if 0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE and board[r, c] == get_opposite_color(color):
while True:
r, c = r + dr, c + dc
if not (0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE):
break
if board[r, c] == EMPTY:
break
if board[r, c] == color:
return True
return False
# Function to perform a move
def perform_move(board, color, row, col):
if not is_valid_move(board, color, row, col):
return False
directions = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
for dr, dc in directions:
r, c = row + dr, col + dc
to_flip = []
while True:
if not (0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE):
break
if board[r, c] == EMPTY:
break
if board[r, c] == color:
for fr, fc in to_flip:
board[fr, fc] = color
break
to_flip.append((r, c))
r, c = r + dr, c + dc
board[row, col] = color
return True
# Function to get the opposite color
def get_opposite_color(color):
return WHITE if color == BLACK else BLACK
# Function to check if a player has any valid moves
def has_valid_moves(board, color):
for row in range(BOARD_SIZE):
for col in range(BOARD_SIZE):
if is_valid_move(board, color, row, col):
return True
return False
# Function to count the number of discs for each player
def count_discs(board):
black_count = np.count_nonzero(board == BLACK)
white_count = np.count_nonzero(board == WHITE)
return black_count, white_count
```
Step 4: JavaScript Interaction (Optional)
In this step, you can use JavaScript to interact with the Python backend without page reloads. To do this, create a new file named `script.js` and add the following content:
```javascript
document.addEventListener("DOMContentLoaded", function () {
const boardDiv = document.getElementById("board");
const startBtn = document.getElementById("start-btn");
let board = [];
let currentPlayer = BLACK;
// Function to create a cell element
function createCellElement(row, col) {
const cellDiv = document.createElement("div");
cellDiv.classList.add("cell");
cellDiv.setAttribute("data-row", row);
cellDiv.setAttribute("data-col", col);
return cellDiv;
}
// Function to update the game board display
function updateBoardDisplay(board) {
boardDiv.innerHTML = "";
for (let row = 0; row < BOARD_SIZE; row++) {
for (let col = 0; col < BOARD_SIZE; col++) {
const cellDiv = createCellElement(row, col);
if (board[row][col] === BLACK) {
cellDiv
.textContent = "●";
} else if (board[row][col] === WHITE) {
cellDiv.textContent = "○";
}
boardDiv.appendChild(cellDiv);
}
}
}
// Function to handle player moves
function handleMove(event) {
const row = parseInt(event.target.getAttribute("data-row"));
const col = parseInt(event.target.getAttribute("data-col"));
fetch("/perform-move", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ board: board, color: currentPlayer, row: row, col: col }),
})
.then((response) => response.json())
.then((data) => {
if (data.valid) {
board = data.new_board;
currentPlayer = data.next_player;
updateBoardDisplay(board);
} else {
alert("Invalid move. Try again.");
}
});
}
// Event listener for the "Start Game" button
startBtn.addEventListener("click", function () {
fetch("/initialize-board")
.then((response) => response.json())
.then((data) => {
board = data.board;
currentPlayer = data.current_player;
updateBoardDisplay(board);
boardDiv.addEventListener("click", handleMove);
startBtn.disabled = true;
});
});
});
```
Step 5: Flask Backend (Python Web Framework)
To create a basic backend server, you can use the Flask web framework in Python. To set up the backend, install Flask using pip:
```
pip install Flask
```
Then, create `app.py` for the Flask application:
```python
from flask import Flask, jsonify, request
from reversi import initialize_board, perform_move, has_valid_moves, get_opposite_color, count_discs
app = Flask(__name__)
board = []
current_player = None
@app.route("/initialize-board", methods=["GET"])
def initialize_game():
global board, current_player
board = initialize_board()
current_player = BLACK
return jsonify({"board": board.tolist(), "current_player": current_player})
@app.route("/perform-move", methods=["POST"])
def play_move():
global board, current_player
data = request.get_json()
color = data["color"]
row = data["row"]
col = data["col"]
new_board = board.copy()
valid = perform_move(new_board, color, row, col)
if valid:
next_player = get_opposite_color(color)
if not has_valid_moves(new_board, next_player):
next_player = color
board = new_board
current_player = next_player
return jsonify({"valid": valid, "new_board": new_board.tolist(), "next_player": current_player})
if __name__ == "__main__":
app.run(debug=True)
```
Step 6: Finishing Up
- Update the `script.js` file to add event listeners for playing moves and handling the game flow.
- Modify the HTML file (`reversi.html`) to display the game board and provide buttons for starting the game.
- Add CSS styles to make the game interface visually appealing and responsive.
- Run the Flask backend by executing the `app.py` file, and open the game in your web browser by visiting `http://127.0.0.1:5000/reversi.html`.
This is a basic implementation of the Reversi game, and you can further enhance it by adding features like multiplayer support, score tracking, and AI players. Have fun developing and playing your Reversi game!