check if the game ends
|
@ -0,0 +1,150 @@
|
|||
{
|
||||
"initHands": [
|
||||
"S2 H2 HK DK HQ CQ DQ CJ S9 H9 D9 C7 S6 H6 C4 D4 S3",
|
||||
"C2 HA CA DA SQ ST HT D8 S7 H7 C6 D6 S5 H5 C5 S4 H4",
|
||||
"RJ BJ D2 SA SK CK SJ HJ DJ CT DT C9 S8 H8 C8 D7 D5 H3 S3 D3"
|
||||
],
|
||||
"playerInfo": [
|
||||
{
|
||||
"id": 0,
|
||||
"index": 0,
|
||||
"role": "peasant"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"index": 1,
|
||||
"role": "peasant"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"index": 2,
|
||||
"role": "landlord"
|
||||
}
|
||||
],
|
||||
"moveHistory": [
|
||||
{
|
||||
"playerIdx": 2,
|
||||
"move": "H3 S3 D3 D5"
|
||||
},
|
||||
{
|
||||
"playerIdx": 0,
|
||||
"move": "S9 H9 D9 S3"
|
||||
},
|
||||
{
|
||||
"playerIdx": 1,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 2,
|
||||
"move": "SJ HJ DJ D7"
|
||||
},
|
||||
{
|
||||
"playerIdx": 0,
|
||||
"move": "HQ CQ DQ C7"
|
||||
},
|
||||
{
|
||||
"playerIdx": 1,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 2,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 0,
|
||||
"move": "C4 D4"
|
||||
},
|
||||
{
|
||||
"playerIdx": 1,
|
||||
"move": "ST HT"
|
||||
},
|
||||
{
|
||||
"playerIdx": 2,
|
||||
"move": "SK CK"
|
||||
},
|
||||
{
|
||||
"playerIdx": 0,
|
||||
"move": "S2 H2"
|
||||
},
|
||||
{
|
||||
"playerIdx": 1,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 2,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 0,
|
||||
"move": "S6 H6"
|
||||
},
|
||||
{
|
||||
"playerIdx": 1,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 2,
|
||||
"move": "CT DT"
|
||||
},
|
||||
{
|
||||
"playerIdx": 0,
|
||||
"move": "HK DK"
|
||||
},
|
||||
{
|
||||
"playerIdx": 1,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 2,
|
||||
"move": "RJ BJ"
|
||||
},
|
||||
{
|
||||
"playerIdx": 0,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 1,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 2,
|
||||
"move": "S8 H8 C8 C9"
|
||||
},
|
||||
{
|
||||
"playerIdx": 0,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 1,
|
||||
"move": "HA CA DA H5"
|
||||
},
|
||||
{
|
||||
"playerIdx": 2,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 0,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 1,
|
||||
"move": "SQ"
|
||||
},
|
||||
{
|
||||
"playerIdx": 2,
|
||||
"move": "D2"
|
||||
},
|
||||
{
|
||||
"playerIdx": 0,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 1,
|
||||
"move": "P"
|
||||
},
|
||||
{
|
||||
"playerIdx": 2,
|
||||
"move": "SA"
|
||||
}
|
||||
]
|
||||
}
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
|
||||
import './index.scss';
|
||||
import '../../assets/doudizhu.scss';
|
||||
|
||||
class DoudizhuGameBoard extends React.Component {
|
||||
constructor(props) {
|
||||
|
@ -15,9 +15,9 @@ class DoudizhuGameBoard extends React.Component {
|
|||
}
|
||||
|
||||
translateCardData(card) {
|
||||
let rankClass = "";
|
||||
let rankClass;
|
||||
let suitClass = "";
|
||||
let rankText = "";
|
||||
let rankText;
|
||||
let suitText = "";
|
||||
// translate rank
|
||||
if(card === "RJ"){
|
||||
|
@ -51,7 +51,6 @@ class DoudizhuGameBoard extends React.Component {
|
|||
}
|
||||
|
||||
computeSingleLineHand(cards) {
|
||||
console.log(cards);
|
||||
if(cards === "P"){
|
||||
return <div className="non-card"><span>Pass</span></div>
|
||||
}else{
|
||||
|
@ -68,7 +67,7 @@ class DoudizhuGameBoard extends React.Component {
|
|||
}
|
||||
|
||||
computeSideHand(cards) {
|
||||
let upCards = [];
|
||||
let upCards;
|
||||
let downCards = [];
|
||||
if(cards.length > 10){
|
||||
upCards = cards.slice(0, 10);
|
||||
|
@ -107,7 +106,6 @@ class DoudizhuGameBoard extends React.Component {
|
|||
}
|
||||
|
||||
playerDecisionArea(playerIdx){
|
||||
console.log(this.props.currentPlayer, playerIdx);
|
||||
if(this.props.currentPlayer === playerIdx){
|
||||
return <div className="non-card"><span>{`Consideration Time: ${this.millisecond2Second(this.props.considerationTime)}s`}</span></div>
|
||||
}else{
|
||||
|
@ -115,6 +113,13 @@ class DoudizhuGameBoard extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if(prevProps.turn !== this.props.turn){
|
||||
// new turn starts
|
||||
this.props.runNewTurn(prevProps);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
// compute the id as well as index in list for every player
|
||||
const bottomId = this.props.mainPlayerId;
|
||||
|
@ -140,7 +145,6 @@ class DoudizhuGameBoard extends React.Component {
|
|||
}
|
||||
return (
|
||||
<div style={{width: "100%", height: "100%", backgroundColor: "#ffcc99", position: "relative"}}>
|
||||
<div>{`Current Player: ${this.props.currentPlayer} , Consideration Time: ${this.props.considerationTime}`}</div>
|
||||
<div id={"left-player"}>
|
||||
<div className="player-main-area">
|
||||
<div className="player-info">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import './assets/index.css';
|
||||
import App from './App';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
|
||||
|
|
|
@ -19,3 +19,10 @@ export function removeCards(cards, hands){ // remove cards from hands, retur
|
|||
return remainedHands;
|
||||
}
|
||||
|
||||
export function doubleRaf (callback) {
|
||||
// secure all the animation got rendered before callback function gets executed
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(callback)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import React from 'react';
|
||||
import DoudizhuGameBoard from '../components/GameBoard';
|
||||
import webSocket from "socket.io-client";
|
||||
import {removeCards} from "../utils";
|
||||
import {removeCards, doubleRaf} from "../utils";
|
||||
|
||||
class DoudizhuGameView extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const mainViewerId = 0; // Id of the player at the bottom of screen
|
||||
this.initConsiderationTime = 2000;
|
||||
this.considerationTimeDeduction = 1000;
|
||||
this.initConsiderationTime = 0;
|
||||
this.considerationTimeDeduction = 100;
|
||||
this.gameStateTimeout = null;
|
||||
|
||||
this.initGameState = {
|
||||
|
@ -20,7 +20,7 @@ class DoudizhuGameView extends React.Component {
|
|||
turn: 0,
|
||||
currentPlayer: null,
|
||||
considerationTime: this.initConsiderationTime,
|
||||
}
|
||||
};
|
||||
|
||||
this.state = {
|
||||
ws: null,
|
||||
|
@ -86,7 +86,6 @@ class DoudizhuGameView extends React.Component {
|
|||
break;
|
||||
case 1:
|
||||
// getting player actions
|
||||
console.log(message.message);
|
||||
let res = message.message;
|
||||
if(res.turn === this.state.gameInfo.turn && res.playerIdx === this.state.gameInfo.currentPlayer){
|
||||
let gameInfo = JSON.parse(JSON.stringify(this.state.gameInfo));
|
||||
|
@ -101,8 +100,9 @@ class DoudizhuGameView extends React.Component {
|
|||
console.log("Cannot find cards in move from player's hand");
|
||||
}
|
||||
gameInfo.considerationTime = this.initConsiderationTime;
|
||||
this.setState({gameInfo: gameInfo});
|
||||
this.gameStateTimer();
|
||||
this.setState({gameInfo: gameInfo}, ()=>{
|
||||
|
||||
});
|
||||
}else{
|
||||
console.log("Mismatched game turn or current player index", message);
|
||||
}
|
||||
|
@ -116,6 +116,26 @@ class DoudizhuGameView extends React.Component {
|
|||
this.setState({ws: ws});
|
||||
};
|
||||
|
||||
runNewTurn(prevTurn){
|
||||
// check if the game ends
|
||||
if(this.state.gameInfo.hands[prevTurn.currentPlayer].length === 0){
|
||||
doubleRaf(()=>{
|
||||
const winner = this.state.gameInfo.playerInfo.find(element => {
|
||||
return element.index === prevTurn.currentPlayer;
|
||||
});
|
||||
if(winner){
|
||||
if(winner.role === "landlord")
|
||||
alert("Landlord Wins");
|
||||
else
|
||||
alert("Peasants Win");
|
||||
}else{
|
||||
console.log("Error in finding winner");
|
||||
}
|
||||
});
|
||||
}else
|
||||
this.gameStateTimer();
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div>
|
||||
|
@ -127,12 +147,17 @@ class DoudizhuGameView extends React.Component {
|
|||
mainPlayerId={this.state.gameInfo.mainViewerId}
|
||||
currentPlayer={this.state.gameInfo.currentPlayer}
|
||||
considerationTime={this.state.gameInfo.considerationTime}
|
||||
turn={this.state.gameInfo.turn}
|
||||
runNewTurn={(prevTurn)=>this.runNewTurn(prevTurn)}
|
||||
/>
|
||||
</div>
|
||||
<div style={{marginTop: "10px"}}>
|
||||
<input type='button' value='Connect' onClick={()=>{this.connectWebSocket()}} />
|
||||
<input style={{marginLeft: "10px"}} type='button' value='Start Replay' onClick={()=>{this.startReplay()}} />
|
||||
</div>
|
||||
<div style={{marginTop: "10px"}}>
|
||||
{`Current Player: ${this.state.gameInfo.currentPlayer} , Consideration Time: ${this.state.gameInfo.considerationTime}, Turn: ${this.state.gameInfo.turn}`}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|