Tic Tac Toe Multiplayer
Tic Tac Toe là một game khá đơn giản, chắc hẳn đã rất quen thuộc với tất cả mọi người. Nay chỉ với một vài dòng code bạn đã có thể tự tạo nên trang game Tic Tac Toe của riêng mình để chơi cùng với bạn bè.Cách thực hiện
1Vào Codepen.io và tạo cho mình một tài khoản. (Lúc đầu mình cũng định post code này vào một bài viết hoặc một page trên Blogger cho tiện nhưng code không hoạt động, nên các bạn chịu khó làm trên Codepen nhé.)2Tạo một Pen mới bằng cách nhấn vào New Pen
3Tiếp theo dán các code sau đây vào pen.
HTML
<center><h1>Tic-Tac-Toe Online</h1></center>
<h2>Cách chơi</h2>
<p><strong>Người chơi 1 (X):</strong>
<ol>
<li>Gửi liên kết sau cho người bạn muốn chơi cùng: <span class="query">http://codepen.io/IrisTips/full/OybRzK/?id=<span id="gameIdQuery"></span></span></li>
<li>Đợi ở trình duyệt này và chờ người chơi 2 sẵn sàng.</li>
<li>Để bắt đầu 1 ván chơi mới vui lòng tải lại trang này và thực hiện lại bước 1.</li>
</ol>
</p>
<p><strong>Người chơi 2 (O):</strong>
<ol>
<li>Mở trình duyệt của bạn lên.</li>
<li>Nhập vào địa chỉ vừa nhận được của người chơi 1.
</li>
</ol>
</p>
<section class="game">
<div class="col">
</div>
<div class="col">
<div id="tictactoe" class="disabled"></div>
</div>
<div class="col">
Game ID: <strong id="gameId"></strong>
<br> Bạn: <span id="you"></span>
<br>
<span id="whosTurn">Đến lượt của bạn!</span>
</div>
</section>
CSS
html {
height: 100%;
}
body {
padding: 0;
margin: 1em;
font-family: "Open Sans", "HelveticaNeueLight", "HelveticaNeue-Light", "Helvetica Neue Light", "HelveticaNeue", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
font-weight: 300;
line-height: 1.4em;
background: #f8f8f8;
background-size: cover;
color: #333;
font-size: 1.2em;
}
a {
color: #E24329;
}
header {
padding: 16px 20px;
background-color: #74B1B4;
color: #fff;
}
header a {
text-decoration: none;
color: #fff;
}
.index a {
color: #333;
}
.index li {
line-height: 1.5em;
}
h1,
h2,
h3 {
font-weight: 200;
text-rendering: optimizeLegibility;
}
h1,
h3,
.query {
color: #FC6D26;
}
h2 {
color: #E24329;
}
.game {
margin: 2em 0;
overflow: auto;
width: 100%
}
.game .col {
float: left;
margin-right: 2em;
}
.game .col:first-of-type {
min-width: 200px;
}
#tictactoe {
margin: 1em auto;
padding: 20px;
background: transparent url(http://pubnub.github.io/api-guide-with-tictactoe/images/tictactoe-bkgd.png) 0 0 no-repeat;
width: 200px;
}
#tictactoe.disabled {
pointer-events: none;
opacity: 0.4;
}
#whosTurn {
color: #E24329;
}
#pubsub span {
color: #E24329;
}
JS
(function() {
var gameId = document.querySelector('#gameId');
var gameIdQuery = document.querySelector('#gameIdQuery');
var tictactoe = document.querySelector('#tictactoe');
var output = document.querySelector('#output');
var whosTurn = document.getElementById('whosTurn');
var gameid = '';
var rand = (Math.random() * 9999).toFixed(0);
gameid = (getGameId()) ? getGameId() : rand;
gameIdQuery.textContent = gameId.textContent = gameid;
var channel = 'tictactoe--' + gameid;
console.log('Channel: ' + channel);
var uuid = PUBNUB.uuid();
var pubnub = PUBNUB.init({
subscribe_key: 'sub-c-182105ac-0001-11e5-8fd4-0619f8945a4f',
publish_key: 'pub-c-ce04f67b-0f26-43ce-8be2-192e9821d1a3',
uuid: uuid
});
function displayOutput(m) {
if (!m) return;
return '<li><strong>' + m.player + '</strong>: ' + m.position + '</li>';
}
/*
* Tic-tac-toe
* Based on the single-player Tic Tac Toe on http://jsfiddle.net/5wKfF/378/
* Multiplayer feature with PubNub
*/
var mySign = 'X';
pubnub.subscribe({
channel: channel,
connect: play,
presence: function(m) {
console.log(m);
whosTurn
if (m.uuid === uuid && m.action === 'join') {
if (m.occupancy < 2) {
whosTurn.textContent = 'Đang đợi đối thủ của bạn...';
} else if (m.occupancy === 2) {
mySign = 'O';
} else if (m.occupancy > 2) {
alert('Phòng này đã có 2 người chơi!');
tictactoe.className = 'disabled';
}
}
if (m.occupancy === 2) {
tictactoe.className = '';
startNewGame();
}
document.getElementById('you').textContent = mySign;
},
callback: function(m) {
// Display the move
if (document.querySelector('#moves')) {
var movesOutput = document.querySelector('#moves');
movesOutput.innerHTML = movesOutput.innerHTML + displayOutput(m);
}
// Display the move on the board
var el = document.querySelector('[data-position="' + m.position + '"]');
el.firstChild.nodeValue = m.player;
console.log(el);
checkGameStatus(m.player, el);
},
});
function publishPosition(player, position) {
pubnub.publish({
channel: channel,
message: {
player: player,
position: position
},
callback: function(m) {
console.log(m);
}
});
}
function getGameId() {
return window.location.search.substring(1).split('?')[0].split('=')[1]
}
var squares = [],
EMPTY = '\xA0',
score,
moves,
turn = 'X',
wins = [7, 56, 448, 73, 146, 292, 273, 84];
function startNewGame() {
var i;
turn = 'X';
score = {
'X': 0,
'O': 0
};
moves = 0;
for (i = 0; i < squares.length; i += 1) {
squares[i].firstChild.nodeValue = EMPTY;
}
whosTurn.textContent = (turn === mySign) ? 'Lượt của bạn' : 'Lượt của đối thủ';
}
function win(score) {
var i;
for (i = 0; i < wins.length; i += 1) {
if ((wins[i] & score) === wins[i]) {
return true;
}
}
return false;
}
function checkGameStatus(player, el) {
moves += 1;
console.log('Moves: ' + moves);
score[player] += el.indicator;
console.log('Score for player, ' + player + ': ' + score[player]);
if (win(score[turn])) {
alert(turn + ' wins!');
} else if (moves === 9) {
alert('Boooo!');
} else {
turn = (turn === 'X') ? 'O' : 'X';
whosTurn.textContent = (turn === mySign) ? 'Lượt của bạn' : 'Lượt của đối thủ';
}
}
function set() {
if (turn !== mySign) return;
if (this.firstChild.nodeValue !== EMPTY) return;
publishPosition(mySign, this.dataset.position);
}
function play() {
var board = document.createElement('table'),
indicator = 1,
i, j,
row, cell;
board.border = 1;
for (i = 1; i < 4; i += 1) {
row = document.createElement('tr');
board.appendChild(row);
for (j = 1; j < 4; j += 1) {
cell = document.createElement('td');
cell.dataset.position = i + '-' + j;
cell.width = cell.height = 50;
cell.align = cell.valign = 'center';
cell.indicator = indicator;
cell.onclick = set;
cell.appendChild(document.createTextNode(''));
row.appendChild(cell);
squares.push(cell);
indicator += indicator;
}
}
tictactoe = document.getElementById('tictactoe');
tictactoe.appendChild(board);
startNewGame();
}
})();
3Nhấn vào Setting trên thanh Menu
4Chọn Tab CSS >> Add External CSS >> Thêm vào dòng code
http://fonts.googleapis.com/css?family=Open+Sans:300,400,700
5 Chuyển qua Tab JavaScript >> Add External JavaScript >> Thêm vào
//cdn.pubnub.com/pubnub-3.7.14.min.js
6Nhấn Save & Close để đóng cửa sổ Setting.
7Và cuối cùng là nhấn Save trên thanh Menu để lưu pen lại.
Chỉnh sửa: http://codepen.io/IrisTips/full/OybRzK thành địa chỉ pen của bạn trên đoạn code HTML ở bước 3.
Đánh giá
+ Ưu điểm
- - Cách chơi đơn giản.
- - Giao diện thân thiện, chơi được trên mọi thiết bị từ desktop đến smartphone, tablet...
- - Có thể chơi cùng với bạn bè trên 2 máy tính khác nhau hoặc "tự sướng" trên 2 tab cũng được :))
+ Nhược điểm
- - Không tự động reset sau mỗi ván.
- - Phải gửi lại liên kết mỗi ván chơi (Do ID thay đổi sau mỗi ván).
Nếu có bất kỳ vấn đề khó khăn hay câu hỏi gì, bạn đừng ngần ngại, hãy để lại bình luận ở form bên dưới nhé.
Chúc bạn thành công!
Mẹo nhỏ khi bình luận