用AI写的一个单机HTML小游戏,折腾了大半天了,但老头网站上内嵌搞了半天都不成,各位自己下载就能玩了。
[ttreply]
感谢大佬给的方法,直接点这个就能玩大富翁WEB测试版
需要源码的看下面。
方法很简单,全复制,然后打开记事本,另存为rich.html,然后双击打开浏览器就能玩了。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>大富翁 - 桌面投骰子游戏</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 15px;
display: flex;
justify-content: center;
align-items: center;
}
.game-container {
background: white;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
padding: 25px;
max-width: 1400px;
width: 100%;
max-height: 95vh;
overflow-y: auto;
}
.game-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 3px solid #667eea;
}
.game-title {
font-size: 32px;
font-weight: bold;
color: #667eea;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
}
.game-controls {
display: flex;
gap: 10px;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
font-weight: bold;
transition: all 0.3s ease;
}
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.btn-secondary {
background: #f0f0f0;
color: #333;
}
.btn-secondary:hover {
background: #e0e0e0;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.game-main {
display: grid;
grid-template-columns: 300px 1fr 320px;
gap: 20px;
align-items: start;
}
.left-panel {
display: flex;
flex-direction: column;
gap: 12px;
}
.right-panel {
display: flex;
flex-direction: column;
gap: 15px;
}
.board-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
.board {
display: grid;
grid-template-columns: repeat(6, 80px);
grid-template-rows: repeat(6, 80px);
gap: 5px;
background: #f5f5f5;
padding: 10px;
border-radius: 10px;
box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.1);
}
.cell {
width: 80px;
height: 80px;
background: white;
border: 2px solid #ddd;
border-radius: 8px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 11px;
text-align: center;
position: relative;
transition: all 0.3s ease;
cursor: pointer;
}
.cell:hover {
transform: scale(1.05);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}
.cell.current-player-position {
border: 4px solid #ff9800;
box-shadow: 0 0 20px rgba(255, 152, 0, 0.6), 0 0 40px rgba(255, 152, 0, 0.3);
animation: pulse 1.5s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% {
box-shadow: 0 0 20px rgba(255, 152, 0, 0.6), 0 0 40px rgba(255, 152, 0, 0.3);
}
50% {
box-shadow: 0 0 30px rgba(255, 152, 0, 0.8), 0 0 60px rgba(255, 152, 0, 0.5);
}
}
.cell.corner {
background: linear-gradient(135deg, #ffeaa7 0%, #fdcb6e 100%);
font-weight: bold;
}
.cell.property {
background: white;
color: #333;
}
.cell.property::before {
content: '🏝️';
font-size: 20px;
margin-bottom: 2px;
}
.cell.player1-owned {
border-color: #e74c3c;
box-shadow: 0 0 10px rgba(231, 76, 60, 0.5);
background-color: rgba(231, 76, 60, 0.2);
}
.cell.player2-owned {
border-color: #3498db;
box-shadow: 0 0 10px rgba(52, 152, 219, 0.5);
background-color: rgba(52, 152, 219, 0.2);
}
.cell.player3-owned {
border-color: #2ecc71;
box-shadow: 0 0 10px rgba(46, 204, 113, 0.5);
background-color: rgba(46, 204, 113, 0.2);
}
.cell.player4-owned {
border-color: #9b59b6;
box-shadow: 0 0 10px rgba(155, 89, 182, 0.5);
background-color: rgba(155, 89, 182, 0.2);
}
.cell-number {
font-size: 10px;
color: #666;
margin-bottom: 2px;
}
.cell-price {
font-size: 10px;
font-weight: bold;
color: #e74c3c;
}
.cell-owner {
font-size: 9px;
margin-top: 2px;
padding: 2px 4px;
border-radius: 3px;
background: rgba(255, 255, 255, 0.9);
color: #333;
}
.cell-building {
font-size: 22px;
margin-top: 4px;
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
}
.cell.player1-owned .cell-building,
.cell.player2-owned .cell-building,
.cell.player3-owned .cell-building,
.cell.player4-owned .cell-building {
animation: bounce 0.5s ease;
}
@keyframes bounce {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.2); }
}
.player-token {
width: 28px;
height: 28px;
border-radius: 50%;
position: absolute;
border: 3px solid white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.player-token.p1 {
background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%);
}
.player-token.p2 {
background: linear-gradient(135deg, #3498db 0%, #2980b9 100%);
}
.player-token.p3 {
background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%);
}
.player-token.p4 {
background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%);
}
.player-token.multiple {
transform: scale(0.75);
}
.center-area {
background: linear-gradient(135deg, #fff9c4 0%, #fff59d 100%);
border-radius: 15px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 25px 20px;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15);
border: 3px solid #ffc107;
}
.dice-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
width: 100%;
}
.dice {
width: 90px;
height: 90px;
background: linear-gradient(135deg, #ffffff 0%, #f0f0f0 100%);
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 52px;
font-weight: bold;
color: #333;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2);
transition: transform 0.3s ease;
border: 3px solid #ffc107;
}
.dice.rolling {
animation: roll 0.5s ease-in-out;
}
@keyframes roll {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(90deg); }
50% { transform: rotate(180deg); }
75% { transform: rotate(270deg); }
}
.dice-result {
font-size: 24px;
font-weight: bold;
color: #667eea;
}
.current-turn {
font-size: 18px;
font-weight: bold;
color: #333;
margin-bottom: 10px;
}
.action-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
justify-content: center;
}
.btn-action {
padding: 12px 24px;
font-size: 16px;
}
.sidebar {
display: flex;
flex-direction: column;
gap: 15px;
}
.player-info {
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
border-radius: 12px;
padding: 12px;
transition: all 0.3s ease;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
}
#player1Info {
border-left: 5px solid #e74c3c; /* 人类玩家使用红色 */
}
#player2Info {
border-left: 5px solid #3498db; /* 阿土仔使用蓝色 */
}
#player3Info {
border-left: 5px solid #2ecc71; /* 钱夫人使用绿色 */
}
#player4Info {
border-left: 5px solid #9b59b6; /* 小美使用紫色 */
}
.player-info.active {
background: linear-gradient(135deg, #fff9c4 0%, #ffe082 100%);
box-shadow: 0 8px 25px rgba(255, 152, 0, 0.4);
transform: scale(1.02);
}
#player1Info.active {
border-left-color: #e74c3c; /* 保持玩家1的红色边框 */
}
#player2Info.active {
border-left-color: #3498db; /* 保持玩家2的蓝色边框 */
}
#player3Info.active {
border-left-color: #2ecc71; /* 保持玩家3的绿色边框 */
}
#player4Info.active {
border-left-color: #9b59b6; /* 保持玩家4的紫色边框 */
}
.player-info.bankrupt {
opacity: 0.4;
text-decoration: line-through;
background: #e0e0e0;
}
.player-name {
font-size: 15px;
font-weight: bold;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 8px;
color: #2c3e50;
}
.player-avatar {
width: 32px;
height: 32px;
font-size: 24px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
}
.player-color {
display: none;
}
.player-stats {
font-size: 12px;
color: #34495e;
line-height: 1.8;
}
.player-money {
font-size: 16px;
font-weight: bold;
color: #27ae60;
}
.game-log {
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
border-radius: 12px;
padding: 18px;
max-height: 400px;
overflow-y: auto;
border: 3px solid #e9ecef;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
}
.log-title {
font-size: 17px;
font-weight: bold;
margin-bottom: 12px;
color: #667eea;
padding-bottom: 8px;
border-bottom: 2px solid #667eea;
}
.log-entry {
font-size: 13px;
padding: 6px 0;
border-bottom: 1px solid #e9ecef;
color: #2c3e50;
line-height: 1.6;
}
.log-entry:last-child {
border-bottom: none;
}
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
z-index: 1000;
justify-content: center;
align-items: center;
}
.modal.show {
display: flex;
}
.modal-content {
background: white;
border-radius: 15px;
padding: 30px;
max-width: 600px;
width: 90%;
max-height: 80vh;
overflow-y: auto;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}
.modal-title {
font-size: 24px;
font-weight: bold;
margin-bottom: 20px;
color: #667eea;
}
.modal-body {
font-size: 14px;
line-height: 1.8;
color: #555;
}
.modal-body h3 {
color: #667eea;
margin: 15px 0 10px 0;
}
.modal-body ul {
margin-left: 20px;
}
.modal-body li {
margin-bottom: 8px;
}
.modal-close {
margin-top: 20px;
text-align: right;
}
.game-over-modal {
text-align: center;
}
.winner-text {
font-size: 28px;
font-weight: bold;
color: #27ae60;
margin: 20px 0;
}
.decision-buttons {
display: flex;
flex-direction: column;
gap: 10px;
width: 100%;
margin-top: 15px;
}
.decision-info-panel {
background: linear-gradient(135deg, #fff9c4 0%, #ffe082 100%);
border-radius: 10px;
padding: 15px;
margin-top: 15px;
border: 2px solid #ff9800;
box-shadow: 0 3px 10px rgba(255, 152, 0, 0.2);
}
.decision-info-panel h4 {
color: #ff9800;
margin-bottom: 10px;
font-size: 15px;
text-align: center;
}
.decision-info-panel p {
margin: 5px 0;
color: #555;
font-size: 13px;
line-height: 1.5;
}
.decision-info-panel .highlight-price {
color: #e74c3c;
font-weight: bold;
font-size: 16px;
}
.decision-info-panel .highlight-money {
color: #27ae60;
font-weight: bold;
font-size: 16px;
}
.btn-decision-inline {
padding: 10px 20px;
font-size: 14px;
width: 100%;
}
@media (max-width: 1100px) {
.game-main {
grid-template-columns: 1fr;
}
.left-panel, .right-panel {
order: 2;
}
.board-container {
order: 1;
}
.board {
grid-template-columns: repeat(6, 60px);
grid-template-rows: repeat(6, 60px);
}
.cell {
width: 60px;
height: 60px;
font-size: 9px;
}
.cell-price {
font-size: 9px;
}
.player-token {
width: 15px;
height: 15px;
}
.decision-modal {
max-width: 90%;
}
.btn-decision {
padding: 10px 20px;
font-size: 14px;
min-width: 100px;
}
}
@media (max-width: 600px) {
.game-container {
padding: 15px;
}
.game-title {
font-size: 20px;
}
.board {
grid-template-columns: repeat(6, 45px);
grid-template-rows: repeat(6, 45px);
}
.cell {
width: 45px;
height: 45px;
font-size: 8px;
}
.cell-number {
font-size: 8px;
}
.cell-price {
font-size: 8px;
}
.cell-owner {
font-size: 7px;
padding: 1px 2px;
}
.cell-building {
font-size: 12px;
}
.player-token {
width: 12px;
height: 12px;
}
.dice {
width: 60px;
height: 60px;
font-size: 36px;
}
.decision-modal {
max-width: 95%;
}
.decision-info {
padding: 10px;
}
.decision-info h3 {
font-size: 16px;
}
.decision-info p {
font-size: 12px;
}
.btn-decision {
padding: 8px 15px;
font-size: 13px;
min-width: 80px;
}
}
@media (min-width: 1600px) {
.game-main {
grid-template-columns: 350px 1fr 380px;
gap: 25px;
}
.game-container {
max-width: 1600px;
}
.board {
grid-template-columns: repeat(6, 90px);
grid-template-rows: repeat(6, 90px);
}
.cell {
width: 90px;
height: 90px;
font-size: 12px;
}
.cell-number {
font-size: 11px;
}
.cell-price {
font-size: 11px;
}
.cell-owner {
font-size: 9px;
}
.cell-building {
font-size: 24px;
}
.player-token {
width: 30px;
height: 30px;
font-size: 20px;
}
.player-avatar {
width: 45px;
height: 45px;
font-size: 36px;
}
.player-info {
padding: 20px;
}
.player-name {
font-size: 18px;
}
.player-stats {
font-size: 15px;
}
.player-money {
font-size: 22px;
}
.dice {
width: 100px;
height: 100px;
font-size: 58px;
}
.btn-action {
padding: 14px 28px;
font-size: 18px;
}
.game-log {
max-height: 450px;
}
.log-entry {
font-size: 14px;
}
}
</style>
</head>
<body>
<div>
<div>
<h1>🎲 大富翁</h1>
<div>
<button class="btn btn-secondary" onclick="showRules()">📖 规则</button>
<button class="btn btn-primary" onclick="startNewGame()">🔄 新游戏</button>
</div>
</div>
<div>
<div>
<div class="player-info active" id="player1Info">
<div>
<div>👨</div>
玩家 (人类)
<div style="display: flex; gap: 10px; margin-left: auto; font-size: 8px;">
<span style="color: green;">+<span id="player1Income">0</span></span>
<span style="color: red;">+<span id="player1Expense">0</span></span>
</div>
</div>
<div>
<div style="display: flex; align-items: center; gap: 15px;">
<div>💰 <span id="player1Money">1000</span>元</div>
<div id="player1LastTransaction" style="font-size: 10px; color: #666; flex-grow: 1; text-align: right;"></div>
</div>
<div>🏠 地产: <span id="player1Properties">0</span>处</div>
<div>📍 位置: <span id="player1Position">0</span></div>
</div>
</div>
<div id="player2Info">
<div>
<div>👴</div>
阿土仔 (AI)
<div style="display: flex; gap: 10px; margin-left: auto; font-size: 8px;">
<span style="color: green;">+<span id="player2Income">0</span></span>
<span style="color: red;">+<span id="player2Expense">0</span></span>
</div>
</div>
<div>
<div style="display: flex; align-items: center; gap: 15px;">
<div>💰 <span id="player2Money">1000</span>元</div>
<div id="player2LastTransaction" style="font-size: 10px; color: #666; flex-grow: 1; text-align: right;"></div>
</div>
<div>🏠 地产: <span id="player2Properties">0</span>处</div>
<div>📍 位置: <span id="player2Position">0</span></div>
</div>
</div>
<div id="player3Info">
<div>
<div>👩</div>
钱夫人 (AI)
<div style="display: flex; gap: 10px; margin-left: auto; font-size: 8px;">
<span style="color: green;">+<span id="player3Income">0</span></span>
<span style="color: red;">+<span id="player3Expense">0</span></span>
</div>
</div>
<div>
<div style="display: flex; align-items: center; gap: 15px;">
<div>💰 <span id="player3Money">1000</span>元</div>
<div id="player3LastTransaction" style="font-size: 10px; color: #666; flex-grow: 1; text-align: right;"></div>
</div>
<div>🏠 地产: <span id="player3Properties">0</span>处</div>
<div>📍 位置: <span id="player3Position">0</span></div>
</div>
</div>
<div id="player4Info">
<div>
<div>👧</div>
小美 (AI)
<div style="display: flex; gap: 10px; margin-left: auto; font-size: 8px;">
<span style="color: green;">+<span id="player4Income">0</span></span>
<span style="color: red;">+<span id="player4Expense">0</span></span>
</div>
</div>
<div>
<div style="display: flex; align-items: center; gap: 15px;">
<div>💰 <span id="player4Money">1000</span>元</div>
<div id="player4LastTransaction" style="font-size: 10px; color: #666; flex-grow: 1; text-align: right;"></div>
</div>
<div>🏠 地产: <span id="player4Properties">0</span>处</div>
<div>📍 位置: <span id="player4Position">0</span></div>
</div>
</div>
</div>
<div>
<div id="board"></div>
</div>
<div>
<div>
<div>
<div id="currentTurn">当前回合: 玩家1</div>
<div id="dice">🎲</div>
<div id="diceResult"></div>
<div>
<button class="btn btn-primary btn-action" id="rollBtn" onclick="rollDice()">🎲 投骰子</button>
</div>
<div id="decisionButtons" style="display: none;">
</div>
</div>
</div>
<div>
<div>📜 游戏日志</div>
<div id="gameLog"></div>
</div>
</div>
</div>
</div>
<div id="rulesModal">
<div>
<h2>📖 游戏规则</h2>
<div>
<h3>🎯 游戏目标</h3>
<ul>
<li>成为最后一名未破产的玩家,或现金超过3000元</li>
</ul>
<h3>🎲 游戏流程</h3>
<ul>
<li>4名玩家轮流投骰子(1名人类+3名AI)</li>
<li>骰子点数决定前进步数(1-6点)</li>
<li>按顺时针方向移动</li>
</ul>
<h3>🏠 地产系统</h3>
<ul>
<li>停留在无主格子时,可选择购买该地皮</li>
<li>再次经过自己的地皮时,可升级建筑</li>
<li>建筑等级:平房 → 别墅 → 大楼</li>
<li>升级需要支付相应费用</li>
</ul>
<h3>💰 经济系统</h3>
<ul>
<li>停留在他人地皮时,需支付租金</li>
<li>租金 = 地皮投资总额 × 50%</li>
<li>投资总额 = 地皮基础价格 + 所有升级费用</li>
</ul>
<h3>💔 破产规则</h3>
<ul>
<li>现金为0时判定破产</li>
<li>破产玩家的所有地皮变为无主状态</li>
<li>3名玩家破产时游戏结束</li>
</ul>
<h3>🏆 胜利条件</h3>
<ul>
<li>成为最后一名未破产的玩家</li>
<li>或现金超过3000元</li>
</ul>
</div>
<div>
<button class="btn btn-primary" onclick="closeRules()">关闭</button>
</div>
</div>
</div>
<div id="gameOverModal">
<div class="modal-content game-over-modal">
<h2>🎉 游戏结束</h2>
<div id="winnerText"></div>
<div>
<button class="btn btn-primary" onclick="closeGameOver(); startNewGame();">再来一局</button>
</div>
</div>
</div>
<script>
const BOARD_SIZE = 6;
const TOTAL_CELLS = 20;
const INITIAL_MONEY = 1000;
const WIN_MONEY = 3000;
const RENT_PERCENTAGE = 0.5;
const CELL_PRICES = [
100, 120, 140, 160, 180,
200, 220, 240, 260, 280,
300, 320, 340, 350, 330,
310, 290, 270, 250, 230
];
const UPGRADE_COSTS = {
1: 150,
2: 300,
3: 500
};
const BUILDING_ICONS = {
0: '',
1: '🏠',
2: '🏡',
3: '🏢'
};
const BUILDING_NAMES = {
0: '',
1: '房屋',
2: '别墅',
3: '高楼'
};
const PLAYER_NAMES = ['玩家', '阿土仔', '钱夫人', '小美'];
const PLAYER_COLORS = ['#e74c3c', '#3498db', '#2ecc71', '#9b59b6'];
let gameState = {
players: [],
cells: [],
currentPlayer: 0,
gameStarted: false,
gameOver: false,
waitingForDecision: false
};
function initCells() {
gameState.cells = [];
for (let i = 0; i < TOTAL_CELLS; i++) {
gameState.cells.push({
id: i,
price: CELL_PRICES[i],
owner: null,
buildingLevel: 0,
totalInvestment: CELL_PRICES[i]
});
}
}
function initPlayers() {
gameState.players = [];
for (let i = 0; i < 4; i++) {
gameState.players.push({
id: i,
name: PLAYER_NAMES[i],
isAI: i > 0,
money: INITIAL_MONEY,
position: 0,
properties: [],
bankrupt: false,
income: 0,
expense: 0,
lastTransaction: ''
});
}
}
function getBoardPosition(cellIndex) {
if (cellIndex < 6) {
return { row: 0, col: cellIndex };
} else if (cellIndex < 10) {
return { row: cellIndex - 5, col: 5 };
} else if (cellIndex < 16) {
return { row: 5, col: 15 - cellIndex };
} else {
return { row: 20 - cellIndex, col: 0 };
}
}
function renderBoard() {
const board = document.getElementById('board');
board.innerHTML = '';
const currentPlayer = gameState.players[gameState.currentPlayer];
for (let row = 0; row < BOARD_SIZE; row++) {
for (let col = 0; col < BOARD_SIZE; col++) {
const cell = document.createElement('div');
cell.className = 'cell';
let cellIndex = -1;
if (row === 0 && col < 6) {
cellIndex = col;
} else if (col === 5 && row > 0 && row < 6) {
cellIndex = 5 + row;
} else if (row === 5 && col >= 0 && col < 6) {
cellIndex = 10 + (5 - col);
} else if (col === 0 && row > 0 && row < 5) {
cellIndex = 16 + (4 - row);
}
if (cellIndex >= 0 && cellIndex < TOTAL_CELLS) {
const cellData = gameState.cells[cellIndex];
cell.innerHTML = `
<div>${cellIndex + 1}</div>
<div>¥${cellData.price}</div>
`;
if (cellData.owner !== null) {
cell.classList.add(`player${cellData.owner + 1}-owned`);
cell.innerHTML += `<div>${PLAYER_NAMES[cellData.owner]}</div>`;
if (cellData.buildingLevel > 0) {
cell.innerHTML += `<div title="${BUILDING_NAMES[cellData.buildingLevel]}">${BUILDING_ICONS[cellData.buildingLevel]}</div>`;
} else {
cell.innerHTML += `<div>🏝️</div>`;
}
} else {
cell.classList.add('property');
}
if (cellIndex === currentPlayer.position && !currentPlayer.bankrupt && !gameState.gameOver) {
cell.classList.add('current-player-position');
}
const playersOnCell = gameState.players.filter(p => p.position === cellIndex && !p.bankrupt);
if (playersOnCell.length > 0) {
playersOnCell.forEach((player, idx) => {
const token = document.createElement('div');
token.className = `player-token p${player.id + 1}`;
if (playersOnCell.length > 1) {
token.classList.add('multiple');
}
token.style.top = `${5 + idx * 20}px`;
token.style.right = `${5 + idx * 20}px`;
const avatarEmojis = ['👨', '👴', '👩', '👧'];
token.textContent = avatarEmojis[player.id];
cell.appendChild(token);
});
}
} else {
cell.style.background = 'transparent';
cell.style.border = 'none';
}
board.appendChild(cell);
}
}
}
function renderPlayerInfo() {
for (let i = 0; i < 4; i++) {
const player = gameState.players[i];
const infoEl = document.getElementById(`player${i + 1}Info`);
const moneyEl = document.getElementById(`player${i + 1}Money`);
const propertiesEl = document.getElementById(`player${i + 1}Properties`);
const positionEl = document.getElementById(`player${i + 1}Position`);
const incomeEl = document.getElementById(`player${i + 1}Income`);
const expenseEl = document.getElementById(`player${i + 1}Expense`);
const lastTransactionEl = document.getElementById(`player${i + 1}LastTransaction`);
moneyEl.textContent = player.money;
propertiesEl.textContent = player.properties.length;
positionEl.textContent = player.position + 1;
incomeEl.textContent = player.income;
expenseEl.textContent = player.expense;
lastTransactionEl.textContent = player.lastTransaction;
if (gameState.currentPlayer === i && !gameState.gameOver) {
infoEl.classList.add('active');
} else {
infoEl.classList.remove('active');
}
if (player.bankrupt) {
infoEl.classList.add('bankrupt');
} else {
infoEl.classList.remove('bankrupt');
}
}
}
// 闪烁动画函数
function animateLastTransaction(playerId) {
const lastTransactionEl = document.getElementById(`player${playerId + 1}LastTransaction`);
if (lastTransactionEl) {
lastTransactionEl.style.animation = 'pulse 0.5s ease-in-out 3';
setTimeout(() => {
lastTransactionEl.style.animation = '';
}, 1500);
}
}
function updateCurrentTurn() {
const turnEl = document.getElementById('currentTurn');
const player = gameState.players[gameState.currentPlayer];
turnEl.textContent = `当前回合: ${player.name}`;
turnEl.style.color = PLAYER_COLORS[gameState.currentPlayer];
}
function addLog(message) {
const logEl = document.getElementById('gameLog');
const entry = document.createElement('div');
entry.className = 'log-entry';
entry.innerHTML = message;
logEl.insertBefore(entry, logEl.firstChild);
if (logEl.children.length > 50) {
logEl.removeChild(logEl.lastChild);
}
}
function rollDice() {
if (gameState.gameOver || !gameState.gameStarted) return;
const player = gameState.players[gameState.currentPlayer];
if (player.bankrupt) {
addLog(`💔 玩家 ${player.name} 已破产,跳过投骰子`);
nextTurn();
return;
}
const diceEl = document.getElementById('dice');
const resultEl = document.getElementById('diceResult');
const rollBtn = document.getElementById('rollBtn');
rollBtn.disabled = true;
diceEl.classList.add('rolling');
const diceValue = Math.floor(Math.random() * 6) + 1;
setTimeout(() => {
diceEl.classList.remove('rolling');
diceEl.textContent = diceValue;
resultEl.textContent = `点数: ${diceValue}`;
addLog(`${player.name} 投出了 ${diceValue} 点`);
movePlayer(player, diceValue);
}, 500);
}
function movePlayer(player, steps) {
const oldPosition = player.position;
let currentStep = 0;
const targetPosition = (player.position + steps) % TOTAL_CELLS;
addLog(`${player.name} 从 ${oldPosition + 1} 移动到 ${targetPosition + 1}`);
// 实现平滑移动动画
function animateStep() {
if (currentStep < steps) {
player.position = (player.position + 1) % TOTAL_CELLS;
currentStep++;
// 检查是否经过1号地块(位置0),即完成一圈
if (player.position === 0 && currentStep > 0) {
const bonus = Math.floor(player.money * 0.1);
player.money += bonus;
player.income += bonus;
addLog(`💰 ${player.name}<span style="color: green;">+${bonus}</span> 完成一圈,获得当前现金10%的奖励 [¥${bonus}],当前资金:¥${player.money}`);
player.lastTransaction = `完成一圈,获得 +¥${bonus}`;
animateLastTransaction(player.id);
}
renderBoard();
renderPlayerInfo();
setTimeout(animateStep, 200); // 控制动画速度
} else {
// 动画完成后处理着陆
setTimeout(() => {
handleCellLanding(player);
}, 300);
}
}
animateStep();
}
function handleCellLanding(player) {
const cell = gameState.cells[player.position];
if (cell.owner === null) {
if (player.money >= cell.price) {
if (player.isAI) {
aiDecideBuy(player, cell);
} else {
showBuyDecision(player, cell);
}
} else {
addLog(`${player.name} 资金不足,无法购买 ${player.position + 1} 号地皮`);
nextTurn();
}
} else if (cell.owner === player.id) {
if (cell.buildingLevel < 3) {
const upgradeCost = UPGRADE_COSTS[cell.buildingLevel + 1];
if (player.money >= upgradeCost) {
if (player.isAI) {
aiDecideUpgrade(player, cell);
} else {
showUpgradeDecision(player, cell);
}
} else {
addLog(`${player.name} 资金不足,无法升级 ${player.position + 1} 号地皮`);
nextTurn();
}
} else {
addLog(`${player.name} 的 ${player.position + 1} 号地皮已达到最高等级`);
nextTurn();
}
} else {
const owner = gameState.players[cell.owner];
if (!owner.bankrupt) {
const rent = Math.floor(cell.totalInvestment * RENT_PERCENTAGE);
if (player.money >= rent) {
player.money -= rent;
player.expense += rent;
owner.money += rent;
owner.income += rent;
addLog(`${player.name}<span style="color: red;">-${rent}</span> 向 ${owner.name}<span style="color: green;">+${rent}</span> 支付租金 [¥${rent}]`);
player.lastTransaction = `支付租金给${owner.name},花费 -¥${rent}`;
owner.lastTransaction = `收到${player.name}的租金,收入 +¥${rent}`;
animateLastTransaction(player.id);
animateLastTransaction(owner.id);
checkBankruptcy(player);
} else {
const actualRent = player.money;
player.money = 0;
player.expense += actualRent;
owner.money += actualRent;
owner.income += actualRent;
addLog(`${player.name}<span style="color: red;">-${actualRent}</span> 向 ${owner.name}<span style="color: green;">+${actualRent}</span> 支付租金(全部资金)[¥${actualRent}]`);
player.lastTransaction = `支付租金给${owner.name},花费 -¥${actualRent}`;
owner.lastTransaction = `收到${player.name}的租金,收入 +¥${actualRent}`;
animateLastTransaction(player.id);
animateLastTransaction(owner.id);
checkBankruptcy(player);
}
renderBoard();
renderPlayerInfo();
} else {
addLog(`${player.name} 停留在 ${player.position + 1} 号地皮,但持有人已破产`);
}
nextTurn();
}
}
function showBuyDecision(player, cell) {
const decisionButtons = document.getElementById('decisionButtons');
const actionButtons = document.querySelector('.action-buttons');
actionButtons.style.display = 'none';
decisionButtons.innerHTML = `
<div>
<h4>🏝️ 购买地皮</h4>
<p>📍 位置:${cell.id + 1} 号地皮</p>
<p>💰 售价:<span>¥${cell.price}</span></p>
<p>💵 你的资金:<span>¥${player.money}</span></p>
</div>
<div style="display: flex; gap: 10px; width: 100%; margin-top: 10px;">
<button class="btn btn-primary btn-action" onclick="confirmBuyProperty()" style="flex: 1;">💰 购买</button>
<button class="btn btn-secondary btn-action" onclick="cancelDecision()" style="flex: 1;">❌ 不购买</button>
</div>
`;
decisionButtons.style.display = 'flex';
}
function showUpgradeDecision(player, cell) {
const decisionButtons = document.getElementById('decisionButtons');
const actionButtons = document.querySelector('.action-buttons');
actionButtons.style.display = 'none';
const currentLevel = cell.buildingLevel;
const nextLevel = currentLevel + 1;
const upgradeCost = UPGRADE_COSTS[nextLevel];
decisionButtons.innerHTML = `
<div>
<h4>🏗️ 升级建筑</h4>
<p>📍 位置:${cell.id + 1} 号地皮</p>
<p>🏠 当前等级:${BUILDING_NAMES[currentLevel]} ${BUILDING_ICONS[currentLevel]}</p>
<p>🏢 升级到:${BUILDING_NAMES[nextLevel]} ${BUILDING_ICONS[nextLevel]}</p>
<p>💰 升级费用:<span>¥${upgradeCost}</span></p>
<p>💵 你的资金:<span>¥${player.money}</span></p>
</div>
<div style="display: flex; gap: 10px; width: 100%; margin-top: 10px;">
<button class="btn btn-primary btn-action" onclick="confirmUpgradeProperty()" style="flex: 1;">🏗️ 升级</button>
<button class="btn btn-secondary btn-action" onclick="cancelDecision()" style="flex: 1;">❌ 不升级</button>
</div>
`;
decisionButtons.style.display = 'flex';
}
function closeDecisionModal() {
document.getElementById('decisionModal').classList.remove('show');
}
function cancelDecision() {
const decisionButtons = document.getElementById('decisionButtons');
const actionButtons = document.querySelector('.action-buttons');
decisionButtons.style.display = 'none';
decisionButtons.innerHTML = '';
actionButtons.style.display = 'flex';
gameState.waitingForDecision = false;
addLog(`${gameState.players[gameState.currentPlayer].name} 选择不操作`);
nextTurn();
}
function confirmBuyProperty() {
const player = gameState.players[gameState.currentPlayer];
const cell = gameState.cells[player.position];
if (player.money >= cell.price) {
player.money -= cell.price;
player.expense += cell.price;
cell.owner = player.id;
player.properties.push(cell.id);
cell.totalInvestment = cell.price;
addLog(`${player.name}<span style="color: red;">-${cell.price}</span> 购买了 ${player.position + 1} 号地皮 [¥${cell.price}]`);
player.lastTransaction = `购买${player.position + 1}号地产,花费 -¥${cell.price}`;
animateLastTransaction(player.id);
const decisionButtons = document.getElementById('decisionButtons');
const actionButtons = document.querySelector('.action-buttons');
decisionButtons.style.display = 'none';
decisionButtons.innerHTML = '';
actionButtons.style.display = 'flex';
gameState.waitingForDecision = false;
addLog(`✅ 购买操作完成,准备切换到下一个玩家`);
renderBoard();
renderPlayerInfo();
checkGameOver();
// 延迟调用nextTurn确保状态完全重置
setTimeout(() => {
nextTurn();
}, 100);
}
}
function confirmUpgradeProperty() {
const player = gameState.players[gameState.currentPlayer];
const cell = gameState.cells[player.position];
if (cell.buildingLevel < 3) {
const upgradeCost = UPGRADE_COSTS[cell.buildingLevel + 1];
if (player.money >= upgradeCost) {
player.money -= upgradeCost;
player.expense += upgradeCost;
cell.buildingLevel++;
cell.totalInvestment += upgradeCost;
addLog(`${player.name}<span style="color: red;">-${upgradeCost}</span> 升级了 ${player.position + 1} 号地皮到 ${BUILDING_NAMES[cell.buildingLevel]} ${BUILDING_ICONS[cell.buildingLevel]} [¥${upgradeCost}]`);
player.lastTransaction = `升级${player.position + 1}号地产,花费 -¥${upgradeCost}`;
animateLastTransaction(player.id);
const decisionButtons = document.getElementById('decisionButtons');
const actionButtons = document.querySelector('.action-buttons');
decisionButtons.style.display = 'none';
decisionButtons.innerHTML = '';
actionButtons.style.display = 'flex';
gameState.waitingForDecision = false;
addLog(`✅ 升级操作完成,准备切换到下一个玩家`);
renderBoard();
renderPlayerInfo();
checkGameOver();
// 延迟调用nextTurn确保状态完全重置
setTimeout(() => {
nextTurn();
}, 100);
}
}
}
function showBuyButton() {
}
function showUpgradeButton() {
}
function hideActionButtons() {
// 修复:只隐藏存在的元素,避免访问null
const buyBtn = document.getElementById('buyBtn');
const upgradeBtn = document.getElementById('upgradeBtn');
if (buyBtn) {
buyBtn.style.display = 'none';
}
if (upgradeBtn) {
upgradeBtn.style.display = 'none';
}
}
function aiDecideBuy(player, cell) {
addLog(`🤖 AI玩家 ${player.name} 开始购买决策...`);
gameState.waitingForDecision = true;
setTimeout(() => {
const buyProbability = 0.7;
if (Math.random() < buyProbability) {
addLog(`🤖 AI玩家 ${player.name} 决定购买地皮 ${cell.id + 1}`);
confirmBuyProperty();
} else {
addLog(`🤖 AI玩家 ${player.name} 选择不购买 ${player.position + 1} 号地皮`);
cancelDecision();
}
}, 1000);
}
function aiDecideUpgrade(player, cell) {
addLog(`🤖 AI玩家 ${player.name} 开始升级决策...`);
gameState.waitingForDecision = true;
setTimeout(() => {
const upgradeProbability = 0.8;
if (Math.random() < upgradeProbability) {
addLog(`🤖 AI玩家 ${player.name} 决定升级地皮 ${cell.id + 1}`);
confirmUpgradeProperty();
} else {
addLog(`🤖 AI玩家 ${player.name} 选择不升级 ${player.position + 1} 号地皮`);
cancelDecision();
}
}, 1000);
}
function checkBankruptcy(player) {
if (player.money <= 0) {
player.bankrupt = true;
addLog(`${player.name} 破产了!`);
// 遍历玩家所有地产,根据升级状态进行不同处理
const updatedProperties = [];
player.properties.forEach(cellId => {
const cell = gameState.cells[cellId];
if (cell.buildingLevel === 0) {
// 基础地产(未升级):充公
addLog(`🏠 ${cellId + 1}号基础地产被系统回收(充公)`);
cell.owner = null;
cell.totalInvestment = cell.price;
} else {
// 已升级地产:保持当前状态,不回收
updatedProperties.push(cellId);
addLog(`🏡 ${cellId + 1}号升级地产保留现有状态,建筑等级:${cell.buildingLevel}`);
}
});
// 更新玩家剩余地产列表(只保留已升级但未被回收的地产)
player.properties = updatedProperties;
renderBoard();
renderPlayerInfo();
// 新增:如果人类玩家(玩家1)破产,游戏结束
if (player.id === 0) {
addLog(`💥 人类玩家破产!游戏结束!`);
showGameOver(player, true); // 人类玩家失败
} else {
// 检查所有AI玩家是否均已破产
checkGameOver();
}
}
}
function checkGameOver() {
const activePlayers = gameState.players.filter(p => !p.bankrupt);
if (activePlayers.length === 1) {
gameState.gameOver = true;
showGameOver(activePlayers[0]);
return;
}
// 检查所有AI玩家是否均失败
const aiPlayers = gameState.players.filter(p => p.isAI);
const allAiBankrupt = aiPlayers.every(p => p.bankrupt);
if (allAiBankrupt) {
// 人类玩家获胜
gameState.gameOver = true;
showGameOver(gameState.players[0]); // 玩家1是人类
return;
}
// 检查人类玩家是否是唯一存活的玩家
const humanPlayer = gameState.players[0];
if (!humanPlayer.bankrupt && aiPlayers.every(p => p.bankrupt)) {
gameState.gameOver = true;
showGameOver(humanPlayer);
return;
}
const winner = gameState.players.find(p => p.money >= WIN_MONEY);
if (winner) {
gameState.gameOver = true;
showGameOver(winner);
return;
}
}
function showGameOver(winner, humanLost = false) {
const modal = document.getElementById('gameOverModal');
const winnerText = document.getElementById('winnerText');
if (humanLost) {
winnerText.textContent = `💥 游戏结束!很遗憾,你破产了!`;
} else {
winnerText.textContent = `🏆 ${winner.name} 获胜!`;
}
modal.classList.add('show');
}
function closeGameOver() {
document.getElementById('gameOverModal').classList.remove('show');
}
function nextTurn() {
if (gameState.gameOver) return;
if (gameState.waitingForDecision) return;
hideActionButtons();
let attempts = 0;
do {
gameState.currentPlayer = (gameState.currentPlayer + 1) % 4;
attempts++;
} while (gameState.players[gameState.currentPlayer].bankrupt && attempts < 4);
updateCurrentTurn();
renderPlayerInfo();
const player = gameState.players[gameState.currentPlayer];
addLog(`🔄 切换到玩家 ${player.name}`);
if (player.isAI && !player.bankrupt) {
setTimeout(() => {
if (!gameState.waitingForDecision && !gameState.gameOver) {
addLog(`🤖 AI玩家 ${player.name} 开始自动投骰子`);
rollDice();
} else {
addLog(`⏸️ AI玩家 ${player.name} 被阻止:等待决策=${gameState.waitingForDecision}, 游戏结束=${gameState.gameOver}`);
}
}, 1500);
} else if (!player.bankrupt) {
addLog(`👤 人类玩家 ${player.name} 回合开始`);
document.getElementById('rollBtn').disabled = false;
} else {
addLog(`💔 玩家 ${player.name} 已破产,跳过`);
nextTurn();
}
}
function startNewGame() {
gameState = {
players: [],
cells: [],
currentPlayer: 0,
gameStarted: true,
gameOver: false,
waitingForDecision: false
};
initCells();
initPlayers();
document.getElementById('gameLog').innerHTML = '';
document.getElementById('dice').textContent = '🎲';
document.getElementById('diceResult').textContent = '';
hideActionButtons();
addLog('🎮 新游戏开始!');
addLog('每位玩家初始资金 ¥1000');
renderBoard();
updateCurrentTurn();
renderPlayerInfo();
// 获取第一个玩家
const firstPlayer = gameState.players[gameState.currentPlayer];
if (firstPlayer.isAI) {
// 如果第一个玩家是AI,自动开始
addLog(`🤖 第一个玩家是AI ${firstPlayer.name},自动开始游戏`);
setTimeout(() => {
rollDice();
}, 1500);
} else {
// 如果第一个玩家是人类,启用投骰子按钮
addLog(`👤 第一个玩家是人类 ${firstPlayer.name},请点击投骰子开始`);
document.getElementById('rollBtn').disabled = false;
}
}
function showRules() {
document.getElementById('rulesModal').classList.add('show');
}
function closeRules() {
document.getElementById('rulesModal').classList.remove('show');
}
// 确保页面加载完成后立即初始化游戏
window.onload = function() {
startNewGame();
};
document.getElementById('rulesModal').addEventListener('click', function(e) {
if (e.target === this) {
closeRules();
}
});
document.getElementById('gameOverModal').addEventListener('click', function(e) {
if (e.target === this) {
closeGameOver();
}
});
</script>
</body>
</html>[/ttreply]
上一篇:谨防各类立人设后的论坛骗局
下一篇:[水]如龍0中配教會了我一件事
收藏的用户(1)
X
正在加载信息~
最新回复 (6)