check if the game ends

This commit is contained in:
songyih 2020-01-16 22:00:38 -08:00
parent cb4fa7b2b7
commit 691ab7b120
22 changed files with 201 additions and 15 deletions

View File

@ -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"
}
]
}

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import './index.scss'; import '../../assets/doudizhu.scss';
class DoudizhuGameBoard extends React.Component { class DoudizhuGameBoard extends React.Component {
constructor(props) { constructor(props) {
@ -15,9 +15,9 @@ class DoudizhuGameBoard extends React.Component {
} }
translateCardData(card) { translateCardData(card) {
let rankClass = ""; let rankClass;
let suitClass = ""; let suitClass = "";
let rankText = ""; let rankText;
let suitText = ""; let suitText = "";
// translate rank // translate rank
if(card === "RJ"){ if(card === "RJ"){
@ -51,7 +51,6 @@ class DoudizhuGameBoard extends React.Component {
} }
computeSingleLineHand(cards) { computeSingleLineHand(cards) {
console.log(cards);
if(cards === "P"){ if(cards === "P"){
return <div className="non-card"><span>Pass</span></div> return <div className="non-card"><span>Pass</span></div>
}else{ }else{
@ -68,7 +67,7 @@ class DoudizhuGameBoard extends React.Component {
} }
computeSideHand(cards) { computeSideHand(cards) {
let upCards = []; let upCards;
let downCards = []; let downCards = [];
if(cards.length > 10){ if(cards.length > 10){
upCards = cards.slice(0, 10); upCards = cards.slice(0, 10);
@ -107,7 +106,6 @@ class DoudizhuGameBoard extends React.Component {
} }
playerDecisionArea(playerIdx){ playerDecisionArea(playerIdx){
console.log(this.props.currentPlayer, playerIdx);
if(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> return <div className="non-card"><span>{`Consideration Time: ${this.millisecond2Second(this.props.considerationTime)}s`}</span></div>
}else{ }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() { render() {
// compute the id as well as index in list for every player // compute the id as well as index in list for every player
const bottomId = this.props.mainPlayerId; const bottomId = this.props.mainPlayerId;
@ -140,7 +145,6 @@ class DoudizhuGameBoard extends React.Component {
} }
return ( return (
<div style={{width: "100%", height: "100%", backgroundColor: "#ffcc99", position: "relative"}}> <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 id={"left-player"}>
<div className="player-main-area"> <div className="player-main-area">
<div className="player-info"> <div className="player-info">

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import './index.css'; import './assets/index.css';
import App from './App'; import App from './App';
import * as serviceWorker from './serviceWorker'; import * as serviceWorker from './serviceWorker';

View File

@ -19,3 +19,10 @@ export function removeCards(cards, hands){ // remove cards from hands, retur
return remainedHands; return remainedHands;
} }
export function doubleRaf (callback) {
// secure all the animation got rendered before callback function gets executed
requestAnimationFrame(() => {
requestAnimationFrame(callback)
})
}

View File

@ -1,15 +1,15 @@
import React from 'react'; import React from 'react';
import DoudizhuGameBoard from '../components/GameBoard'; import DoudizhuGameBoard from '../components/GameBoard';
import webSocket from "socket.io-client"; import webSocket from "socket.io-client";
import {removeCards} from "../utils"; import {removeCards, doubleRaf} from "../utils";
class DoudizhuGameView extends React.Component { class DoudizhuGameView extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const mainViewerId = 0; // Id of the player at the bottom of screen const mainViewerId = 0; // Id of the player at the bottom of screen
this.initConsiderationTime = 2000; this.initConsiderationTime = 0;
this.considerationTimeDeduction = 1000; this.considerationTimeDeduction = 100;
this.gameStateTimeout = null; this.gameStateTimeout = null;
this.initGameState = { this.initGameState = {
@ -20,7 +20,7 @@ class DoudizhuGameView extends React.Component {
turn: 0, turn: 0,
currentPlayer: null, currentPlayer: null,
considerationTime: this.initConsiderationTime, considerationTime: this.initConsiderationTime,
} };
this.state = { this.state = {
ws: null, ws: null,
@ -86,7 +86,6 @@ class DoudizhuGameView extends React.Component {
break; break;
case 1: case 1:
// getting player actions // getting player actions
console.log(message.message);
let res = message.message; let res = message.message;
if(res.turn === this.state.gameInfo.turn && res.playerIdx === this.state.gameInfo.currentPlayer){ if(res.turn === this.state.gameInfo.turn && res.playerIdx === this.state.gameInfo.currentPlayer){
let gameInfo = JSON.parse(JSON.stringify(this.state.gameInfo)); 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"); console.log("Cannot find cards in move from player's hand");
} }
gameInfo.considerationTime = this.initConsiderationTime; gameInfo.considerationTime = this.initConsiderationTime;
this.setState({gameInfo: gameInfo}); this.setState({gameInfo: gameInfo}, ()=>{
this.gameStateTimer();
});
}else{ }else{
console.log("Mismatched game turn or current player index", message); console.log("Mismatched game turn or current player index", message);
} }
@ -116,6 +116,26 @@ class DoudizhuGameView extends React.Component {
this.setState({ws: ws}); 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(){ render(){
return ( return (
<div> <div>
@ -127,12 +147,17 @@ class DoudizhuGameView extends React.Component {
mainPlayerId={this.state.gameInfo.mainViewerId} mainPlayerId={this.state.gameInfo.mainViewerId}
currentPlayer={this.state.gameInfo.currentPlayer} currentPlayer={this.state.gameInfo.currentPlayer}
considerationTime={this.state.gameInfo.considerationTime} considerationTime={this.state.gameInfo.considerationTime}
turn={this.state.gameInfo.turn}
runNewTurn={(prevTurn)=>this.runNewTurn(prevTurn)}
/> />
</div> </div>
<div style={{marginTop: "10px"}}> <div style={{marginTop: "10px"}}>
<input type='button' value='Connect' onClick={()=>{this.connectWebSocket()}} /> <input type='button' value='Connect' onClick={()=>{this.connectWebSocket()}} />
<input style={{marginLeft: "10px"}} type='button' value='Start Replay' onClick={()=>{this.startReplay()}} /> <input style={{marginLeft: "10px"}} type='button' value='Start Replay' onClick={()=>{this.startReplay()}} />
</div> </div>
<div style={{marginTop: "10px"}}>
{`Current Player: ${this.state.gameInfo.currentPlayer} , Consideration Time: ${this.state.gameInfo.considerationTime}, Turn: ${this.state.gameInfo.turn}`}
</div>
</div> </div>
) )
} }