[connect_four]
connect-four.php
PHP
A fully functional Connect Four game where users can play against the computer
<?php
/**
* Plugin Name: Connect Four Game
* Plugin URI: https://it-breeze.info
* Description: A fully functional Connect Four game where users can play against the computer. Use shortcode [connect_four] to display the game.
* Version: 2.0.3
* Author: Mike Vahldieck
* Author URI: https://it-breeze.info
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
<?php
/**
* Plugin Name: Connect Four Game
* Plugin URI: https://it-breeze.info
* Description: A fully functional Connect Four game where users can play against the computer. Use shortcode [connect_four] to display the game.
* Version: 2.0.3
* Author: Mike Vahldieck
* Author URI: https://it-breeze.info
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
class ConnectFourPlugin {
public function __construct() {
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
add_shortcode('connect_four', array($this, 'display_game'));
add_action('admin_menu', array($this, 'add_admin_menu'));
}
public function enqueue_scripts() {
// Check if shortcode exists on current page
global $post;
if (is_a($post, 'WP_Post') && has_shortcode($post->post_content, 'connect_four')) {
// Enqueue inline styles and scripts since we're embedding everything
add_action('wp_footer', array($this, 'add_inline_assets'));
}
}
public function add_inline_assets() {
?>
<style>
.c4-container {
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #ffffff 0%, #ffffff 100%);
padding: 20px;
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
text-align: center;
max-width: 600px;
margin: 20px auto;
}
.c4-wrapper {
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
padding: 30px;
}
.c4-title {
color: #333;
margin-bottom: 20px;
font-size: 2.2em;
}
.c4-info {
display: flex;
justify-content: space-around;
margin-bottom: 20px;
padding: 15px;
background: rgba(0, 0, 0, 0.05);
border-radius: 10px;
}
.c4-player {
display: flex;
align-items: center;
gap: 10px;
font-size: 1.1em;
font-weight: bold;
}
.c4-preview {
width: 25px;
height: 25px;
border-radius: 50%;
border: 2px solid #333;
}
.c4-red {
background: radial-gradient(circle at 30% 30%, #ff4757, #c44569);
}
.c4-yellow {
background: radial-gradient(circle at 30% 30%, #ffa502, #ff6348);
}
.c4-turn {
background: rgba(76, 175, 80, 0.2);
padding: 10px 15px;
border-radius: 10px;
margin-bottom: 20px;
font-size: 1.2em;
font-weight: bold;
color: #333;
}
.c4-buttons {
margin-bottom: 10px;
}
.c4-col-btn {
background: linear-gradient(45deg, #00d2d3, #54a0ff);
color: white;
border: none;
padding: 10px;
font-size: 14px;
border-radius: 50%;
cursor: pointer;
margin: 3px 1px;
width: 60px;
height: 35px;
transition: all 0.3s ease;
}
.c4-col-btn:hover {
transform: translateY(-2px);
background: linear-gradient(45deg, #00a8ff, #3742fa);
}
.c4-col-btn:disabled {
background: #ccc;
cursor: not-allowed;
transform: none;
}
.c4-board {
display: grid;
grid-template-columns: repeat(7, 60px);
grid-template-rows: repeat(6, 60px);
gap: 6px;
background: #3742fa;
padding: 15px;
border-radius: 15px;
margin: 15px auto;
justify-content: center;
}
.c4-cell {
width: 60px;
height: 60px;
background: #fff;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
transition: all 0.3s ease;
}
.c4-cell:hover {
transform: scale(1.05);
}
.c4-piece {
width: 50px;
height: 50px;
border-radius: 50%;
border: 3px solid #333;
animation: c4-drop 0.5s ease-out;
}
@keyframes c4-drop {
0% { transform: translateY(-300px) scale(0.8); }
70% { transform: translateY(8px) scale(1.1); }
100% { transform: translateY(0) scale(1); }
}
.c4-piece.c4-red {
background: radial-gradient(circle at 30% 30%, #ff4757, #c44569);
}
.c4-piece.c4-yellow {
background: radial-gradient(circle at 30% 30%, #ffa502, #ff6348);
}
.c4-controls {
margin-top: 25px;
}
.c4-btn {
background: linear-gradient(45deg, #5f27cd, #341f97);
color: white;
border: none;
padding: 12px 25px;
font-size: 14px;
border-radius: 20px;
cursor: pointer;
margin: 0 8px;
}
.c4-btn:hover {
transform: translateY(-2px);
}
.c4-result {
background: linear-gradient(45deg, #ff9ff3, #f368e0);
padding: 15px;
border-radius: 12px;
margin-top: 15px;
font-size: 1.2em;
font-weight: bold;
color: #333;
}
.c4-thinking {
color: #ff6348;
font-style: italic;
margin-top: 10px;
}
.c4-win {
background: rgba(255, 255, 255, 0.8) !important;
animation: c4-highlight 1s ease-in-out infinite;
}
@keyframes c4-highlight {
0%, 100% { opacity: 0.8; }
50% { opacity: 1; }
}
@media (max-width: 600px) {
.c4-board {
grid-template-columns: repeat(7, 45px);
grid-template-rows: repeat(6, 45px);
}
.c4-cell { width: 45px; height: 45px; }
.c4-piece { width: 38px; height: 38px; }
.c4-col-btn { width: 45px; }
}
</style>
<script>
var C4 = {
EMPTY: 0,
PLAYER: 1,
COMPUTER: 2,
ROWS: 6,
COLS: 7,
board: [],
currentPlayer: 1,
gameOver: false,
init: function() {
this.board = [];
for (var row = 0; row < this.ROWS; row++) {
this.board[row] = [];
for (var col = 0; col < this.COLS; col++) {
this.board[row][col] = this.EMPTY;
}
}
this.currentPlayer = this.PLAYER;
this.gameOver = false;
this.createBoard();
this.updateDisplay();
},
createBoard: function() {
var boardEl = document.getElementById('c4-board');
if (!boardEl) return;
boardEl.innerHTML = '';
for (var row = 0; row < this.ROWS; row++) {
for (var col = 0; col < this.COLS; col++) {
var cell = document.createElement('div');
cell.className = 'c4-cell';
cell.id = 'c4-cell-' + row + '-' + col;
cell.onclick = (function(c) {
return function() { C4.drop(c); };
})(col);
boardEl.appendChild(cell);
}
}
},
updateDisplay: function() {
for (var row = 0; row < this.ROWS; row++) {
for (var col = 0; col < this.COLS; col++) {
var cell = document.getElementById('c4-cell-' + row + '-' + col);
if (cell) {
cell.innerHTML = '';
if (this.board[row][col] !== this.EMPTY) {
var piece = document.createElement('div');
piece.className = 'c4-piece ' + (this.board[row][col] === this.PLAYER ? 'c4-red' : 'c4-yellow');
cell.appendChild(piece);
}
}
}
}
this.updateButtons();
this.updateTurn();
},
updateButtons: function() {
for (var col = 0; col < this.COLS; col++) {
var btn = document.getElementById('c4-btn-' + col);
if (btn) {
btn.disabled = this.gameOver || this.isColumnFull(col) || this.currentPlayer !== this.PLAYER;
}
}
},
updateTurn: function() {
var turnEl = document.getElementById('c4-turn');
var thinkEl = document.getElementById('c4-thinking');
if (this.gameOver) return;
if (this.currentPlayer === this.PLAYER) {
if (turnEl) {
turnEl.textContent = 'Your turn - Drop a red piece!';
turnEl.style.display = 'block';
}
if (thinkEl) thinkEl.style.display = 'none';
} else {
if (turnEl) turnEl.style.display = 'none';
if (thinkEl) thinkEl.style.display = 'block';
}
},
isColumnFull: function(col) {
return this.board[0][col] !== this.EMPTY;
},
drop: function(col) {
if (this.gameOver || this.currentPlayer !== this.PLAYER || this.isColumnFull(col)) {
return false;
}
for (var row = this.ROWS - 1; row >= 0; row--) {
if (this.board[row][col] === this.EMPTY) {
this.board[row][col] = this.PLAYER;
this.updateDisplay();
if (this.checkWin(row, col, this.PLAYER)) {
this.endGame('š You won!');
return true;
}
if (this.isBoardFull()) {
this.endGame('š¤ Tie game!');
return true;
}
this.currentPlayer = this.COMPUTER;
this.updateDisplay();
var self = this;
setTimeout(function() { self.computerMove(); }, 800);
return true;
}
}
return false;
},
computerMove: function() {
if (this.gameOver || this.currentPlayer !== this.COMPUTER) return;
var col = this.getBestMove();
if (col !== -1 && !this.isColumnFull(col)) {
for (var row = this.ROWS - 1; row >= 0; row--) {
if (this.board[row][col] === this.EMPTY) {
this.board[row][col] = this.COMPUTER;
this.updateDisplay();
if (this.checkWin(row, col, this.COMPUTER)) {
this.endGame('š¤ Computer won!');
return;
}
if (this.isBoardFull()) {
this.endGame('š¤ Tie game!');
return;
}
this.currentPlayer = this.PLAYER;
this.updateDisplay();
return;
}
}
}
},
getBestMove: function() {
// Try to win
for (var col = 0; col < this.COLS; col++) {
if (!this.isColumnFull(col)) {
var row = this.getLowestRow(col);
this.board[row][col] = this.COMPUTER;
if (this.checkWin(row, col, this.COMPUTER)) {
this.board[row][col] = this.EMPTY;
return col;
}
this.board[row][col] = this.EMPTY;
}
}
// Block player
for (var col = 0; col < this.COLS; col++) {
if (!this.isColumnFull(col)) {
var row = this.getLowestRow(col);
this.board[row][col] = this.PLAYER;
if (this.checkWin(row, col, this.PLAYER)) {
this.board[row][col] = this.EMPTY;
return col;
}
this.board[row][col] = this.EMPTY;
}
}
// Prefer center
var cols = [3, 2, 4, 1, 5, 0, 6];
for (var i = 0; i < cols.length; i++) {
if (!this.isColumnFull(cols[i])) {
return cols[i];
}
}
return -1;
},
getLowestRow: function(col) {
for (var row = this.ROWS - 1; row >= 0; row--) {
if (this.board[row][col] === this.EMPTY) {
return row;
}
}
return -1;
},
checkWin: function(row, col, player) {
var directions = [[0,1], [1,0], [1,1], [1,-1]];
for (var d = 0; d < directions.length; d++) {
var dr = directions[d][0];
var dc = directions[d][1];
var count = 1;
var cells = [[row, col]];
// Positive direction
var r = row + dr, c = col + dc;
while (r >= 0 && r < this.ROWS && c >= 0 && c < this.COLS && this.board[r][c] === player) {
count++;
cells.push([r, c]);
r += dr;
c += dc;
}
// Negative direction
r = row - dr;
c = col - dc;
while (r >= 0 && r < this.ROWS && c >= 0 && c < this.COLS && this.board[r][c] === player) {
count++;
cells.push([r, c]);
r -= dr;
c -= dc;
}
if (count >= 4) {
this.highlightWin(cells);
return true;
}
}
return false;
},
highlightWin: function(cells) {
for (var i = 0; i < cells.length; i++) {
var cell = document.getElementById('c4-cell-' + cells[i][0] + '-' + cells[i][1]);
if (cell) cell.classList.add('c4-win');
}
},
isBoardFull: function() {
for (var col = 0; col < this.COLS; col++) {
if (!this.isColumnFull(col)) return false;
}
return true;
},
endGame: function(message) {
this.gameOver = true;
var resultEl = document.getElementById('c4-result');
if (resultEl) {
resultEl.textContent = message;
resultEl.style.display = 'block';
}
var turnEl = document.getElementById('c4-turn');
var thinkEl = document.getElementById('c4-thinking');
if (turnEl) turnEl.style.display = 'none';
if (thinkEl) thinkEl.style.display = 'none';
this.updateButtons();
},
newGame: function() {
var resultEl = document.getElementById('c4-result');
var thinkEl = document.getElementById('c4-thinking');
if (resultEl) resultEl.style.display = 'none';
if (thinkEl) thinkEl.style.display = 'none';
var winCells = document.querySelectorAll('.c4-win');
for (var i = 0; i < winCells.length; i++) {
winCells[i].classList.remove('c4-win');
}
this.init();
},
showRules: function() {
alert('š“ Vier gewinnt Regeln š”\\n\\nšÆ Get 4 pieces in a row to win!\\n\\n⢠Click ā buttons to drop red pieces\\n⢠Pieces fall to lowest spot\\n⢠Win horizontally, vertically, or diagonally\\n⢠Computer plays orange pieces\\n\\nGood luck! š');
}
};
// Initialize when page loads
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
setTimeout(function() {
if (document.getElementById('c4-board')) {
C4.init();
}
}, 200);
});
} else {
setTimeout(function() {
if (document.getElementById('c4-board')) {
C4.init();
}
}, 200);
}
</script>
<?php
}
public function display_game($atts) {
$atts = shortcode_atts(array(
'width' => '100%',
'height' => 'auto'
), $atts, 'connect_four');
ob_start();
?>
<div class="c4-container" style="width: <?php echo esc_attr($atts['width']); ?>; height: <?php echo esc_attr($atts['height']); ?>;">
<div class="c4-wrapper">
<h3 class="c4-title">š“ Vier gewinnt š”</h3>
<div class="c4-info">
<div class="c4-player">
<div class="c4-preview c4-red"></div>
<span>You (Red)</span>
</div>
<div class="c4-player">
<div class="c4-preview c4-yellow"></div>
<span>Computer (Orange)</span>
</div>
</div>
<div id="c4-turn" class="c4-turn">Your turn - Drop a red piece!</div>
<div id="c4-thinking" class="c4-thinking" style="display: none;">š¤ Computer thinking...</div>
<div class="c4-buttons">
<button id="c4-btn-0" class="c4-col-btn" onclick="C4.drop(0)">ā</button>
<button id="c4-btn-1" class="c4-col-btn" onclick="C4.drop(1)">ā</button>
<button id="c4-btn-2" class="c4-col-btn" onclick="C4.drop(2)">ā</button>
<button id="c4-btn-3" class="c4-col-btn" onclick="C4.drop(3)">ā</button>
<button id="c4-btn-4" class="c4-col-btn" onclick="C4.drop(4)">ā</button>
<button id="c4-btn-5" class="c4-col-btn" onclick="C4.drop(5)">ā</button>
<button id="c4-btn-6" class="c4-col-btn" onclick="C4.drop(6)">ā</button>
</div>
<div class="c4-board" id="c4-board"></div>
<div class="c4-controls">
<button class="c4-btn" onclick="C4.newGame()">š® New Game</button>
<button class="c4-btn" onclick="C4.showRules()">š Rules</button>
</div>
<div id="c4-result" class="c4-result" style="display: none;"></div>
</div>
</div>
<?php
return ob_get_clean();
}
public function add_admin_menu() {
add_options_page(
'Connect Four Settings',
'Connect Four',
'manage_options',
'connect-four-settings',
array($this, 'admin_page')
);
}
public function admin_page() {
?>
<div class="wrap">
<h1>Connect Four Game Settings</h1>
<div class="card">
<h2>How to Use</h2>
<p>To display the Connect Four game on any post or page, use the following shortcode:</p>
<code>[connect_four]</code>
<h3>Shortcode Options</h3>
<ul>
<li><strong>width</strong> - Set the game container width (default: 100%)</li>
<li><strong>height</strong> - Set the game container height (default: auto)</li>
</ul>
<h3>Examples</h3>
<p><code>[connect_four width="600px"]</code></p>
<p><code>[connect_four width="100%" height="700px"]</code></p>
</div>
<div class="card">
<h2>Game Rules</h2>
<ol>
<li><strong>Objective:</strong> Be the first to connect 4 pieces in a row</li>
<li><strong>Gameplay:</strong> Players take turns dropping pieces into columns</li>
<li><strong>Pieces fall:</strong> to the lowest available spot in the column</li>
<li><strong>Win conditions:</strong> Get 4 in a row horizontally, vertically, or diagonally</li>
<li><strong>You are Red pieces,</strong> Computer is Orange pieces</li>
<li><strong>Strategy:</strong> Control center columns and watch for winning threats</li>
</ol>
</div>
</div>
<?php
}
}
// Initialize the plugin
new ConnectFourPlugin();
// Add settings link on plugin page
if (is_admin()) {
add_filter('plugin_action_links_' . plugin_basename(__FILE__), function($links) {
$settings_link = '<a href="' . admin_url('options-general.php?page=connect-four-settings') . '">Settings</a>';
array_unshift($links, $settings_link);
return $links;
});
}
?>